RosettaCodeData/Task/100-prisoners/GDScript/100-prisoners.gd

65 lines
1.6 KiB
GDScript

extends MainLoop
enum Strategy {Random, Optimal}
const prisoner_count := 100
func get_random_drawers() -> Array[int]:
var drawers: Array[int] = []
drawers.resize(prisoner_count)
for i in range(0, prisoner_count):
drawers[i] = i + 1
drawers.shuffle()
return drawers
var random_strategy = func(drawers: Array[int], prisoner: int) -> bool:
# Randomly selecting 50 drawers is equivalent to shuffling and picking the first 50
var drawerCopy: Array[int] = drawers.duplicate()
drawerCopy.shuffle()
for i in range(50):
if drawers[drawerCopy[i]-1] == prisoner:
return true
return false
var optimal_strategy = func(drawers: Array[int], prisoner: int) -> bool:
var choice: int = prisoner
for _i in range(50):
var drawer_value: int = drawers[choice-1]
if drawer_value == prisoner:
return true
choice = drawer_value
return false
func play_all(drawers: Array[int], strategy: Callable) -> bool:
for prisoner in range(1, prisoner_count+1):
if not strategy.call(drawers, prisoner):
return false
return true
func _process(_delta: float) -> bool:
# Constant seed for reproducibility, call randomize() in real use
seed(1234)
const SAMPLE_SIZE: int = 10_000
var random_successes: int = 0
for i in range(SAMPLE_SIZE):
if play_all(get_random_drawers(), random_strategy):
random_successes += 1
var optimal_successes: int = 0
for i in range(SAMPLE_SIZE):
if play_all(get_random_drawers(), optimal_strategy):
optimal_successes += 1
print("Random play: %%%f" % (100.0 * random_successes/SAMPLE_SIZE))
print("Optimal play: %%%f" % (100.0 * optimal_successes/SAMPLE_SIZE))
return true # Exit