infundibulum

Nutty Dice Trick

March 26th, 2006

Boing Boing: Nontransitive dice — how to win every time

This is sooo counterintuitive that I had to convince myself by writing a program (in Python, as it happens):

from random import choice
import sys

verbose = 1

dice = {
 'A' : [0,0,4,4,4,4],
 'B' : [3,3,3,3,3,3],
 'C' : [6,6,2,2,2,2],
 'D' : [5,5,5,1,1,1]
}

trick = {
    'B' : 'A',
    'C' : 'B',
    'D' : 'C',
    'A' : 'D'
}

scoreboard = {
    'matches' : 0,
    'sucker' : 0,
    'con' : 0
}

def match():
    scoreboard['matches'] += 1
    sucker = choice(dice.keys())
    sucker_roll = choice(dice[sucker])
    if verbose: print 'sucker rolls %d on %s' % (sucker_roll,sucker)
    con = trick[sucker]
    con_roll = choice(dice[con])
    sucker_roll = choice(dice[sucker])
    if verbose: print 'con rolls %d on %s' % (con_roll,con)
    if  sucker_roll > con_roll:
        scoreboard['sucker'] += 1
    else:
        scoreboard['con'] += 1

def score():
    print 'nnTotal:'
    print "sucker wins: ",
    print "%.2f%% of matches" % (scoreboard['sucker'] / float(scoreboard['matches']))
    print "con wins: ",
    print "%.2f%% of matches" % (scoreboard['con'] / float(scoreboard['matches']))

for i in range(int(sys.argv[1])):
    match()

score()

Lo and behold:

$ python ntdice.py 1000
sucker rolls 5 on D
con rolls 6 on C
sucker rolls 2 on C
con rolls 3 on B
sucker rolls 5 on D
con rolls 2 on C
sucker rolls 1 on D
con rolls 6 on C
...
sucker rolls 1 on D
con rolls 2 on C
sucker rolls 3 on B
con rolls 0 on A
sucker rolls 2 on C
con rolls 3 on B

Total:
sucker wins:  0.33% of matches
con wins:  0.67% of matches

I suppose proving it to myself would involve some sigmas.