Books · The Fiddler: Solutions
Chapter 82
Can You Win at “Rock, Paper, Scissors, Lizard, Spock”?
Three friends play a single round of Rock, Paper, Scissors, Lizard, Spock, the five-way version in which each gesture beats exactly two of the others and loses to the other two. All three reveal at once, choosing their gesture uniformly at random and independently. What is the probability that one player is immediately victorious, beating both of the others?
The Fiddler, Zach Wissner-Gross, September 27, 2024(original post)
Solution
Fix one player. Whatever gesture they throw beats exactly two of the five gestures, so each of the other two players, choosing independently and uniformly, is beaten with probability . This player beats both with probability , whatever they chose. These three “player beats both others” events cannot overlap: if beats , then has lost and cannot be a sole victor. Being mutually exclusive, their probabilities add, so some player is the sole winner with probability The other of rounds end with no clean winner: a three-way cycle, or a repeated gesture that leaves someone unbeaten.
The computation
With only outcomes, enumerate them all and count those with exactly one player beating both others.
from fractions import Fraction as F
beats = {0: {2, 3}, 1: {3, 4}, 2: {4, 0}, 3: {0, 1}, 4: {1, 2}} # each beats two
def sole_victor(a, b, c):
wins = [(b in beats[a]) and (c in beats[a]),
(a in beats[b]) and (c in beats[b]),
(a in beats[c]) and (b in beats[c])]
return sum(wins) == 1
n = sum(sole_victor(a, b, c) for a in range(5) for b in range(5) for c in range(5))
print(F(n, 125)) # 12/25
Extra Credit
The classic one-line description, “Scissors cuts Paper, Paper covers Rock, , and Rock crushes Scissors,” strings the ten “beats” into a single chain of eleven gesture-mentions. Including that one, how many such chains describe the rules?
Solution
Treat the five gestures as vertices and the ten “beats” as directed edges; each gesture has two arrows out and two in. A single chain that names every beat exactly once, returning to its start, is an Eulerian circuit of this graph. The graph has essentially different Eulerian circuits, or once you also count which of the ten beats opens the sentence.
The computation
Count the Eulerian trails directly by backtracking over the ten edges, then divide by the ten possible starting edges.
edges = [(u, v) for u in beats for v in beats[u]] # 10 directed "beats"
adj = {u: [] for u in range(5)}
for i, (u, v) in enumerate(edges): adj[u].append((v, i))
def count(node, used, length):
if length == len(edges): return 1
return sum(count(v, used | (1 << i), length + 1)
for v, i in adj[node] if not (used >> i) & 1)
chains = sum(count(s, 0, 0) for s in range(5))
print(chains, chains // len(edges)) # 50 5