Join two for loops, separated by a print statement into one - python

In the following code, everything is working as expected.
It gets a 4 character long user input that ends with 0.
And simply adds stores in a dictonary the occurances of vowels and consonants.
input ="" #get input from user
while 4 < len(input) or 4 > len(input) or input[-1] != "0": #string has to be 4 char long and end in 0
input = raw_input("insert code:")
occurrences = {"a":0,"e":0,"i":0,"o":0,"u":0,"consonants":0} #store the vouel count
for x in input:
if x in occurrences.keys():
occurrences[x] += 1 #count cowels
elif x != "0":
occurrences["consonants"] += 1 #count consonants
for x in occurrences:
if occurrences[x] > 0 and x != "consonants":
print x + ",",
print "were inserted",
for x in occurrences:
if occurrences[x] > 0 and x != "consonants":
print str(occurrences[x]) + ",",
print "times respectively"
if occurrences["consonants"] == 1:
print "there was %d consonant"%occurrences["consonants"]
else:
print "there was %d consonants"%occurrences["consonants"]
For the input "aef0" the program will print:
e, a, were inserted 1, 1, times
respectively there was 1 consonant
My questions is about this particular lines.
I know there must be a better way to do:
for x in ocurrances:
if ocurrances[x] > 0 and x != "consonants":
print x + ",",
print "were inserted",
for x in ocurrances:
if ocurrances[x] > 0 and x != "consonants":
print str(ocurrances[x]) + ",",
print "times respectively"
It just feels sloppy.
What I don't like about it is that I'm calling twice the same for loop and I feel this could be only one move in a much more elegant way, but I'm not finding the way to do so.
A pseudo code (or whatever) of what I'm trying to achieve would be the following.
loop the dictionary
print all key with values >= 1
print "were inserted" only once
print all the respective vales.
print "times respectively"
As I said I want the same output, but expressed in a more elegant way, I'm assuming the elegant would imply only one for loop but any other (more elegant) options are welcome!
I thought about doing something like this, but it's obviously not working. (Don't worry about it, it's just plain wrong, but the approach shows what I was aiming for)
Thanks in advance!

Another way to write your code might be something like this:
print ", ".join(k for k, v in occurrences.items() if k != "consonants" and v > 0),
print "were inserted"
print ", ".join(str(v) for k, v in occurrences.items() if k != "consonants" and v > 0),
print "times respectively"
You can shorten this a bit more by factoring out the search:
a = [(k, str(v)) for k, v in occurrences.items() if k != "consonants" and v > 0]
print ", ".join(x[0] for x in a), "were inserted",
print ", ".join(x[1] for x in a), "times respectively"

You have a few more problems with elegance and other things that matter more. For a start your users would revolt against having to type a 0 that you don't do anything meaningful with. In fact you need to dedicate code to ignoring it! Keeping the count of consonants in the dict is rather inelegant. You don't check whether the user typed all letters. You don't handle uppercase.
Here's some code that addresses those issues plus a few verbosities:
input = "" # get input from user
while len(input) != 3 or not input.isalpha():
input = raw_input("insert code:").lower()
ocurrances = {"a":0, "e":0, "i":0, "o":0, "u":0}
nconsonants = 0
for x in input:
if x in ocurrances:
ocurrances[x] += 1 #count vowels
else:
nconsonants += 1 #count consonants
for x in ocurrances:
if ocurrances[x]:
print x + ",",
print "were inserted",
for x in ocurrances:
if ocurrances[x]:
print str(ocurrances[x]) + ",",
print "times respectively"
if nconsonants == 1:
print "there was 1 consonant"
else:
print "there were %d consonants" % nconsonants
and you might like to change "ocurrances" to "occurrences". By the way, if the number of vowels is less than 2, the output is not very pretty.

Related

How to make function loop on its own separate line?

