So I have 2 functions - displayHand(hand) and calculateHandlen(hand)
def displayHand(hand):
"""
Displays the letters currently in the hand.
For example:
>>> displayHand({'a':1, 'x':2, 'l':3, 'e':1})
Should print out something like:
a x x l l l e
The order of the letters is unimportant.
hand: dictionary (string -> int)
"""
for letter in hand.keys():
for j in range(hand[letter]):
print(letter,end=" ")
print()
def calculateHandlen(hand):
"""
Returns the length (number of letters) in the current hand.
hand: dictionary (string-> int)
returns: integer
"""
handLen = 0
for i in hand:
handLen = handLen + hand.get(i,0)
return handLen
There's a loop in another function that is dependent on the above functions -
def playHand(hand, wordList, n):
"""
hand = dictionary
wordList = list of valid words
n = an integer passed while function call
"""
totalscore = 0
while(calculateHandlen(hand)>0):
print("Current Hand: " +str(displayHand(hand)))
newWord = input('Enter word, or a "." to indicate that you are finished: ')
Function call for playHand() is as follows:
wordList = loadWords() #loadWords could be a list of words
playHand({'n':1, 'e':1, 't':1, 'a':1, 'r':1, 'i':2}, wordList, 7)
I'm expecting the output to be:
Current Hand: n e t a r i i
Enter word, or a "." to indicate that you are finished:
However, it displays the following:
n e t a r i i
Current Hand: None
Enter word, or a "." to indicate that you are finished:
Don't know where I'm going wrong.
Note: I'm not allowed to make any changes to the first 2 functions.
displayHand() doesn't return anything, so the default None is returned. When you call it, it prints the output directly.
If you are not allowed to alter displayHand(), you need to print your label first, then call the function:
print("Current Hand: ", end='')
displayHand(hand)
The end='' removes the newline print() would normally write.
Related
I want to take input of how many inputs the user is going to give next and collect those inputs in a single line. For eg. if user enters '3' next he has to give 3 inputs like '4' '5' '6' on the same line.
N = int(input())
result = 0
randomlist = []
for number in range(N):
K = int(input())
for number2 in range(K):
a = int(input())
if number2 != K - 1:#Ignore these on below
result += a - 1
else:
result += a
randomlist.append(result)
result = 0
break
for num in range(N):
b = randomlist[num]
print(b)
Now I want the input for K and a (also looped inputs of a) to be on the same line. I have enclosed the whole code for the program here. Please give me a solution on how to get input in the same line with a space in between instead of hitting enter and giving inputs
Based on what I read from your question, you are trying to request input from the user and the desired format of the input is a series of numbers (both integers and floats) separated by spaces.
I see a couple of ways to accomplish this:
Use a single input statement to request the series of numbers including the count,
Just ask the user for a list of numbers separated by spaces and infer the count.
To perform these operations you can do one of the following:
#Request User to provide a count followed by the numbers
def getInputwithCount():
# Return a list Numbers entered by User
while True:
resp = input("Enter a count followed by a series of numbers: ").split(' ')
if len(resp) != int(resp[0]) + 1:
print("Your Input is incorrect, try again")
else:
break
rslt = []
for v in resp[1:]:
try:
rslt.append(int(v))
except:
rslt.append(float(v))
return rslt
or for the simpler solution just ask for the numbers as follows:
def getInput():
# Return the list of numbers entered by the user
resp = input("Enter a series of numbers: ").split(' ')
rslt = []
for v in resp:
try:
rslt.append(int(v))
except:
rslt.append(float(v))
return rslt
My attempt:
m = str(input())
# m = list(m)
w = ""
r = ""
num = [int(i) for i in m.split() if i.isdigit()]
for c in range(0,len(m)-1):
if m[len(m)-1]:
for num in w:
if num.isnumeric():
w.remove(num)
num.join(r)
elif m[c].isalpha():
r.join(m[c])
elif m[c].isnumeric() and (len(w)==0 or w[c]=='('):
w.join(m[c])
elif len(num)!=0:
try:
if int(m[c])>int(w[c]):
w.join(m[c])
else:
n = [int(i) for i in w.split() if i.isdigit()]
if len(n)!=0:
r = ''.join([str(elem) for elem in w])
except:
continue
elif m[c]==')':
for number in m:
if number.isnumeric():
w+=number
elif number=='(':
m.remove('(')
m.remove(')')
break
elif (w[c]=='(') or ((int(w[c]))<(int(m[c]))) or (w=""): # In this statement it gives an invalid syntax error
w = m[c]
else:
break
print(r)
I would like to know why get a invalid syntax at line 34 (elif statement).
Also, would like to know if there is any better way to solve this question.
Thanks
QUESTION:
Midnumeral Strings to Rightnumeral Strings
Midnumeral string is a string which contains one number in between letters. For example, a1b2c is a midnumeral string. A midnumeral strings may contain letters a to z, numbers 1 to 9 and both left and the right parentheses.
Rightnumeral string is a string which can be formed from midnumeral string:
(i) All the characters except left and right parenthesis in the midnumeral string is present in rightnumeral string.
(ii) A number ‘n’ which is between letters ‘a’ anb ‘b’ in the midnumeral string will appear in the right hand of side of the letters ‘a’ and ‘b’ in rightnumeral string in a particular fashion.
(iii)During the process of conversion of a midnumeral string to a rightnumeral string, a waiting stream is used.
Given a midnumeral string ‘m’ it can be converted to a rightnumeral string ‘r’ as follows:
i. Process character by character of midnumeral string ‘m’.
ii. When a letter is seen add it to rightnumeral string ‘r’.
iii. When a number ‘n’ is seen and waiting stream is empty or the recently added character to waiting stream is left parenthesis then add ‘n’ to waiting stream
iv. If a number ‘n’ seen and there are some numbers in the waiting stream then, If the recently added numeral in waiting stream is less than ‘n’ then add ‘n’ to waiting stream, Otherwise process waiting stream from most recent to least recent:-Remove number from waiting stream and add it to ‘r’
Repeat part (i), until the recent value available in waiting stream is less than ‘n’ or the recent character the waiting stream is left parenthesis or the waiting stream becomes empty
v. Add ‘n’ to the waiting stream
vi. If a left parenthesis is seen then add it to waiting stream
vii. When right parenthesis is seen then remove all numbers from most recent to least recent from waiting stream and add it to r till left parenthesis is seen. Discard left and right parenthesis
viii. When the end of the midnumeral ‘m’ string is reached remove all numerals from most recent to least recent from waiting stream and add it to right numeral string ‘r’
For example,
a1b2c will be abc21
a2b1c will be ab2c1
(a1b)2c will be ab1c2
a1b4(c5d2e)7f will be abcd5e2f741
Note: All the characters in the midnumeral will be distinct and only valid input is given
Input Format
First line contains the midnumeral string, m
Output Format
First line should contain the rightnumeral string, r
.1 The Syntax error
It is simple a missing '=' sign, so change it to this
elif (w[c]=='(') or ((int(w[c]))<(int(m[c]))) or (w==""):
w = m[c]
else:
break
.2 Code improvements & Best practices
I suggest you for this to post the answer on Code Review as is meant for this. There are quite few errors and not best practices follow.
For instance, this error block:
try:
if int(m[c])>int(w[c]):
w.join(m[c])
else:
n = [int(i) for i in w.split() if i.isdigit()]
if len(n)!=0:
r = ''.join([str(elem) for elem in w])
except:
continue
The except is catching too many types of error, better like:
try:
if int(m[c])>int(w[c]):
w.join(m[c])
else:
n = [int(i) for i in w.split() if i.isdigit()]
if len(n)!=0:
r = ''.join([str(elem) for elem in w])
except ValueError:
continue
Have a look at Should I always specify an exception type in except statements? for more information about this. Also there is too much 'logic' in that try block. but for simplicity that is ok.
EDIT
Consideration
Note that I used different combination of sets ( accepted_numbers, accepted_chars, left_parenthesis, right_parenthesis) instead of list of other thing, this is because set are super fast when used for Looks up, more info --> Time complexity of python set operations?. And also is very clear what you are trying to use them for.
The Variable r, is way better decision to use it during the Algorithm as a List and Then turn it as a String, that's because is just easier to manipulate.
I don't even used 1 try except block, this is because, is was clear what to do, I mean we knew it ahead, so you can just handle it with a if else block, apart of what I stated Above regarding the Try blocks, another important aspect is that the slow down the code if finds and exception (in this code it won't even matter) look here try-except vs If in Python
The Algorithm problem that you posted uses and demands a Stack as a Collection, you can see it implemented in the process_waiting_stream() function
in a LIFO (last in, first out) fashion.
process_waiting_stream()
Answer Testing one case
m = '(a1b)2c' # test string Added on the top as requested in the exercise
import string # If you don't want to import string, just hard code the letters
m = m
r = []
# ----- CONSTANTS
accepted_numbers = {str(i) for i in range(1, 10)} # 1 to 9
accepted_chars = {*string.ascii_lowercase}
left_parenthesis = '('
right_parenthesis = ')'
parenthesis = {left_parenthesis, right_parenthesis}
midnumeral_string = accepted_numbers | accepted_chars | parenthesis
# ---- NOTE: Run a quick check is Input is Correct |!(a1b)2c or (a1b)0c is not good
for char in m:
if char in midnumeral_string:
pass
else:
print('Input String is not a Midnumeral string')
continue
# ---------------------------
WAITING_STREAM = []
r = [] # Use a list, not a string, easier to work with :)
def process_waiting_stream():
global WAITING_STREAM
if WAITING_STREAM:
WAITING_STREAM.reverse() # LIFO from most recent to least recent
while True:
if not WAITING_STREAM:
break
item = WAITING_STREAM[0]
if item == left_parenthesis:
break
elif item in accepted_numbers:
item = WAITING_STREAM.pop(0)
r.append(item)
WAITING_STREAM.reverse()
def checK_stream(): # NOTE: We check this in case there is only '(' and not a num
return any([item in accepted_numbers for item in WAITING_STREAM])
for char in m:
if WAITING_STREAM:
recently_added = WAITING_STREAM[-1]
if char in accepted_chars:
r.append(char)
elif char in accepted_numbers:
if not WAITING_STREAM or recently_added == left_parenthesis:
WAITING_STREAM.append(char)
elif checK_stream():
if (recently_added not in parenthesis
and recently_added not in accepted_chars) and int(recently_added) < int(char):
WAITING_STREAM.append(char)
else:
process_waiting_stream()
WAITING_STREAM.append(char)
else:
WAITING_STREAM.append(char)
elif char == left_parenthesis:
WAITING_STREAM.append(char)
elif char == right_parenthesis:
process_waiting_stream()
for item in WAITING_STREAM:
if item == left_parenthesis:
left_para = WAITING_STREAM.index(left_parenthesis)
WAITING_STREAM.pop(left_para)
break
process_waiting_stream()
r = ''.join(r)
print(r)
Answer 2
Testing All cases
import string # If you don't want to import string, just hard code the letters
def rightnumeral_string(m):
# ----- CONSTANTS
accepted_numbers = {str(i) for i in range(1, 10)} # 1 to 9
accepted_chars = {*string.ascii_lowercase}
left_parenthesis = '('
right_parenthesis = ')'
parenthesis = {left_parenthesis, right_parenthesis}
midnumeral_string = accepted_numbers | accepted_chars | parenthesis
# ---- NOTE: Run a quick check is Input is Correct |!(a1b)2c or (a1b)0c is not good
for char in m:
if char in midnumeral_string:
pass
else:
print('Input String is not a Midnumeral string')
continue
# ---------------------------
WAITING_STREAM = []
r = [] # Use a list, not a string, easier to work with :)
def process_waiting_stream():
nonlocal WAITING_STREAM
if WAITING_STREAM:
WAITING_STREAM.reverse() # LIFO from most recent to least recent
while True:
if not WAITING_STREAM:
break
item = WAITING_STREAM[0]
if item == left_parenthesis:
break
elif item in accepted_numbers:
item = WAITING_STREAM.pop(0)
r.append(item)
WAITING_STREAM.reverse()
def checK_stream(): # NOTE: We check this in case there is only '(' and not a num
return any([item in accepted_numbers for item in WAITING_STREAM])
# ------ Iterate Through each Character (number included) in the string
for char in m:
if WAITING_STREAM:
recently_added = WAITING_STREAM[-1]
if char in accepted_chars:
r.append(char)
elif char in accepted_numbers:
if not WAITING_STREAM or recently_added == left_parenthesis:
WAITING_STREAM.append(char)
elif checK_stream(): # Check if there are currently nums in stream
if (recently_added not in parenthesis
and recently_added not in accepted_chars) and int(recently_added) < int(char):
WAITING_STREAM.append(char)
else:
process_waiting_stream()
WAITING_STREAM.append(char)
else:
WAITING_STREAM.append(char)
elif char == left_parenthesis:
WAITING_STREAM.append(char)
elif char == right_parenthesis:
process_waiting_stream()
# Last Step is to Remove left_parenthesis
for item in WAITING_STREAM:
if item == left_parenthesis:
left_para = WAITING_STREAM.index(left_parenthesis)
WAITING_STREAM.pop(left_para)
break
process_waiting_stream()
r = ''.join(r)
return r
print(rightnumeral_string('a1b2c'))
print(rightnumeral_string('a2b1c'))
print(rightnumeral_string('(a1b)2c'))
print(rightnumeral_string('a1b4(c5d2e)7f'))
# Checking if the Answer Are correct
assert rightnumeral_string('a1b2c') == 'abc21'
assert rightnumeral_string('a2b1c') == 'ab2c1'
assert rightnumeral_string('(a1b)2c') == 'ab1c2'
assert rightnumeral_string('a1b4(c5d2e)7f') == 'abcd5e2f741'
Documentation
string
Iterating each character in a string using Python
What is the use of “assert” in Python?
I need to check if the input is a palindrome.
I converted the input to a string and compared the input with the reverse of the input using list slicing. I want to learn a different way without converting input to a string.
def palindrome(n):
num = str(n)
if num == num[::-1]:
return True
Assuming that n is a number, you can get digits from right to left and build a number with those digits from left to right:
n = 3102
m = n
p = 0
while m:
p = p*10 + m%10 # add the rightmost digit of m to the right of p
m //= 10 # remove the rightmost digit of m
print(p) # 2013
Hence the function:
def palindrome(n):
m = n
p = 0
while m:
p = p*10 + m%10
m //= 10
return p == n
Note that:
if num == num[::-1]:
return True
will return None if num != num[::-1] (end of the function). You should write:
if num == num[::-1]:
return True
else:
return False
Or (shorter and cleaner):
return num == num[::-1]
There can be 2 more approaches to that as follows:
Iterative Method: Run loop from starting to length/2 and check first character to last character of string and second to second last one and so on. If any character mismatches, the string wouldn’t be palindrome.
Sample Code Below:
def isPalindrome(str):
for i in xrange(0, len(str)/2):
if str[i] != str[len(str)-i-1]:
return False
return True
One Extra Variable Method: In this method, user take a character of string one by one and store in a empty variable. After storing all the character user will compare both the string and check whether it is palindrome or not.
Sample Code Below:
def isPalindrome(str):
w = ""
for i in str:
w = i + w
if (str==w):
return True
return False
You can try the following approach:
Extract all the digits from the number n
In each iteration, append the digit to one list (digits) and at that digit at the beginning of another list (reversed_digits)
Once all digits have been extracted, compare both lists
def palindrome(n):
digits = []
reversed_digits = []
while n > 0:
digit = n % 10
digits.append(digit)
reversed_digits.insert(0, digit)
n //= 10
return digits == reversed_digits
Note: this might not be the most efficient way to solve this problem, but I think it is very easy to understand.
What I am trying to do is alter my original hangman game into what is called evil hangman. In order to do this, I need to first generate a random length of a word and pull out all words of that length from the original list.
Here is the code I am working with:
def setUp():
"""shows instructions, reads file,and returns a list of words from the english dictionary"""
try:
print(60*'*' +'''\n\t\tWelcome to Hangman!\n\t
I have selected a word from an english dictionary. \n\t
I will first show you the length of the secret word\n\t
as a series of dashes.\n\t
Your task is to guess the secret word one letter at a time.\n\t
If you guess a correct letter I will show you the guessed\n\t
letter(s) in the correct position.\n
You can only make 8 wrong guesses before you are hanged\n
\t\tGood luck\n''' + 60*'*')
infile=open('dictionary.txt')
l=infile.readlines()# list of words from which to choose
infile.close()
cleanList = []
for word in l:
cleanList.append(l[:-1])
return(cleanList)
except IOError:
print('There was a problem loading the dictionary file as is.')
def sort_dict_words_by_length(words):
"""Given a list containing words of different length,
sort those words based on their length."""
d = defaultdict(list)
for word in words:
d[len(word)].append(word)
return d
def pick_random_length_from_dictionary(diction):
max_len, min_len = ( f(diction.keys()) for f in (max, min) )
length = random.randint(min_len, max_len)
return diction[length]
def playRound(w,g):
""" It allows user to guess one letter. If right,places letter in correct positions in current guess string g, and shows current guess to user
if not, increments w, number of wrongs. Returns current number of wrongs and current guess string"""
print('You have ' + str(8 - w) + ' possible wrong guesses left.\n')
newLetter = input('Please guess a letter of the secret word:\n')
glist = list(g)#need to make changes to current guess string so need a mutable version of it
if newLetter in secretWord:
for j in range (0,len(secretWord)):
if secretWord[j]==newLetter:
glist[j] = newLetter
g = ''.join(glist)#reassemble the guess as a string
print('Your letter is indeed present in the secret word: ' + ' '.join(g)+'\n')
else:
w += 1
print('Sorry, there are no ' + newLetter + ' in the secret word. Try again.\n')
return(w,g)
def endRound(wr, w,l):
"""determines whether user guessed secret word, in which case updates s[0], or failed after w=8 attempts, in s\which case it updates s[1]"""
if wr == 8:
l += 1
print('Sorry, you have lost this game.\n\nThe secret word was '+secretWord +'\n')#minor violation of encapsulation
else:
w +=1
print(15*'*' + 'You got it!' + 15*'*')
return(w,l)
def askIfMore():
"""ask user if s/he wants to play another round of the game"""
while True:
more = input('Would you like to play another round?(y/n)')
if more[0].upper() == 'Y' or more[0].upper()=='N':
return more[0].upper()
else:
continue
def printStats(w,l):
"""prints final statistics"""
wGames='games'
lGames = 'games'
if w == 1:
wGames = 'game'
if l ==1:
lGames = 'game'
print('''Thank you for playing with us!\nYou have won {} {} and lost {} {}.\nGoodbye.'''.format(w,wGames,l,lGames))
try:
import random
from collections import defaultdict
words=setUp()#list of words from which to choose
won, lost = 0,0 #accumulators for games won, and lost
while True:
wrongs=0 # accumulator for wrong guesses
secretWord = random.choice(words)[:#eliminates '\n' at the end of each line
print(secretWord) #for testing purposes
guess= len(secretWord)*'_'
print('Secret Word:' + ' '.join(guess))
while wrongs < 8 and guess != secretWord:
wrongs, guess = playRound(wrongs, guess)
won, lost = endRound(wrongs,won,lost)
if askIfMore()== 'N':
break
printStats(won, lost)
except:
quit()
What I would like to do is generate a random number with the lower bound being the shortest length word and the upper bound being the highest length word, and then use that random number to create a new container with words of only that length, and finally returning that container to be used by the game further. I tried using min and max, but it seems to only return the first and last item of the list instead of showing the word with the most characters. Any help is appreciated.
If your 'dictionary.txt' has a single word on each line, you could use the following, which is speed efficient, because it'll only go over the list once. But it'll consume the memory of your original list again.
from collections import defaultdict
import random
def sort_dict_words_by_length(words):
"""Given a list containing words of different length,
sort those words based on their length."""
d = defaultdict(list)
for word in words:
d[len(word)].append(word)
return d
def pick_random_length_from_dictionary(diction):
max_len, min_len = ( f(diction.keys()) for f in (max, min) )
length = random.randint(min_len, max_len)
return diction[length]
You would then pass the output from your setUp to sort_dict_words_by_length and that output to pick_random_length_from_dictionary.
If you are memory-limited, then you should first go over all words in the wordlist, keeping track of the minimal and maximal length of those words and then reiterate over that wordlist, appending only those words of the desired length. What you need for that is mentioned in the code above and just requires some code reshuffling. I'll leave that up to you as an exercise.
So far, I have this:
def main():
bad_filename = True
l =[]
while bad_filename == True:
try:
filename = input("Enter the filename: ")
fp = open(filename, "r")
for f_line in fp:
a=(f_line)
b=(f_line.strip('\n'))
l.append(b)
print (l)
bad_filename = False
except IOError:
print("Error: The file was not found: ", filename)
main()
this is my program and when i print this what i get
['1,2,3,4,5']
['1,2,3,4,5', '6,7,8,9,0']
['1,2,3,4,5', '6,7,8,9,0', '1.10,2.20,3.30,0.10,0.30']
but instead i need to get
[1,2,3,4,5]
[6,7,8,9,0.00]
[1.10,2.20,3.3.0,0.10,0.30]
Each line of the file is a series on numbers separated by commas, but to python they are just characters. You need one more conversion step to get your string into a list. First split on commas to create a list of strings each of which is a number. Then use what is called "list comprehension" (or a for loop) to convert each string into a number:
b = f_line.strip('\n').split(',')
c = [float(v) for v in b]
l.append(c)
If you really want to reset the list each time through the loop (your desired output shows only the last line) then instead of appending, just assign the numerical list to l:
b = f_line.strip('\n').split(',')
l = [float(v) for v in b]
List comprehension is a shorthand way of saying:
l = []
for v in b:
l.append(float(v))
You don't need a or the extra parentheses around the assignment of a and b.