#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define QUEUE_SIZE 256
#define HEAD (QUEUE_SIZE - 1)
#define TAIL (QUEUE_SIZE - 2)
#define MODULUS (HEAD < TAIL ? HEAD : TAIL)
#define INCREMENT(x) x = (x + 1) % MODULUS
typedef unsigned short baboon;
enum direction { EAST, WEST };
enum list_type { FORWARD, BACKWARD, STARVATION };
baboon **lists;
unsigned short num_cycles;
char *input = "EEWEWWWEWEEEWEE";
unsigned short default_crossing_time = 3;
unsigned short current_direction;
unsigned short use_starvation_queue = FALSE;
int main(int argc, char **argv);
void initialize();
int lists_are_empty();
void add_baboon(int cycle);
void run_one_cycle();
void check_for_swap();
void swap(void *first, void *second);
int main (int argc, char **argv) {
initialize();
int cycle = 0;
while ((cycle <= num_cycles) || !lists_are_empty()) {
printf("Cycle %3d: ", cycle
+ 1); add_baboon(cycle);
run_one_cycle();
check_for_swap();
cycle++;
}
return (0);
}
void add_baboon(int cycle) {
if (cycle >= num_cycles)
return;
int list, tail, crossing_time = default_crossing_time;
unsigned short direction = input[cycle] == 'E' ? EAST : WEST;
if (direction == current_direction) {
if (use_starvation_queue) {
list = STARVATION;
} else {
list = FORWARD;
}
} else {
list = BACKWARD;
#ifdef STARVATION
use_starvation_queue = TRUE;
#endif
}
tail = lists[list][TAIL];
if (lists[list][HEAD] != lists[list][TAIL]) {
int previous = (lists[list][TAIL] - 1) % MODULUS;
printf("previous: %d", previous
); printf("previous_time: %d", lists
[list
][previous
]); crossing_time = lists[list][previous] >= crossing_time ?
lists[list][previous] + 1 : crossing_time;
printf("crossing_time: %d", crossing_time
); }
lists[list][tail] = crossing_time;
INCREMENT(lists[list][TAIL]);
}
void run_one_cycle() {
baboon start, end, head;
start = head = lists[FORWARD][HEAD];
end = lists[FORWARD][TAIL];
while (start != end) {
lists[FORWARD][start]--;
INCREMENT(start);
}
if (lists[FORWARD][head] == 0) {
printf("%c", current_direction
== EAST
? 'E' : 'W'); INCREMENT(lists[FORWARD][HEAD]);
} else {
}
}
void check_for_swap() {
if (lists[FORWARD][HEAD] == lists[FORWARD][TAIL]) {
lists[FORWARD][HEAD] = lists[FORWARD][TAIL] = 0;
baboon *temp = lists[FORWARD];
lists[FORWARD] = lists[BACKWARD];
lists[BACKWARD] = temp;
current_direction = !current_direction;
if (use_starvation_queue) {
temp = lists[BACKWARD];
lists[BACKWARD] = lists[STARVATION];
lists[STARVATION] = temp;
use_starvation_queue = FALSE; // ***STARVATION SEMAPHORE P***
}
}
}
void initialize() {
int i;
lists
= (baboon
**) calloc(STARVATION
+ 1, sizeof(baboon
*)); for (i = 0; i <= STARVATION; i++)
lists
[i
] = (baboon
*) calloc(QUEUE_SIZE
, sizeof(baboon
)); current_direction = input[0] == 'E' ? EAST : WEST;
}
int lists_are_empty() {
return (lists[FORWARD][HEAD] == lists[FORWARD][TAIL] &&
lists[BACKWARD][HEAD] == lists[BACKWARD][TAIL] &&
lists[STARVATION][HEAD] == lists[STARVATION][TAIL]);
}
void swap(void *first, void *second) {
void *swap = first;
first = second;
second = swap;
}