Skip to content

Instantly share code, notes, and snippets.

@triffid
Created July 28, 2022 11:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save triffid/e68247fcb5491dafc870f8b3d8b445e0 to your computer and use it in GitHub Desktop.
Save triffid/e68247fcb5491dafc870f8b3d8b445e0 to your computer and use it in GitHub Desktop.
cat box puzzle
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from random import randint
from functools import reduce
print("There is a row of boxes. A cat is hiding in one of the boxes.")
print("Every time you check a box, the cat (invisibly) moves to an adjacent box.")
print()
print("Find a pattern that corners the cat with the least number of checks!")
print(" (select a box with 100% probability to win)")
print()
while True:
try:
n_boxes = int(input("How many boxes in the row? (≥2) \x1B[1m"))
if (n_boxes >= 2):
print("\x1B[0m", end='')
break
except ValueError:
print("\x1B[0mPlease enter an integer!")
pass
except KeyboardInterrupt:
print("\x1B[0m\nBye!")
exit(0)
else:
print("\x1B[0mBox count must be at least 2!")
boxprob = [1 / n_boxes for i in range(n_boxes)]
print("Box Index : |" + "".join(map(lambda p: "\x1B[1m%7s\x1B[0m |" % (p + 1), range(n_boxes))))
guesses = 0
while True:
print("Probabilities : |" + "".join(list(map( lambda p: "\x1B[1m%7.4g%%\x1B[0m|" % (p * 100), boxprob))))
# select box to check
while True:
try:
b = int(input("Check box number (1-%d): \x1B[1m" % n_boxes)) - 1
if ((b >= 0) and (b < n_boxes)):
print("\x1B[0m", end='')
break
except ValueError:
print("\x1B[0mPlease enter an integer between 1 and %d!" % n_boxes)
except KeyboardInterrupt:
print("\n\x1B[0mBye!")
exit(0)
else:
print("\x1B[0mBox number must be between 1 and %d!" % n_boxes)
guesses += 1
print("Box %d goes to 0%% probability" % (b + 1))
boxprob[b] = 0
# rescale probabilities
scale = reduce((lambda x, y: x + y), boxprob)
if (scale == 0):
print("\nCat cornered after %d checks! Score: %.3g%%\n" % (guesses, max(n_boxes - 2, 1) * 200 / guesses))
exit(0)
boxprob = list(map(lambda r: r / scale, boxprob))
print("Probabilities after choice: |" + "".join(list(map( lambda p: "\x1B[1m%7.4g%%\x1B[0m|" % (p * 100), boxprob))))
# move cat
print("\n→ Cat moves one box left or right\n")
boxprobn = [0 for z in range(n_boxes)]
for i in range(n_boxes):
if (i == 0):
boxprobn[i + 1] += boxprob[i]
elif (i == (n_boxes - 1)):
boxprobn[i - 1] += boxprob[i]
else:
boxprobn[i + 1] += boxprob[i] / 2
boxprobn[i - 1] += boxprob[i] / 2
boxprob = boxprobn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment