Copyright 2000, Neal R. Wagner
#define ISODD(n) ((n)&1) #define ISEVEN(n) (!((n)&1)) #define MOD(x,y) (((x) % (y)) >= 0 ? (x)%(y) : ((x)%(y)) + (y)) #define M(i,j) (MOD(((i) + orient*(j)), 6)) #define EVENODD(i) (orient == 1 ? ISEVEN(i) : ISODD(i)) long orient; /* heading right or left, orient = 1 or -1 */ /* T: takes an input puzzle configuration as the array W[6], * an input puzzle orientation D, and an input roller * insertion point In. Produces a new configurataion W[6] * and output exit hole Out. * W[6]: gives orientation of each rotor arm, 0 to 5 * D: gives orientation of whole puzzle, 0 to 5 * In: gives hole where roller is inserted, D-1, D, or D+1 * Out: gives hole roller exits, D+2, D+3, or D+4 * orient: global that keeps track of whether roller is * heading left (-1) or right (1) */ void T(long W[6], long D, long In, long *Out) { orient = 1; if (In == D) { if ( ISEVEN (M(D, W[D])) ) orient = 1; else orient = -1; W[D] = M( W[D], 1); /* head to W[D+1] */ if ( EVENODD( M(D, W[ M(D,1)])) ) W[ M(D, 1) ] = M( W[ M(D, 1) ], -1); else W[ M(D, 1) ] = M( W[ M(D, 1) ], -2); } else if (In == M(D, 1)) { orient = 1; /* into W[D+1] */ if ( ISODD( M(D, W[ M(D,1)])) ) W[ M(D, 1) ] = M( W[ M(D, 1) ], 1); else W[ M(D, 1) ] = M( W[ M(D, 1) ], 2); } else if (In == M(D, -1)) { orient = -1; /* into W[D+orient*1], i.e., into W[D-1] */ if ( ISEVEN( M(D, W[ M(D,1)])) ) W[ M(D, 1) ] = M( W[ M(D, 1) ], 1); else W[ M(D, 1) ] = M( W[ M(D, 1) ], 2); } /***** else ERROR */ /* head to W[D+orient*2] */ if ( EVENODD( M(D, W[ M(D,2)])) ) { W[ M(D, 2) ] = M( W[ M(D, 2) ], 1); *Out = M(D, 2); } else { W[ M(D, 2) ] = M( W[ M(D, 2) ], -1); /* head to W[D+orient*3] */ if ( EVENODD( M(D, W[ M(D, 3) ] )) ) W[ M(D, 3) ] = M( W[ M(D, 3) ], 2); else W[ M(D, 3) ] = M( W[ M(D, 3) ], 1); *Out = M(D, 3); } }