How to get rid of a repeating word in this function? - python

I don't know what kind of problem this is called and couldn't find something related to this on the site. I am trying to make a function that prints out the first letter of the word on the first line then the next two letters and so on. However, I am not sure on how to prevent repeating the complete word. For example in the word 'bar', it should go
b
ba
bar
ba
b
but my function repeats bar twice. Thanks!
a= []
def letters():
x = input("Enter a string")
count = 0
for c in x:
count +=1
y = 0
while y <= count:
z = (x[:y])
a.append(z)
y += 1
negWords = a[::-1]
for words in a:
print (words)
for words in negWords:
print (words)

You seem to be doing some unnecessary work for simply wanting to print something. You can make use of len to get the length of the word, without having to go through a loop to get the size.
Also, collecting the data in a list seems unnecessary.
To stick to the nature of your approach with the while loop, you can go through the entire length of the word and back again until "0". So, to me, I see that as twice the length of the word. With that in mind, that would be my control for the while loop. I would simply then check for when my incrementer reaches about the length of the word, and start going backwards from there:
w = "bar"
l = len(w)
i = 0
while i <= l*2:
if i > l:
print(w[:(l - i)])
else:
print(w[:i])
i += 1
Output:
b
ba
bar
ba
b

Try this:
negWords= a[:-1:-1]
This will not include the full word a second time
Also, your code could use a lot of cleanup. For example:
count = len(x)
Makes more sense than what you have

Related

Trying to solve a Python looping vowel question

I want to solve the below question:
Input_str - "I love Programming in Python"
Initialise 'n_cnt' as 0 and 'output' as 0
v='aeiouAEIOU'
FOR every w in input_str.split()
Initialise cnt to 0
FOR every c in w
check IF c is present in v
if true, increment 'cnt' by 1
end inner for loop
check IF 'cnt' is greater than or equal to 'n_cnt'
if true, assign 'cnt' to 'n_cnt' and assign 'w' to 'output'
end outer for loop
Print 'output'
Here's my code:
Input_str="I love Programming in Python"
n_cnt=0
output=0
v='aeiouAEIOU'
Split=Input_str.split()
for w in Split:
cnt=1
for c in w:
if c in v:
cnt=cnt+1
break
if cnt>=n_cnt:
cnt=n_cnt
output=w
print(output)
What am I doing wrong?
I am not quite sure what your motive is with this program but I assume you want to count the number of vowels in a particular string:
So, here is my implementation:
string = "I love Programming in Python"
vowel_cnt = 0
for i in string:
if i in "aeiouAEIOU":
vowel_cnt += 1
print("number of vowels = ", vowel_cnt)
First, you initialize a counter to 0, then you iterate through all the indices of the string one by one and check if the element at that index is in the String with all the vowels i.e "aeiouAEIOU", if yes, you increment the counter by 1.
First, use StackOverflow code editor to create python indentations, so the code can be easily read. Also, try to state your problem clearly, so when someone solves it, you can check that the result is what you want. The following code seems to be the correct version of your source code, it splits the sentence into words and selects the words that contain one character from v.
Input_str="I love Programming in zzzz Python"
n_cnt=0
output=0
v='aeiouAEIOU'
Split=Input_str.split()
print(Split)
for w in Split:
cnt=1
for c in w:
if c in v:
cnt=cnt+1
break
if cnt >= n_cnt:
n_cnt=cnt
output=w
print(output)
also you said in your question that cnt should be assigned to n_cnt but in your codes you did it incorrectly. The above source code will skip zzzz and print the other words in each line.

Intro to Python - Lists questions

we've started doing Lists in our class and I'm a bit confused thus coming here since previous questions/answers have helped me in the past.
The first question was to sum up all negative numbers in a list, I think I got it right but just want to double check.
import random
def sumNegative(lst):
sum = 0
for e in lst:
if e < 0:
sum = sum + e
return sum
lst = []
for i in range(100):
lst.append(random.randrange(-1000, 1000))
print(sumNegative(lst))
For the 2nd question, I'm a bit stuck on how to write it. The question was:
Count how many words occur in a list up to and including the first occurrence of the word “sap”. I'm assuming it's a random list but wasn't given much info so just going off that.
I know the ending would be similar but no idea how the initial part would be since it's string opposed to numbers.
I wrote a code for a in-class problem which was to count how many odd numbers are on a list(It was random list here, so assuming it's random for that question as well) and got:
import random
def countOdd(lst):
odd = 0
for e in lst:
if e % 2 = 0:
odd = odd + 1
return odd
lst = []
for i in range(100):
lst.append(random.randint(0, 1000))
print(countOdd(lst))
How exactly would I change this to fit the criteria for the 2nd question? I'm just confused on that part. Thanks.
The code to sum -ve numbers looks fine! I might suggest testing it on a list that you can manually check, such as:
print(sumNegative([1, -1, -2]))
The same logic would apply to your random list.
A note about your countOdd function, it appears that you are missing an = (== checks for equality, = is for assignment) and the code seems to count even numbers, not odd. The code should be:
def countOdd(lst):
odd = 0
for e in lst:
if e%2 == 1: # Odd%2 == 1
odd = odd + 1
return odd
As for your second question, you can use a very similar function:
def countWordsBeforeSap(inputList):
numWords = 0
for word in inputList:
if word.lower() != "sap":
numWords = numWords + 1
else:
return numWords
inputList = ["trees", "produce", "sap"]
print(countWordsBeforeSap(inputList))
To explain the above, the countWordsBeforeSap function:
Starts iterating through the words.
If the word is anything other than "sap" it increments the counter and continues
If the word IS "sap" then it returns early from the function
The function could be more general by passing in the word that you wanted to check for:
def countWordsBefore(inputList, wordToCheckFor):
numWords = 0
for word in inputList:
if word.lower() != wordToCheckFor:
numWords = numWords + 1
else:
return numWords
inputList = ["trees", "produce", "sap"]
print(countWordsBeforeSap(inputList, "sap"))
If the words that you are checking come from a single string then you would initially need to split the string into individual words like so:
inputString = "Trees produce sap"
inputList = inputString.split(" ")
Which splits the initial string into words that are separated by spaces.
Hope this helps!
Tom
def count_words(lst, end="sap"):
"""Note that I added an extra input parameter.
This input parameter has a default value of "sap" which is the actual question.
However you can change this input parameter to any other word if you want to by
just doing "count_words(lst, "another_word".
"""
words = []
# First we need to loop through each item in the list.
for item in lst:
# We append the item to our "words" list first thing in this loop,
# as this will make sure we will count up to and INCLUDING.
words.append(item)
# Now check if we have reached the 'end' word.
if item == end:
# Break out of the loop prematurely, as we have reached the end.
break
# Our 'words' list now has all the words up to and including the 'end' variable.
# 'len' will return how many items there are in the list.
return len(words)
lst = ["something", "another", "woo", "sap", "this_wont_be_counted"]
print(count_words(lst))
Hope this helps you understand lists better!
You can make effective use of list/generator comprehensions. Below are fast and memory efficient.
1. Sum of negatives:
print(sum( i<0 for i in lst))
2. Count of words before sap: Like you sample list, it assumes no numbers are there in list.
print(lst.index('sap'))
If it's a random list. Filter strings. Find Index for sap
l = ['a','b',1,2,'sap',3,'d']
l = filter(lambda x: type(x)==str, l)
print(l.index('sap'))
3. Count of odd numbers:
print(sum(i%2 != 0 for i in lst))

How to compare words in two lists according to same order in python?(I have def a function)

Recently, I def a function which can compare two words in each wordlist. However, I also found some problems here.
def printcorrectletters():
x=0
for letters in correctanswer:
for letters2 in userinput:
if letters == letters2:
x = x+1
break
return x
In this function, if the correctanswer='HUNTING', and I input 'GHUNTIN', it will show 6 letters are correct. However, I want it compare words' letters 1 by 1. So, it should march 0. For example, 'H' will match first letter of userinput.. and so on.
I also think another function which can solve it by using 'zip'. However, our TA ask me to finish it without things like 'zip'.
If the strings are different lengths, you want to compare each letter of the shorter string:
shortest_length = min(len(correctanswer), len(userinput))
min just gives you the minimum of two or more values. You could code it yourself as:
def min(a, b):
return a if a < b else b
You can index a character in a string, using [index]:
>>> 'Guanfong'[3]
n
So you can loop over all the letter indices:
correct = 0
for index in range(shortest_length):
if correctanswer[index] == userinput[index]:
correct += 1
If you did use zip and sum:
correct = sum(1 for (correct_char, user_char) in zip(correctanswer, userinput)
if correct_char == user_char)
Python provides great facilities for simplifying ideas and for communicating with the computer and programmers (including yourself, tomorrow).
Without zip you can use enumerate() to loop over elements of correctanswer , and get index and element at the same time. Example -
def printcorrectletters():
x=0
for i, letter in enumerate(correctanswer):
if i < len(userinput) and letter == userinput[i]:
x = x+1
return x
Or if even enumerate() is not allowed, simply use range() loop till len(correctanswer) and get elements from each index.

Finding common letters between 2 strings in Python

For a homework assignment, I have to take 2 user inputted strings, and figure out how many letters are common (in the same position of both strings), as well as find common letters.. For example for the two strings 'cat' and 'rat', there are 2 common letter positions (which are positions 2 and 3 in this case), and the common letters are also 2 because 'a' is found one and 't' is found once too..
So I made a program and it worked fine, but then my teacher updated the homework with more examples, specifically examples with repetitive letters, and my program isn't working for that.. For example, with strings 'ahahaha' and 'huhu' - there are 0 common letters in same positions, but there's 3 common letters between them (because 'h' in string 2 appears in string 1, three times..)
My whole issue is that I can't figure out how to count if "h" appears multiple times in the first string, as well as I don't know how to NOT check the SECOND 'h' in huhu because it should only count unique letters, so the overall common letter count should be 2..
This is my current code:
S1 = input("Enter a string: ")
S2 = input("Enter a string: ")
i = 0
big_string = 0
short_string = 0
same_letter = 0
common_letters = 0
if len(S1) > len(S2):
big_string = len(S1)
short_string = len(S2)
elif len(S1) < len(S2):
big_string = len(S2)
short_string = len(S1)
elif len(S1) == len(S2):
big_string = short_string = len(S1)
while i < short_string:
if (S1[i] == S2[i]) and (S1[i] in S2):
same_letter += 1
common_letters += 1
elif (S1[i] == S2[i]):
same_letter += 1
elif (S1[i] in S2):
common_letters += 1
i += 1
print("Number of positions with the same letter: ", same_letter)
print("Number of letters from S1 that are also in S2: ", common_letters)
So this code worked for strings without common letters, but when I try to use it with "ahahaha" and "huhu" I get 0 common positions (which makes sense) and 2 common letters (when it should be 3).. I figured it might work if I tried to add the following:
while x < short_string:
if S1[i] in S2[x]:
common_letters += 1
else:
pass
x += 1
However this doesn't work either...
I am not asking for a direct answer or piece of code to do this, because I want to do it on my own, but I just need a couple of hints or ideas how to do this..
Note: I can't use any functions we haven't taken in class, and in class we've only done basic loops and strings..
You need a data structure like multidict. To my knowledge, the most similar data structure in standard library is Counter from collections.
For simple frequency counting:
>>> from collections import Counter
>>> strings = ['cat', 'rat']
>>> counters = [Counter(s) for s in strings]
>>> sum((counters[0] & counters[1]).values())
2
With index counting:
>>> counters = [Counter(zip(s, range(len(s)))) for s in strings]
>>> sum(counters[0] & counters[1].values())
2
For your examples ahahaha and huhu, you should get 2 and 0, respectively since we get two h but in wrong positions.
Since you can't use advanced constructs, you just need to simulate counter with arrays.
Create 26 elements arrays
Loop over strings and update relevant index for each letter
Loop again over arrays simultaneously and sum the minimums of respective indexes.
A shorter version is this:
def gen1(listItem):
returnValue = []
for character in listItem:
if character not in returnValue and character != " ":
returnValue.append(character)
return returnValue
st = "first string"
r1 = gen1(st)
st2 = "second string"
r2 = gen1(st2)
if len(st)> len(st2):
print list(set(r1).intersection(r2))
else:
print list(set(r2).intersection(r1))
Note:
This is a pretty old post but since its got new activity,I posted my version.
Since you can't use arrays or lists,
Maybe try to add every common character to a var_string then test
if c not in var_string:
before incrementing your common counter so you are not counting the same character multiple times.
You are only getting '2' because you're only going to look at 4 total characters out of ahahaha (because huhu, the shortest string, is only 4 characters long). Change your while loop to go over big_string instead, and then add (len(S2) > i) and to your two conditional tests; the last test performs an in, so it won't cause a problem with index length.
NB: All of the above implicitly assumes that len(S1) >= len(S2); that should be easy enough to ensure, using a conditional and an assignment, and it would simplify other parts of your code to do so. You can replace the first block entirely with something like:
if (len(S2) > len(S1)): (S2, S1) = (S1, S2)
big_string = len(S1)
short_string = len(S2)
We can solve this by using one for loop inside of another as follows
int y=0;
for(i=0;i<big_string ;i++)
{
for(j=0;j<d;j++)
{
if(s1[i]==s2[j])
{y++;}
}
If you enter 'ahahaha' and 'huhu' this code take first character of big
string 'a' when it goes into first foor loop. when it enters into second for loop
it takes first letter of small string 'h' and compares them as they are not
equal y is not incremented. In next step it comes out of second for loop but
stays in first for loop so it consider first character of big string 'a' and
compares it against second letter of small string 'u' as 'j' is incremented even
in this case both of them are not equal and y remains zero. Y is incremented in
the following cases:-
when it compares second letter of big string 'h' and small letter of first string y is incremented for once i,e y=1;
when it compares fourth letter of big string 'h' and small letter of first string y is incremented again i,e y=2;
when it compares sixth letter of big string 'h' and small letter of first string y is incremented again i,e y=3;
Final output is 3. I think that is what we want.

HOW TO "Arbitrary" format items in list/dict/etc. EX: change 4th character in every string in list

first of all i want to mention that there might not be any real life applications for this simple script i created, but i did it because I'm learning and I couldn't find anything similar here in SO. I wanted to know what could be done to "arbitrarily" change characters in an iterable like a list.
Sure tile() is a handy tool I learned relatively quick, but then I got to think what if, just for kicks, i wanted to format (upper case) the last character instead? or the third, the middle one,etc. What about lower case? Replacing specific characters with others?
Like I said this is surely not perfect but could give away some food for thought to other noobs like myself. Plus I think this can be modified in hundreds of ways to achieve all kinds of different formatting.
How about helping me improve what I just did? how about making it more lean and mean? checking for style, methods, efficiency, etc...
Here it goes:
words = ['house', 'flower', 'tree'] #string list
counter = 0 #counter to iterate over the items in list
chars = 4 #character position in string (0,1,2...)
for counter in range (0,len(words)):
while counter < len(words):
z = list(words[counter]) # z is a temp list created to slice words
if len(z) > chars: # to compare char position and z length
upper = [k.upper() for k in z[chars]] # string formatting EX: uppercase
z[chars] = upper [0] # replace formatted character with original
words[counter] = ("".join(z)) # convert and replace temp list back into original word str list
counter +=1
else:
break
print (words)
['housE', 'flowEr', 'tree']
This is somewhat of a combination of both (so +1 to both of them :) ). The main function accepts a list, an arbitrary function and the character to act on:
In [47]: def RandomAlter(l, func, char):
return [''.join([func(w[x]) if x == char else w[x] for x in xrange(len(w))]) for w in l]
....:
In [48]: RandomAlter(words, str.upper, 4)
Out[48]: ['housE', 'flowEr', 'tree']
In [49]: RandomAlter([str.upper(w) for w in words], str.lower, 2)
Out[49]: ['HOuSE', 'FLoWER', 'TReE']
In [50]: RandomAlter(words, lambda x: '_', 4)
Out[50]: ['hous_', 'flow_r', 'tree']
The function RandomAlter can be rewritten as this, which may make it a bit more clear (it takes advantage of a feature called list comprehensions to reduce the lines of code needed).
def RandomAlter(l, func, char):
# For each word in our list
main_list = []
for w in l:
# Create a container that is going to hold our new 'word'
new_word = []
# Iterate over a range that is equal to the number of chars in the word
# xrange is a more memory efficient 'range' - same behavior
for x in xrange(len(w)):
# If the current position is the character we want to modify
if x == char:
# Apply the function to the character and append to our 'word'
# This is a cool Python feature - you can pass around functions
# just like any other variable
new_word.append(func(w[x]))
else:
# Just append the normal letter
new_word.append(w[x])
# Now we append the 'word' to our main_list. However since the 'word' is
# a list of letters, we need to 'join' them together to form a string
main_list.append(''.join(new_word))
# Now just return the main_list, which will be a list of altered words
return main_list
There's much better Pythonistas than me, but here's one attempt:
[''.join(
[a[x].upper() if x == chars else a[x]
for x in xrange(0,len(a))]
)
for a in words]
Also, we're talking about the programmer's 4th, right? What everyone else calls 5th, yes?
Some comments on your code:
for counter in range (0,len(words)):
while counter < len(words):
This won't compile unless you indent the while loop under the for loop. And, if you do that, the inner loop will completely screw up the loop counter for the outer loop. And finally, you almost never want to maintain an explicit loop counter in Python. You probably want this:
for counter, word in enumerate(words):
Next:
z = list(words[counter]) # z is a temp list created to slice words
You can already slice strings, in exactly the same way you slice lists, so this is unnecessary.
Next:
upper = [k.upper() for k in z[chars]] # string formatting EX: uppercase
This is a bad name for the variable, since there's a function with the exact same name—which you're calling on the same line.
Meanwhile, the way you defined things, z[chars] is a character, a copy of words[4]. You can iterate over a single character in Python, because each character is itself a string. but it's generally pointless—[k.upper() for k in z[chars]] is the same thing as [z[chars].upper()].
z[chars] = upper [0] # replace formatted character with original
So you only wanted the list of 1 character to get the first character out of it… why make it a list in the first place? Just replace the last two lines with z[chars] = z[chars].upper().
else:
break
This is going to stop on the first string shorter than length 4, rather than just skip strings shorter than length 4, which is what it seems like you want. The way to say that is continue, not break. Or, better, just fall off the end of the list. In some cases, it's hard to write things without a continue, but in this case, it's easy—it's already at the end of the loop, and in fact it's inside an else: that has nothing else in it, so just remove both lines.
It's hard to tell with upper that your loops are wrong, because if you accidentally call upper twice, it looks the same as if you called it once. Change the upper to chr(ord(k)+1), which replaces any letter with the next letter. Then try it with:
words = ['house', 'flower', 'tree', 'a', 'abcdefgh']
You'll notice that, e.g., you get 'flowgr' instead of 'flowfr'.
You may also want to add a variable that counts up the number of times you run through the inner loop. It should only be len(words) times, but it's actually len(words) * len(words) if you have no short words, or len(words) * len(<up to the first short word>) if you have any. You're making the computer do a whole lot of extra work—if you have 1000 words, it has to do 1000000 loops instead of 1000. In technical terms, your algorithm is O(N^2), even though it only needs to be O(N).
Putting it all together:
words = ['house', 'flower', 'tree', 'a', 'abcdefgh'] #string list
chars = 4 #character position in string (0,1,2...)
for counter, word in enumerate(words):
if len(word) > chars: # to compare char position and z length
z = list(word)
z[chars] = chr(ord(z[chars]+1) # replace character with next character
words[counter] = "".join(z) # convert and replace temp list back into original word str list
print (words)
That does the same thing as your original code (except using "next character" instead of "uppercase character"), without the bugs, with much less work for the computer, and much easier to read.
I think the general case of what you're talking about is a method that, given a string and an index, returns that string, with the indexed character transformed according to some rule.
def transform_string(strng, index, transform):
lst = list(strng)
if index < len(lst):
lst[index] = transform(lst[index])
return ''.join(lst)
words = ['house', 'flower', 'tree']
output = [transform_string(word, 4, str.upper) for word in words]
To make it even more abstract, you could have a factory that returns a method, like so:
def transformation_factory(index, transform):
def inner(word):
lst = list(word)
if index < len(lst):
lst[index] = transform(lst[index])
return inner
transform = transformation_factory(4, lambda x: x.upper())
output = map(transform, words)

Categories