/* * A breadth-first search of the Tower of Hanoi problem. */ #include "Array.h" #include "BitArray.h" #include "HashTable.h" #include "ReadBuffer.h" #include "WriteBuffer.h" #include "types.h" #include "roomy.h" #include "params.h" #include "knudirs.h" #include "RoomyBitArray.h" #include "RoomyBitsArray.h" #include #include #include #include #define N_PEGS 4 #define N_RINGS 15 #define N_STATES 1073741824 #define TRACING /****************************************************************************** * Representing Locations of Rings *****************************************************************************/ typedef uint8 Peg; typedef uint8 Ring; typedef Peg State[N_RINGS]; // list the peg each ring is on void getHomeState(State out) { Ring i; for(i=0; i=0; i--) { out[i] = r/m; r -= out[i] * m; m /= N_PEGS; } } /****************************************************************************** * Generation of Neighboring States *****************************************************************************/ // Return a list containing the top (smallest) ring for each peg. If there // are no rings on a peg, N_RINGS will be returned for that peg. void topRings(State s, Ring tops[]) { int i; for(i=0; i=0; i--) tops[s[i]] = i; } // Generate all states that can be reached in one move from the given state // (represented as integers). Return the number of neighbors generated. int genAll(uint64 r, uint64 nbrs[]) { State s; unrank(r, s); Ring tops[N_PEGS]; topRings(s, tops); int numGen = 0; Peg i; for(i=0; icur) { uint64 nbrs[N_PEGS * N_PEGS]; int numGen = genAll(r, nbrs); int i; for(i=0; inext) { // if it's a dupe, remove it from next level if(input->dupe) { output->dupe = 1; output->next = 0; // else, leave it at next level and mark as a future dupe } else { output->dupe = 1; output->next = 1; } // if it's not at the next level, leave it as is } else { output->dupe = input->dupe; output->next = input->next; } } // Top level function for method using three 1-bit arrays void threeBitBFS() { #ifdef TRACING Roomy_log("BEGINING %i-RING %i-PEG BFS\n", N_RINGS, N_PEGS); #endif // Initialize bit arrays for duplicates, current level, and next level dupe = RoomyBitArray_make("dupes", N_STATES); cur = RoomyBitArray_make("lev0", N_STATES); next = RoomyBitArray_make("lev1", N_STATES); #ifdef TRACING Roomy_log("Initial RoomyBitArrays constructed\n"); #endif // set home state State home; getHomeState(home); uint64 homePos = rank(home); RoomyBitArray_set(dupe, homePos); RoomyBitArray_set(cur, homePos); Roomy_sync(); // generate levels int curLevel = 0; uint64 numThisLevel = 1; #ifdef TRACING Roomy_log("Level %i done: %lli elements\n", curLevel, numThisLevel); #endif while(numThisLevel) { // generate next level from current RoomyBitArray** rbaList = malloc(1 * sizeof(RoomyBitArray*)); rbaList[0] = cur; RoomyBitArray_map(rbaList, 1, generate); RoomyBitArray_sync(next); free(rbaList); // detect duplicates rbaList = malloc(2 * sizeof(RoomyBitArray*)); rbaList[0] = dupe; rbaList[1] = next; RoomyBitArray_mapAndModify(rbaList, 2, mergeDupes); // create new next level, delete current level, rotate pointers curLevel++; RoomyBitArray_destroy(cur); cur = next; char levName[1024]; sprintf(levName, "lev%i", curLevel+1); next = RoomyBitArray_make(levName, N_STATES); // get the number of new states at current level numThisLevel = RoomyBitArray_numSet(cur); #ifdef TRACING Roomy_log("Level %i done: %lli elements\n", curLevel, numThisLevel); #endif } RoomyBitArray_destroy(dupe); RoomyBitArray_destroy(cur); RoomyBitArray_destroy(next); #ifdef TRACING Roomy_log("PANCAKE BFS DONE\n"); #endif } /****************************************************************************** * Tests *****************************************************************************/ void testStates() { uint64 i; for(i=0; i500) break; } } /****************************************************************************** * Main *****************************************************************************/ int main(int argc, char **argv) { //testStates(); Roomy_init(&argc, &argv); threeBitBFS(); Roomy_finalize(); return 0; }