mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-14 22:38:46 +00:00
194 lines
4.6 KiB
C
194 lines
4.6 KiB
C
//**************************************************************************
|
|
// Towers of Hanoi benchmark
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Towers of Hanoi is a classic puzzle problem. The game consists of
|
|
// three pegs and a set of discs. Each disc is a different size, and
|
|
// initially all of the discs are on the left most peg with the smallest
|
|
// disc on top and the largest disc on the bottom. The goal is to move all
|
|
// of the discs onto the right most peg. The catch is that you are only
|
|
// allowed to move one disc at a time and you can never place a larger
|
|
// disc on top of a smaller disc.
|
|
//
|
|
// This implementation starts with NUM_DISC discs and uses a recursive
|
|
// algorithm to solve the puzzle.
|
|
|
|
struct Node {
|
|
int val;
|
|
struct Node* next;
|
|
};
|
|
|
|
struct List {
|
|
int size;
|
|
struct Node* head;
|
|
};
|
|
|
|
struct List g_nodeFreeList;
|
|
struct Node g_nodePool[7];
|
|
|
|
int list_getSize(struct List* list) {
|
|
return list->size;
|
|
}
|
|
|
|
void list_init(struct List* list) {
|
|
list->size = 0;
|
|
list->head = 0;
|
|
}
|
|
|
|
void list_push(struct List* list, int val) {
|
|
struct Node* newNode;
|
|
|
|
// Pop the next free node off the free list
|
|
newNode = g_nodeFreeList.head;
|
|
g_nodeFreeList.head = g_nodeFreeList.head->next;
|
|
|
|
// Push the new node onto the given list
|
|
newNode->next = list->head;
|
|
list->head = newNode;
|
|
|
|
// Assign the value
|
|
list->head->val = val;
|
|
|
|
// Increment size
|
|
list->size++;
|
|
}
|
|
|
|
int list_pop(struct List* list) {
|
|
struct Node* freedNode;
|
|
int val;
|
|
|
|
// Get the value from the->head of given list
|
|
val = list->head->val;
|
|
|
|
// Pop the head node off the given list
|
|
freedNode = list->head;
|
|
list->head = list->head->next;
|
|
|
|
// Push the freed node onto the free list
|
|
freedNode->next = g_nodeFreeList.head;
|
|
g_nodeFreeList.head = freedNode;
|
|
|
|
// Decrement size
|
|
list->size--;
|
|
|
|
return val;
|
|
}
|
|
|
|
void list_clear(struct List* list) {
|
|
while (list_getSize(list) > 0)
|
|
list_pop(list);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Tower data structure and functions
|
|
|
|
struct Towers {
|
|
int numDiscs;
|
|
int numMoves;
|
|
struct List pegA;
|
|
struct List pegB;
|
|
struct List pegC;
|
|
};
|
|
|
|
void towers_init(struct Towers* towers, int n, int nonce) {
|
|
int i;
|
|
|
|
towers->numDiscs = n;
|
|
towers->numMoves = 0;
|
|
|
|
list_init(&(towers->pegA));
|
|
list_init(&(towers->pegB));
|
|
list_init(&(towers->pegC));
|
|
|
|
for (i = 0; i < n; i++)
|
|
list_push(&(towers->pegA), nonce * (n - i));
|
|
}
|
|
|
|
void towers_clear(struct Towers* towers, int nonce) {
|
|
list_clear(&(towers->pegA));
|
|
list_clear(&(towers->pegB));
|
|
list_clear(&(towers->pegC));
|
|
|
|
towers_init(towers, towers->numDiscs, nonce);
|
|
}
|
|
|
|
void towers_solve_h(struct Towers* towers, int n, struct List* startPeg, struct List* tempPeg, struct List* destPeg) {
|
|
int val;
|
|
|
|
if (n == 1) {
|
|
val = list_pop(startPeg);
|
|
list_push(destPeg, val);
|
|
towers->numMoves++;
|
|
} else {
|
|
towers_solve_h(towers, n - 1, startPeg, destPeg, tempPeg);
|
|
towers_solve_h(towers, 1, startPeg, tempPeg, destPeg);
|
|
towers_solve_h(towers, n - 1, tempPeg, startPeg, destPeg);
|
|
}
|
|
}
|
|
|
|
void towers_solve(struct Towers* towers) {
|
|
towers_solve_h(towers, towers->numDiscs, &(towers->pegA), &(towers->pegB), &(towers->pegC));
|
|
}
|
|
|
|
int towers_verify(struct Towers* towers, int nonce) {
|
|
struct Node* ptr;
|
|
int numDiscs = 0;
|
|
int result = 0;
|
|
|
|
if (list_getSize(&towers->pegA) != 0) {
|
|
return 2;
|
|
}
|
|
|
|
if (list_getSize(&towers->pegB) != 0) {
|
|
return 3;
|
|
}
|
|
|
|
if (list_getSize(&towers->pegC) != towers->numDiscs) {
|
|
return 4;
|
|
}
|
|
|
|
for (ptr = towers->pegC.head; ptr != 0; ptr = ptr->next) {
|
|
numDiscs++;
|
|
if (ptr->val != nonce * numDiscs) {
|
|
return 5;
|
|
}
|
|
result += ptr->val;
|
|
}
|
|
|
|
if (towers->numMoves != ((1 << towers->numDiscs) - 1)) {
|
|
return 6;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Main
|
|
|
|
int run_towers(int dummy_0, int nonce) {
|
|
struct Towers towers;
|
|
int i;
|
|
|
|
// Initialize free list
|
|
|
|
list_init(&g_nodeFreeList);
|
|
g_nodeFreeList.head = &(g_nodePool[0]);
|
|
g_nodeFreeList.size = 7;
|
|
g_nodePool[7 - 1].next = 0;
|
|
g_nodePool[7 - 1].val = 99;
|
|
for (i = 0; i < (7 - 1); i++) {
|
|
g_nodePool[i].next = &(g_nodePool[i + 1]);
|
|
g_nodePool[i].val = nonce * i;
|
|
}
|
|
|
|
towers_init(&towers, 7, nonce);
|
|
|
|
// Solve it
|
|
|
|
towers_clear(&towers, nonce);
|
|
towers_solve(&towers);
|
|
|
|
// Check the results
|
|
return towers_verify(&towers, nonce);
|
|
}
|