Skip to content

Instantly share code, notes, and snippets.

@duck57
Last active September 22, 2021 01:56
Show Gist options
  • Save duck57/79526f78479fafd5747ecbda88791096 to your computer and use it in GitHub Desktop.
Save duck57/79526f78479fafd5747ecbda88791096 to your computer and use it in GitHub Desktop.
User-configurable Fizz Buzz
#!/usr/bin/env python3
import click
from typing import *
"""
Fizz Buzz Pow Pop Bang
Like your classic FizzBuzz but with more interactivity and control
of which numbers get replaced
"""
def make_strings(
freq_dict: Dict[int, str], start: int, stop: int
) -> Generator[str, None, None]:
"""
The method that does all the fizzbuzz hard work.
:param freq_dict: see get_dict() for how this is generated
:param start: starting number
:param stop: stop number (included in outupt)
:return a generator of strings with either the number or its phrase replacement
"""
for i in range(start, stop + 1):
x: str = "".join(freq_dict[n] for n in freq_dict.keys() if not i % n)
yield x if x else str(i)
def get_dict() -> Dict[int, str]:
"""
Generates the dictionary of numbers and phrases to feed to make_strings()
:return a dict in the form of {x: "something"} (which will output something every x)
"""
defaults: List[Tuple(int, str)] = [
(5, "fizz"),
(3, "buzz"),
(7, "pow"),
(11, "pop"),
(17, "bang"),
]
i: int = 0
d: Dict[int, str] = {}
cont: bool = True
def prompt(idx: int, num: int, phrase: str) -> bool:
"""
User-defined replacement definitions
:return whether to prompt for another replacement or not
"""
n: int = click.prompt(
"(0 to finish phrasebook creation)\n" + f"Chime in every n numbers",
default=num,
type=click.IntRange(0, None),
)
if not n:
return False
p: str = click.prompt(
"(negative number to treat these as normal numbers "
+ "and finish phrasebook creation)\n"
+ f"Say what every {n} numbers ",
default=phrase,
type=click.STRING,
)
if p[0] == "-":
return False
d[n] = p
return True
while cont:
ea: Tuple[int, str] = defaults[i] if i < len(defaults) else (0, f"-{i}")
cont = prompt(i, *ea)
i += 1
return d
@click.command()
@click.option(
"-min",
type=click.INT,
help="Starting number",
default=1,
)
@click.option(
"-max",
type=click.INT,
default=100,
help="Stop number",
)
@click.option(
"-demo",
is_flag=True,
type=click.BOOL,
help="A normal fizzbuzz",
)
def main(min: int, max: int, demo: bool):
d: Dict[int, str] = {5: "fizz", 3: "buzz"} if demo else get_dict()
print("\n".join(make_strings(d, min, max)))
if __name__ == "__main__":
main()
@duck57
Copy link
Author

duck57 commented Sep 22, 2021

Tonight's update: moved to using a generator and also improved the prompts.

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