I have written for a coding problem assigned to me essentially there is a scratch and win ticket and I have to figure out what prizes I could win. I will be given 10 inputs and each output after running through should be on its own line. However Every time I run the code with 10 inputs all of the inputs just appear on one line.
How do I make sure that each output appears on its own line?
Although to be noted my code does output the correct answer its just the formatting that is troubling I want each answer to be on its own line instead of just being on one line.
from collections import Counter
def Winner(L):
zz = Counter(L)
if zz["63"] == 9:
print("No Prizes Possible")
elif zz["63"] == 0:
for T in zz:
if zz[T] >= 3:
print("$" + T, end=" ")
else:
for V in zz:
KK = zz[V] + zz["63"]
if KK >= 3:
if V != "63":
print("$" + V, end=" ")
for d in range(10):
z = [input() for i in range(9)]
yy = []
for g in z:
if g == "?":
yy.append(ord(g))
else:
yy.append(g.replace("$", ""))
yy = [int(i) for i in yy]
yy.sort()
yy = [str(i) for i in yy]
Winner(yy)
Here is a sample input of what I mean:
$10
$100
?
$10
$1
$50
$50
$1000
$1
essentially having 10 inputs like these.
If you add \n (the newline character) at the end of your string, you will add a newline after each time your program prints. For example, you could have this loop which would print "hello world" 10 times, each on its own separate line.
for i in range (10):
print('hello world', '\n')
Or more conveniently, you can get rid of the end = " ", and Python will automatically add a new line.
You are using end=" " in your print function.
Just leave it as print("$" + T) and print("$" + V) so it appends newline by default.

Last character of string not being picked up

Trying to solve the problem where I can reverse each word in a string , Since there is no "\0" in python unlike C, My logic is failing to pick up the last character of the string.
Any idea how can this be fixed with not too many changes to the code
Input = This is an example
Output = sihT si na elpmaxe
import os
import string
a = "This is an example"
temp=[]
store=[]
print(a)
x=0
while (x <= len(a)-1):
if ((a[x] != " ") and (x != len(a)-1)):
temp.append(a[x])
x += 1
else:
temp.reverse()
store.extend(temp)
store.append(' ')
del temp[:]
x += 1
str1 = ''.join(store)
print (str1)
My output is truncating the last character
sihT si na lpmaxe
As pvg suggested, you are excluding the last character yourself. You don't need to check for x != len(a)-1, so that you can add the last character in the temp string. The last word than can be added once you exit the loop, it will be contained in the temp variable. This hint is just to get your code working, otherwise you could do it in a much shorter way in python as suggested by people.
You have remove -1 in both len(a)-1 and change order in and (so when x == len(a) it will no try to get a[x] which could give "index out of range")
while (x <= len(a)):
if (x != len(a)) and (a[x] != " "):
Full version which works for me
import os
import string
a = "This is an example"
temp = []
store = []
print(a)
x = 0
while (x <= len(a)):
if (x != len(a)) and (a[x] != " "):
temp.append(a[x])
x += 1
else:
temp.reverse()
store.extend(temp)
store.append(' ')
del temp[:]
x += 1
str1 = ''.join(store)
print(str1)
It's pretty simple and no need a extra loop:
a = "This is an example"
print(a)
str1 = " ".join([word[::-1] for word in a.split(" ")])
print(str1)
input and output:
This is an example
sihT si na elpmaxe

Counting how many words are over a certain limit in a string Python

Thank you all for help on previous part. I have now finished that.
However changing title slightly and rewording question I now say that this is my code.
s = raw_input("Enter your text: ")
longestWord = max(s.split(), key=len)
k = list(s)
count = len(k)
wordsOver = []
over = count - 140
def numLen(s, n):
return sum(1 for x in s.split() if len(x) >= n)
for x in s.split():
if len(x) >= n:
wordsOver.insert(0, x)
val = numLen(s, 7)
if count > 140:
print ("Sorry, that is more than 140 characters.")
print ("You had a total of " + str(count) + " characters.")
print ("That's " + str(over) + " over the max allowed.")
print ("You're longest word was, " + longestWord)
print ("There are " + str(val) + " words over 7 characters.")
print ("They were:")
print (wordsOver)
print ("You may want to consider changing them for shorter words.")
else:
print ("That's short enough!")
So now what I'm looking for is why the displaying of the words that are over isn't working, why and how to fix it. BTW for a little help it's the wordsOver bit that's broken
Welcome to SO!
I think this is what you want to do. In your numLen function you need to use append() rather than insert() when adding to your list. This is because when using insert you're not incrementing the index so each time you insert at index 0 you overwrite any value that's already there. Append does the legwork of finding out where the end of your list is and puts what you pass to it onto the end.
s = raw_input("Enter your text: ")
longestWord = max(s.split(), key=len)
k = list(s)
count = len(k)
wordsOver = []
over = count - 140
def numLen(s, n):
for x in s.split():
if len(x) >= 7:
wordsOver.append(x)
return len(wordsOver)
val = numLen(s, 7)
if count > 140:
print ("Sorry, that is more than 140 characters.")
print ("You had a total of " + str(count) + " characters.")
print ("That's " + str(over) + " over the max allowed.")
print ("You're longest word was, \"" + longestWord + "\"")
print ("There are " + str(val) + " words over 7 characters.")
print ("They were:")
print (wordsOver)
print ("You may want to consider changing them for shorter words.")
else:
print ("That's short enough!")
in the for loop you're looking at each character and checking if that character i is a character that is in an alphabet using .isalpha() which will return false when it encounters a space since it is not alphabetic.
See: https://docs.python.org/2/library/stdtypes.html#str.isalpha
isalpha() doesn't return true for whitespace.
Additionally, there are a whole slew of better ways to do this. You should look at the Counter class in collections. It's a dictionary that will provide you with what you need.

Counting consecutive repeats in a string and returning a value in python

Asked my friend to give me an assignment for me to practice. It is:
If a user enters a string "AAABNNNNNNDJSSSJENDDKEW" the program will return
"3AB6NDJ2SJEN2DKEW" and vice versa.
This what I tried so far:
from collections import Counter
list_user_input =[]
list_converted_output=[]
current_char = 0 #specifies the char it is reading
next_char = 1
cycle = 0 # counts number of loops
char_repeat = 1
prev_char=""
count = 1
user_input = input("Enter your string: ")
user_input_strip = user_input.strip()
user_input_striped_replace = user_input_strip.replace(" ", "").lower()
list_user_input.append(user_input_striped_replace[0:len(user_input_striped_replace)])
print(list_user_input)
print(user_input_striped_replace)
I have "cleaned" the code so it removes white spaces and keeps it in low cap
Here is where I am stuck - the logics. I was thinking to go the through the string one index at a time and compare the next on to the other. Is this the wright way to go about it? And I'm not even sure about the loop construction.
#counter = Counter(list_user_input)
#print(counter)
#while cycle <= len(user_input_striped_replace):
for letter in user_input_striped_replace:
cycle+=1
print("index nr {}, letter: ".format(current_char)+letter +" and cycle : " + str(cycle))
current_char+=1
if letter[0:1] == letter[1:2]:
print("match")
print("index nr {}, letter: ".format(current_char)+letter +" and cycle : " + str(cycle))
current_char+=1
Counter is a good choice for such task but about the rest you can use sorted to sort the items of Counter then use a list comprehension to create the desire list then concatenate with join :
>>> from collections import Counter
>>> c=Counter(s)
>>> sor=sorted(c.items(),key=lambda x:s.index(x[0]))
>>> ''.join([i if j==1 else '{}{}'.format(j,i) for i,j in sor])
'3AB7N3D2J3S2EKW'
I'd do it with regular expressions. Have a look at those.
Spoiler:
import re
def encode(s):
return re.sub(r'(.)\1+', lambda m: str(len(m.group(0)))+m.group(1), s)
def decode(e):
return re.sub('(\d+)(.)', lambda m: int(m.group(1))*m.group(2), e)
s = "AAABNNNNNNDJSSSJENDDKEW"
e = encode(s)
print(e, decode(e) == s)
Prints:
3AB6NDJ3SJEN2DKEW True
Your "and vice versa" sentence sounds like the program needs to detect itself whether to encode or to decode, so here's that (proof of correctness left as an exercise :-)
def switch(s):
e = re.sub(r'(\D)\1+', lambda m: str(len(m.group(0)))+m.group(1), s)
d = re.sub('(\d+)(.)', lambda m: int(m.group(1))*m.group(2), s)
return e if e != s else d

Make program continue action till line has been created

Currently my program takes line1 such as "taaaaaaaaaaNataggggggggggNccc" and will cut 1 character of the end untill it matches line2 such as "taaaaaaaaaaNcccggggggggggNccc" and once they match it concatenates them together to form line3, however if they dont match it should cut another character off. How can I make it repeat the cutting action until they match and line3 has been made? I have thought about for and while loops but am unsure how to state this issue. Everything else about this program works as it should but when it tries matching them if it fails it just stops and wont go back to try trimming again.
I have tried the below code where magic(matching) is essentially the counting code used to idnetfy how much the 2 lines match and if below 8 it should repeat the cutting. However when used it asks for matching and magic to be stated before the while loop which is right at the start and this messes up the rest of the code.
while magic(matching) >=8:
line3=line1+line2
print ("Matching and merging has occured as shown below")
print (line3)
The code of interest is below:
n = 0
consec_matches = []
chars = defaultdict(int)
for k, group in groupby(zip(line1_u_i, line2_u_rev_comp_join_i), class_chars):
elems = len(list(group))
chars[k] += elems
if k == 'match':
consec_matches.append((n, n+elems-1))
n += elems
print ("Print chars below")
print (chars)
print ("Print consec_matches below")
print (consec_matches)
print ([x for x in consec_matches if x[1]-x[0] >= 9])
print (" Matches longer than 10 below")
list = [x for x in consec_matches if x[1]-x[0] >= 9]
flatten_list= [x for y in list for x in y]
print (flatten_list)
print ("Flatterend list")
matching=[y[1] for y in list for x in y if x ==0 ]
print ("Matching list below")
print (matching)
magic = lambda matching: int(''.join(str(i) for i in matching) or 0)
print (" Print magic matching below")
print (magic(matching))
line2_u_rev_comp_join_i_l = line2_u_rev_comp_join_i[magic(matching):]
print ("Print line2_u_rev_comp_join_i_l type below")
print (type(line2_u_rev_comp_join_i_l))
print ("Print line2_u_rev_comp_join_i_l sequence below")
print (line2_u_rev_comp_join_i_l)
line2_u_rev_comp_join_i_l_str = ''.join(line2_u_rev_comp_join_i_l)
print ('List of line2 converted to string')
print ("List2 before as list below")
print (line2_u_rev_comp_join_i_l)
print ("Line 2 reprinted when string as below")
print (line2_u_rev_comp_join_i_l_str)
print (line1_u_i)
print ("Magic below")
print (magic)
if magic(matching) >=8:
line3=line1_u_i+line2_u_rev_comp_join_i_l_str
print ("Matching and merging has occured as shown below")
print (line3)
else:
continue
The cutting code is:
line2_u_rev_comp_join_i = line2_u_rev_comp_join[1:]
line1_u_i = line1_u[:-1]
l1 = "taaaaaaaaaaNataggggggggggNccc"
l2 = "taaaaaaaaaaNcccggggggggggNccc"
l1_ten=l1[0:10] # first ten chars
l2_ten=l2[0:10]
if l1_ten==l2_ten:
print l1_ten+l2_ten
taaaaaaaaataaaaaaaaa
If you want the chars that are equal at the same index in each string.
l1 = "taaaaaaaaaaNataggggggggggNccc"
l2 = "taaaaaaaaaaNcccggggggggggNccc"
count = 0
slice = 0
new_s=''
while count < len(l1):
if l1[slice]==l2[slice]:
new_s+= l1[slice]
count += 1
slice += 1
new_s
In [13]: new_s
Out[13]: 'taaaaaaaaaaNggggggggggNccc'
You can just use a for loop to achieve the same:
new_s1=""
for i in range(len(l1)):
if l1[i] ==l2[i]:
new_s+=l1[i]
I have assumed you are using strings of equal lengths

Categories