/* * */ package unholeycounters; /** * * @author mason */ public class UnholeyCounters { /** * @param args the command line arguments */ public static void main(String[] args) { long startTime = System.currentTimeMillis(); new Runner(args); long endTime = System.currentTimeMillis(); long elapsedTime = (endTime - startTime) / 1000; System.err.println("Elapsed " + elapsedTime); } } package unholeycounters; /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ /* * @author mason */ public class Runner { /** * @param args the command line arguments */ public Runner(String[] args) { if (args.length < 2) usage("too few arguments"); run(args); } void run(String args[]) { int n; if ((n = testCMD(args[0],"countEnew")) > 0) { String in = args[0].substring(n); Counter counter = new CounterLetterECentreFull( in); counter.run(); } else if ((n = testCMD(args[0],"countallccf")) > 0) { String in = args[0].substring(n); Counter counter = new CounterAllCCentreFull( in); counter.run(); } else if ((n = testCMD(args[0],"countr90ccf")) > 0) { String in = args[0].substring(n); Counter counter = new CounterR90CCentreFull( in); counter.run(); } else if ((n = testCMD(args[0],"countr180cf")) > 0) { String in = args[0].substring(n); Counter counter = new CounterR180CentreFull( in); counter.run(); } else if ((n = testCMD(args[0],"countm90c")) > 0) { String in = args[0].substring(n); Counter counter = new CounterM90C( in); counter.run(); } else if ((n = testCMD(args[0],"countm90v")) > 0) { String in = args[0].substring(n); Counter counter = new CounterM90V( in); counter.run(); } else if ((n = testCMD(args[0],"count2m90v")) > 0) { String in = args[0].substring(n); Counter counter = new Counter2M90VCentreFull( in); counter.run(); } else if ((n = testCMD(args[0],"countr90vcf")) > 0) { String in = args[0].substring(n); Counter counter = new CounterR90VCentreFull( in); counter.run(); } else if ((n = testCMD(args[0],"countallvcf")) > 0) { String in = args[0].substring(n); Counter counter = new CounterAllVCentreFull( in); counter.run(); } else if ((n = testCMD(args[0],"countdomino")) > 0) { String in = args[0].substring(n); Counter counter = new CountDominoCentre2M90( in); counter.run(); } else if ((n = testCMD(args[0],"countm45")) > 0) { String in = args[0].substring(n); Counter counter = new CounterM45( in); counter.run(); } else usage("unknown first parameter"); } int testCMD(String arg, String cmd) { if (arg.equals(cmd)) return arg.length(); if (arg.startsWith(cmd + ":")) return cmd.length() + 1; return 0; } void usage(String error) { System.err.println(error); System.exit(1); } public static void printArgs(String place, String args[]) { String cmd = ""; for (int i = 0 ; i < args.length ; i++) cmd += args[i] + " "; System.err.println(place + " : " + cmd); } public static void notImplemented(String place) { System.err.println(place + " not implemented"); System.exit(1); } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author mason * used in more recent counting filters; lists possible new squares. * offers exclusion from list * may have a position with respect to the origin distinct from associated polyomino */ public class InclusionListF { public int[][] coordArray; //public int[] valueArray; int board[][]; int baseX , baseY ; public InclusionListF(int board[][], int baseX , int baseY ) { this.board = board; coordArray = new int[128][2]; //valueArray = new int[128]; this.baseX = baseX; this.baseY = baseY; } public int add(int x, int y, int currSize) { this.coordArray[currSize][0] = x; this.coordArray[currSize][1] = y; //System.err.println("add " + x + " " + y + " -1" ); board[baseX + x][baseY + y] = -1; return currSize + 1; } public int getX(int i) { return coordArray[i][0]; } public int getY(int i) { return coordArray[i][1]; } public int indexOf(int x, int y, int currSize) { for (int i = 0 ; i < currSize; i++) if (coordArray[i][0] == x && coordArray[i][1] == y) return i; return -1; } public String toString(int currSize) { String ret = // history + ""; for (int i = 0; i < currSize ; i++) { ret += coordArray[i][0] + "/" + coordArray[i][1] + " "; } return ret; } public InclusionListF sort(int start, int end) { InclusionListF newIncl = new InclusionListF(board, baseX, baseY); int[] tmpx, tmpy, tmpc; //tmpx = new int[end]; //tmpy = new int[end]; tmpc = new int[end]; for (int i = 0; i < end ; i++) { newIncl.coordArray[i][0] = this.coordArray[i][0]; newIncl.coordArray[i][1] = this.coordArray[i][1]; } boolean flag = true; for (int k = start; k < end - 1; k++) { tmpc[k] = countNear(coordArray[k][0], coordArray[k][1]); } while (flag) { flag = false; for (int k = start; k < end - 1; k++) { if (tmpc[k] < tmpc[k + 1]) { int tmpx1 = coordArray[k][0]; int tmpy1 = coordArray[k][1]; int tmpc1 = tmpc[k]; coordArray[k][0] = coordArray[k + 1][0]; coordArray[k][1] = coordArray[k + 1][1]; tmpc[k] = tmpc[k + 1]; coordArray[k + 1][0] = tmpx1; coordArray[k + 1][1] = tmpy1; tmpc[k + 1] = tmpc1; flag = true; } } } return newIncl; } int countNear(int x, int y) { int ret = 0; ret += countNear(x, y, 1, 0); ret += countNear(x, y, -1, 0); ret += countNear(x, y, 0, 1); ret += countNear(x, y, 0, -1); return ret; } int countNear(int x, int y, int dx, int dy) { if (content(x + dx, y + dy) >= 1) return 1; else return 0; } int content( int x, int y) { return board[baseX + x][baseY + y]; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author mason * used to analyze parameters passed to filters */ public class ParameterAnalyzer { String resultsParameters[]; String resultValues[]; String rules[]; int number = 0; public ParameterAnalyzer(String input, String rules[]) { this.rules = rules; resultsParameters = new String[rules.length]; resultValues = new String[rules.length]; while (input.length() > 0) input = doOne(input); } String doOne(String input) { int n = input.indexOf(","); String param = input; if (n >= 0) { param = input.substring(0, n); input = input.substring(n + 1); } else input = ""; int m = param.indexOf("="); if (m < 0) { System.err.println("erroneous \"" + param + "\""); System.exit(1); } String paramName = param.substring(0, m); String paramValue = param.substring(m + 1); for (int i = 0; i < rules.length ; i++) { if (paramName.equals(rules[i])) { resultsParameters[number] = paramName; resultValues[number] = paramValue; number++; return input; } } System.err.println("erroneous \"" + paramName + "\""); String list = ""; for (int i = 0; i < rules.length ; i++) { list += rules[i] + " "; } System.err.println("looking for one of " + list); System.exit(1); return null; } public String getStringValue(String paramName) { for (int i = 0 ; i < number; i++) { if (paramName.equals(this.resultsParameters[i])) return this.resultValues[i]; } return null; } public String getStringValue(String paramName, boolean obligatory) { for (int i = 0 ; i < number; i++) { if (paramName.equals(this.resultsParameters[i])) return this.resultValues[i]; } if (obligatory) { System.err.println("missing " + paramName); System.exit(1); } return null; } public int getIntValue(String paramName, int def) { String t = getStringValue(paramName); if (t == null) return def; return Integer.parseInt(t); } public double getDoubleValue(String paramName, double def) { String t = getStringValue(paramName); if (t == null) return def; return Double.parseDouble(t); } public int getIntValue(String paramName) { String t = getStringValue(paramName); if (t == null) { System.err.println("missing " + paramName); System.exit(1); } return Integer.parseInt(t); } public long getLongValue(String paramName, long def) { String t = getStringValue(paramName); if (t == null) { return def; } return Long.parseLong(t); } public boolean getBooleanValue(String paramName) { String t = getStringValue(paramName); if (t == null || t.equals("false")) return false; if (t.equals("true")) return true; System.err.println("erroneous " + t); System.exit(1); return false; } public boolean getBooleanValue(String paramName, boolean def) { String t = getStringValue(paramName); if (t == null) return def; if (t.equals("false")) return false; if (t.equals("true")) return true; System.err.println("erroneous " + t); System.exit(1); return false; } public Boolean getTrooleanValue(String paramName, boolean obbli) { Boolean ret = getTrooleanValue( paramName); if (ret == null && obbli) { System.err.println("missing " + paramName); System.exit(1); } return ret; } public Boolean getTrooleanValue(String paramName) { String t = getStringValue(paramName); if (t == null) return null; if (t.equals("false")) return Boolean.FALSE; if (t.equals("true")) return Boolean.TRUE; System.err.println("erroneous " + t); System.exit(1); return false; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * location 1,1 is the top half of the domino. * we put on the board only locations with x>=1 and y>=1 * Any location with x and y > 1 corresponds to 3 other virtual locations * Any locations with x = 1 corresponds to 1 other virtual location * */ public class CountDominoCentre2M90 extends CounterBase { public CountDominoCentre2M90( String params) { super(params); } void printResults() { for (int i = 1 ; i <= targetSize; i++) System.out.println(i + " " + counter2[i]); } public void run() { counter2 = new long[targetSize + 1]; root[0][0] = 1; root[0][1] = 1; incl.add( 1, 2, 0); incl.add( 2, 1, 1); setHit(1, 1, 1); // horrible force counter[2]=1; counter2[2]=1; recurse2(1, 2, 1, 1, 1, 1, 2, 0, 1); printResults(); //endFun(); } boolean useThese(int x, int y, int effectiveSize) { if ((x > 1) && (effectiveSize + 4 > targetSize)) return false; return true; } int getNewEffectiveSize(int x, int y, int effectiveSize) { int newEffectiveSize; if (x == 1) { newEffectiveSize = effectiveSize + 2; } else { newEffectiveSize = effectiveSize + 4; } return newEffectiveSize; } boolean symmetryOK(int newPolySize, int newMinX, int newMaxX, int newMinY, int newMaxY) { return true; } boolean proposeThese(int nx, int ny, int newEffectiveSize) { if ((nx > 1) && (newEffectiveSize > targetSize - 1)) return false; if (nx < 1 || ny < 1) return false; return true; } int getHoleyMultiplier(int x, int y) { if (x != 1) return 4; else return 2; } boolean containsSpecific(int x, int y) { if (x < 1) x = -x + 2; if (y < 1) y = -y + 1; return contains(x, y); } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * * */ public abstract class Counter { ParameterAnalyzer pa; int targetSize, distance, targetPerimeter; long counter[], counter2[], counter3[], counter4[]; int board[][]; int width, widthm1; InclusionListF incl; int hitList[][]; int[][] root; String starterSize; boolean divFlag, noSymFlag, debug, squareFlag, drawFlag, repFlag, terminalFlag, treeFlag, w4cat, unholey; int baseX = 100, baseY = 100; int[] deltaX = {0, 0, 1, -1}; int[] deltaY = {1, -1, 0, 0}; int deltaSize = 4; int[] delta3X = {-1, 1, 0, -1, 1, 0}; int[] delta3Y = {0, 0, -1, 0, 0, 1}; int[] termX = { -1, -2, -1 , 0, 1, 2, 1, 0}; int[] termY = { -1, 0, 1, 2, 1, 0, -1, -2 }; public Counter( String params) { String[] rules = new String[] {"size", "only", "prefix", "start", "restart", "stopat", "startersize", "div", "rep", "tree", "draw", "repeat", "nosym", "debug", "square", "terminal", "distance", "width", "w4cat", "perimeter" , "unholey"}; pa = new ParameterAnalyzer(params , rules); targetSize = pa.getIntValue("size", 0); targetPerimeter = pa.getIntValue("perimeter", 0); distance = pa.getIntValue("distance", 0); counter = new long[targetSize + 1]; starterSize = pa.getStringValue("startersize", false); unholey = pa.getBooleanValue("unholey"); repFlag = pa.getBooleanValue("rep"); treeFlag = pa.getBooleanValue("tree"); drawFlag = pa.getBooleanValue("draw"); debug = pa.getBooleanValue("debug"); w4cat = pa.getBooleanValue("w4cat"); divFlag = pa.getBooleanValue("div"); noSymFlag = pa.getBooleanValue("nosym"); squareFlag = pa.getBooleanValue("square"); terminalFlag = pa.getBooleanValue("terminal"); width = pa.getIntValue("width", 3); widthm1 = width - 1; arrayStart(); // run(); } void arrayStart() { board = new int[200][200]; root = new int[200][2]; hitList = new int[200][2]; incl = new InclusionListF(board, baseX, baseY); } public abstract void run(); //abstract void printResults(); String cString(int size) { String ret = ""; for (int j = 0 ; j < size; j++) { ret += root[j][0] + "," + root[j][1] + ";"; } return ret; } boolean contains( int x, int y) { boolean newRet = false; if (content(x, y) >= 1) newRet = true; return newRet; } int content( int x, int y) { return board[baseX + x][baseY + y]; } boolean empty(int x, int y) { int c = content(x, y); if (c == 0) return true; return false; } boolean matches(int x1, int y1, int x2, int y2) { return content(x1, y1) == content(x2, y2); } public boolean testMirrorH(int polySize, int minY, int maxY) { for (int i = 0 ; i < polySize; i++) { int x = root[i][0], y = root[i][1]; int oppY = maxY - (y - minY); if (!matches(x, y, x, oppY)) return false; } return true; } public boolean testMirrorHnew(int polySize, int minY, int maxY) { for (int i = 0 ; i < polySize; i++) { int x = root[i][0], y = root[i][1]; int oppY = maxY - (y - minY); if (!containsSpecific( x, oppY)) return false; } return true; } boolean containsSpecific(int x, int y) { return contains(x, y); } public boolean testMirrorV(int polySize, int minX, int maxX) { for (int i = polySize - 1; i >= 0 ; i--) { // for (int i = 0 ; i < polySize; i++) { int x = root[i][0], y = root[i][1]; int oppX = maxX - (x - minX); if (!matches(x, y, oppX, y)) return false; } return true; } boolean testRotate90(int polySize, int minX, int minY, int maxX, int maxY) { for (int i = polySize - 1; i >= 0 ; i--) { // for (int i = 0 ; i < polySize; i++) { int x = root[i][0], y = root[i][1]; if (!matches(x, y, y - minY + minX, maxY - (x - minX))) return false; } return true; } boolean testRotate180(int polySize, int minX, int minY, int maxX, int maxY) { for (int i = polySize - 1; i >= 0 ; i--) { // for (int i = 0 ; i < polySize; i++) { int x = root[i][0], y = root[i][1]; if (!matches(x, y, maxX - x + minX, maxY - y + minY )) return false; } return true; } boolean testMirrorSWNE(int polySize, int minX, int minY, int maxX, int maxY) { if (maxX - minX != maxY - minY) return false; for (int i = polySize - 1; i >= 0 ; i--) { // for (int i = 0 ; i < polySize; i++) { int x = root[i][0], y = root[i][1]; if (!matches(x, y, y - minY + minX , x - minX + minY )) return false; } return true; } public boolean testMirrorSENW(int polySize, int minX, int minY, int maxX, int maxY) { if (maxX - minX != maxY - minY) return false; for (int i = polySize - 1; i >= 0 ; i--) { // for (int i = 0 ; i < polySize; i++) { int x = root[i][0], y = root[i][1]; if (!matches(x, y, minY + maxX - y, maxX - x + minY)) return false; } return true; } void setHit( int x, int y, int v) { //System.err.println("set " + j + " " + x + " " + y + " " + v); if ( board[baseX + x][baseY + y] != 0) { int qq = 1 / 0; } board[baseX + x][baseY + y] = v; } void setRootAndHit(int pos, int x, int y) { //System.err.println("set " + j + " " + x + " " + y + " " + v); if ( board[baseX + x][baseY + y] == 1) { int qq = board[baseX + x][baseY + y]; qq /= 0; } root[pos][0] = x; root[pos][1] = y; board[baseX + x][baseY + y] = 1; } void setRootAndOveride(int pos, int x, int y, int v) { //System.err.println("set " + j + " " + x + " " + y + " " + v); if ( board[baseX + x][baseY + y] == 0) { int qq = 1 / 0; } root[pos][0] = x; root[pos][1] = y; board[baseX + x][baseY + y] = v; } void overideHit( int x, int y, int v) { //System.err.println("over " + j + " " + x + " " + y + " " + v); if ( board[baseX + x][baseY + y] == 0) { int qq = 1 / 0; } board[baseX + x][baseY + y] = v; } void eraseHit(int j) { int bx = baseX + hitList[j][0], by = baseY + hitList[j][1]; //System.err.println("clear " + j + " " + hitList[j][0] + " " + hitList[j][1] + " " + 0); if (board[bx][by] == 0) { int qq = 1 / 0; } board[bx][by] = 0; } void verifPoly(int polySize) { for (int i = 0; i < polySize; i++) { int x = root[i][0], y = root[i][1]; if (board[baseX + x][baseY + y] != 1) { int b = board[baseX + x][baseY + y]; int qq = 1 / 0; } } for (int x = -30; x < 30 ; x++) for (int y = -30; y < 30 ; y++) { if (board[baseX + x][baseY + y] == 1) { if (!contains( x, y)) { int qq = 1 / 0; } } } } int countNear(int x, int y) { int ret = 0; ret += countNear(x, y, 1, 0); ret += countNear(x, y, -1, 0); ret += countNear(x, y, 0, 1); ret += countNear(x, y, 0, -1); return ret; } int countNear(int x, int y, int dx, int dy) { if (content(x + dx, y + dy) >= 1) return 1; else return 0; } long div(long a , long b) { if (a % b != 0) { System.err.println("a=" + a + " b=" + b); int qq = 1 / 0; } return a / b; } boolean isHoley(int size) { // H = n + 1 - i - s / 2 long sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0; for (int i = 0 ; i < size ; i++) { int x = root[i][0], y = root[i][1]; int n = calculateAdjacent(x, y, x - 1, y - 1, x, y - 1, x - 1, y); switch (n) { case 1: sum1++; break; case 2: sum2++; break; case 3: sum3++; break; case 4: sum4++; break; } n = calculateAdjacent(x, y, x + 1, y - 1, x, y - 1, x + 1, y); switch (n) { case 1: sum1++; break; case 2: sum2++; break; case 3: sum3++; break; case 4: sum4++; break; } n = calculateAdjacent(x, y, x - 1, y + 1, x, y + 1, x - 1, y); switch (n) { case 1: sum1++; break; case 2: sum2++; break; case 3: sum3++; break; case 4: sum4++; break; } n = calculateAdjacent(x, y, x + 1, y + 1, x, y + 1, x + 1, y); switch (n) { case 1: sum1++; break; case 2: sum2++; break; case 3: sum3++; break; case 4: sum4++; break; } } sum2 = div(sum2, 2); sum3 = div(sum3, 3); sum4 = div(sum4, 4); long h = size + 1 - sum4 - div(sum1 + sum2 + sum3, 2) ; if (h > 0) return true; return false; } int calculateAdjacent(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) { int ret = 0; boolean b1 = contains(x1, y1); boolean b2 = contains(x2, y2); boolean b3 = contains(x3, y3); boolean b4 = contains(x4, y4); if (b1) ret++; if (b2) ret++; if (b3) ret++; if (b4) ret++; if (ret == 2) { if (b1 && b2) ret = 0; if (b3 && b4) ret = 0; } return ret; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * * */ public class Counter2M90VCentreFull extends CounterBase { public Counter2M90VCentreFull( String params) { super( params); } void printResults() { printResults(2); } public void run() { counter2 = new long[targetSize + 1]; int currInclSize = incl.add(1, 1, 0); recurse2(0, 0, 1, 1, 1, 1, currInclSize, 0, 0); printResults(); } boolean useThese(int x, int y, int effectiveSize) { if (x < 1 || y < 1) { int qq = 1 /0; } if ((effectiveSize + 4 > targetSize)) return false; return true; } int getNewEffectiveSize(int x, int y, int effectiveSize) { int newEffectiveSize; if (x == 1 && y == 1) { newEffectiveSize = 4; } else { newEffectiveSize = effectiveSize + 4; } return newEffectiveSize; } boolean symmetryOK(int newPolySize, int newMinX, int newMaxX, int newMinY, int newMaxY) { return !testMirrorSWNE(newPolySize, newMinX, newMinY, newMaxX, newMaxY); } boolean proposeThese(int nx, int ny, int newEffectiveSize) { if ((newEffectiveSize > targetSize - 4)) return false; if (nx < 1 || ny < 1) { return false; } return true; } int getHoleyMultiplier(int x, int y) { return 4; } boolean containsSpecific(int x, int y) { int tx = x, ty = y; if (x < 1 ) { tx = flip(x); } if (y < 1) { ty = flip(y); } boolean ret; ret = contains(tx, ty); if (debug) System.err.println(x + "," + y + " = " + ret); return ret; } int flip(int z) { return -z + 1; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * * */ public class CounterAllCCentreFull extends CounterBase { public CounterAllCCentreFull( String params) { super(params); } void printResults() { printResults(1); } public void run() { counter2 = new long[targetSize + 1]; int currInclSize = incl.add(1, 1, 0); recurse2(0, 0, 1, 1, 1, 1, currInclSize, 0, 0); printResults(); } boolean useThese(int x, int y, int effectiveSize) { if (x < 1 || y < 1) { int qq = 1 /0; } if ((x > 1 && y > 1 && x != y) && (effectiveSize + 8 > targetSize)) return false; if ((effectiveSize + 4 > targetSize)) return false; return true; } int getNewEffectiveSize(int x, int y, int effectiveSize) { int newEffectiveSize; if (x == 1 && y == 1) { newEffectiveSize = effectiveSize + 1; } else if (x == 1 || y == 1 || x == y) { newEffectiveSize = effectiveSize + 4; } else { newEffectiveSize = effectiveSize + 8; } return newEffectiveSize; } boolean symmetryOK(int newPolySize, int newMinX, int newMaxX, int newMinY, int newMaxY) { return true; } boolean proposeThese(int nx, int ny, int newEffectiveSize) { if ((nx > 1 && ny > 1 && nx != ny) && (newEffectiveSize > targetSize - 8)) return false; if ((newEffectiveSize > targetSize - 4)) return false; if (nx < 1 || ny < 1 || ny > nx) return false; return true; } int getHoleyMultiplier(int x, int y) { int multiplier = 1; if (x != 1 && y != 1 && x != y) { multiplier = 8; } else if (x == 1 && y == 1) { // noop } else { multiplier = 4; } return multiplier; } boolean containsSpecific(int x, int y) { if (x < 1) x = flip(x); if (y < 1) y = flip(y); boolean ret; if (y > x) ret = contains(y, x); else ret = contains(x, y); if (debug) System.err.println(x + "," + y + " = " + ret); return ret; } int flip(int z) { return -z + 2; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * * */ public class CounterAllVCentreFull extends CounterBase { public CounterAllVCentreFull(String params) { super( params); } void printResults() { printResults(1); } public void run() { counter2 = new long[targetSize + 1]; int currInclSize = incl.add(1, 1, 0); recurse2(0, 0, 1, 1, 1, 1, currInclSize, 0, 0); printResults(); } boolean useThese(int x, int y, int effectiveSize) { if (x < 1 || y < 1) { int qq = 1 /0; } if ((x > 1 && y > 1 && x != y) && (effectiveSize + 8 > targetSize)) return false; if ((effectiveSize + 4 > targetSize)) return false; return true; } int getNewEffectiveSize(int x, int y, int effectiveSize) { int newEffectiveSize; if (x == 1 && y == 1) { newEffectiveSize = 4; } else if (x == y) { newEffectiveSize = effectiveSize + 4; } else { newEffectiveSize = effectiveSize + 8; } return newEffectiveSize; } boolean symmetryOK(int newPolySize, int newMinX, int newMaxX, int newMinY, int newMaxY) { return true; } boolean proposeThese(int nx, int ny, int newEffectiveSize) { if ((nx != ny) && (newEffectiveSize > targetSize - 8)) return false; if ((newEffectiveSize > targetSize - 4)) return false; if (nx < 1 || ny < 1 || ny > nx) return false; return true; } int getHoleyMultiplier(int x, int y) { int multiplier = 4; if (x != y) { multiplier = 8; } return multiplier; } boolean containsSpecific(int x, int y) { if (x < 1) x = flip(x); if (y < 1) y = flip(y); boolean ret; if (y > x) ret = contains(y, x); else ret = contains(x, y); if (debug) System.err.println(x + "," + y + " = " + ret); return ret; } int flip(int z) { return -z + 1; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * * */ public abstract class CounterBase extends CounterWithMultipleCopies { public CounterBase( String params) { super( params); } abstract boolean useThese(int x, int y, int effectiveSize); abstract int getNewEffectiveSize(int x, int y, int effectiveSize); abstract boolean symmetryOK(int newPolySize, int newMinX, int newMaxX, int newMinY, int newMaxY); abstract boolean proposeThese(int nx, int ny, int newEffectiveSize); void recurse2(int currPolySize, int effectiveSize, int minX, int maxX, int minY, int maxY, int currInclSize, int startPos, int hitListSize) { /* effectiveSize should not be greater than targetSize but for some reason, in CounterAllVCentreFull thsi happens if (effectiveSize > this.targetSize) { int qq = 1 / 0; } */ if (effectiveSize >= this.targetSize) return; int newInclSize = currInclSize; int newMaxY = maxY, newMinY = minY; int newMaxX = maxX, newMinX = minX; int newPolySize = currPolySize + 1; for (int i = startPos; i < currInclSize ; i++) { int x = incl.getX(i), y = incl.getY(i) ; if (!useThese(x, y, effectiveSize)) continue; if (y > newMaxY) newMaxY = y; if (y < newMinY) { newMinY = y; } if (x > newMaxX) newMaxX = x; if (x < newMinX) { newMinX = x; } root[currPolySize][0] = x; root[currPolySize][1] = y; int newHitListSize = hitListSize ; overideHit( x, y, 1); int newEffectiveSize = getNewEffectiveSize(x, y, effectiveSize); if (newEffectiveSize <= targetSize) { if (symmetryOK(newPolySize, newMinX, newMaxX, newMinY, newMaxY)) { if (!unholey || !isHoleySpecific(newPolySize, newEffectiveSize)) counter2[newEffectiveSize]++; counter[newEffectiveSize]++; } else { // noop } } for (int j = 0; j < 4 ; j++) { int dx = deltaX[j], dy = deltaY[j]; int nx = x + dx; int ny = y + dy; if (!proposeThese(nx, ny, newEffectiveSize)) continue; if (empty( nx, ny)) { newInclSize = incl.add( nx, ny , newInclSize) ; hitList[newHitListSize][0] = nx; hitList[newHitListSize][1] = ny; newHitListSize++; } } recurse2( newPolySize, newEffectiveSize, newMinX, newMaxX, newMinY, newMaxY, newInclSize, i + 1, newHitListSize); for (int j = hitListSize ; j < newHitListSize; j++) { eraseHit(j); } overideHit( x, y, -1); recurse2(currPolySize, effectiveSize, minX, maxX, minY, maxY, currInclSize, i + 1, hitListSize + 1); break; } } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author mason */ public abstract class CounterCommon extends Counter { public CounterCommon(String params) { super( params); } void printResults(int divisor) { for (int i = 1 ; i <= targetSize; i++) { if (unholey) System.out.println(i + " " + div(counter2[i] , divisor) ); else System.out.println(i + " " + div(counter[i] , divisor) ); } } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * This counts letter E but only those with 1,1 full * */ public class CounterLetterECentreFull extends CounterBase { public CounterLetterECentreFull( String params) { super( params); } void printResults() { printResults(2); } public void run() { counter2 = new long[targetSize + 1]; int currInclSize = incl.add(1, 1, 0); recurse2(0, 0, 1, 1, 1, 1, currInclSize, 0, 0); printResults(); } boolean useThese(int x, int y, int effectiveSize) { if (x < 1 || y < 1) { int qq = 1 /0; } if ((x > 1 && y > 1) && (effectiveSize + 4 > targetSize)) return false; if ((effectiveSize + 2 > targetSize)) return false; return true; } int getNewEffectiveSize(int x, int y, int effectiveSize) { int newEffectiveSize; if (x == 1 && y == 1) { newEffectiveSize = effectiveSize + 1; } else if (x == 1 || y == 1) { newEffectiveSize = effectiveSize + 2; } else { newEffectiveSize = effectiveSize + 4; } return newEffectiveSize; } boolean symmetryOK(int newPolySize, int newMinX, int newMaxX, int newMinY, int newMaxY) { return !testMirrorSWNE(newPolySize, newMinX, newMinY, newMaxX, newMaxY); } boolean proposeThese(int nx, int ny, int newEffectiveSize) { if ((nx > 1 && ny > 1) && (newEffectiveSize > targetSize - 4)) return false; if ((newEffectiveSize > targetSize - 2)) return false; if (nx < 1 || ny < 1) return false; return true; } int getHoleyMultiplier(int x, int y) { int multiplier = 1; if (x != 1 && y != 1) { multiplier = 4; } else if (x == 1 && y == 1) { // noop } else multiplier = 2; return multiplier; } boolean containsSpecific(int x, int y) { if (x < 1) x = -x + 2; if (y < 1) y = -y + 2; return contains(x, y); } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * * */ public class CounterM45 extends CounterWithMultipleCopies { public CounterM45( String params) { super( params); } void initLocalData() { } void printResults() { for (int i = 1 ; i <= targetSize; i++) { if (this.unholey) System.out.println(i + ";" + div(counter2[i] , 2) + ";" + div(counter3[i] , 2) + ";" + div(counter4[i] , 2)); else System.out.println(div(counter[i] , 2)); } } public void run() { counter2 = new long[targetSize + 1]; counter3 = new long[targetSize + 1]; counter4 = new long[targetSize + 1]; root[0][0] = 1; root[0][1] = 1; incl.add( 2, 1, 0); incl.add( 1, 0, 1); setHit(1, 1, 1); recurse2(1, 1, 1, 1, 1, 1, 2, 0, 2); printResults(); } void recurse2(int currPolySize, int effectiveSize, int minX, int maxX, int minY, int maxY, int currInclSize, int startPos, int hitListSize) { //String dbg = currentPoly.drawing(); if (effectiveSize > this.targetSize) { int qq = 1 / 0; } if (effectiveSize >= this.targetSize) return; int newInclSize = currInclSize; //long newExcluded1 = excluded1, newExcluded2 = excluded2; int newMaxX = maxX, newMinX = minX; int newMaxY = maxY, newMinY = minY; int newPolySize = currPolySize + 1; //incl.verify2(currentPoly); //incl.verifDupl(currInclSize); for (int i = startPos; i < currInclSize ; i++) { int x = incl.getX(i), y = incl.getY(i) ; if (x == y && y < 1) { int qq = 1 /0; } if ((x > y) && (effectiveSize + 2 > targetSize)) continue; if (y > newMaxY) newMaxY = y; if (y < newMinY) { newMinY = y; } if (x > newMaxX) newMaxX = x; if (x < newMinX) { newMinX = x; } root[currPolySize][0] = x; root[currPolySize][1] = y; int newHitListSize = hitListSize ; overideHit( x, y, 1); int newEffectiveSize; if (x == y) { newEffectiveSize = effectiveSize + 1; } else { newEffectiveSize = effectiveSize + 2; } if (newEffectiveSize <= targetSize) { if (!testMirrorSENW(newPolySize, newMinX, newMinY, newMaxX, newMaxY)) { if (this.unholey && !isHoleySpecific(newPolySize, newEffectiveSize)) counter2[newEffectiveSize]++; counter[newEffectiveSize]++; } else if (this.unholey && !isHoleySpecific(newPolySize, newEffectiveSize)) { boolean fH = testMirrorHnew(newPolySize, newMinY, newMaxX); // maxY forced according to maxX if (!fH ) { if (newEffectiveSize % 2 == 1) counter3[newEffectiveSize]++; else counter4[newEffectiveSize]++; //System.out.println(gen(newPolySize, newMinX, newMinY).drawing()); } } } //newInclSize = increase(newPolySize, x, y, newEffectiveSize, newInclSize); for (int j = 0; j < 4 ; j++) { int dx = deltaX[j], dy = deltaY[j]; int nx = x + dx; int ny = y + dy; if ((nx > ny) && (newEffectiveSize > targetSize - 1)) continue; if (nx == ny && ny < 1) continue; if (nx >= ny) { if (empty( nx, ny)) { newInclSize = incl.add( nx, ny , newInclSize) ; hitList[newHitListSize][0] = nx; hitList[newHitListSize][1] = ny; newHitListSize++; } } } recurse2( newPolySize, newEffectiveSize, newMinX, newMaxX, newMinY, newMaxY, newInclSize, i + 1, newHitListSize); for (int j = hitListSize ; j < newHitListSize; j++) { eraseHit(j); } overideHit( x, y, -1); recurse2(currPolySize, effectiveSize, minX, maxX, minY, maxY, currInclSize, i + 1, hitListSize + 1); break; } } boolean containsSpecific(int x, int y) { if (x >= y) return contains(x, y); else return contains(y, x); } int getHoleyMultiplier(int x, int y) { if (x == y) return 1; else return 2; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * * */ public class CounterM90C extends CounterBase { public CounterM90C( String params) { super( params); } void printResults() { printResults(2); } public void run() { counter2 = new long[targetSize + 1]; counter3 = new long[targetSize + 1]; counter4 = new long[targetSize + 1]; root[0][0] = 1; root[0][1] = 1; //board[baseX + 1][baseY + 1] = 1; setHit(1, 1, 1); incl.add( 2, 1, 0); incl.add( 1, 2, 1); recurse2(1, 1, 1, 1, 1, 1, 2, 0, 2); printResults(); } boolean useThese(int x, int y, int effectiveSize) { if (x == 1 && y < 1) { int qq = 1 /0; } if ((x > 1) && (effectiveSize + 2 > targetSize)) return false; return true; } int getNewEffectiveSize(int x, int y, int effectiveSize) { int newEffectiveSize; if (x == 1) { newEffectiveSize = effectiveSize + 1; } else { newEffectiveSize = effectiveSize + 2; } return newEffectiveSize; } boolean symmetryOK(int newPolySize, int newMinX, int newMaxX, int newMinY, int newMaxY) { return !testMirrorH(newPolySize, newMinY, newMaxY); } boolean proposeThese(int nx, int ny, int newEffectiveSize) { if ((nx > 1) && (newEffectiveSize > targetSize - 1)) return false; if (nx == 1 && ny < 1) return false; if (nx >= 1) return true; return false; } int getHoleyMultiplier(int x, int y) { int multiplier = 1; if (x != 1) multiplier = 2; return multiplier; } boolean containsSpecific(int x, int y) { if (x < 1) x = flip(x); boolean ret; ret = contains(x, y); if (debug) System.err.println(x + "," + y + " = " + ret); return ret; } int flip(int z) { return -z + 2; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * * */ public class CounterM90V extends CounterBase { public CounterM90V( String params) { super( params); } void printResults() { printResults(2); } public void run() { counter2 = new long[targetSize + 1]; root[0][0] = 1; root[0][1] = 1; //board[baseX + 1][baseY + 1] = 1; setHit(1, 1, 1); incl.add( 2, 1, 0); incl.add( 1, 2, 1); recurse2(1, 2, 1, 1, 1, 1, 2, 0, 2); printResults(); } boolean useThese(int x, int y, int effectiveSize) { if (x == 1 && y < 1) { int qq = 1 /0; } return true; } int getNewEffectiveSize(int x, int y, int effectiveSize) { return effectiveSize + 2; } boolean symmetryOK(int newPolySize, int newMinX, int newMaxX, int newMinY, int newMaxY) { return !testMirrorH(newPolySize, newMinY, newMaxY); } boolean proposeThese(int nx, int ny, int newEffectiveSize) { if (nx == 1 && ny < 1) return false; if (nx >= 1) return true; return false; } int getHoleyMultiplier(int x, int y) { int multiplier = 2; return multiplier; } boolean containsSpecific(int x, int y) { if (x < 1) x = flip(x); boolean ret; ret = contains(x, y); if (debug) System.err.println(x + "," + y + " = " + ret); return ret; } int flip(int z) { return -z + 1; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * */ public class CounterR180CentreFull extends Counter { boolean loopR90 = true, domino = false; //Propagator prop; public CounterR180CentreFull( String params) { super( params); } public void setDebug() { debug = true; } public void run() { if (starterSize.equals("1x1")) { loopR90 = true; } else if (starterSize.equals("2x1")) { loopR90 = false; domino = true; } else if (starterSize.equals("2x2")) { loopR90 = true; } else { System.err.println("bad starter size"); System.exit(1); } outerGrowth(); printResults(); } void printResults() { int divc = 0; if (!loopR90) { divc = 2; } else { divc = 4; } for (int i = 1; i <= targetSize; i++) System.out.println(i + " " + div(counter[i], divc)); } long div(long c, long d) { if (c == 0 && d == 0) return 0; if (c % d != 0) { System.err.println("c=" + c + ",d=" + d); int qq = 1 / 0; } return c / d; } void verify(boolean b) { if (!b) { int qq = 1 / 0; } } void outerGrowth() { if (starterSize.equals("1x1")) { incl.add(1, 2, 0); incl.add(2, 1, 1); setHit(0, 1, -1); setHit(1, 0, -1); root[0][0] = 1; root[0][1] = 1; setHit( 1, 1, 1); recurse2(2, 1, 1, 1, 1, 1, 0, 2); } else if (starterSize.equals("2x2")) { incl.add(0, 2, 0); incl.add(1, 3, 1); incl.add(2, 3, 2); incl.add(3, 2, 3); setHit(0, 1, -1); setHit(1, 0, -1); setHit(2, 0, -1); setHit(3, 1, -1); root[0][0] = 1; root[0][1] = 1; root[1][0] = 1; root[1][1] = 2; root[2][0] = 2; root[2][1] = 1; root[3][0] = 2; root[3][1] = 2; setHit( 1, 1, 1); setHit( 1, 2, 1); setHit( 2, 1, 1); setHit( 2, 2, 1); recurse2(4, 4, 1, 1, 2, 2, 0, 4); } else if (starterSize.equals("2x1")) { incl.add(1, 2, 0); incl.add(2, 2, 1); incl.add(3, 1, 2); setHit(0, 1, -1); setHit(1, 0, -1); setHit(2, 0, -1); root[0][0] = 1; root[0][1] = 1; root[1][0] = 2; root[1][1] = 1; setHit( 1, 1, 1); setHit( 2, 1, 1); recurse2(3, 2, 1, 1, 2, 1, 0, 3); } else { System.err.println("wrong starter size"); System.exit(1); } } void recurse2(int currInclSize, int currPolySize, int minX, int minY, int maxX, int maxY, int startPos, int hitListSize) { //verifPoly(currPolySize); int newMinX = minX, newMinY = minY, newMaxX = maxX, newMaxY = maxY; if (currPolySize >= this.targetSize) return; for (int i = startPos; i < currInclSize ; i++) { int x = incl.coordArray[i][0], y = incl.coordArray[i][1]; int oppX = oppCoord(x, minX, maxX), oppY = oppCoord(y, minY, maxY); int newPolySize = currPolySize + 2; if (x > newMaxX) newMaxX = x; if (x < newMinX) newMinX = x; if (y > newMaxY) newMaxY = y; if (y < newMinY) newMinY = y; root[currPolySize][0] = x; root[currPolySize][1] = y; if (oppX > newMaxX) newMaxX = oppX; if (oppX < newMinX) newMinX = oppX; if (oppY > newMaxY) newMaxY = oppY; if (oppY < newMinY) newMinY = oppY; root[currPolySize + 1][0] = oppX; root[currPolySize + 1][1] = oppY; int newHitListSize = hitListSize ; overideHit( x, y, 1); overideHit( oppX, oppY, 1); if (newPolySize <= targetSize && (!unholey || !isHoley(newPolySize))) { if (noSymFlag) { //counter[outerChiral]++; } else { boolean r90 = loopR90 && testRotate90(newPolySize, newMinX, newMinY, newMaxX, newMaxY); boolean m45 = !domino && testMirrorSWNE(newPolySize, newMinX, newMinY, newMaxX, newMaxY); boolean achiral = false; if (m45) { achiral = true; //System.err.println("m45"); } else { achiral = testMirrorH(newPolySize, newMinY, newMaxY); } if (r90) { // noop } else { if (achiral) { // noop } else counter[newPolySize]++; } } } //System.err.println(newPoly.drawing(newMinX, newMinY, newMaxX, newMaxY)); //incl.verify(newPoly); //int newInclSize = increase( currInclSize, newPolySize, x, y, minX, minY, maxX, maxY); int newInclSize = currInclSize; for (int j = 0; j < 4 ; j++) { int dx = deltaX[j], dy = deltaY[j]; int nx = x + dx; int ny = y + dy; if (empty( nx, ny)) { if (inRestrictedSet(nx, ny, newMinX, newMinY, newMaxX, newMaxY)) { newInclSize = incl.add( nx, ny , newInclSize) ; setHit(oppCoord(nx, newMinX, newMaxX), oppCoord(ny, newMinY, newMaxY), -1); hitList[newHitListSize][0] = nx; hitList[newHitListSize][1] = ny; newHitListSize++; } } } for (int j = 0; j < 4 ; j++) { int dx = deltaX[j], dy = deltaY[j]; int nx = oppX + dx; int ny = oppY + dy; if (empty( nx, ny)) { if (inRestrictedSet(nx, ny, newMinX, newMinY, newMaxX, newMaxY)) { newInclSize = incl.add( nx, ny , newInclSize) ; setHit(oppCoord(nx, newMinX, newMaxX), oppCoord(ny, newMinY, newMaxY), -1); hitList[newHitListSize][0] = nx; hitList[newHitListSize][1] = ny; newHitListSize++; } } } //newInclSize = increase( newInclSize, newPolySize, oppX, oppY, minX, minY, maxX, maxY); recurse2(newInclSize, newPolySize, newMinX, newMinY, newMaxX, newMaxY, i + 1, newHitListSize); for (int j = hitListSize ; j < newHitListSize; j++) { eraseHit(j); eraseOppHit( j, newMinX, newMinY, newMaxX, newMaxY); } overideHit( x, y, -1); overideHit( oppCoord(x, newMinX, newMaxX), oppCoord(y, newMinY, newMaxY), -1); recurse2(currInclSize, currPolySize, minX, minY, maxX, maxY, i + 1, hitListSize + 1); break; } } void eraseOppHit(int j, int newMinX, int newMinY, int newMaxX, int newMaxY) { int bx = baseX + oppCoord(hitList[j][0],newMinX, newMaxX), by = baseY + oppCoord(hitList[j][1], newMinY, newMaxY); //System.err.println("clear " + j + " " + hitList[j][0] + " " + hitList[j][1] + " " + 0); if (board[bx][by] == 0) { int qq = 1 / 0; } board[bx][by] = 0; } int oppCoord(int z, int minZ, int maxZ) { return maxZ - z + minZ; } public boolean inRestrictedSet(int x, int y, int localMinX, int localMinY, int localMaxX, int localMaxY) { x = x - localMinX + 1; y = y - localMinY + 1; localMaxY = localMaxY - localMinY + 1; localMaxX = localMaxX - localMinX + 1; /* if (maxX == 1) { return (x >= 1 && y > maxY / 2); } */ if (localMaxY % 2 == 0) { return y > localMaxY / 2; } int halfV = (localMaxY + 1) / 2; if (y > halfV) return true; if (y < halfV) return false; int halfH = (localMaxX + 1) / 2; return (x > halfH); } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * Does not suit extending CounterBase * */ public class CounterR90CCentreFull extends CounterWithMultipleCopies { public CounterR90CCentreFull( String params) { super( params); } void printResults() { printResults(2); //System.err.println("Results need dividing"); } public void run() { counter2 = new long[targetSize + 1]; int currInclSize = incl.add(1, 1, 0); recurse2(0, 0, 1, 1, 1, 1, currInclSize, 0, 0); printResults(); } void recurse2(int currPolySize, int effectiveSize, int minX, int maxX, int minY, int maxY, int currInclSize, int startPos, int hitListSize) { //System.err.println("recurse " + hitListSize ); //verifPoly(currPolySize); if (effectiveSize > this.targetSize) { return; } if (effectiveSize == this.targetSize) return; int newInclSize = currInclSize; //long newExcluded1 = excluded1, newExcluded2 = excluded2; int newMaxY = maxY, newMinY = minY; int newMaxX = maxX, newMinX = minX; int newPolySize = currPolySize + 1; //incl.verify2(currentPoly); //incl.verifDupl(currInclSize); for (int i = startPos; i < currInclSize ; i++) { int x = incl.getX(i), y = incl.getY(i) ; if (x < 1 || y < 1) { int qq = 1 /0; } if ((effectiveSize + 4 > targetSize)) continue; if (y > newMaxY) newMaxY = y; if (y < newMinY) { newMinY = y; } if (x > newMaxX) newMaxX = x; if (x < newMinX) { newMinX = x; } root[currPolySize][0] = x; root[currPolySize][1] = y; //hitList[hitListSize][0] = x; //hitList[hitListSize][1] = y; int newHitListSize = hitListSize ; overideHit( x, y, 1); int newEffectiveSize; if (x == 1 && y == 1) { newEffectiveSize = effectiveSize + 1; } else { newEffectiveSize = effectiveSize + 4; } boolean fH = testMirrorHnew(newPolySize, 2 - newMaxY, newMaxY); // minY forced according to maxY if (!fH && newEffectiveSize <= targetSize) { if (this.unholey && !isHoleySpecific(newPolySize, newEffectiveSize)) { //fH = testMirrorHnew(newPolySize, 2 - newMaxY, newMaxY); counter2[newEffectiveSize]++; //System.err.println(gen(newPolySize).drawing()); } counter[newEffectiveSize]++; } //newInclSize = increase(newPolySize, x, y, newEffectiveSize, newInclSize); for (int j = 0; j < 4 ; j++) { int dx = deltaX[j], dy = deltaY[j]; int nx = x + dx; int ny = y + dy; if ((newEffectiveSize > targetSize - 4)) continue; if (nx == 1) { nx = ny; ny = 1; } if (ny == 0) { ny = nx; nx = 2; } if (x == 1 && y == 1) { if (nx < 2) continue; } if (nx < 1 || ny < 1) { int qq = 1 / 0; } if (empty( nx, ny)) { newInclSize = incl.add( nx, ny , newInclSize) ; hitList[newHitListSize][0] = nx; hitList[newHitListSize][1] = ny; newHitListSize++; } } recurse2( newPolySize, newEffectiveSize, newMinX, newMaxX, newMinY, newMaxY, newInclSize, i + 1, newHitListSize); for (int j = hitListSize ; j < newHitListSize; j++) { eraseHit(j); } overideHit( x, y, -1); recurse2(currPolySize, effectiveSize, minX, maxX, minY, maxY, currInclSize, i + 1, hitListSize + 1); break; } //System.err.println("return " ); } int getHoleyMultiplier(int x, int y) { int multiplier = 1; if (x != 1 || y != 1 ) multiplier = 4; return multiplier; } boolean containsSpecific(int x, int y) { int tx = x, ty = y; if (x <= 1 && y > 1) { tx = y; ty = flip(x); } else if (x < 1 && y <= 1) { tx = flip(x); ty = flip(y); } else if (x >= 1 && y < 1) { tx = flip(y); ty = x; } boolean ret; ret = contains(tx, ty); if (debug) { //System.err.println(x + "," + y + " " + tx + "," + ty + " = " + ret); } return ret; } int flip(int z) { return -z + 2; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author jmason * Does not suit extending CounterBase * */ public class CounterR90VCentreFull extends CounterWithMultipleCopies { public CounterR90VCentreFull( String params) { super( params); } void printResults() { printResults(2); } public void run() { counter2 = new long[targetSize + 1]; int currInclSize = incl.add(1, 1, 0); recurse2(0, 0, 1, 1, 1, 1, currInclSize, 0, 0); printResults(); } void recurse2(int currPolySize, int effectiveSize, int minX, int maxX, int minY, int maxY, int currInclSize, int startPos, int hitListSize) { //System.err.println("recurse " + hitListSize ); //verifPoly(currPolySize); if (effectiveSize > this.targetSize) { return; } if (effectiveSize == this.targetSize) return; int newInclSize = currInclSize; //long newExcluded1 = excluded1, newExcluded2 = excluded2; int newMaxY = maxY, newMinY = minY; int newMaxX = maxX, newMinX = minX; int newPolySize = currPolySize + 1; //incl.verify2(currentPoly); //incl.verifDupl(currInclSize); for (int i = startPos; i < currInclSize ; i++) { int x = incl.getX(i), y = incl.getY(i) ; if (x < 1 || y < 1) { int qq = 1 /0; } if ((effectiveSize + 4 > targetSize)) continue; if (y > newMaxY) newMaxY = y; if (y < newMinY) { newMinY = y; } if (x > newMaxX) newMaxX = x; if (x < newMinX) { newMinX = x; } root[currPolySize][0] = x; root[currPolySize][1] = y; //hitList[hitListSize][0] = x; //hitList[hitListSize][1] = y; int newHitListSize = hitListSize ; overideHit( x, y, 1); int newEffectiveSize; if (x == 1 && y == 1) { newEffectiveSize = 4; } else { newEffectiveSize = effectiveSize + 4; } boolean fH = testMirrorHnew(newPolySize, 1 - newMaxY, newMaxY); // minY forced according to maxY if (!fH && newEffectiveSize <= targetSize) { if (this.unholey && !isHoleySpecific(newPolySize, newEffectiveSize)) counter2[newEffectiveSize]++; counter[newEffectiveSize]++; } //newInclSize = increase(newPolySize, x, y, newEffectiveSize, newInclSize); for (int j = 0; j < 4 ; j++) { int dx = deltaX[j], dy = deltaY[j]; int nx = x + dx; int ny = y + dy; if ((newEffectiveSize > targetSize - 4)) continue; if (nx == 0) { nx = ny; ny = 1; } if (ny == 0) { ny = nx; nx = 1; } if (x == 1 && y == 1) { if (nx < 1 || ny < 1) continue; } if (nx < 1 || ny < 1) { int qq = 1 / 0; } if (empty( nx, ny)) { newInclSize = incl.add( nx, ny , newInclSize) ; hitList[newHitListSize][0] = nx; hitList[newHitListSize][1] = ny; newHitListSize++; } } //System.err.println("before " + hitListSize + " " + newHitListSize); recurse2( newPolySize, newEffectiveSize, newMinX, newMaxX, newMinY, newMaxY, newInclSize, i + 1, newHitListSize); for (int j = hitListSize ; j < newHitListSize; j++) { eraseHit(j); } overideHit( x, y, -1); recurse2(currPolySize, effectiveSize, minX, maxX, minY, maxY, currInclSize, i + 1, hitListSize + 1); //System.err.println("after " + hitListSize + " " + newHitListSize); //System.err.println("break " ); break; } } int getHoleyMultiplier(int x, int y) { return 4; } boolean containsSpecific(int x, int y) { int tx = x, ty = y; if (x < 1 && y > 0) { tx = y; ty = flip(x); } else if (x < 1 && y <= 0) { tx = flip(x); ty = flip(y); } else if (x >= 1 && y < 1) { tx = flip(y); ty = x; } boolean ret; ret = contains(tx, ty); if (debug) System.err.println(x + "," + y + " = " + ret); return ret; } int flip(int z) { return -z + 1; } } /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package unholeycounters; /** * * @author mason */ public abstract class CounterWithMultipleCopies extends CounterCommon { public CounterWithMultipleCopies(String params) { super( params); } long sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0; //abstract void isHoleySpecificLoop(int size); abstract boolean containsSpecific(int x, int y); boolean isHoleySpecific(int size, int effectiveSize) { // H = n + 1 - i - s / 2 //System.err.println("start"); sum1 = 0; sum2 = 0; sum3 = 0; sum4 = 0; //isHoleySpecificLoop(size); for (int i = 0 ; i < size ; i++) { int x = root[i][0], y = root[i][1]; if (debug) System.err.println("start x=" + x + " y=" + y); isHoleySingleSquareSpecific(x, y, getHoleyMultiplier(x, y)); } sum2 = div(sum2, 2); sum3 = div(sum3, 3); sum4 = div(sum4, 4); long h = effectiveSize + 1 - sum4 - div(sum1 + sum2 + sum3, 2) ; if (debug) { System.err.println("sum1 = " + sum1); System.err.println("sum2 = " + sum2); System.err.println("sum3 = " + sum3); System.err.println("sum4 = " + sum4); System.err.println("size = " + effectiveSize); System.err.println("h = " + h); } if (h > 0) return true; return false; } abstract int getHoleyMultiplier(int x, int y) ; void isHoleySingleSquareSpecific(int x, int y, int multiplier) { if (debug) { System.err.println("test x=" + x + " y=" + y); } int n = calculateAdjacentSpecific(x, y, x - 1, y - 1, x, y - 1, x - 1, y); switch (n) { case 1: sum1 += multiplier; break; case 2: sum2 += multiplier; break; case 3: sum3 += multiplier; break; case 4: sum4 += multiplier; break; } n = calculateAdjacentSpecific(x, y, x + 1, y - 1, x, y - 1, x + 1, y); switch (n) { case 1: sum1 += multiplier; break; case 2: sum2 += multiplier; break; case 3: sum3 += multiplier; break; case 4: sum4 += multiplier; break; } n = calculateAdjacentSpecific(x, y, x - 1, y + 1, x, y + 1, x - 1, y); switch (n) { case 1: sum1 += multiplier; break; case 2: sum2 += multiplier; break; case 3: sum3 += multiplier; break; case 4: sum4 += multiplier; break; } n = calculateAdjacentSpecific(x, y, x + 1, y + 1, x, y + 1, x + 1, y); switch (n) { case 1: sum1 += multiplier; break; case 2: sum2 += multiplier; break; case 3: sum3 += multiplier; break; case 4: sum4 += multiplier; break; } } int calculateAdjacentSpecific(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) { int ret = 0; boolean b1 = containsSpecific(x1, y1); boolean b2 = containsSpecific(x2, y2); boolean b3 = containsSpecific(x3, y3); boolean b4 = containsSpecific(x4, y4); if (b1) ret++; if (b2) ret++; if (b3) ret++; if (b4) ret++; if (ret == 2) { if (b1 && b2) ret = 0; if (b3 && b4) ret = 0; } if (debug) { //System.err.println("(" + x1 + "," + y1 + ")(" + x2 + "," + y2 + ")(" + x3 + "," + y3 + ")(" + x4 + "," + y4 + ") : " + ret); } return ret; } }