Selecting a random value from a dictionary in python - python-3.x

Here is my function:
def evilSetup():
words = setUp()
result = {}
char = input('Please enter your one letter guess: ')
for word in words:
key = ' '.join(char if c == char else '-' for c in word)
if key not in result:
result[key] = []
result[key].append(word)
return max(result.items(), key=lambda keyValue: len(keyValue[1]))
from collections import defaultdict
import random
words= evilSetup()#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 = words
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)
The function will take a list of words, and sort them into a dictionary based on the position of the guessed letter. As of now, it returns the key,value pair that is the largest. What I would like it to ultimately return is a random word from the biggest dictionary entry. The values as of now are in the form of a list.
For example {- - -, ['aah', 'aal', 'aas']}
Ideally I would grab a random word from this list to return. Any help is appreciated. Thanks in advance.

If you have a list lst, then you can simply do:
random_word = random.choice(lst)
to get a random entry of the list. So here, you will want something like:
return random.choice(max(result.items(), key=lambda kv: len(kv[1]))[1])
# ^^^^^^^^^^^^^^ ^^^^

Related

Find anagrams of a given sentence from a list of words

I have a sentence with no spaces and only lowercase letters, for example:
"johndrinksmilk"
and a list of words, which contains only words that could be anagrams of the sentence above, also these words are in alphabetical order, for example:
["drink","drinks","john","milk","milks"]
I want to create a function (without using libraries) which returns a tuple of three words that together can form the anagram of the given sentence. This tuple has to be the last possible anagram of the sentence. If the words in the given list can't be used to form the given sentence, the function should return None. Since I know I'm very bad at explaining things I'll try to give you some examples:
For example, with:
sentence = "johndrinksmilk"
g_list = ["drink","drinks","john","milk","milks"]
the result should be:
r_result = ("milks","john","drink")
while these results should be wrong:
w_result = ("drinks","john","milk")
w_result = None
w_result = ("drink","john","milks")
I tried this:
def find_anagram(sentence, g_list):
g_list.reverse()
for fword in g_list:
if g_list.index(fword) == len(g_list)-1:
break
for i in range(len(fword)):
sentence_1 = sentence.replace(fword[i],"",1)
if sentence_1 == "":
break
count2 = g_list.index(fword)+1
for sword in g_list[count2:]:
if g_list.index(sword) == len(g_list)-1:
break
for i in range(len(sword)):
if sword.count(sword[i]) > sentence_1.count(sword[i]):
break
else:
sentence_2 = sentence_1.replace(sword[i],"",1)
count3 = g_list.index(sword)+1
if sentence_2 == "":
break
for tword in g_list[count3:]:
for i in range(len(tword)):
if tword.count(tword[i]) != sentence_2.count(tword[i]):
break
else:
return (fword,sword,tword)
return None
but instead of returning:
("milks","john","drink")
it returns:
None
Can anyone please tell me what's wrong? If you think my function is bad feel free to show me a different approach (but still without using libraries), because I have the feeling my function is both complex and very slow (and wrong of course...).
Thanks for your time.
Edit: new examples as requested.
sentence = "markeatsbread"
a_list = ["bread","daerb","eats","kram","mark","stae"] #these are all the possibles anagrams
the correct result is:
result = ["stae","mark","daerb"]
wrong results should be:
result = ["mark","eats","bread"] #this could be a possible anagram, but I need the last possible one
result = None #can't return None because there's at least one anagram
Try this and see if it works with all of your cases:
def findAnagram(sentence, word_list):
word_list.reverse()
for f_word in word_list:
if word_list[-1] == f_word:
break
index1 = word_list.index(f_word) + 1
for s_word in word_list[index1:]:
if word_list[-1] == s_word: break
index2 = word_list.index(s_word) + 1
for t_word in word_list[index2:]:
if (sorted(list(f_word + s_word + t_word)) == sorted(list(sentence))):
return (f_word, s_word, t_word)
Hopefully this helps you

hello friends i cant execute my else condition

The program must accept a string S as the input. The program must replace every vowel in the string S by the next consonant (alphabetical order) and replace every consonant in the string S by the next vowel (alphabetical order). Finally, the program must print the modified string as the output.
s=input()
z=[let for let in s]
alpa="abcdefghijklmnopqrstuvwxyz"
a=[let for let in alpa]
v="aeiou"
vow=[let for let in v]
for let in z:
if(let=="a"or let=="e" or let=="i" or let=="o" or let=="u"):
index=a.index(let)+1
if index!="a"or index!="e"or index!="i"or index!="o"or index!="u":
print(a[index],end="")
else:
for let in alpa:
ind=alpa.index(let)
i=ind+1
if(i=="a"or i=="e" or i=="i"or i=="o"or i=="u"):
print(i,end="")
the output is :
i/p orange
pbf
the required output is:
i/p orange
puboif
I would do it like this:
import string
def dumb_encrypt(text, vowels='aeiou'):
result = ''
for char in text:
i = string.ascii_letters.index(char)
if char.lower() in vowels:
result += string.ascii_letters[(i + 1) % len(string.ascii_letters)]
else:
c = 'a'
for c in vowels:
if string.ascii_letters.index(c) > i:
break
result += c
return result
print(dumb_encrypt('orange'))
# puboif
Basically, I would use string.ascii_letters, instead of defining that anew. Also, I would not convert all to list as it is not necessary for looping through. The consonants you got right. The vowels, I would just do an uncertain search for the next valid consonant. If the search, fails it sticks back to default a value.
Here I use groupby to split the alphabet into runs of vowels and consonants. I then create a mapping of letters to the next letter of the other type (ignoring the final consonants in the alphabet). I then use str.maketrans to build a translation table I can pass to str.translate to convert the string.
from itertools import groupby
from string import ascii_lowercase as letters
vowels = "aeiou"
is_vowel = vowels.__contains__
partitions = [list(g) for k, g in groupby(letters, is_vowel)]
mapping = {}
for curr_letters, next_letters in zip(partitions, partitions[1:]):
for letter in curr_letters:
mapping[letter] = next_letters[0]
table = str.maketrans(mapping)
"orange".translate(table)
# 'puboif'

Python lists and ranges

I'm trying to practice my python so I can improve. I'm kinda stuck and not sure how to proceed. I get an error saying "can only concatenate list(not 'int') to list." I'll leave my code and what I'm trying to do below.
Input a word string (word)
find the string length of word
use range() to iterate through each letter in word (can use to range loops)
Save odd and even letters from the word as lists
odd_letters: starting at index 0,2,...
even_letters: starting at index 1,3,...
print odd and even lists
word = input("Type: ")
word = list(word)
print(word)
odd_letters = []
even_letters = []
length = int(len(word))
for i in range(length):
if i/2 == 0:
even_letters = even_letters + i
elif i/2 != 0:
odd_letters = odd_letters + i
print(even_letters)
print(odd_letters)
I wrote this... Let me know what you think...
word = input("Choose a word to test: ")
word_len = len(word)
print(word," contains ",word_len," letters")
odd_letters = []
even_letters = []
for i in range(1,len(word),2):
even_letters.append(word[i])
for i in range(0,word_len,2):
odd_letters.append(word[i])
print("Odd letters are: ",odd_letters)
print("Even letters are: ",even_letters)
Your code is good, but i decided to find a quicker solution for the program you want. This is my code:
word = str(input("Enter word:"))
store_1 = [x for x in word]
store_2 = []
for idx, val in enumerate(store_1):
store_2.append(idx)
even_numbers = [y for y in store_2 if y%2 == 0]
odd_numbers = [z for z in store_2 if z%2 == 1]
print("List of Even numbers:",even_numbers)
print("List of Odd numbers:",odd_numbers)
The variable 'word' takes in the word from the user. The list 'store_1' uses list comprehension to separate the letters the in the word and store it. Next, i enumerate through 'store_1' and use the variable 'store_2' to only store the indexes of 'store_1'.
Next, I declare another variable 'even_numbers' that uses list comprehension to iterate through 'store_2' and find the even numbers. The next variable 'odd_numbers' also uses list comprehension to find the odd numbers in 'store_2'.
Then, it just prints the even and odd lists to the user. Hope this helps :)
You cannot add an integer to a list, as you have attempted to do here:
even_letters = even_letters + i
You can instead do this (which is now adding a list to a list, which is valid):
even_letters = even_letters + [i]
Or, use append to alter the list in-place, adding the new element to the end:
even_letters.append(i)
Few things:
You cannot "add" an integer directly to a list using '+'. Using append() would be best.
str and str types can be concatenated using '+' so you could change odd_letters and even_letters to str as shown below.
also, by adding 'i' to even and odd, you are adding the iteration variable value.
Since you want the letter to be appended, you need to refer the list index i.e word[i]
and the first letter of what is entered will be at an odd position :)
word = input("Type: ")
word = list(word)
print(word)
odd_letters = ''
even_letters = ''
length = int(len(word))
for i in range(1,length+1):
if i%2 == 0:
even_letters = even_letters + word[i-1]
else:
odd_letters = odd_letters + word[i-1]
print("even_letters",even_letters)
print("odd_letters",odd_letters)
word=input()
word_num=len(word)
print(word_num)
odd_num=[]
even_num=[]
for letters in range(0,word_num,2):
odd_num.append(word[letters])
for letters in range(1,word_num,2):
even_num.append(word[letters])
print(odd_num)
print(even_num)
This is the answer it works with every word, and follows all the requirements.

Mastermind Python Using "ABCDEF"

Mastermind Game using "ABCEF"I dont know how to check whether it is partial correct. I have to use red to mean correct letter and position. I use white to mean correct letter.
import random
def play_one_round():
N_code=''.join(random.sample("ABCDEF",4))
print (N_code)
guess=input("Enter your guess as 4 letters e.g. XXXX:")
count_guess= 1
while N_code != guess and count_guess < 10:
check(N_code,guess)
guess=input("Enter your guess as 4 letters e.g. XXXX:")
count_guess=count_guess + 1
print("This is your",count_guess, "guess")
if guess==N_code:
print('r') #Here I have if the code and guess are equal print r, which mean its the right letters in the right order.
def check(N_code,guess):
result=['r' if c1==c2 else c2 for c1,c2 in zip(guess, N_code)]
for index, char in enumerate(guess):
if result[index] !='r':
if char in result:
result[result.index(char)]='w'
print(result)
def Master_m():
print("Welcome to Mastermind!\n")
print("Start by Choosing four letters")
play_one_round()
answer=input("Play Again? ")
if answer[0]=='y':
Master_m()
Master_m()
I wrote this ages ago but it will do the trick
import random
import itertools
def start():
""" this function is used to initialise the users interaction with the game
Primarily this functions allows the user to see the rules of the game or play the game"""
print ('Mastermind, what would you like to do now?\n')
print ('Type 1 for rules')
print ('Type 2 to play')
path = input('Type your selection 1 or 2: ')
if path == '1':
print ('Great lets look at the rules')
rules()
elif path == '2':
print('Great lets play some Mastermind!\n')
begingame()
start()
else:
print('that was not a valid response there is only one hidden option that is not a 1 or a 2')
start()
def rules():
"""This just prints out the rules to the user."""
print ('The rules are as follows:\n')
print ('1)Mastermind will craft you a 4 digit number that will contain all unique numbers from 1-9, there is no 0s.\n')
print ('2)You will have 12 attempts to guess the correct number.\n')
print ('3)Whites represent a correct number that is not in the correct order\n')
print ('4)Reds represent a correct number in the correct order.\n')
print ('5)If you enter a single number or the same number during a guess it will consume 1 of your 12 guesses.\n')
print ('6)to WIN you must guess the 4 numbers in the correct order.\n')
print ('7)If you run out of guesses the game will end and you lose.\n')
print ('8)if you make a guess that has letters or more than 4 digits you will lose a turn.')
start()
def makeRandomWhenGameStarts():
"""A random 4 digit number is required this is created as its own
variable that can be passed in at the start of the game, this allows the user
to guess multiple times against the one number."""
#generate a 4 digit number
num = random.sample(range(1,9), 4)
#roll is the random 4 digit number as an int supplied to the other functions
roll = int(''.join(map(str,num)))
return roll
def begingame():
"""This is the main game function. primarily using the while loop, the makeRandomWhenGameStarts variable is
passed in anbd then an exception handling text input is used to ask the user for their guees """
print ('please select 4 numbers')
#bring in the random generated number for the user to guess.
roll = makeRandomWhenGameStarts()
whiteResults = []
redResults = []
collectScore = []
guessNo = 0
#setup the while loop to end eventually with 12 guesses finishing on the 0th guess.
guesses = 12
while (guesses > 0 ):
guessNo = guessNo + 1
try:
#choice = int(2468) #int(input("4 digit number"))
choice = int(input("Please try a 4 digit number: "))
if not (1000 <= choice <= 9999):
raise ValueError()
pass
except ValueError:
print('That was not a valid number, you lost a turn anyway!')
pass
else:
print ( "Your choice is", choice)
#Use for loops to transform the random number and player guess into lists
SliceChoice = [int(x) for x in str(choice)]
ranRoll = [int(x) for x in str(roll)]
#Take the individual digits and assign them a variable as an identifier of what order they exist in.
d1Guess = SliceChoice[0:1]
d2Guess = SliceChoice[1:2]
d3Guess = SliceChoice[2:3]
d4Guess = SliceChoice[3:4]
#combine the sliced elements into a list
playGuess = (d1Guess+d2Guess+d3Guess+d4Guess)
#Set reds and whites to zero for while loop turns
nRed = 0
nWhite = 0
#For debugging use these print statements to compare the guess from the random roll
# print(playGuess, 'player guess')
# print(ranRoll,'random roll')
#Use for loops to count the white pegs and red pegs
nWhitePegs = len([i for i in playGuess if i in ranRoll])
nRedPegs = sum([1 if i==j else 0 for i, j in zip(playGuess,ranRoll)])
print ('Oh Mastermind that was a good try! ')
#Take the results of redpegs and package as turnResultsRed
TurnResultsRed = (nRedPegs)
#Take the results of whitepegs and remove duplication (-RedPegs) package as TurnResultsWhite
TurnResultsWhite = ( nWhitePegs - nRedPegs) #nWhite-nRed
#Create a unified list with the first element being the guess number
# using guessNo as an index and storing the players choice and results to feedback at the end
totalResults = ( guessNo,choice , TurnResultsWhite ,TurnResultsRed)
# collectScore = collectScore + totalResults for each turn build a list of results for the 12 guesses
collectScore.append(totalResults)
#End the while loop if the player has success with 4 reds
if nRed == (4):
print('Congratulations you are a Mastermind!')
break
#Return the results of the guess to the user
print ('You got:',TurnResultsWhite,'Whites and',TurnResultsRed,'Red\n')
#remove 1 value from guesses so the guess counter "counts down"
guesses = guesses -1
print ('You have', guesses, "guesses left!")
#First action outside the while loop tell the player the answer and advise them Game Over
print('Game Over!')
print('The answer was', roll)
#At the end of the game give the player back their results as a list
for x in collectScore:
print ('Guess',x[0],'was',x[1],':','you got', x[2],'Red','and', x[3],'Whites')
if __name__ == '__main__':
start()
When you are stuck, decompose into smaller chunks and test those. Focusing on check, you can check whether a guess letter exactly matches the code via its index and whether its in the code at all with in. Here is a self-contained example. Notice that I've pulled out everything except the problem at hand.
If this works for you, I suggest writing a self-contained example of your next problem, test it, and if you are still stuck, post that as a new question.
def check(N_code, guess):
print('code', N_code, 'guess', guess)
result = []
# enumerate gives you each letter and its index from 0
for index, letter in enumerate(guess):
if N_code[index] == letter:
# right letter in right position
vote = 'red'
elif letter in N_code:
# well, at least the letter is in the code
vote = 'white'
else:
# not even close
vote = 'black'
# add partial result
result.append('{} {}'.format(letter, vote))
# combine and print
print(', '.join(result))
check('ABCD', 'ABCD')
check('DEFA', 'ABCD')

Using the random function in Python for Evil Hangman

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.

Resources