!include #1000522 // image helper functions static abstract class Predictor { // col = immutable array! abstract float[] nextColumn(float[] col); } sclass Best { S desc; double score; Predictor renderer; *() {} *(S *desc, double *score, Predictor *renderer) {} int l() { ret main.l(desc); } } sclass Reproducing { BWImage bw; // original float[][] bwCols; // in columns bool testFirst; // test first column? new LinkedBlockingQueue newProducts; int maxQueueLength = 10; volatile Best shortest100, best; int pivotLength = -1; // no length punishment at start int pivotStep = 1; O startProduction; // optional runnable that starts production void push(S product) { if (product == null) ret; while (newProducts.size() >= maxQueueLength && mayRun()) sleep(100); newProducts.add(product); } bool solved() { ret getScore(best) >= 100.0; } S bestDesc() { ret getDesc(best); } void produce() { callF(startProduction); } void search() { produce(); long lastPrint = 0, lastN = 0; for (long ntry = 1; ; ntry++) { ping(); long now = now(); if (now >= lastPrint+1000) { long tps = (ntry-lastN)*1000/(now-lastPrint); lastPrint = now; lastN = ntry; String s = "Try " + ntry + " (" + tps + "/s)"; /*if (best == null) print(s); else { print("Best: " + best.desc); print(s + ", score: " + formatDouble(best.score, 2) + "%, l=" + l(best.desc) + ", pivotL=" + pivotLength + "/" + fullGrabLength + (shortest100 == null ? "" : ", shortest100=" + shortest100.l())); }*/ } S desc = grabFromQueue(newProducts); Predictor p; try { p = makePredictor(desc); } catch { print("Can't unstructure: " + desc); continue; } print("Predictor: " + desc); double score = testPredictor(p); print(" Score: " + score); } } Predictor nextPredictor() { S desc = grabFromQueue(newProducts); try { ret makePredictor(desc); } catch { print("Can't unstructure: " + desc); null; } } double testPredictor(Predictor p) { ret main.testPredictor(p, getCols(), testFirst); } float[][] getCols() { if (bwCols == null) bwCols = imageToColumns(bw); ret bwCols; } } static Predictor makePredictor(S desc) { ret (Predictor) unstructure(desc); } static double getScore(Best b) { ret b == null ? 0 : b.score; } static S getDesc(Best b) { ret b == null ? null : b.desc; } static float[][] imageToColumns(BWImage img) { int w = img.getWidth(), h = img.getHeight(); float[][] f = new float[w][h]; for x to w: for y to h: f[x][y] = img.getPixel(x, y); ret f; } static BWImage columnsToImage(float[][] cols) { ret columnsToImage(cols, l(cols[0])); } static BWImage columnsToImage(float[][] cols, int h) { float emptyBrightness = 0.5f; int w = l(cols); BWImage img = new BWImage(w, h, emptyBrightness); for x to w: if (cols[x] != null) for y to h: img.setPixel(x, y, cols[x][y]); ret img; } static float[] copyColumn(float[] f) { ret copyFloatArray(f); } static double testPredictor(Predictor p, float[][] bwCols, bool testFirst) { int w = l(bwCols), h = l(bwCols[0]); double error = 0; for (int x = testFirst ? 0 : 1; x < w; x++) { float[] f = p.nextColumn(x == 0 ? null : bwCols[x-1]); error += colDiff(f, bwCols[x]); } ret 1-error/((testFirst ? w : w-1)*h); } // x0 = from where we start feeding // x1 = where we start testing static double testColumnRange(Predictor p, float[][] bwCols, int x0, int x1, int x2) { int h = l(bwCols[0]); double error = 0; for (int x = x0; x < x2; x++) { float[] f = p.nextColumn(x == 0 ? null : bwCols[x-1]); if (x >= x1) error += colDiff(f, bwCols[x]); } ret 1-error/((x2-x1)*h); } static double colDiff(float[] a, float[] b) { if (a == null) ret l(b); if (b == null) ret l(a); int n = l(a); double d = 0; for (int i = 0; i < n; i++) d += Math.abs(a[i]-b[i]); ret d; } static BufferedImage renderPrediction(S desc, float[][] bwCols) { Predictor p = makePredictor(desc); int w = l(bwCols), h = l(bwCols[0]); float[][] cols = new float[w][]; for (int x = 0; x < w; x++) { float[] f = p.nextColumn(x == 0 ? null : bwCols[x-1]); cols[x] = f; } ret columnsToImage(cols, h).getBufferedImage(); }