Skip to content

Instantly share code, notes, and snippets.

@tslater2006
Last active August 20, 2024 14:18
Show Gist options
  • Select an option

  • Save tslater2006/d865ffaf825ed7244be46fa5f578f272 to your computer and use it in GitHub Desktop.

Select an option

Save tslater2006/d865ffaf825ed7244be46fa5f578f272 to your computer and use it in GitHub Desktop.
Simulates the 1-20 game found here (https://fleetfoxx.github.io/1-to-20/) to see how often this strategy wins.
"""
This script simulates a game where numbers are drawn randomly between 1 and 1000 and placed into 20 slots.
The goal is to place the numbers in the slots in the most optimal way to win the game.
Numbers cannot be rearranged after placement and must be strictly in ascending order.
The script keeps track of the number of games played and the minimum, maximum, and average number of games required to win.
To see a visual representation of the game, uncomment the replay_game function call and set number of games to 1.
In my testing it takes on average it takes around ~160,000 games to win one.
"""
import random
from time import sleep
# Rest of the code...
import random
from time import sleep
def find_range(num, slots):
if num in slots:
return None, None
lower = None
upper = None
for index in range(len(slots)):
if slots[index] is None and lower is None:
lower = index
continue
if slots[index] is not None and slots[index] < num:
lower = None
continue
if slots[index] is not None and slots[index] > num:
upper = None if index - 1 < 0 else index - 1
break
if lower is not None and upper is None:
upper = len(slots) - 1
return lower, upper
def find_best_index(num, range_indexes, slots):
# determine what the number before and after the valid range is
num_before = 0 if range_indexes[0] == 0 else slots[range_indexes[0] - 1]
num_after = (
1001 if range_indexes[1] == len(slots) - 1 else slots[range_indexes[1] + 1]
)
# of the numbers that the valid range needs to cover, how many are before and after the current number
count_before = num - num_before
count_after = num_after - num
# what percent of the valid range is before the current number
percent_before = count_before / (count_before + count_after)
# we should put the number at the index that is the same percentage through the range of valid indexes
index = range_indexes[0] + round(
(range_indexes[1] - range_indexes[0]) * percent_before
)
return index
def play_number(slots, draw_order, index_order):
# get random number between 1 and 1000 inclusive
num = random.randint(1, 1000)
draw_order.append(num)
# print("Drew number: ", num)
valid_range = find_range(num, slots)
if valid_range[0] is None:
# print("No valid move!")
return False
index = find_best_index(num, valid_range, slots)
index_order.append(index)
# print("Best index: ", index)
slots[index] = num
# print(slots)
return True
def play_game():
slots = [None] * 20
draw_order = []
index_order = []
for i in range(20):
should_continue = play_number(slots, draw_order, index_order)
if not should_continue:
return False, slots, None, None
return True, slots, draw_order, index_order
def replay_game(draw_order, index_order):
print("Replaying game...")
slots = [" "] * 20
print("-" * ((20 * 6) + 4))
cols_found = []
for i in range(20):
# draw vertical wall to match = signs
num = draw_order[i]
# print("Drawing number: ", num)
index = index_order[i]
# pad number with spaces so that all are 4 characters long
slots[index] = f"{num:4}"
print(f"|{(i+1):2}|", end="")
for z in range(20):
if z == index:
# print the number in green
print(f"\033[92m{slots[z]:5}\033[0m", end="")
cols_found.append(z)
else:
# print(f"{slots[z]:5}", end="")
if z in cols_found:
print(f" . ", end="")
else:
print(f" ", end="")
if z < 19:
print("|", end="")
print("|")
print("|--|", end="")
for z in range(20):
print(f"{slots[z]:5}", end="")
if z < 19:
print("|", end="")
print("|")
print("-" * ((20 * 6) + 4))
return slots
wins = []
num_games = 10
for i in range(num_games):
game_count = 0
while True:
# print("Playing game ", game_count) if game_count % 100000 == 0 else None
game_won, slots, draw_order, index_order = play_game()
game_count += 1
if game_won:
print("Game won after ", game_count, " games!")
# print("Draw order: ", draw_order)
# print("Index order: ", index_order)
# print("Slots: ", slots)
print()
# replay_game(draw_order, index_order)
break
wins.append(game_count)
print("Current min games to win: ", min(wins))
print("Current max games to win: ", max(wins))
print(
f"Current average games to win ({len(wins)} data points): ",
int(sum(wins) / len(wins)),
)
print()
@tslater2006
Copy link
Author

Game won after  258665  games!

Replaying game...
----------------------------------------------------------------------------------------------------------------------------
| 1|     |     |     |     |     |     |     |     |     |     |     |     |     |     |     |     | 861 |     |     |     |
| 2|     |     |     |     |     |     | 374 |     |     |     |     |     |     |     |     |     |  .  |     |     |     |
| 3|     |     |     |     |     |     |  .  |     |     |     | 572 |     |     |     |     |     |  .  |     |     |     |
| 4|     |     |     |     |     |     |  .  | 419 |     |     |  .  |     |     |     |     |     |  .  |     |     |     |
| 5|     |     |     | 265 |     |     |  .  |  .  |     |     |  .  |     |     |     |     |     |  .  |     |     |     |
| 6|     |     |     |  .  |     |     |  .  |  .  |     |     |  .  |     |     |     |     |     |  .  |     | 957 |     |
| 7|     |     |     |  .  |     |     |  .  |  .  |     |     |  .  |     |     |     |     |     |  .  | 924 |  .  |     |
| 8|     |     |     |  .  |     |     |  .  |  .  |     |     |  .  |     | 660 |     |     |     |  .  |  .  |  .  |     |
| 9|     | 186 |     |  .  |     |     |  .  |  .  |     |     |  .  |     |  .  |     |     |     |  .  |  .  |  .  |     |
|10|     |  .  | 227 |  .  |     |     |  .  |  .  |     |     |  .  |     |  .  |     |     |     |  .  |  .  |  .  |     |
|11|     |  .  |  .  |  .  |     |     |  .  |  .  |     |     |  .  |     |  .  |     |     |     |  .  |  .  |  .  | 975 |
|12|     |  .  |  .  |  .  | 274 |     |  .  |  .  |     |     |  .  |     |  .  |     |     |     |  .  |  .  |  .  |  .  |
|13|     |  .  |  .  |  .  |  .  |     |  .  |  .  | 424 |     |  .  |     |  .  |     |     |     |  .  |  .  |  .  |  .  |
|14|     |  .  |  .  |  .  |  .  |     |  .  |  .  |  .  | 564 |  .  |     |  .  |     |     |     |  .  |  .  |  .  |  .  |
|15|     |  .  |  .  |  .  |  .  |     |  .  |  .  |  .  |  .  |  .  | 615 |  .  |     |     |     |  .  |  .  |  .  |  .  |
|16|     |  .  |  .  |  .  |  .  | 341 |  .  |  .  |  .  |  .  |  .  |  .  |  .  |     |     |     |  .  |  .  |  .  |  .  |
|17|     |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |     | 762 |     |  .  |  .  |  .  |  .  |
|18| 126 |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |     |  .  |     |  .  |  .  |  .  |  .  |
|19|  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |     |  .  | 820 |  .  |  .  |  .  |  .  |
|20|  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  |  .  | 664 |  .  |  .  |  .  |  .  |  .  |  .  |
|--| 126 | 186 | 227 | 265 | 274 | 341 | 374 | 419 | 424 | 564 | 572 | 615 | 660 | 664 | 762 | 820 | 861 | 924 | 957 | 975 |
----------------------------------------------------------------------------------------------------------------------------

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment