Skip to content

Instantly share code, notes, and snippets.

@DamianDominoDavis
Last active May 26, 2020 08:12
Show Gist options
  • Save DamianDominoDavis/d04fbab6ec06e21ee907945e89551dbb to your computer and use it in GitHub Desktop.
Save DamianDominoDavis/d04fbab6ec06e21ee907945e89551dbb to your computer and use it in GitHub Desktop.
from random import random, randrange, choice, sample
from math import gcd
comebacks = (1,2,3,4,5,6,7,8)
# shorthand probability test
def p(r):
return random() < r
# imperative: like the wiki says
def useBook(book):
which = first = choice(comebacks)
if first in book and p(.5):
which = second = choice([x for x in comebacks if x is not first])
if second in book and p(.5):
which = third = choice([x for x in comebacks if x is not second])
return (which not in book) and p(.75)
# pythonic: sufficient to guarantee the uniqueness of at least two dice
def simpler(book):
(first, second), third = sample(comebacks,2), choice(comebacks)
if (first not in book) \
or (p(.5) and second not in book) \
or (p(.25) and third not in book):
return p(.75)
return False
# categorical eqeuivalence: don't even care which specific one you mean
def arithmetic(book):
dice = [randrange(len(comebacks)), randrange(1,len(comebacks)), randrange(len(comebacks))]
if not p(.25):
return (dice[0] >= len(book)) \
or (p(.5) and (dice[0] + dice[1]) % len(comebacks) >= len(book)) \
or (p(.25) and dice[2] >= len(book))
return False
# P-function: nonbinary; accepts loaded dice
def cheating(booklen, dice):
if (dice[0] >= booklen):
return 0.75
if ((dice[0] + dice[1]) % len(comebacks) >= booklen):
return 0.5
if dice[2] >= booklen:
return 0.25
return 0
# see for yourself they're all the same math
def statistically(tnum=1000):
book = []
for llen in range(1,10):
print('{} comebacks:'.format(llen-1), end=' ')
rate = sum((1 if useBook(book) else 0 for test in range(tnum)))
rata = sum((1 if simpler(book) else 0 for test in range(tnum)))
rato = sum((1 if arithmetic(book) else 0 for test in range(tnum)))
book.append(llen)
print("{}%\t{}\t{}".format(100*rate/tnum, 100*rata/tnum, 100*rato/tnum))
# deterministically roll all 8*8*7=448 dice outcome sets
# Todo: compute this less expensively by weighting 7*(8 choose 2) outcome sets
def deterministically():
def loadedBook():
for A in range(len(comebacks)):
for B in range(1,len(comebacks)):
for C in range(len(comebacks)):
yield [A,B,C]
massive = [list() for _ in range(len(comebacks))]
for book in loadedBook():
for known, history in enumerate(massive):
history.append(cheating(known,book))
for known, history in enumerate(massive):
s,l = int(100*sum(history)), int(100*len(history))
g = gcd(s,l)
s,l = int(s/g), int(l/g)
print(known, 'comebacks: {}% ({} / {})'.format(100*s/l, s, l))
# backing down gives 10+ more turns to prepare; here's how little that's worth
def learnInTenTurns(alreadyKnown,tnum=1000):
history = []
for test in range(tnum):
book = list(range(alreadyKnown))
for turn in range(10):
if arithmetic(book):
book.append(turn)
history.append(len(book))
print(alreadyKnown, "comebacks + 10 uses = ~{} comebacks".format(sum(history)/len(history)))
print('odds of actually learning anything each use:')
# statistically(int(1E5))
# print('deterministically:')
deterministically()
print('\nand backing down is a loser\'s game because:')
for known in range(8):
learnInTenTurns(known,1000)
@DamianDominoDavis
Copy link
Author

~/repositories/pyground: python3 bbopi.py ✔

odds of actually learning anything each use:
0 comebacks: 75.0% (3 / 4)
1 comebacks: 71.875% (23 / 32)
2 comebacks: 67.63392857142857% (303 / 448)
3 comebacks: 61.941964285714285% (555 / 896)
4 comebacks: 54.464285714285715% (61 / 112)
5 comebacks: 44.86607142857143% (201 / 448)
6 comebacks: 32.8125% (21 / 64)
7 comebacks: 17.96875% (23 / 128)

and backing down is a loser's game because:
0 comebacks + 10 uses = ~5.672 comebacks
1 comebacks + 10 uses = ~6.192 comebacks
2 comebacks + 10 uses = ~6.543 comebacks
3 comebacks + 10 uses = ~6.839 comebacks
4 comebacks + 10 uses = ~7.173 comebacks
5 comebacks + 10 uses = ~7.415 comebacks
6 comebacks + 10 uses = ~7.637 comebacks
7 comebacks + 10 uses = ~7.804 comebacks

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