In the challenge you are asked to find the length of the longest substring that consists of the same letter. For example, line "aaabbcaaaa" contains four substrings with the same letters "aaa", "bb","c" and "aaaa". The last substring is the longest one which makes it an answer. Input: String. Output: Int. Example:
long_repeat('sdsffffse') == 4
long_repeat('ddvvrwwwrggg') == 3
Here is my code :
def long_repeat(text):
text = list(text)
counter = []
c = []
for i in range(len(text)):
if text[0] == text[1]:
c.append(text.pop(0))
else:
counter.append(c)
c = []
print text # should be empty
print counter # should contain a lists of the repeated letters
Output:
>>>long_repeat('aaabbccc')
['a', 'b', 'b', 'c', 'c', 'c', 'c']
[['a', 'a'], [], [], [], [], [], []]
why the loop stopes when it finishes the first letter which is 'a' in this case?
The loop does not stop. Your else statement does not move the list forward (no pop here). By the way, your logic is not quite correct. And also, it is not a good idea to pop the character and then collect it each turn. You can use integers to record all necessary information you need, including position, current count, maximum count and etc.
When test[0] != text[1] e.g when input is at "ab" you aren't appending the a to the c variable
In addition, Python string has no "pop" method hence why it's exiting out (pay close attention to error returned).
Use something like this for pop
c.append(text[-1])
text = text[:-1]
Related
Good day I just want to understand the logic behind this code
lst = []
word = "ABCD"
lst[:0] = word
print(lst)
OUTPUT: ['A', 'B', 'C', 'D'] why not ['ABCD'] how?
for i in word: # this code I understand it's looping through the string
lst.append(i) # then appending to list
but the first code above I don't get the logic.
lst[:0] = ... is implemented by lst.__setitem__(slice(0, None, 0), ...), where ... is an arbitrary iterable.
The resulting slice is the empty list at the beginning of lst (though in this case, it doesn't really matter since lst is empty), so each element of ... is inserted into lst, starting at the beginning.
You can see this starting with a non-empty list.
>>> lst = [1,2,3]
>>> word = "ABCD"
>>> lst[:0] = word
>>> lst
['A', 'B', 'C', 'D', 1, 2, 3]
To get lst == ['ABCD'], you need to make the right-hand side an iterable containing the string:
lst[:0] = ('ABCD', ) # ['ABCD'] would also work.
Actually it's a well known way to convert string to a list character by character
you can find here -> https://www.geeksforgeeks.org/python-program-convert-string-list/
if you wanna try to get your list element like 'ABCD' then try
lst[:0] = [word,]
by doing that you specify that you need whole word as an element
I am trying to do slicing in string "abcdeeefghij", here I want the slicing in such a way that whatever input I use, i divide the output in the format of a list (such that in one list element no alphabets repeat).
In this case [abcde,e,efghij].
Another example is if input is "aaabcdefghiii". Here the expected output is [a,a,acbdefghi,i,i].
Also amongst the list if I want to find the highest len character i tried the below logic:
max_str = max(len(sub_strings[0]),len(sub_strings[1]),len(sub_strings[2]))
print(max_str) #output - 6
which will yield 6 as the output, but i presume this logic is not a generic one: Can someone suggest a generic logic to print the length of the maximum string.
Here is how:
s = "abcdeeefghij"
l = ['']
for c in s: # For character in s
if c in l[-1]: # If the character is already in the last string in l
l.append('') # Add a new string to l
l[-1] += c # Add the character to either the last string, either new, or old
print(l)
Output:
['abcde', 'e', 'efghij']
Use a regular expression:
import re
rx = re.compile(r'(\w)\1+')
strings = ['abcdeeefghij', 'aaabcdefghiii']
lst = [[part for part in rx.split(item) if part] for item in strings]
print(lst)
Which yields
[['abcd', 'e', 'fghij'], ['a', 'bcdefgh', 'i']]
You would loop over the characters in the input and start a new string if there is an existing match, otherwise join them onto the last string in the output list.
input_ = "aaabcdefghiii"
output = []
for char in input_:
if not output or char in output[-1]:
output.append("")
output[-1] += char
print(output)
To avoid repetition of alphabet within a list element repeat, you can greedily track what are the words that are already in the current list. Append the word to your answer once you detected a repeating alphabet.
from collections import defaultdict
s = input()
ans = []
d = defaultdict(int)
cur = ""
for i in s:
if d[i]:
ans.append(cur)
cur = i # start again since there is repeatition
d = defaultdict(int)
d[i] = 1
else:
cur += i #append to cur since no repetition yet
d[i] = 1
if cur: # handlign the last part
ans.append(cur)
print(ans)
An input of aaabcdefghiii produces ['a', 'a', 'abcdefghi', 'i', 'i'] as expected.
I want to write a loop function that go through each letter in my list called original.
original = ['ABCD', 'DCBA', 'AAAA', 'AABB']
letters = ['A', 'B', 'C', 'D']
p = 1
for o in original: # loop through the original list
for i in range(0,len(o)): # loop through each letter in selected list
if random.randint(1,10) == p: #if this gives me the probability that is met
# I want to change the current letter on the current index to
# something else different from the letter list by random (maybe random.choice)
Im new to python please can you advice.
I dont want to use class or any other library but random please
First, the zero in
for i in range(0, len(o))
is redundant. You want to give random.choice a list of letters that include everything in letters minus the current letter. The fastest way I can think of doing this is with a set:
newletters = list(set(letters).difference(o[i])
Now you have a list that includes all the letters in "letters" except for the letter at o[i].
To assign the letter (after you get it from random.choice), turn your "original" word into a list:
o_list = list(o)
and assign it as
l = random.choice(newletters)
o_list[i] = l
new_word = "".join(o_list)
As for actually inserting that new word back into your list of originals, you would have to know the index of the old word - I would use enumerate to do this:
original = ['ABCD', 'DCBA', 'AAAA', 'AABB']
letters = ['A', 'B', 'C', 'D']
p = 1
for index, o in enumerate(original): # loop through the original list
for i in range(len(o)): # loop through each letter in selected list
if random.randint(1,10) == p:
newletters = list(set(letters).difference(o[i])
o_list = list(o)
l = random.choice(newletters)
o_list[i] = l
new_word = "".join(o_list)
original[index] = new_word
In python, you can not modify strings at all. You can get letters by index, select specific strings, but not modify them. To change the said list you can use original.pop(o) and add the said edited string in the list with original.append('AB" + random.choice(letters) + 'C' as you said. To be more clear: you use list.append(element) to add element to list and you use list.pop(element) to remove element from list. Again, you can never edit strings in python, you can only create new ones and store the edited old ones, for example, new_string = old_string[:4], this particular code will store all the characters in old_string, up to index 4 into the new string. Really hope I helped!
Assuming you want to update original
import random
original = ['ABCD', 'DCBA', 'AAAA', 'AABB']
letters = ['A', 'B', 'C', 'D']
p = 1
for i, o in enumerate(original):
new_letters = [] # updated letters for word o
for c in o:
if random.randint(1,10) == p:
t = letters[:] # copy of letters
t.remove(c) # remove letter from copy (so letters remains unchanged)
new_letters.append(random.choice(t)) # choice over remaining letters
else:
new_letters.append(c)
original[i] = ''.join(new_letters) # convert newsletters list to string
# and replace in original
print(original)
How would you make a list of all the possible substrings in a string using recursion? (no loops) I know that you can recurse using s[1:] to cut off the first position and s[:-1] to cut off the last position. So far I have come up with this:
def lst_substrings(s):
lst = []
if s == "":
return lst
else:
lst.append(s)
return lst_substrings(s[1:])
but this would only make a list of all the substrings that are sliced by the first position if it worked
Fun problem, here's my solution - feedback appreciated.
Output
In [73]: lstSubStrings("Hey")
Out[73]: ['', 'y', 'H', 'Hey', 'He', 'e', 'ey']
Solution
def lstSubStrings(s):
# BASE CASE: when s is empty return the empty string
if(len(s) is 0):
return [s]
substrs = []
# a string is a substring of itself - by the definition of subset in math
substrs.append(s)
# extend the list of substrings by all substrings with the first
# character cut out
substrs.extend(lstSubStrings(s[1:]))
# extend the list of substrings by all substrings with the last
# character cut out
substrs.extend(lstSubStrings(s[:-1]))
# convert the list to `set`, removing all duplicates, and convert
# back to a list
substrs = list(set(substrs))
return substrs
EDIT: Duh. Just realized now that practically the same solution has been posted by someone who was quicker than me. Vote for his answer. I'll leave this as it is a bit more concise and in case you want to sort the resulting list by substring length. Use len(item, item), i.e. leave the - sign, to sort in ascending order.
This will do:
def lst_substrings(s):
lst = [s]
if len(s) > 0:
lst.extend(lst_substrings(s[1:]))
lst.extend(lst_substrings(s[:-1]))
return list(set(lst))
sub = lst_substrings("boby")
sub.sort(key=lambda item: (-len(item), item))
print(sub)
Output is:
['boby', 'bob', 'oby', 'bo', 'by', 'ob', 'b', 'o', 'y', '']
Question: DO NOT USE SETS IN YOUR FUNCTION: Uses lists to return a list of the common letters in the first and last names (the intersection) Prompt user for first and last name and call the function with the first and last names as arguments and print the returned list.
I can't figure out why my program is just printing "No matches" even if there are letter matches. Anything helps! Thanks a bunch!
Code so far:
import string
def getCommonLetters(text1, text2):
""" Take two strings and return a list of letters common to
both strings."""
text1List = text1.split()
text2List = text2.split()
for i in range(0, len(text1List)):
text1List[i] = getCleanText(text1List[i])
for i in range(0, len(text2List)):
text2List[i] = getCleanText(text2List[i])
outList = []
for letter in text1List:
if letter in text2List and letter not in outList:
outList.append(letter)
return outList
def getCleanText(text):
"""Return letter in lower case stripped of whitespace and
punctuation characters"""
text = text.lower()
badCharacters = string.whitespace + string.punctuation
for character in badCharacters:
text = text.replace(character, "")
return text
userText1 = raw_input("Enter your first name: ")
userText2 = raw_input("Enter your last name: ")
result = getCommonLetters(userText1, userText2)
numMatches = len(result)
if numMatches == 0:
print "No matches."
else:
print "Number of matches:", numMatches
for letter in result:
print letter
Try this:
def CommonLetters(s1, s2):
l1=list(''.join(s1.split()))
l2=list(''.join(s2.split()))
return [x for x in l1 if x in l2]
print CommonLetters('Tom','Dom de Tommaso')
Output:
>>> ['T', 'o', 'm']
for letter in text1List:
Here's your problem. text1List is a list, not a string. You iterate on a list of strings (['Bobby', 'Tables'] for instance) and you check if 'Bobby' is in the list text2List.
You want to iterate on every character of your string text1 and check if it is present in the string text2.
There's a few non-pythonic idioms in your code, but you'll learn that in time.
Follow-up: What happens if I type my first name in lowercase and my last name in uppercase? Will your code find any match?
Prior to set() being the common idiom for duplicate removal in Python 2.5, you could use the conversion of a list to a dictionary to remove duplicates.
Here is an example:
def CommonLetters(s1, s2):
d={}
for l in s1:
if l in s2 and l.isalpha():
d[l]=d.get(l,0)+1
return d
print CommonLetters('matteo', 'dom de tommaso')
This prints the count of the common letters like so:
{'a': 1, 'e': 1, 'm': 1, 't': 2, 'o': 1}
If you want to have a list of those common letters, just use the keys() method of the dictionary:
print CommonLetters('matteo', 'dom de tommaso').keys()
Which prints just the keys:
['a', 'e', 'm', 't', 'o']
If you want upper and lower case letters to match, add the logic to this line:
if l in s2 and l.isalpha():