The Floor
Empirical solution to Fiddler released on December 14, 2024.
Simulation
import copy
from collections import Counter
import random
import pandas as pd
import numpy as np
from utils import get_neighbors, pretty_print_matrix
import pprint as pp
from pprint import pprint
from termcolor import colored
HEIGHT= 3
WIDTH = 3
A = np.arange(HEIGHT*WIDTH).reshape(HEIGHT, WIDTH)
player_names = [x for x in range(HEIGHT*WIDTH)]
players = {}
idx = 0
for i in range(A.shape[0]):
for j in range(A.shape[1]):
players[player_names[idx]] = [(i,j)]
A[i,j] = player_names[idx]
idx +=1
A_copy = copy.deepcopy(A)
def get_secondary_cands(A, primary_locs):
candidates = {}
for (x,y) in primary_locs:
# These are the neighbours of A that have other people
nbrs = [ A[i,j] for (i,j) in get_neighbors(HEIGHT,
WIDTH,
x,
y)
if A[i,j] != A[x,y]]
for name in nbrs:
candidates[name] = None
return candidates
def pick_primary(players):
res = key, val = random.choice(list(players.items()))
return key, val
def single_round(r, A, players):
primary_name, primary_locs = pick_primary(players)
second_cands = get_secondary_cands(A, primary_locs)
secondary_name, _ = random.choice(list(second_cands.items()))
game = [primary_name, secondary_name]
loser_idx = 1 if np.random.random() <= 1/2 else 0
winner_idx = 1 - loser_idx
winner = game[winner_idx]
loser = game[loser_idx]
loser_locs = players.pop(loser)
players[winner] += loser_locs
for (i,j) in loser_locs:
A[i,j] = winner
# print("Round: {}, Match {} vs {} | Winner - {}".format(r+1,
# primary_name,
# secondary_name,
# winner))
# print(A)
# print('-'*80)
# print()
def game(A, players, rounds=HEIGHT*WIDTH-1):
for r in range(rounds):
single_round(r, A, players)
return A, players
def highlight(data):
# Find the maximum value
max_value = max(data.values())
# Print dictionary with highlights
print("{")
for key, value in data.items():
if value == max_value:
print(f" '{key}': {colored(value, 'red', attrs=['bold'])},")
else:
print(f" '{key}': {value},")
print("}")
# -----------------------------------
# A full game
# -----------------------------------
win_dist = []
num_games = 300000
for _ in range(num_games):
board, rem_players = game(copy.deepcopy(A), copy.deepcopy(players))
win_dist.append(board[0,0])
pretty_print_matrix(A)
print("Prob they don't win")
ranking = pd.Series({x: v/num_games for x,v in Counter(win_dist).items()})
print(1- ranking.sort_values())
# -----------------------------------
# -----------------------------------
# R rounds
# -----------------------------------
pretty_print_matrix(A)
win_dist = {x: 0 for x in player_names}
num_games = 300000
# rounds_to_survive = HEIGHT*WIDTH-1 # R
rounds_to_survive = 1 # R
for _ in range(num_games):
board, rem_players = game(copy.deepcopy(A),
copy.deepcopy(players),
rounds=rounds_to_survive)
# pretty_print_matrix(board)
# print()
for x in rem_players:
win_dist[x] += 1
print("Empirical distribution of players that survive round {}".format(
rounds_to_survive))
ranking = pd.Series(win_dist)/num_games
print(ranking.sort_values())