Upload folder using huggingface_hub
Browse files- squid_game.py +190 -54
- squid_game_core.py +97 -0
squid_game.py
CHANGED
|
@@ -3,6 +3,9 @@ from squid_game_core import (
|
|
| 3 |
parse_tier_map,
|
| 4 |
get_expected_value,
|
| 5 |
compute_ev_win_lose_two_extremes,
|
|
|
|
|
|
|
|
|
|
| 6 |
)
|
| 7 |
from typing import List, Tuple
|
| 8 |
|
|
@@ -93,6 +96,100 @@ def solve_game(distribution: str, total_squids: int, tier_map_str: str) -> str:
|
|
| 93 |
except Exception as e:
|
| 94 |
return f"Error occurred: {str(e)}"
|
| 95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
# Default value for tier map used in interface
|
| 97 |
DEFAULT_TIER_MAP = """0-0:0
|
| 98 |
1-2:1
|
|
@@ -103,64 +200,103 @@ DEFAULT_TIER_MAP = """0-0:0
|
|
| 103 |
9-9:32
|
| 104 |
10-100:64"""
|
| 105 |
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
label="Players' Current Squids",
|
| 111 |
-
placeholder="0,0",
|
| 112 |
-
value="0,0",
|
| 113 |
-
info="""Enter each player's current squids, separated by commas.
|
| 114 |
-
Example: '1,0,1,2,0' represents:
|
| 115 |
-
- Player 1 has 1 squid
|
| 116 |
-
- Player 2 has 0 squids
|
| 117 |
-
- Player 3 has 1 squid
|
| 118 |
-
- Player 4 has 2 squids
|
| 119 |
-
- Player 5 has 0 squids"""
|
| 120 |
-
),
|
| 121 |
-
gr.Number(
|
| 122 |
-
label="Total Squids in Game",
|
| 123 |
-
value=9,
|
| 124 |
-
minimum=0,
|
| 125 |
-
step=1,
|
| 126 |
-
precision=0,
|
| 127 |
-
info="The total number of squids to be distributed (must be ≥ sum of current squids)"
|
| 128 |
-
),
|
| 129 |
-
gr.Textbox(
|
| 130 |
-
label="Squid Value Tiers",
|
| 131 |
-
placeholder=DEFAULT_TIER_MAP,
|
| 132 |
-
value=DEFAULT_TIER_MAP,
|
| 133 |
-
lines=8,
|
| 134 |
-
info="""Define the value tiers for squids.
|
| 135 |
-
Format: range:multiplier (one per line)
|
| 136 |
-
Example:
|
| 137 |
-
0-0:0
|
| 138 |
-
1-2:1
|
| 139 |
-
3-4:2
|
| 140 |
-
5-6:4
|
| 141 |
-
7-7:8
|
| 142 |
-
8-8:16
|
| 143 |
-
9-9:32
|
| 144 |
-
10-100:64"""
|
| 145 |
-
)
|
| 146 |
-
],
|
| 147 |
-
outputs=gr.Textbox(label="Results", lines=15),
|
| 148 |
-
title="Squid Game Expected Value Calculator",
|
| 149 |
-
description="""
|
| 150 |
Calculate the expected payoff for each player in the Squid Game.
|
| 151 |
-
|
| 152 |
-
Rules
|
| 153 |
1. Players take turns collecting squids randomly.
|
| 154 |
2. The game ends when either:
|
| 155 |
- Exactly one player has 0 squids, OR
|
| 156 |
- There are no squids left to distribute.
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
|
| 165 |
if __name__ == "__main__":
|
| 166 |
-
iface.launch()
|
|
|
|
| 3 |
parse_tier_map,
|
| 4 |
get_expected_value,
|
| 5 |
compute_ev_win_lose_two_extremes,
|
| 6 |
+
finite_squid_game_probabilities,
|
| 7 |
+
dp_ev,
|
| 8 |
+
infinite_squid_game_expected_counts_partial,
|
| 9 |
)
|
| 10 |
from typing import List, Tuple
|
| 11 |
|
|
|
|
| 96 |
except Exception as e:
|
| 97 |
return f"Error occurred: {str(e)}"
|
| 98 |
|
| 99 |
+
def solve_finite_game(distribution: str, total_squids: int) -> str:
|
| 100 |
+
"""Calculate the probability of each player getting a squid in the finite variant"""
|
| 101 |
+
# Validate distribution
|
| 102 |
+
valid_dist, error_msg, dist = validate_distribution(distribution)
|
| 103 |
+
if not valid_dist:
|
| 104 |
+
return error_msg
|
| 105 |
+
|
| 106 |
+
# Validate that no player has more than 1 squid (finite variant rule)
|
| 107 |
+
if any(x > 1 for x in dist):
|
| 108 |
+
return "Error: In the finite variant, players can only have 0 or 1 squid. Please adjust your input."
|
| 109 |
+
|
| 110 |
+
# Validate total squids
|
| 111 |
+
try:
|
| 112 |
+
X = int(total_squids)
|
| 113 |
+
if X < 0:
|
| 114 |
+
return "Total squids cannot be negative"
|
| 115 |
+
|
| 116 |
+
# Check if total squids exceeds number of players
|
| 117 |
+
if X > len(dist):
|
| 118 |
+
return f"Error: In the finite variant, total squids cannot exceed the number of players ({len(dist)})"
|
| 119 |
+
|
| 120 |
+
# Check if remaining squids + already distributed squids exceeds number of players
|
| 121 |
+
current_sum = sum(dist)
|
| 122 |
+
if current_sum + (X - current_sum) > len(dist):
|
| 123 |
+
return f"Error: Total squids to distribute ({X}) plus already distributed squids ({current_sum}) cannot exceed the number of players ({len(dist)})"
|
| 124 |
+
except ValueError:
|
| 125 |
+
return "Total squids must be an integer"
|
| 126 |
+
|
| 127 |
+
try:
|
| 128 |
+
# Clear cache for new calculation
|
| 129 |
+
dp_ev.cache_clear()
|
| 130 |
+
|
| 131 |
+
# Calculate probabilities using the finite variant
|
| 132 |
+
n = len(dist) # Number of players
|
| 133 |
+
|
| 134 |
+
# Calculate remaining squids to distribute
|
| 135 |
+
remaining = X - sum(dist)
|
| 136 |
+
|
| 137 |
+
# Create bitmask for players who already have squids
|
| 138 |
+
bitmask_u = (1 << n) - 1 # Start with all 1s
|
| 139 |
+
for i, val in enumerate(dist):
|
| 140 |
+
if val == 1: # If player already has a squid
|
| 141 |
+
bitmask_u ^= (1 << i) # Set bit to 0
|
| 142 |
+
|
| 143 |
+
# Calculate probabilities
|
| 144 |
+
probs = dp_ev(n, bitmask_u, remaining)
|
| 145 |
+
|
| 146 |
+
result = "Finite Squid Game Probabilities:\n"
|
| 147 |
+
result += "(Probability of each player getting a squid)\n\n"
|
| 148 |
+
|
| 149 |
+
for i, prob in enumerate(probs):
|
| 150 |
+
result += f"Player {i+1}: {prob:.4f}\n"
|
| 151 |
+
|
| 152 |
+
return result
|
| 153 |
+
|
| 154 |
+
except Exception as e:
|
| 155 |
+
return f"Error occurred: {str(e)}"
|
| 156 |
+
|
| 157 |
+
def solve_infinite_game(distribution: str) -> str:
|
| 158 |
+
"""Calculate the expected final squid count for each player in the infinite variant"""
|
| 159 |
+
# Validate distribution
|
| 160 |
+
valid_dist, error_msg, dist = validate_distribution(distribution)
|
| 161 |
+
if not valid_dist:
|
| 162 |
+
return error_msg
|
| 163 |
+
|
| 164 |
+
try:
|
| 165 |
+
# Calculate expected final counts
|
| 166 |
+
expected_counts = infinite_squid_game_expected_counts_partial(dist)
|
| 167 |
+
|
| 168 |
+
result = "Infinite Squid Game Expected Final Counts:\n"
|
| 169 |
+
result += "(Expected number of squids each player will have at the end)\n\n"
|
| 170 |
+
|
| 171 |
+
for i, count in enumerate(expected_counts):
|
| 172 |
+
if count == float('inf'):
|
| 173 |
+
result += f"Player {i+1}: ∞ (infinite)\n"
|
| 174 |
+
else:
|
| 175 |
+
result += f"Player {i+1}: {count:.4f}\n"
|
| 176 |
+
|
| 177 |
+
# Add explanation based on zero count
|
| 178 |
+
zero_count = sum(1 for x in dist if x == 0)
|
| 179 |
+
if zero_count == 1:
|
| 180 |
+
result += "\nExplanation: Game ends immediately as there is exactly one player with 0 squids."
|
| 181 |
+
elif zero_count == 0:
|
| 182 |
+
result += "\nExplanation: Game never ends (infinite loop) as there are no players with 0 squids."
|
| 183 |
+
else:
|
| 184 |
+
H_z = sum(1.0 / k for k in range(1, zero_count+1))
|
| 185 |
+
increment = (H_z - 1.0)
|
| 186 |
+
result += f"\nExplanation: Each player is expected to receive {increment:.4f} additional squids before the game ends."
|
| 187 |
+
|
| 188 |
+
return result
|
| 189 |
+
|
| 190 |
+
except Exception as e:
|
| 191 |
+
return f"Error occurred: {str(e)}"
|
| 192 |
+
|
| 193 |
# Default value for tier map used in interface
|
| 194 |
DEFAULT_TIER_MAP = """0-0:0
|
| 195 |
1-2:1
|
|
|
|
| 200 |
9-9:32
|
| 201 |
10-100:64"""
|
| 202 |
|
| 203 |
+
with gr.Blocks(title="Squid Game Calculator") as iface:
|
| 204 |
+
gr.Markdown("""
|
| 205 |
+
# Squid Game Expected Value Calculator
|
| 206 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
Calculate the expected payoff for each player in the Squid Game.
|
| 208 |
+
|
| 209 |
+
**Classic Variant Rules:**
|
| 210 |
1. Players take turns collecting squids randomly.
|
| 211 |
2. The game ends when either:
|
| 212 |
- Exactly one player has 0 squids, OR
|
| 213 |
- There are no squids left to distribute.
|
| 214 |
+
|
| 215 |
+
**Finite Variant Rules:**
|
| 216 |
+
1. Players take turns collecting squids randomly.
|
| 217 |
+
2. Once a player gets a squid, they can't get another one.
|
| 218 |
+
3. The game ends when all squids are distributed or only one player remains without a squid.
|
| 219 |
+
|
| 220 |
+
**Infinite Variant Rules:**
|
| 221 |
+
1. Players take turns collecting squids randomly (unlimited supply).
|
| 222 |
+
2. Players accumulate squids over time.
|
| 223 |
+
3. The game ends only when exactly one player has 0 squids.
|
| 224 |
+
""")
|
| 225 |
+
|
| 226 |
+
with gr.Row():
|
| 227 |
+
with gr.Column():
|
| 228 |
+
distribution_input = gr.Textbox(
|
| 229 |
+
label="Players' Current Squids",
|
| 230 |
+
placeholder="0,0",
|
| 231 |
+
value="0,0",
|
| 232 |
+
info="""Enter each player's current squids, separated by commas.
|
| 233 |
+
Example: '1,0,1,2,0' represents:
|
| 234 |
+
- Player 1 has 1 squid
|
| 235 |
+
- Player 2 has 0 squids
|
| 236 |
+
- Player 3 has 1 squid
|
| 237 |
+
- Player 4 has 2 squids
|
| 238 |
+
- Player 5 has 0 squids"""
|
| 239 |
+
)
|
| 240 |
+
total_squids_input = gr.Number(
|
| 241 |
+
label="Total Squids in Game (Classic & Finite Variants Only)",
|
| 242 |
+
value=9,
|
| 243 |
+
minimum=0,
|
| 244 |
+
step=1,
|
| 245 |
+
precision=0,
|
| 246 |
+
info="The total number of squids to be distributed (must be ≥ sum of current squids for classic variant)"
|
| 247 |
+
)
|
| 248 |
+
tier_map_input = gr.Textbox(
|
| 249 |
+
label="Squid Value Tiers (Classic Variant Only)",
|
| 250 |
+
placeholder=DEFAULT_TIER_MAP,
|
| 251 |
+
value=DEFAULT_TIER_MAP,
|
| 252 |
+
lines=8,
|
| 253 |
+
info="""Define the value tiers for squids.
|
| 254 |
+
Format: range:multiplier (one per line)
|
| 255 |
+
Example:
|
| 256 |
+
0-0:0
|
| 257 |
+
1-2:1
|
| 258 |
+
3-4:2
|
| 259 |
+
5-6:4
|
| 260 |
+
7-7:8
|
| 261 |
+
8-8:16
|
| 262 |
+
9-9:32
|
| 263 |
+
10-100:64"""
|
| 264 |
+
)
|
| 265 |
+
|
| 266 |
+
with gr.Column():
|
| 267 |
+
results_output = gr.Textbox(label="Results", lines=15)
|
| 268 |
+
|
| 269 |
+
with gr.Row():
|
| 270 |
+
classic_btn = gr.Button("Calculate Classic Variant", variant="primary")
|
| 271 |
+
finite_btn = gr.Button("Calculate Finite Variant", variant="stop")
|
| 272 |
+
infinite_btn = gr.Button("Calculate Infinite Variant", variant="secondary")
|
| 273 |
+
|
| 274 |
+
gr.Examples(
|
| 275 |
+
examples=[
|
| 276 |
+
["0,0", 9, DEFAULT_TIER_MAP],
|
| 277 |
+
["1,0,1", 12, DEFAULT_TIER_MAP],
|
| 278 |
+
["2,0,2,0", 14, DEFAULT_TIER_MAP],
|
| 279 |
+
],
|
| 280 |
+
inputs=[distribution_input, total_squids_input, tier_map_input],
|
| 281 |
+
)
|
| 282 |
+
|
| 283 |
+
classic_btn.click(
|
| 284 |
+
fn=solve_game,
|
| 285 |
+
inputs=[distribution_input, total_squids_input, tier_map_input],
|
| 286 |
+
outputs=results_output
|
| 287 |
+
)
|
| 288 |
+
|
| 289 |
+
finite_btn.click(
|
| 290 |
+
fn=solve_finite_game,
|
| 291 |
+
inputs=[distribution_input, total_squids_input],
|
| 292 |
+
outputs=results_output
|
| 293 |
+
)
|
| 294 |
+
|
| 295 |
+
infinite_btn.click(
|
| 296 |
+
fn=solve_infinite_game,
|
| 297 |
+
inputs=[distribution_input],
|
| 298 |
+
outputs=results_output
|
| 299 |
+
)
|
| 300 |
|
| 301 |
if __name__ == "__main__":
|
| 302 |
+
iface.launch()
|
squid_game_core.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
# squid_game.py
|
| 2 |
|
| 3 |
from functools import lru_cache
|
|
|
|
| 4 |
|
| 5 |
def parse_tier_map(tier_str: str):
|
| 6 |
"""
|
|
@@ -204,3 +205,99 @@ def compute_ev_win_lose_two_extremes(distribution, leftover, tier_map_tuple):
|
|
| 204 |
'difference': diff_i
|
| 205 |
})
|
| 206 |
return results
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
# squid_game.py
|
| 2 |
|
| 3 |
from functools import lru_cache
|
| 4 |
+
import math
|
| 5 |
|
| 6 |
def parse_tier_map(tier_str: str):
|
| 7 |
"""
|
|
|
|
| 205 |
'difference': diff_i
|
| 206 |
})
|
| 207 |
return results
|
| 208 |
+
|
| 209 |
+
# Infinite Squid Game Implementation
|
| 210 |
+
def infinite_squid_game_expected_counts_partial(distribution):
|
| 211 |
+
"""
|
| 212 |
+
For the "infinite squid + cumulative score, stop when only 1 player has 0" game,
|
| 213 |
+
given the current distribution (list/tuple, representing each player's current count),
|
| 214 |
+
returns a list representing the expected number of squids each player will have at the end of the game.
|
| 215 |
+
|
| 216 |
+
Rule summary:
|
| 217 |
+
- If the current number of players with 0 squids = z:
|
| 218 |
+
* z=1 => Game stops immediately, no more squids distributed => final value = current holdings
|
| 219 |
+
* z=0 => "Exactly 1 player with 0" can never occur, infinite loop => return inf
|
| 220 |
+
* z>=2 => Expected to distribute n*(H_z -1) more times (H_z=1+1/2+...+1/z),
|
| 221 |
+
Expected number of times each player is selected = (H_z-1),
|
| 222 |
+
Therefore final = distribution[i] + (H_z-1).
|
| 223 |
+
"""
|
| 224 |
+
n = len(distribution)
|
| 225 |
+
zero_count = sum(1 for x in distribution if x == 0)
|
| 226 |
+
|
| 227 |
+
# Already satisfied or exceeded "end/cannot end" condition
|
| 228 |
+
if zero_count == 1:
|
| 229 |
+
# Game ends immediately => maintain current state
|
| 230 |
+
return list(distribution)
|
| 231 |
+
if zero_count == 0:
|
| 232 |
+
# "Exactly 1 player with 0" can never occur => game never ends => infinite score
|
| 233 |
+
return [math.inf]*n
|
| 234 |
+
|
| 235 |
+
# zero_count >= 2 => continue distributing squids until z=1
|
| 236 |
+
H_z = sum(1.0 / k for k in range(1, zero_count+1)) # Harmonic number H_z
|
| 237 |
+
increment = (H_z - 1.0)
|
| 238 |
+
return [x + increment for x in distribution]
|
| 239 |
+
|
| 240 |
+
# Finite Squid Game Implementation
|
| 241 |
+
def get_bitmask(n):
|
| 242 |
+
"""
|
| 243 |
+
Returns a list [0,1,2,...,(1<<n)-1], purely for iteration reference
|
| 244 |
+
"""
|
| 245 |
+
return list(range(1 << n))
|
| 246 |
+
|
| 247 |
+
def count_ones(x):
|
| 248 |
+
"""Count how many 1s are in the binary representation of x"""
|
| 249 |
+
return bin(x).count("1")
|
| 250 |
+
|
| 251 |
+
@lru_cache(None)
|
| 252 |
+
def dp_ev(n, bitmask_u, leftover):
|
| 253 |
+
"""
|
| 254 |
+
Returns a length-n tuple (prob0, prob1, ..., prob_{n-1}),
|
| 255 |
+
representing the "final probability" of each player getting a squid in state (U=bitmask_u, leftover).
|
| 256 |
+
|
| 257 |
+
- n: total number of players
|
| 258 |
+
- bitmask_u: which players haven't received a squid yet (binary mask)
|
| 259 |
+
- leftover: remaining squids that can be distributed
|
| 260 |
+
"""
|
| 261 |
+
# 1) Terminal condition
|
| 262 |
+
num_u = count_ones(bitmask_u) # Number of players who haven't received a squid yet
|
| 263 |
+
if num_u <= 1 or leftover == 0:
|
| 264 |
+
# Game ends immediately
|
| 265 |
+
# For players who already have a squid, their probability=1
|
| 266 |
+
# For those who don't, probability=0
|
| 267 |
+
ret = []
|
| 268 |
+
for i in range(n):
|
| 269 |
+
# If i is in bitmask_u => probability=0, otherwise =1
|
| 270 |
+
if (bitmask_u & (1 << i)) != 0:
|
| 271 |
+
ret.append(0.0)
|
| 272 |
+
else:
|
| 273 |
+
ret.append(1.0)
|
| 274 |
+
return tuple(ret)
|
| 275 |
+
|
| 276 |
+
# 2) Not terminated => randomly select 1 person from U to give a squid
|
| 277 |
+
ret_accum = [0.0]*n
|
| 278 |
+
# Randomly select w from U with equal probability
|
| 279 |
+
for w in range(n):
|
| 280 |
+
bit_w = (1 << w)
|
| 281 |
+
if (bitmask_u & bit_w) != 0:
|
| 282 |
+
# w is in U
|
| 283 |
+
# Next state: after w gets a squid, remove w from bitmask
|
| 284 |
+
next_u = bitmask_u ^ bit_w # Set to 0
|
| 285 |
+
sub_ev = dp_ev(n, next_u, leftover - 1)
|
| 286 |
+
|
| 287 |
+
for i in range(n):
|
| 288 |
+
ret_accum[i] += sub_ev[i] / num_u
|
| 289 |
+
|
| 290 |
+
# 3) Return accumulated result
|
| 291 |
+
return tuple(ret_accum)
|
| 292 |
+
|
| 293 |
+
def finite_squid_game_probabilities(n, r):
|
| 294 |
+
"""
|
| 295 |
+
Returns a length-n probability vector: prob[i] = probability of player i getting a squid
|
| 296 |
+
Based on dp_ev().
|
| 297 |
+
|
| 298 |
+
- n: number of players
|
| 299 |
+
- r: number of squids to distribute
|
| 300 |
+
"""
|
| 301 |
+
# Initial U = (1<<n)-1, meaning no one has a squid yet
|
| 302 |
+
bitmask_u = (1 << n) - 1
|
| 303 |
+
return dp_ev(n, bitmask_u, r)
|