Skip to content

Instantly share code, notes, and snippets.

@190n
Created July 1, 2022 19:14
Show Gist options
  • Save 190n/799621a3b46dde83c462d5041f894526 to your computer and use it in GitHub Desktop.
Save 190n/799621a3b46dde83c462d5041f894526 to your computer and use it in GitHub Desktop.
100 prisoners in zig
// based on https://www.youtube.com/watch?v=iSNsgj1OCLA
const std = @import("std");
const Strategy = fn (my_num: u32, boxes: [100]u32, random: std.rand.Random) bool;
fn searchRandom(my_num: u32, boxes: [100]u32, random: std.rand.Random) bool {
var i: u32 = 0;
var tried = [_]bool{false} ** 100;
while (i < 50) : (i += 1) {
const guess = blk: {
while (true) {
const maybe_guess = random.intRangeLessThan(u32, 0, 100);
if (!tried[maybe_guess]) {
break :blk maybe_guess;
}
}
};
tried[guess] = true;
if (boxes[guess] == my_num) {
return true;
}
}
return false;
}
fn searchLoop(my_num: u32, boxes: [100]u32, random: std.rand.Random) bool {
_ = random;
var i: u32 = 0;
var guess = my_num;
while (i < 50) : (i += 1) {
if (boxes[guess] == my_num) {
return true;
}
guess = boxes[guess];
}
return false;
}
fn group(boxes: [100]u32, random: std.rand.Random, strategy: Strategy) u32 {
var i: u32 = 0;
var succeeded: u32 = 0;
while (i < 100) : (i += 1) {
if (strategy(i, boxes, random)) {
succeeded += 1;
}
}
return succeeded;
}
pub fn main() !void {
var prng = std.rand.DefaultPrng.init(blk: {
var seed: u64 = undefined;
try std.os.getrandom(@ptrCast([*]u8, &seed)[0..@sizeOf(u64)]);
break :blk seed;
});
const random = prng.random();
var boxes = comptime blk: {
var wip: [100]u32 = undefined;
var i: u32 = 0;
while (i < 100) : (i += 1) {
wip[i] = i;
}
break :blk wip;
};
const stdout = std.io.getStdOut().writer();
const strats = [_]struct { name: []const u8, func: Strategy }{
.{ .name = "random", .func = searchRandom },
.{ .name = "loop", .func = searchLoop },
};
const iters = 250_000;
for (strats) |strat| {
var prisoner_win: u32 = 0;
var group_win: u32 = 0;
var i: u32 = 0;
while (i < iters) : (i += 1) {
random.shuffle(u32, &boxes);
const num_passed = group(boxes, random, strat.func);
prisoner_win += num_passed;
if (num_passed == 100) {
group_win += 1;
}
try stdout.print("{}\n", .{num_passed});
}
try std.io.getStdErr().writer().print(
\\== Strategy "{s}" ==
\\Pass rate (prisoner): {d}%
\\Pass rate (group): {d}%
\\
\\
, .{ strat.name, @intToFloat(f64, prisoner_win) / (iters * 100) * 100.0, @intToFloat(f64, group_win) / iters * 100 });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment