Task: 100 prisoners




Go: package main

import (
    "fmt"
    "math/rand"
    "time"
)


func doTrials(trials, np int, strategy string) {
    pardoned := 0
trial:
    for t := 0; t < trials; t++ {
        var drawers [100]int
        for i := 0; i < 100; i++ {
            drawers[i] = i
        }
        rand.Shuffle(100, func(i, j int) {
            drawers[i], drawers[j] = drawers[j], drawers[i]
        })
    prisoner:
        for p := 0; p < np; p++ {
            if strategy == "optimal" {
                prev := p
                for d := 0; d < 50; d++ {
                    this := drawers[prev]
                    if this == p {
                        continue prisoner
                    }
                    prev = this
                }
            } else {
                
                
                var opened [100]bool
                for d := 0; d < 50; d++ {
                    var n int
                    for {
                        n = rand.Intn(100)
                        if !opened[n] {
                            opened[n] = true
                            break
                        }
                    }
                    if drawers[n] == p {
                        continue prisoner
                    }
                }
            }
            continue trial
        }
        pardoned++
    }
    rf := float64(pardoned) / float64(trials) * 100
    fmt.Printf("  strategy = %-7s  pardoned = %-6d relative frequency = %5.2f%%\n\n", strategy, pardoned, rf)
}

func main() {
    rand.Seed(time.Now().UnixNano())
    const trials = 100000
    for _, np := range []int{10, 100} {
        fmt.Printf("Results from %d trials with %d prisoners:\n\n", trials, np)
        for _, strategy := range [2]string{"random", "optimal"} {
            doTrials(trials, np, strategy)
        }
    }
}




Python: import random

def play_random(n):
    
    pardoned = 0
    in_drawer = list(range(100))
    sampler = list(range(100))
    for _round in range(n):
        random.shuffle(in_drawer)
        found = False
        for prisoner in range(100):
            found = False
            for reveal in random.sample(sampler, 50):
                card = in_drawer[reveal]
                if card == prisoner:
                    found = True
                    break
            if not found:
                break
        if found:
            pardoned += 1
    return pardoned / n * 100   

def play_optimal(n):
    
    pardoned = 0
    in_drawer = list(range(100))
    for _round in range(n):
        random.shuffle(in_drawer)
        for prisoner in range(100):
            reveal = prisoner
            found = False
            for go in range(50):
                card = in_drawer[reveal]
                if card == prisoner:
                    found = True
                    break
                reveal = card
            if not found:
                break
        if found:
            pardoned += 1
    return pardoned / n * 100   

if __name__ == '__main__':
    n = 100_000
    print(" Simulation count:", n)
    print(f" Random play wins: {play_random(n):4.1f}% of simulations")
    print(f"Optimal play wins: {play_optimal(n):4.1f}% of simulations")