Skip to content

Instantly share code, notes, and snippets.

@Nircek
Last active March 6, 2022 13:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nircek/80a4d3d5050c517beff73778c4778de0 to your computer and use it in GitHub Desktop.
Save Nircek/80a4d3d5050c517beff73778c4778de0 to your computer and use it in GitHub Desktop.
Dynamic task roulette
#!/usr/bin/env python3
import random
import shutil
import math
N = 100
bag, weights = [], []
W = shutil.get_terminal_size((80, 20))[0]
class BreakException(Exception):
"""Break the line parsing loop"""
class ContinueException(Exception):
"""Continue the line parsing loop"""
def ignore(line):
print(f'# ignoring `{line}`')
raise ContinueException()
def parseLine(line):
stripped = line.replace('-', '').strip()
if stripped == 'END':
raise BreakException()
if stripped == '':
raise ContinueException()
l = line.split('x ', 1)
if len(l) != 2:
ignore(line)
q, x = l[0].rsplit(' ', 1)[-1], l[1]
try:
q = int(q)
except ValueError:
ignore(line)
if q <= 0:
raise ContinueException()
return q, x
def drawn(number):
o = number
sign, number = '+' if number >= 0 else '-', round(abs(number))
r = sign*number
return r.replace('+'*4, '\N{CIRCLED PLUS}').replace('-'*4, '\N{CIRCLED MINUS}')
print('''Paste your list like this:
```
- 1x thing
```
and end it with the `END` keyword or send the EOF signal.''', end=2*'\n')
try:
while True:
try:
w, b = parseLine(input())
bag += [b]
weights += [w]
except ContinueException:
pass
except (BreakException, EOFError):
pass
print()
assert bag
pool = sum(weights)
wanted = {}
for b, w in zip(bag, weights):
wanted[b] = w/pool
if sum(weights) <= N:
bag = sum([w*[b] for w, b in zip(weights, bag)], []) + (random.choices(bag, weights, k=N-sum(weights)) if sum(weights) < N else [])
if len(bag) < N:
bag += random.choices(bag, weights, k=N-len(bag))
if len(bag) > N:
bag = random.choices(bag, weights, k=N)
bag.sort()
assert len(bag) == N
name_size = max([len(e) for e in bag])
number_size = len(str(N-1))
column_size = name_size + number_size + 4
columns = (W+2)//column_size # ignore the last spaces
real = {}
for e in bag:
real[e] = (real[e] if e in real else 0) + 1/N
for r, w, k in sorted([(100*real[k], 100*wanted[k], k) for k in wanted], reverse=True):
print(f'{k:<{name_size}} {r:2.0f} {w:5.2f} {r-w:7.2f} {drawn(4*(r-w))}')
print()
for i, e in enumerate(bag):
print(f'{i:0>{number_size}}. {e:<{name_size}}', end=' ' if (i+1)%columns else '\n')
print()
@Nircek
Copy link
Author

Nircek commented Mar 3, 2022

demonstration

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