23 Prisoners, in code

And here is a C program that tests my solution.
#include <stdlib.h>
#include <stdio.h>

#define PRISONERS_COUNT (23)
#define STRAGGLER_FACTOR (4)

enum {
MANAGER_SYNC,
MANAGER_RESYNC,
MANAGER_COUNT,
PRISONER_UNKNOWN,
PRISONER_UNKNOWN_SAW_ON,
PRISONER_UNKNOWN_SAW_OFF,
PRISONER_READY,
PRISONER_IDLE
};

enum {
ACTION_UNDECIDED,
ACTION_FLIP_A,
ACTION_FLIP_B,
ACTION_CALL_WARDEN
};

int switch_a, switch_b;
int prisoner_visited[PRISONERS_COUNT];
int prisoner_state[PRISONERS_COUNT];
int manager_count;
int manager_straggler_count;
int stats_visits;

static int call_warden(void) {
int i = PRISONERS_COUNT;
while (i--) {
if (0 == prisoner_visited[i]) {
return 1; // execute
}
}
return 0; // set free
}

static int visit_room(int prisoner) {
int action = ACTION_UNDECIDED;

prisoner_visited[prisoner]++;

switch (prisoner_state[prisoner]) {
case MANAGER_SYNC:
action = ACTION_FLIP_A;
if (switch_a) {
prisoner_state[prisoner] = MANAGER_COUNT;
}
break;
case MANAGER_RESYNC:
if (switch_a) {
if (++manager_count == PRISONERS_COUNT) {
action = ACTION_CALL_WARDEN;
} else {
action = ACTION_FLIP_A;
}
} else {
action = ACTION_FLIP_A;
prisoner_state[prisoner] = MANAGER_SYNC;
}
break;
case MANAGER_COUNT:
if (switch_a) {
if (++manager_count == PRISONERS_COUNT) {
action = ACTION_CALL_WARDEN;
} else {
action = ACTION_FLIP_A;
}
} else {
action = ACTION_FLIP_B;
if (++manager_straggler_count > STRAGGLER_FACTOR) {
manager_straggler_count = 0;
prisoner_state[prisoner] = MANAGER_RESYNC;
}
}
break;
case PRISONER_UNKNOWN:
action = ACTION_FLIP_B;
if (switch_a) {
prisoner_state[prisoner] = PRISONER_UNKNOWN_SAW_ON;
} else {
prisoner_state[prisoner] = PRISONER_UNKNOWN_SAW_OFF;
}
break;
case PRISONER_UNKNOWN_SAW_ON:
action = ACTION_FLIP_B;
if (!switch_a) {
prisoner_state[prisoner] = PRISONER_READY;
}
break;
case PRISONER_UNKNOWN_SAW_OFF:
action = ACTION_FLIP_B;
if (switch_a) {
prisoner_state[prisoner] = PRISONER_READY;
}
break;
case PRISONER_READY:
if (!switch_a) {
action = ACTION_FLIP_A;
prisoner_state[prisoner] = PRISONER_IDLE;
} else {
action = ACTION_FLIP_B;
}
break;
case PRISONER_IDLE:
action = ACTION_FLIP_B;
break;
}

switch (action) {
case ACTION_FLIP_A:
switch_a = !switch_a;
break;
case ACTION_FLIP_B:
switch_b = !switch_b;
break;
case ACTION_CALL_WARDEN:
return 1;
default:
printf("ERROR: no action taken by prisoner #%d\n", prisoner);
return -1;
}
return 0;
}

static int run_session(void) {
int i;

for (i = 0; i < PRISONERS_COUNT; i++) {
prisoner_state[i] = PRISONER_UNKNOWN;
prisoner_visited[i] = 0;
}
prisoner_state[0] = MANAGER_SYNC;
manager_count = 1; // always count self
manager_straggler_count = 0;
switch_a = abs(rand()) % 2;
switch_b = abs(rand()) % 2;
stats_visits = 0;

while (1) {
int r = visit_room(abs(rand()) % PRISONERS_COUNT);
stats_visits++;
if (1 == r) {
return call_warden();
}
if (-1 == r) {
return 1; // same as dying
}
}
}

int main(int argc, char* argv[]) {
int i = 0;
int visits_total = 0;

while (i++ < 5000) {
printf(".");
if (1 == run_session()) {
printf("executed after %d visits.\n", stats_visits);
break;
}
visits_total += stats_visits;
}
printf("Average visits per session: %d (%d/prisoner)\n", visits_total / i,
(visits_total / i) / PRISONERS_COUNT);
return 0;
}

Categories

About this Entry

This page contains a single entry by Mike Tsao published on March 13, 2004 11:12 AM.

The 23 prisoners problem was the previous entry in this blog.

Bloom Filters is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by Movable Type 4.2-en