Skip to content

Instantly share code, notes, and snippets.

@sjdv1982
Created June 28, 2021 13:26
Show Gist options
  • Save sjdv1982/d18046b0e2727cd6223aa30b0286827f to your computer and use it in GitHub Desktop.
Save sjdv1982/d18046b0e2727cd6223aa30b0286827f to your computer and use it in GitHub Desktop.
"""
11 cards, 55 points in total
S = current score
K = cards remaining
score increase = (chance to draw a non-joker * average value of non-joker) - (chance to draw a joker * S)
= (K-1)/K * (55-S)/(K-1) - 1/K * S
= (55-S)/K - S/K
= (55 - 2S)/K
=> score increase is larger than zero if S < 28, regardless of K
"""
# Define a pattern that describes which cards have been drawn (yes/no from card 1 to card 10)
import numpy as np
pos_weights = np.array([2**n for n in range(10)],int)
pos_weights = pos_weights[::-1]
def pattern_to_position(pattern):
return (pos_weights * pattern).sum()
score_weights = np.arange(1, 11,dtype=int)
def pattern_to_score(pattern):
return (score_weights * pattern).sum()
# All possible patterns
import itertools
patterns = list(itertools.product([0,1], repeat=10))
patterns = np.array(patterns, dtype=bool)
# Store the prob of reaching a pattern
probs = np.zeros(len(patterns))
probs[0] = 1 # we start at the all-zero pattern
# If we draw a card (without drawing the joker), the position *increases*.
# We keep track of prob, the probability of reaching the current pattern.
# We know the probability of drawing each card, and multiply this with prob
# Now we iterate over the patterns *in order*, starting with the lowest position (all zeros)
# This means that when we reach a pattern, we have processed already all patterns that reach this pattern
# So prob will have reached its final value already.
expected_value = 0
for pos in range(len(patterns)):
pattern = patterns[pos]
assert pattern_to_position(pattern) == pos, (pattern, pos, pattern_to_position(pattern))
prob = probs[pos]
score = pattern_to_score(pattern)
if score >= 28: # we walk away
expected_value += prob * score
# print("%2.2d" % (pos+1), "%2.2d" % score, "%-7.3g" % prob, "%-7.3g" % (prob * score), pattern)
continue
else: # we continue
# print("%2.2d" % (pos+1), "%2.2d" % score, "%-7.3g" % prob, None, " ", pattern)
pass
remaining_cards = 11 - pattern.sum()
draw_prob = 1/remaining_cards
new_prob = prob * draw_prob
for n in range(10):
if pattern[n]:
continue
new_pattern = pattern.copy()
new_pattern[n] = 1
new_position = pattern_to_position(new_pattern)
probs[new_position] += new_prob
print("Expected value", expected_value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment