projects/solution-2.py

79 lines
1.9 KiB
Python
Executable File

#!/usr/bin/env python3
import random, datetime, os, math, decimal
MAX_SIMULATIONS = 100_000
class ProgressBar:
def __init__(self, size=100, prompt=None):
self.size = size
self.prompt = prompt
self.at = 0
self.columns = os.get_terminal_size().columns
self.space = self.columns - 9
self.percent = None
self.moved = None
if self.prompt is not None:
self.space -= len(self.prompt) + 1
decimal.getcontext().prec = 4
def move(self, amt=1):
self.at += amt
self.percent = decimal.Decimal.from_float(self.at / self.size)
self.moved = math.floor(self.space * self.percent)
def render_bar(self):
return ("\u2588" * self.moved) + (" " * (self.space - self.moved))
def progress(self):
percent = self.percent * 100
if percent.compare(decimal.Decimal(100)) == decimal.Decimal(-1):
return f"{percent:05.2f}"
else:
return f"{percent:.1f}"
def render(self):
if self.prompt is not None:
return f"{self.prompt} [{self.render_bar()}] {self.progress()}%"
else:
return f"[{self.render_bar()}] {self.progress()}%"
def __str__(self):
return self.render()
count = int(input(f"Total birthdays: "))
matches = 0
prog_bar = ProgressBar(size=MAX_SIMULATIONS, prompt="Running simulations")
for simulation in range(MAX_SIMULATIONS):
birthdays = { }
for idx in range(count):
year = datetime.date(2001, 1, 1)
days = datetime.timedelta(random.randint(0, 364))
birthday = year + days
if birthday in birthdays:
matches += 1
break
else:
birthdays[birthday] = 0
prog_bar.move(1)
end = ""
if simulation == MAX_SIMULATIONS - 1:
end = "\n"
print(f"\r{prog_bar}", end=end)
percent = decimal.Decimal.from_float(matches / MAX_SIMULATIONS) * 100
if matches == MAX_SIMULATIONS:
print(f"Calculated {percent:.1f}% people shared a birthday.")
else:
print(f"Calculated {percent:05.2f}% people shared a birthday.")