Skip to content

Instantly share code, notes, and snippets.

@initzx
Created March 18, 2022 10:49
Show Gist options
  • Save initzx/cb6077926a148d58f1f2141ec09f2c0a to your computer and use it in GitHub Desktop.
Save initzx/cb6077926a148d58f1f2141ec09f2c0a to your computer and use it in GitHub Desktop.
Simple arithmetic game
#!/usr/bin/python
# Arithmetic game where you have to multiply numbers in your head
# Choose up to n digits
# Ideas for game
# More digits as you progress, game gets harder incrementally
# Encode numbers a and b as 2x10 2,13,4x10 or 7-8x10
# - Recursively parse 2-9,45-29x2
# Hints after periods of inactivity, for example if asked to multiply 68x92, then a hint could be 90x8=720
import random
import time
from collections import namedtuple, OrderedDict
operations = {
'+': lambda a, b: a+b,
'-': lambda a, b: a-b,
'*': lambda a, b: a*b,
}
Preset = namedtuple('Preset', 'name operation specific_numbers digits questions')
presets = OrderedDict([
(1, Preset('multiply 1 digit (20 q)', '*', None, 1, 20)),
(2, Preset('multiply 1x2 digits (20 q)', '*', '1-10', 2, 20)),
(3, Preset('multiply 2 digits (20 q)', '*', None, 2, 20)),
(4, Preset('add 1 digit (20 q)', '+', None, 1, 20)),
(5, Preset('subtract 1x2 digit (20 q)', '-', None, 1, 20)),
])
preset_text = '\n'.join([f'{k}: {v.name}' for k,v in presets.items()])
def gen_random_number_factory(start=2, digits=1, rng=None, choices=None):
# Factory method
if choices:
return lambda: random.choice(choices)
elif rng:
return lambda: random.randrange(*rng)
else:
return lambda: random.randrange(start, 10**digits)
def get_generators(specific_numbers, digits):
if not specific_numbers:
gen_random_number_1 = gen_random_number_factory(digits=digits)
elif '-' in specific_numbers:
gen_random_number_1 = gen_random_number_factory(rng=[int(i) for i in specific_numbers.split('-')])
else:
gen_random_number_1 = gen_random_number_factory(choices=[int(i) for i in specific_numbers.split()])
gen_random_number_2 = gen_random_number_factory(digits=digits)
return gen_random_number_1, gen_random_number_2
# The game itself
print('Welcome to the arithmetic game! You can choose a number of preset modes to begin with')
print(preset_text)
preset = input('Select a preset (hit enter if you want to customize) ')
if preset:
preset_num = int(preset)
operation_literal, specific_numbers, digits, rounds = presets[preset_num][1:]
else:
specific_numbers = input('Do you want to train with specific numbers? (default no) ')
digits = int(input('How many digits would you like? (default 1) ') or 1)
operation_literal = input('What operation would you like? (default *) ') or '*'
rounds = int(input('How many rounds would you like? (default 20) ') or 20)
# Determine which numbers and what operation
g1, g2 = get_generators(specific_numbers, digits)
operation = operations.get(operation_literal)
avg_time = 0
correct = rounds
for k in range(rounds):
a = g1()
b = g2()
start = time.time()
ans = int(input(f'Round {k+1}/{rounds}: What is {a} {operation_literal} {b}? '))
correct_ans = operation(a, b)
diff = time.time()-start
avg_time += diff/rounds
if ans != correct_ans:
correct -= 1
print(f'Incorrect! the answer was {correct_ans}')
print(f'Your average time was {avg_time:.2f}s with {correct}/{rounds} correct answers')
@initzx
Copy link
Author

initzx commented Mar 18, 2022

This game is a demonstration of some different tricks that you can do in Python.

Line 16 where we define the operations dictionary, is similar to a factory method which is demonstrated on line 33
OrderedDicts are used to number the presets, which are defined as NamedTuples on lines 23-30
On Line 31 we have a classic list-comprehension + join, on line 46 and 48 we also use list-comprehension
On line 60 we destructure (borrowed terminology from JS) the tuple into multiple variables, this is possible since the tuple is ordered
Line 62-65 we use the or operator to select a default value. It utilizes the fact that an empty string is returned when the user hits enter, i.e. default action, then '' or value will evaluate to value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment