Last active
November 30, 2021 19:28
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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