Last active
May 26, 2020 08:12
-
-
Save DamianDominoDavis/d04fbab6ec06e21ee907945e89551dbb to your computer and use it in GitHub Desktop.
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
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) |
Author
DamianDominoDavis
commented
May 26, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment