Skip to content

Instantly share code, notes, and snippets.

@shitchell
Last active November 30, 2021 19:28
Show Gist options
  • Save shitchell/df42ebe1faf6e6cc173cb5385286fac1 to your computer and use it in GitHub Desktop.
Save shitchell/df42ebe1faf6e6cc173cb5385286fac1 to your computer and use it in GitHub Desktop.
a simple script for automatically playing games of higher/lower for the purpose of calculating the odds of winning using different methods
#!/usr/bin/env python
HIGHER: int = 3
EXACT: int = 2
LOWER: int = 1
AUTO: int = 0
def run(mode: int = AUTO, ceil: int = 100, repeat: int = 10):
"""
Runs a sequence of Higher/Lower games using the given answering method and
yields each individual game.
:param mode <int> how to guess--one of AUTO, LOWER, HIGHER, or EXACT
:param ceil <int> the upper bound for the range used to pick random numbers
:param repeat <int> the number of rounds to play
:yield <dict> a dict containing information about each round, e.g.:
{"target": 38, "random": 8, "mode": HIGHER, "success": True}
"""
import random
if mode not in {HIGHER, EXACT, LOWER, AUTO}:
raise ValueError("invalid run mode")
# used to determine if we should automatically change the mode each round
auto: bool = mode == AUTO
for i in range(repeat):
# generate two random numbers
targetnum = random.randint(1, ceil)
randomnum = random.randint(1, ceil)
# make the guess
correct_guess = False
if auto:
# if auto is set, determine whether to guess higher or lower
if randomnum < ((ceil // 2) + 1):
mode = HIGHER
else:
mode = LOWER
if (mode == HIGHER and targetnum > randomnum
or mode == LOWER and targetnum < randomnum
or mode == EXACT and targetnum == randomnum):
correct_guess = True
# return the results
yield {
"target": targetnum,
"random": randomnum,
"mode": mode,
"success": correct_guess
}
# def run(mode: int = AUTO, ceil: int = 100, repeat: int = 10):
# """
# Runs a sequence of Higher/Lower games using the given answering method and
# returns the win/loss statistics.
#
# :param mode <int> how to guess--one of AUTO, LOWER, HIGHER, or EXACT
# :param ceil <int> the upper bound for the range used to pick random numbers
# :param repeat <int> the number of rounds to play
# :return <dict> contains information about the wins/losses. e.g.:
# {"win": 98, "lose": 2, "mode": AUTO}
# """
# if mode not in {HIGHER, EXACT, LOWER, AUTO}:
# raise ValueError("invalid run mode")
def accuracy_rate(mode: int = AUTO, ceil: int = 100):
"""
Calculate the expected percentage of correct answers for the given mode and
ceiling
:param mode <int> how to guess--one of AUTO, LOWER, HIGHER, or EXACT
:param ceil <int> the upper bound for the range used to pick random numbers
:returns <float> the expected percentage of wins as a float between 0-1
"""
if mode == AUTO:
return (ceil - 1) / ceil
if mode == HIGHER or mode == LOWER:
return ((ceil / 2) - 0.5) / ceil
if mode == EXACT:
return 1 / ceil
if __name__ == "__main__":
import random
import argparse
parser = argparse.ArgumentParser(description="Guess a random number.")
guess_mode = parser.add_mutually_exclusive_group()
parser.add_argument("-m", "--max", type=int, default=100,
help="select random numbers between 1 and `max`")
guess_mode.add_argument("-i", "--higher", dest="higher", action="store_true",
help="always guess higher")
guess_mode.add_argument("-l", "--lower", dest="lower", action="store_true",
help="always guess lower")
guess_mode.add_argument("-e", "--exact", dest="exact", action="store_true",
help="always guess the exact value")
guess_mode.add_argument("-a", "--auto", dest="auto", action="store_true",
help="always guess based on highest probability")
parser.add_argument("-r", "--repeat", dest="repeat", type=int, default=1,
help="number of times to repeat")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true",
help="show each trial")
args = parser.parse_args()
stats: dict = {
"win": 0,
"lose": 0,
}
if args.higher:
mode = HIGHER
elif args.lower:
mode = LOWER
elif args.exact:
mode = EXACT
else:
mode = AUTO
for result in run(mode, args.max, args.repeat):
if args.verbose:
print(f"{result['target']:<2}", end=" ")
if mode == HIGHER:
print(">", end=" ")
elif mode == LOWER:
print("<", end=" ")
elif mode == EXACT:
print("=", end=" ")
else:
print("?", end=" ")
print(f"{result['random']:<2}", end=" ")
print(result['success'])
if result['success']:
stats["win"] += 1
else:
stats["lose"] += 1
print(stats)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment