Reputation: 219
I'm trying to improve this code which asks the user to say what the state capital is when given a state, but I've noticed that sometimes it will repeat a state and ask it twice.
I tried using random.sample instead, but I got an error "TypeError: Unhashable type: 'list'. Here is the code that works (but repeats) with the random.sample commented out:
capitals_dict = {
'Alabama': 'Montgomery',
'Alaska': 'Juneau',
'Arizona': 'Phoenix',
'Arkansas': 'Little Rock',
'California': 'Sacramento',
'Colorado': 'Denver',
'Connecticut': 'Hartford',
'Delaware': 'Dover',
'Florida': 'Tallahassee',
'Georgia': 'Atlanta',
'Hawaii': 'Honolulu',
'Idaho': 'Boise',
'Illinois': 'Springfield',
'Indiana': 'Indianapolis',
'Iowa': 'Des Moines',
'Kansas': 'Topeka',
'Kentucky': 'Frankfort',
'Louisiana': 'Baton Rouge',
'Maine': 'Augusta',
'Maryland': 'Annapolis',
'Massachusetts': 'Boston',
'Michigan': 'Lansing',
'Minnesota': 'St. Paul',
'Mississippi': 'Jackson',
'Missouri': 'Jefferson City',
'Montana': 'Helena',
'Nebraska': 'Lincoln',
'Nevada': 'Carson City',
'New Hampshire': 'Concord',
'New Jersey': 'Trenton',
'New Mexico': 'Santa Fe',
'New York': 'Albany',
'North Carolina': 'Raleigh',
'North Dakota': 'Bismarck',
'Ohio': 'Columbus',
'Oklahoma': 'Oklahoma City',
'Oregon': 'Salem',
'Pennsylvania': 'Harrisburg',
'Rhode Island': 'Providence',
'South Carolina': 'Columbia',
'South Dakota': 'Pierre',
'Tennessee': 'Nashville',
'Texas': 'Austin',
'Utah': 'Salt Lake City',
'Vermont': 'Montpelier',
'Virginia': 'Richmond',
'Washington': 'Olympia',
'West Virginia': 'Charleston',
'Wisconsin': 'Madison',
'Wyoming': 'Cheyenne',
}
import random
states = list(capitals_dict.keys())
for i in [1, 2, 3, 4, 5]:
state = random.choice(states)
#state = random.sample(states, 5)
capital = capitals_dict[state]
capital_guess = input('What is the capital of ' + state + '?')
if capital_guess == capital:
print('Correct! Nice job!')
else:
print('Incorrect. The Capital of ' + state + ' is ' + capital + '.')
print('All done.')
I also tried just using the dictionary name capitals_dict like this:
random.sample(capitals_dict, 5)
but I got a different error then found out that I can't use dictionaries like that.
Upvotes: 3
Views: 15104
Reputation: 219
If anyone reading this wants a decent US States Capitals quizzer, I updated the code to include tracking the users score. It will ask all 50 states in a random order, and it will also let you skip and quit any time.
capitals_dict = {
'Alabama': 'Montgomery',
'Alaska': 'Juneau',
'Arizona': 'Phoenix',
'Arkansas': 'Little Rock',
'California': 'Sacramento',
'Colorado': 'Denver',
'Connecticut': 'Hartford',
'Delaware': 'Dover',
'Florida': 'Tallahassee',
'Georgia': 'Atlanta',
'Hawaii': 'Honolulu',
'Idaho': 'Boise',
'Illinois': 'Springfield',
'Indiana': 'Indianapolis',
'Iowa': 'Des Moines',
'Kansas': 'Topeka',
'Kentucky': 'Frankfort',
'Louisiana': 'Baton Rouge',
'Maine': 'Augusta',
'Maryland': 'Annapolis',
'Massachusetts': 'Boston',
'Michigan': 'Lansing',
'Minnesota': 'St. Paul',
'Mississippi': 'Jackson',
'Missouri': 'Jefferson City',
'Montana': 'Helena',
'Nebraska': 'Lincoln',
'Nevada': 'Carson City',
'New Hampshire': 'Concord',
'New Jersey': 'Trenton',
'New Mexico': 'Santa Fe',
'New York': 'Albany',
'North Carolina': 'Raleigh',
'North Dakota': 'Bismarck',
'Ohio': 'Columbus',
'Oklahoma': 'Oklahoma City',
'Oregon': 'Salem',
'Pennsylvania': 'Harrisburg',
'Rhode Island': 'Providence',
'South Carolina': 'Columbia',
'South Dakota': 'Pierre',
'Tennessee': 'Nashville',
'Texas': 'Austin',
'Utah': 'Salt Lake City',
'Vermont': 'Montpelier',
'Virginia': 'Richmond',
'Washington': 'Olympia',
'West Virginia': 'Charleston',
'Wisconsin': 'Madison',
'Wyoming': 'Cheyenne',
}
import random
counterQuestions = 0 # Represents the number of questions asked to the user
counterCorrect = 0
print('Enter the name of the State Capital with proper spelling. Enter "skip" to skip or "quit" to quit')
for state in random.sample(list(capitals_dict), 50):
capital = capitals_dict[state]
capital_guess = input('What is the capital of {}? '.format(state))
if capital_guess == 'skip':
#print('The Capital of {} is {}.'.format(state, capital)) #study mode - use comment feature to turn this on/off.
counterQuestions = counterQuestions + 1
continue
elif capital_guess == 'quit':
break
elif capital_guess == capital:
print('Correct! Nice job!')
counterCorrect = counterCorrect + 1
counterQuestions = counterQuestions + 1
else:
print('Incorrect. The Capital of {} is {}.'.format(state, capital))
counterQuestions = counterQuestions + 1
score = (counterCorrect / counterQuestions) * 100
counterIncorrect = counterQuestions - counterCorrect
print('All done. Your score is ' + str(score) + '% correct, or ' + str(counterCorrect) + ' out of ' + str(counterQuestions) + ' (' + str(counterIncorrect) + ' incorrect)')
Upvotes: 0
Reputation: 123483
Try doing it this way. which just samples the state names:
import random
num_queries = 5
for state in random.sample(capitals_dict.keys(), num_queries):
capital = capitals_dict[state]
capital_guess = input('What is the capital of ' + state + '?')
if capital_guess == capital:
print('Correct! Nice job!')
else:
print('Incorrect. The Capital of ' + state + ' is ' + capital + '.')
print('All done.')
While you could also use:
for state in random.sample(list(capitals_dict), num_queries):
because list(dictionary)
will implicitly return a list of the dictionary's keys, but I prefer making what's going on explicit.
Upvotes: 1
Reputation: 1122352
You can create a list of all keys in the dictionary by passing the dictionary to the list()
function first, then sample from that list:
sample = random.sample(list(capitals_dict), 5)
You can also pass in the dict.keys()
dictionary view:
sample = random.sample(capitals_dict.keys(), 5)
but internally random.sample()
will just convert that to a sequence too (a tuple()
) so using list()
is actually more efficient here.
The exception you encountered actually tells you this:
>>> random.sample(capitals_dict, 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../lib/python3.4/random.py", line 311, in sample
raise TypeError("Population must be a sequence or set. For dicts, use list(d).")
TypeError: Population must be a sequence or set. For dicts, use list(d).
# ^^^^^^^^^^^^^^^^^^^^^^^
Demo:
>>> import random
>>> capitals_dict = {
... 'Alabama': 'Montgomery',
... 'Alaska': 'Juneau',
... 'Arizona': 'Phoenix',
... 'Arkansas': 'Little Rock',
... 'California': 'Sacramento',
... # ... elided ...
... }
>>>
>>> random.sample(list(capitals_dict), 5)
['Maryland', 'Mississippi', 'Wisconsin', 'Texas', 'West Virginia']
To incorporate that into your code:
import random
for state in random.sample(list(capitals_dict), 5):
capital = capitals_dict[state]
capital_guess = input('What is the capital of {}?'.format(state))
if capital_guess == capital:
print('Correct! Nice job!')
else:
print('Incorrect. The Capital of {} is {}.'.format(state, capital))
I also replaced your string concatenations with str.format()
calls to put values into string templates instead.
Upvotes: 6