Count number of letters until one letters has changed - python

I want to count number of same letter at beginning between two words (letter by letter) until there's one different and return who has the most same letter.
This is my code :
def same(word, liste):
letter = 0
dico = dict()
for i in liste:
while word[letter] == i[letter]:
letter += 1;
dico[i] = letter;
letter = 0;
same = max(dico, key=dico.get)
return same
But i get always this error of string index out of range, I've tried with much way but nothing
while word[letter] == i[letter]:
IndexError: string index out of range
In input :
same('hello',['hi,'hell','helo'])
Output:
'hell'
Thanks

I would just use a list comprehension along with basic substring logic:
def same(word, liste):
return max([x for x in liste if x in word], key=len)
print(same('hello',['hi','hell','helo'])) # hell

you can't go out of range in your while
verify the length of your word before word[letter] == i[letter]
while letter < len(word) and letter < len(i) and word[letter] == i[letter]:
gives you :
def same(word, liste):
letter = 0
dico = dict()
for i in liste:
while letter < len(word) and letter < len(i) and word[letter] == i[letter]:
letter += 1;
dico[i] = letter;
letter = 0;
same = max(dico, key=dico.get)
return same
print(same('blablabla',['blaze','bli']))
----------
>>> blaze

A combination of zip, sum and max should give you the result -
def same(word, liste):
pairs = [zip(word, x) for x in liste]
match_len = [sum([x == y for x, y in pair]) for pair in pairs]
return lst[match_len.index(max(match_len))]

Yet an other solution:
def same(word, liste):
def get_score(word, other):
for i, (l1, l2) in enumerate(zip(word, other)):
if l1 != l2:
break
return i
scores = {other:get_score(word, other) for other in liste}
return max(scores, key=scores.get)
In this case, I define the function get_score to count the number of common letters in a pair of words. I am sure to not run in IndexError because of the zip that makes an iterator over the 2 words.
Then I just did the same as you to get the word associated with the greatest score.

Related

Why i m only getting the first word of the list

why I am getting only the first word of the list
def concat_short_words(s):
i = 0
word = s.split()
while i < len(word):
if len(word[i]) <= 4:
result = "".join(word[i])
return(result)
i = i+1
def concat_short_words(s):
i=0
result=[]
word=s.split()
while i<len(word):
if len(word[i])<=4:
result.append(word[i])
i+=1
return result
Ignoring what I'm assuming is the accidental duplication of this function, you are returning the result of the first word matched. The return keyword will exit the function concat_short_words with the result as the returned value. Therefore, at the point of the first match to your predicate "len(word[i) <= 4" you will exit the function with the return value of the word matched. What you are probably trying to do is the following:
def concat_short_words(s):
i = 0
word = s.split()
result = ""
while i < len(word):
if len(word[i]) <= 4:
result = result + word[i]
i = i+1
return(result)
the function ends with a single iteration due to "return" so you have to put it outside the loop
You need a variable to hold your results and the correct indentation:
def concat_short_words(s):
i = 0
word = s.split()
result = ""
while i < len(word):
if len(word[i]) <= 4:
result += word[i]
i = i+1
return(result)
concat_short_words('The temperature is 22.625 ˚C')
'Theis˚C'
Your function can be rewritten more succinctly using a for loop:
def concat_short_words(s):
result = ""
for word in s.split():
if len(word) <= 4:
result += word
return(result)
concat_short_words('The temperature is 22.625 ˚C')
'Theis˚C'

count the same character which comes in sequence

def count_squences(string):
i= 0
total = 0
total_char_list = []
while i < len(string):
print(string[i])
if string[i] == "x":
total += 1
if string[i] == "y":
total_char_list.append(total)
total = 0
i = i + 1
return total_char_list
print(count_squences("xxxxyyxyxx"))
I am trying to return the most used x characters in a file format. for example this functions should return [4, 1, 2].
For example if string is "xxxxxyxxyxxx' it should return [5, 2, 3]
My function does not return the correct list. Any helps would be really appreciated. Thanks
You are not resetting your counter when you encounter a y character, and you should only append to total_char_list if there was at least one x character counted by the time you find a y character (y characters could be duplicated too):
total = 0
while i < len(string):
if string[i] == "x":
total += 1
if string[i] == "y":
if total:
total_char_list.append(total)
total = 0
i = i + 1
Next, when the loop ends and total is not zero, you need to append that value too, or you won't be counting 'x' characters at the end of the sequence:
while ...:
# ...
if total:
# x characters at the end
total_char_list.append(total)
Next, you really want to use a for loop to loop over a sequence. You are given the individual characters that way:
total = 0
for char in string:
if char == 'x':
total += 1
if char == 'y':
if total:
total_charlist.append(total)
total = 0
if total:
# x characters at the end
total_char_list.append(total)
You can make this faster with itertools.groupby():
from itertools import groupby
def count_squences(string):
return [sum(1 for _ in group) for char, group in groupby(string) if char == 'x']
groupby() divides up an iterable input (such as a string) into separate iterators per group, where a group is defined as any consecutive value with the same key(value) result. The default key() function just returns the value, so groupby(string) gives you groups of consecutive characters that are the same. char is the repeated character, and sum(1 for _ in group) takes the length of an iterator.
You can then make it more generic, and count all groups:
def count_all_sequences(string):
counts = {}
for char, group in groupby(string):
counts.setdefault(char, []).append(sum(1 for _ in group))
return counts
The same can be done with a regular expression:
import re
def count_all_sequences(string):
counts = {}
# (.)(\1*) finds repeated characters; (.) matching one, \1 matching the same
# This gives us (first, rest) tuples, so len(rest) + 1 is the total length
for char, group in re.findall(r'(.)(\1*)', string):
counts.setdefault(char, []).append(len(group) + 1)
return counts
You don't initialize the value of total between the sequences so it keeps on counting.
def count_squences(string):
i= 0
total = 0
total_char_list = []
while i < len(string):
if string[i] == "x":
total += 1
if string[i] == "y":
if total != 0:
total_char_list.append(total)
total = 0
i = i + 1
if total != 0:
total_char_list.append(total)
return total_char_list
Update (17:00) - fixed the original procedure and I thought of a better solution -
my_str = "xxxxyyxyxx"
[len(z) for z in re.split("y+", my_str)]
Edited for function format:
def count_sequences(string):
return [len(x) for x in re.findall(r"x+", string)]
count_sequences("xxxxyyxyxx")
returns [4,1,2]

sequence containing at least three consecutive vowels

I'm trying to create a function to evaluate if contains at least three vowels consecutively.
I've tried so far:
( I don't know how to evaluate if they are consecutive)
any ideas?
def isConsecutive(word):
# initialize vowel count
vCounter = 0
for letter in word:
if letter == isVowel(word):
vCounter += 1
else:
vCounter = 0
if vCounter < 3:
return False
return True
Helper function
def isVowel(char):
return len(char) == 1 and char.lower() in 'aeiou'
The check, whether you have reached the third vovel in sequence, should be right after the vCounter += 1. If there are three vovels: return true.
Also, the isVowel check should be applied to the letter, not the whole word.
def isVowel(char):
return char.lower() in 'aeiou'
def isConsecutive(word):
# initialize vowel count
vCounter = 0
for letter in word:
if isVowel(letter): # <= check if the letter is a vowel
vCounter += 1
if vCounter >= 3: # <= do the check right here
return True
else:
vCounter = 0
return False # <= if we did not find three vovels in the loop, then there is none
print "hello: " + str(isConsecutive("hello"))
print "heeello: " + str(isConsecutive("heeello"))
print "hellooo: " + str(isConsecutive("hellooo"))
Give it a try online: DEMO
You can do this also with two list comprehensions:
a list of booleans, if the characters in a word are vowels
a list of booleans, if there are three consecutive True values in the first list
.
def three_consecutive_vowels(s):
is_vow = [c.lower() in 'aeiou' for c in s]
three_cons = [all(is_vow[i:i+2]) for i in range(len(is_vow) - 2)]
return any(three_cons)
Test:
words = ['hellO', 'heIah', 'aAarrgh']
for w in words:
print(three_consecutive_vowels(w))
False
True
True

Alternating letter in python

def myfunc(word):
result = ""
index = 0
for letter in word:
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
return result
index +=1
I am trying to return a matching string where every even letter is uppercase and every odd letter is lowercase. But the code doesn't show this exact result, any solution?
The problem is that you're only incrementing index after the loop, rather than each time through it. So, inside the loop, it's always 0. The smallest fix is:
def myfunc(word):
result = ""
index = 0
for letter in word:
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
index += 1
return result
But this kind of mistake is very easy to make (and sometimes not as easy as this to debug)—which is exactly why Python has nice tools like enumerate, that make it impossible to get wrong:
def myfunc(word):
result = ""
for index, letter in enumerate(word):
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
return result
People, including myself, have already pointed out your programming error. Here is an alternative one-liner solution to your problem using a generator expression and a ternary conditional operator:
def myfunc(word):
return "".join(w.upper() if i%2 else w.lower() for i,w in enumerate(word))
enumerate will return a tuple of the form (index, value) for each item in the iterable. In this case, the iterable is the string word.
At each step in the iteration, we check to see if the index i is odd.
i%2 will return 0 for even numbers and the if statement will evaluate to False.
Likewise, it will evaluate to True for odd numbers.
Respectively, we call lower() and upper() on the current character w.
Finally we use str.join to concatenate all the individual letters back together. Here we join the characters using an "" with is the empty string.
The problem was with how you were incrementing. You only set up your index to increment inside the "Else" block of your code. It was missing from the "If" block. As such as soon as you entered the "If" block you would be stuck there.
def myfunc(string):
result = ""
index = 0
for letter in string:
if index % 2 == 0:
result += letter.upper()
index += 1
else:
result += letter.lower()
index += 1
return result
def myfunc(word):
result = ""
for index, letter in enumerate(word):
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
return result
this worked for me.
Also it is much easier to understand the above block of code if you understand the enumerate function well
def myfunc(word):
index = 0
result = ''
for letter in word:
if index % 2 == 0:
result += letter.lower()
else:
result += letter.upper()
index += 1
print result
You weren't increment your index in the correct spot ;)
If you execute myfunc(word) it will print hElLo
def gonna(st) :
a = []
Index = 0
for index, c in enumerate(st) :
if index ℅ 2 == 0:
a.append(c.upper())
Index = Index + 1
else:
a.append(c.lower())
Index = Index + 1
return a
def myfunc(a):
result=""
for x in range(0,len(a)):
if x%2==0:
result=result+a[x].upper()
else:
result=result+a[x].lower()
return result
def myfunc(word):
z=list(word)
x=[]
y=[]
new_list=[]
str=""
for a in z:
x+=[a]
if len(x)==2:
y+=[x]
x=[]
for i in y:
odd=i[0].lower()
even=i[1].upper()
new_list.append(odd)
new_list.append(even)
for el in new_list:
str+=el
return str
def myfunc(str):
# Create an empty string to append the values to
result = ''
# Iterate through the loop using the enumerate function on the string so that you can use the index and the letter at the same time.
for index,letter in enumerate(str):
if index %2 == 0:
result += letter.lower()
else:
result += letter.upper()
# Return the string after all the letters have been appended to the string
return result
More Simpler , which is made using all the basic conecpts of Python
def myfunc(string):
new_string=""
for items in range(len(string)): # help us to to know about the index
if items % 2 == 0:
new_string = new_string + string[items].upper()
else:
new_string = new_string + string[items].lower()
return new_string
result=myfunc("Draco")
print(result)
def myfunc(word):
index=0
result = ''
for letter in word:
if index%2==0:
result=result+letter.upper()
else:
result=result+letter.lower()
index+=1
return result
**
Heading
**
def myfunc(word):
result = ""
for index, letter in enumerate(word):
if index % 2 == 0:
result += letter.upper()
else:
result += letter.lower()
return result

Looping and Counting w/find

So I am working diligently on some examples for my homework and came across yet another error.
The original:
word = 'banana'
count = 0
for letter in word:
if letter == 'a':
count = count + 1
print count
Ok. Looks simple.
I then used this code in a function name count and generalized it so that it accepts the string and the letter as argument.
def count1(str, letter):
count = 0
word = str
for specific_letter in word:
if specific_letter == letter:
count = count + 1
print count
This is where I'm still not sure what I'm doing wrong.
I have to rewrite this function so that instead of traversing the string, it uses the three-parameter version of find from the previous section. Which this is:
def find(word, letter, startat):
index = startat
while index <= len(word):
if word[index] == letter:
return index
index = index + 1
return -1
This is how far I got... but the program doesn't work the way I want it to.
def find(str, letter, startat):
index = startat
word = str
count = 0
while index <= len(word):
if word[index] == letter:
for specific_letter in word:
if specific_letter == letter:
count = count + 1
print count
index = index + 1
Can someone point me in the right direction. I want to understand what I'm doing instead of just given the answer. Thanks.
The point of the exercise is to use the previously defined function find as a building block to implement a new function count. So, where you're going wrong is by trying to redefine find, when you should be trying to change the implementation of count.
However, there is a wrinkle in that find as you have given has a slight error, you would need to change the <= to a < in order for it to work properly. With a <=, you could enter the body of the loop with index == len(word), which would cause IndexError: string index out of range.
So fix the find function first:
def find(word, letter, startat):
index = startat
while index < len(word):
if word[index] == letter:
return index
index = index + 1
return -1
And then re-implement count, this time using find in the body:
def count(word, letter):
result = 0
startat = 0
while startat < len(word):
next_letter_position = find(word, letter, startat)
if next_letter_position != -1:
result += 1
startat = next_letter_position + 1
else:
break
return result
if __name__ == '__main__':
print count('banana', 'a')
The idea is to use find to find you the next index of the given letter.
In your code you don't use the find function.
If you want to try something interesting and pythonic: Change the original find to yield index and remove the final return -1. Oh, and fix the <= bug:
def find(word, letter, startat):
index = startat
while index < len(word):
if word[index] == letter:
yield index
index = index + 1
print list(find('hello', 'l', 0))
Now find returns all of the results. You can use it like I did in the example or with a for position in find(...): You can also simply write count in terms of the length of the result.
(Sorry, no hints on the final function in your question because I can't tell what you're trying to do. Looks like maybe you left in too much of the original function and jumbled their purposes together?)
Here's what I came up with: This should work.
def find(word, letter, startat)
index = startat
count = 0
while index < len(word):
if word[index] == letter:
count = count + 1 ##This counts when letter matches the char in word
index = index + 1
print count
>>> find('banana', 'a', 0)
3
>>> find('banana', 'n', 0)
2
>>> find('mississippi', 's', 0)
4
>>>
Try using :
def find_count(srch_wrd, srch_char, startlookingat):
counter = 0
index = startlookingat
while index < len(srch_wrd):
if srch_wrd[index] == srch_char:
counter += 1
index += 1
return counter`
def count_letter2(f, l):
count = 0
t = 0
while t < len(f):
np = f.find(l, t)
if np != -1:
count += 1
t = np + 1
"I was wrong by doing t =t +1"
else:
break
return count
print(count_letter2("banana", "a"))
print(count_letter2("abbbb", "a"))

Categories

Resources