// the pond tiling problem // data is seed, length of first side, length of second side import java.io.*; import java.lang.*; import java.text.*; // Pattern is stored as an integer a + 4b + 16c + 64d // +---+---+ // | c | d | // +---+---+ // | b | a | // +---+---+ public class Pond { private static int[][] pat = new int[81][]; // each row in pat holds all different rotated variants of the same pattern private static int npat; // number of unique patterns stored so far private static int seed; // initial half pattern that must match the final private static int solnCount = 0; // initial half pattern that must match the final private static int[] soln; // list of patterns in the solution private static boolean[] corner; // true if this level is the end of a row private static boolean verbose = true; private static boolean unique(int p) // true if the pattern p is not already stored in pat { int n = npat; while ( --n >= 0 ) { int[] patn = pat[n]; int m = patn.length; while ( --m >= 0 ) if ( patn[m] == p ) return false; } return true; } private static int[] newpat(int p) // deliver a row representing all possible rotations of p { int[] pp = new int[4]; int n = 4; pp[0] = p; for ( int i = 1; i<4; i++ ) // make 3 more rotations pp[i] = (pp[i-1]<<2)&0xFF | ((pp[i-1]&0xC0) >> 6); for ( int j = 0; j<3; j++ ) // set any duplicates to zero for ( int i = j+1; i<4; i++ ) if ( pp[i] == pp[j] ) { pp[j] = 0; n --; } if ( n == 4 ) // if there were no duplicates return pp; int[] ppp = new int[n]; // otherwise, make a shorter array for ( int i = 3; i>= 0; i-- ) if ( pp[i] != 0 ) ppp[--n] = pp[i]; return ppp; } private static void printMatches(PrintStream outstr, int p0, int level) // look for all patterns that have 2 bottom squares (i.e. 8 bits) matching p0 { int n = npat; int mcount = 0; // for counting number of further attempts while ( --n >= 0 ) // search for a matching pattern { int[] patn = pat[n]; if ( patn != null ) // if not used already { int m = patn.length; while ( --m >= 0 ) // look at all possible orientations if ( (patn[m]&0xF) == p0 ) // bottom two cells match { mcount ++; // outstr.println(level + " Matched " + p0%4 + ' ' + p0/4 + " at (" + n + ',' + m + ')'); pat[n] = null; // mark this pattern as used int pm = patn[m]; soln[level] = pm; // remember the one that we chose if ( corner[level] ) // if we are at a corner, we must ... pm = (pm<<2) & 0xFF; // ... look at the LH side of the pattern not the top printMatches(outstr, (pm>>6) + ((pm&0x30)>>2), level + 1); pat[n] = patn; // put back the pattern that we used so that other tests can use it } } } if ( mcount == 0 && level > npat && p0 == seed ) { solnCount ++; // we have used all patterns and the two ends match if ( verbose || ((solnCount-1)&solnCount) == 0 ) // verbose or count is a power of 2 { for ( int i = 1; i> 2; } outstr.println(); } outstr.println(solnCount + " solutions so far"); } } } public static void main(String[] args) { PrintStream outstr = System.out; try { int i0, i1, i2, i3, p0, p1, p2, p3; npat = 0; // first compute all possible patterns for ( i0 = 1; i0<4; i0++ ) { p0 = i0; for ( i1 = 1; i1<4; i1++ ) { p1 = 4*i1 + p0; for ( i2 = 1; i2<4; i2++ ) { p2 = 16*i2 + p1; for ( i3 = 1; i3<4; i3++ ) { p3 = 64*i3 + p2; if ( unique(p3) ) pat[npat++] = newpat(p3); } } } } // print out a list of patterns outstr.println(npat + " patterns"); i0 = npat; while ( --i0 >= 0 ) { int p = pat[i0][0]; outstr.print(i0 + ": "); while ( p != 0 ) { outstr.print( (p&3) + " " ); p = p >> 2; } for ( int i = 1; i> 2; } } outstr.println(" " + pat[i0].length + " rotations"); } // Now look for solutions seed = Integer.parseInt(args[0]); // initial half pattern if ( seed < 0 ) // crude way to specify not verbose { seed = -seed; verbose = false; } i1 = Integer.parseInt(args[1]); // length of one side i2 = Integer.parseInt(args[2]); // length of the other side soln = new int[npat+1]; corner = new boolean[npat+1]; // mark the position of the corners corner[i1] = true; corner[i1+i2] = true; corner[i1+i1+i2] = true; corner[i1+i1+i2+i2] = true; printMatches(outstr, seed, 1); // make it all happen outstr.println(); outstr.println(solnCount + " solutions"); } catch(Throwable x) { x.printStackTrace(); } } }