Skip to content

Instantly share code, notes, and snippets.

@zackmdavis
Created March 12, 2016 02:50
Show Gist options
  • Save zackmdavis/f0e436c0665a8460d4af to your computer and use it in GitHub Desktop.
Save zackmdavis/f0e436c0665a8460d4af to your computer and use it in GitHub Desktop.
#/usr/bin/env python3
from enum import Enum
from random import choice, randint
from datetime import datetime
from operator import add, sub, mul # binary operations as functions!
# Enums were introduced in 3.4!
Operation = Enum('Operation', ('add', 'subtract', 'multiply'))
class Expression:
operations = {Operation.add: ('+', add),
Operation.subtract: ('-', sub),
Operation.multiply: ('*', mul)}
def __init__(self, operation, first_operand, second_operand):
self.operation = operation
self.first_operand = first_operand
self.second_operand = second_operand
@classmethod # class methods!
# the convention is to say `cls` instead of `self` for these
def arbitrary_expression(cls, maximum_figure):
return cls(choice(list(Operation)),
# gratuitously splatting a list comprehension because <3
*[randint(0, maximum_figure) for _ in range(2)])
def evaluate(self):
_symbol, action = self.operations[self.operation]
return action(self.first_operand, self.second_operand)
def __str__(self): # pretty end-user string form of class
# (contrast to __repr__, for the developer debugging string form)
symbol, _action = self.operations[self.operation]
return "{} {} {}".format(
self.first_operand, symbol, self.second_operand)
def play(maximum_figure=12):
start_time = datetime.now()
wins = tries = 0 # multiple assignment targets!
should_continue = True
while should_continue:
expression = Expression.arbitrary_expression(maximum_figure)
try:
user_says = input("{}\n".format(expression))
except KeyboardInterrupt: # catch ^C
break
if "done" in user_says:
should_continue = False
else:
tries += 1
try:
user_answer = int(user_says)
if user_answer == expression.evaluate():
wins += 1
print("Correct!")
continue
except ValueError: # they typed a non-number
pass # fallthrough to ...
print("Wrong. Answer was {}".format(expression.evaluate()))
end_time = datetime.now()
total_time = (end_time - start_time).total_seconds()
print(
"{} wins / {} tries in {} sec {}".format(
wins, tries, total_time,
"({} sec/try)".format(
# can't divide by zero, which is falsey
round(total_time / tries, 2)) if tries else ''
)
)
# only if we're running as a script, not if imported as module
if __name__ == "__main__":
play(maximum_figure=12)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment