1 //**************************************************************************
2 // Towers of Hanoi benchmark
3 //--------------------------------------------------------------------------
5 // Towers of Hanoi is a classic puzzle problem. The game consists of
6 // three pegs and a set of discs. Each disc is a different size, and
7 // initially all of the discs are on the left most peg with the smallest
8 // disc on top and the largest disc on the bottom. The goal is to move all
9 // of the discs onto the right most peg. The catch is that you are only
10 // allowed to move one disc at a time and you can never place a larger
11 // disc on top of a smaller disc.
13 // This implementation starts with NUM_DISC discs and uses a recursive
14 // algorithm to sovel the puzzle. The smips-gcc toolchain does not support
15 // system calls so printf's can only be used on a host system, not on the
16 // smips processor simulator itself. You should not change anything except
17 // the HOST_DEBUG and PREALLOCATE macros for your timing run.
21 // This is the number of discs in the puzzle.
25 //--------------------------------------------------------------------------
26 // List data structure and functions
40 struct List g_nodeFreeList
;
41 struct Node g_nodePool
[NUM_DISCS
];
43 int list_getSize( struct List
* list
)
48 void list_init( struct List
* list
)
54 void list_push( struct List
* list
, int val
)
58 // Pop the next free node off the free list
59 newNode
= g_nodeFreeList
.head
;
60 g_nodeFreeList
.head
= g_nodeFreeList
.head
->next
;
62 // Push the new node onto the given list
63 newNode
->next
= list
->head
;
67 list
->head
->val
= val
;
74 int list_pop( struct List
* list
)
76 struct Node
* freedNode
;
79 // Get the value from the->head of given list
80 val
= list
->head
->val
;
82 // Pop the head node off the given list
83 freedNode
= list
->head
;
84 list
->head
= list
->head
->next
;
86 // Push the freed node onto the free list
87 freedNode
->next
= g_nodeFreeList
.head
;
88 g_nodeFreeList
.head
= freedNode
;
96 void list_clear( struct List
* list
)
98 while ( list_getSize(list
) > 0 )
102 //--------------------------------------------------------------------------
103 // Tower data structure and functions
114 void towers_init( struct Towers
* this, int n
)
121 list_init( &(this->pegA
) );
122 list_init( &(this->pegB
) );
123 list_init( &(this->pegC
) );
125 for ( i
= 0; i
< n
; i
++ )
126 list_push( &(this->pegA
), n
-i
);
130 void towers_clear( struct Towers
* this )
133 list_clear( &(this->pegA
) );
134 list_clear( &(this->pegB
) );
135 list_clear( &(this->pegC
) );
137 towers_init( this, this->numDiscs
);
142 void towers_print( struct Towers
* this )
148 for ( i
= 0; i
< ((this->numDiscs
)-list_getSize(&(this->pegA
))); i
++ )
150 for ( ptr
= this->pegA
.head
; ptr
!= 0; ptr
= ptr
->next
)
151 printf( "%d ", ptr
->val
);
154 for ( i
= 0; i
< ((this->numDiscs
)-list_getSize(&(this->pegB
))); i
++ )
156 for ( ptr
= this->pegB
.head
; ptr
!= 0; ptr
= ptr
->next
)
157 printf( "%d ", ptr
->val
);
160 for ( i
= 0; i
< ((this->numDiscs
)-list_getSize(&(this->pegC
))); i
++ )
162 for ( ptr
= this->pegC
.head
; ptr
!= 0; ptr
= ptr
->next
)
163 printf( "%d ", ptr
->val
);
169 void towers_solve_h( struct Towers
* this, int n
,
170 struct List
* startPeg
,
171 struct List
* tempPeg
,
172 struct List
* destPeg
)
180 val
= list_pop(startPeg
);
181 list_push(destPeg
,val
);
185 towers_solve_h( this, n
-1, startPeg
, destPeg
, tempPeg
);
186 towers_solve_h( this, 1, startPeg
, tempPeg
, destPeg
);
187 towers_solve_h( this, n
-1, tempPeg
, startPeg
, destPeg
);
192 void towers_solve( struct Towers
* this )
194 towers_solve_h( this, this->numDiscs
, &(this->pegA
), &(this->pegB
), &(this->pegC
) );
197 int towers_verify( struct Towers
* this )
202 if ( list_getSize(&this->pegA
) != 0 ) {
204 printf( "ERROR: Peg A is not empty!\n" );
209 if ( list_getSize(&this->pegB
) != 0 ) {
211 printf( "ERROR: Peg B is not empty!\n" );
216 if ( list_getSize(&this->pegC
) != this->numDiscs
) {
218 printf( " ERROR: Expected %d discs but found only %d discs!\n", \
219 this->numDiscs
, list_getSize(&this->pegC
) );
224 for ( ptr
= this->pegC
.head
; ptr
!= 0; ptr
= ptr
->next
) {
226 if ( ptr
->val
!= numDiscs
) {
228 printf( " ERROR: Expecting disc %d on peg C but found disc %d instead!\n", \
229 numDiscs
, ptr
->val
);
235 if ( this->numMoves
!= ((1 << this->numDiscs
) - 1) ) {
237 printf( " ERROR: Expecting %d num moves but found %d instead!\n", \
238 ((1 << this->numDiscs
) - 1), this->numMoves
);
246 //--------------------------------------------------------------------------
249 int main( int argc
, char* argv
[] )
251 struct Towers towers
;
254 // Initialize free list
256 list_init( &g_nodeFreeList
);
257 g_nodeFreeList
.head
= &(g_nodePool
[0]);
258 g_nodeFreeList
.size
= NUM_DISCS
;
259 g_nodePool
[NUM_DISCS
-1].next
= 0;
260 g_nodePool
[NUM_DISCS
-1].val
= 99;
261 for ( i
= 0; i
< (NUM_DISCS
-1); i
++ ) {
262 g_nodePool
[i
].next
= &(g_nodePool
[i
+1]);
263 g_nodePool
[i
].val
= i
;
266 towers_init( &towers
, NUM_DISCS
);
268 // If needed we preallocate everything in the caches
271 towers_solve( &towers
);
276 towers_clear( &towers
);
278 towers_solve( &towers
);
281 // Print out the results
284 towers_print( &towers
);
288 return towers_verify( &towers
);