Libraryless. Click here for Pure Java version (4762L/31K/104K).
1 | !752 |
2 | |
3 | static BWImage bw; |
4 | static ImageSurface imageSurface; |
5 | static Thread producer; |
6 | static Reproducing rp; |
7 | |
8 | !include #1000522 // image helper functions |
9 | |
10 | p { |
11 | rp = new Reproducing; |
12 | bw = rp.bw = loadBWImage("#1004541"); |
13 | imageSurface = showImage(rp.bw.getBufferedImage()); |
14 | rp.imageSurfaceToUpdateWithBest = imageSurface; |
15 | |
16 | //showImage("Full Grab", descToImage(fullGrab(bw))); |
17 | |
18 | produce(); |
19 | rp.reproduceOpenEnd(); |
20 | |
21 | while (rp.solved()) { |
22 | rp.pivotLength = l(rp.bestDesc) - rp.pivotStep; |
23 | print("Trying pivot length " + rp.pivotLength); |
24 | |
25 | produce(); |
26 | rp.reproduceOpenEnd(); |
27 | } |
28 | } |
29 | |
30 | static void produce() { |
31 | cancelThread(producer); |
32 | producer = new Thread(r { |
33 | // STRATEGY! |
34 | |
35 | rp.push(fullGrab(bw)); |
36 | int w = 1; |
37 | while licensed { |
38 | rp.push(new RandomSolid().reproduce(bw)); |
39 | S best = rp.bestDesc; |
40 | if (best != null) |
41 | rp.push(varyFloat(best)); |
42 | if (w < rp.bw.getWidth()) |
43 | rp.push(hrepeat(bw, w++)); |
44 | } |
45 | }, "Producer"); |
46 | producer.start(); |
47 | } |
48 | |
49 | sclass Best { |
50 | S desc; |
51 | double score; |
52 | BWImage image; |
53 | |
54 | *() {} |
55 | *(S *desc, double *score, BWImage *image) {} |
56 | |
57 | int l() { ret main.l(desc); } |
58 | } |
59 | |
60 | sclass Reproducing { |
61 | BWImage bw; // original |
62 | ImageSurface imageSurfaceToUpdateWithBest; |
63 | new LinkedBlockingQueue<S> newProducts; |
64 | int maxQueueLength = 10; |
65 | Best shortest100; |
66 | double bestScore; |
67 | volatile S bestDesc; |
68 | BWImage bestRendering; |
69 | int pivotLength = -1; // no length punishment at start |
70 | int pivotStep = 1; |
71 | int fullGrabLength; // length of full grab for reference |
72 | |
73 | void push(S product) { |
74 | if (product == null) ret; |
75 | while (newProducts.size() >= maxQueueLength && mayRun()) |
76 | sleep(100); |
77 | newProducts.add(product); |
78 | } |
79 | |
80 | double formula(S desc, double pixelScore) { |
81 | int lengthPunishment = pivotLength < 0 ? 0 |
82 | : max(0, l(desc)-pivotLength); |
83 | ret pixelScore-lengthPunishment; |
84 | } |
85 | |
86 | void reproduceOpenEnd() { |
87 | bestDesc = null; |
88 | bestScore = 0; |
89 | bestRendering = null; |
90 | Renderer best = null; |
91 | fullGrabLength = l(fullGrab(bw)); |
92 | long lastPrint = 0, lastN = 0; |
93 | for (long ntry = 1; ; ntry++) { |
94 | ping(); |
95 | long now = now(); |
96 | if (now >= lastPrint+1000) { |
97 | long tps = (ntry-lastN)*1000/(now-lastPrint); |
98 | lastPrint = now; |
99 | lastN = ntry; |
100 | String s = "Try " + ntry + " (" + tps + "/s)"; |
101 | if (best == null) |
102 | System.out.println(s); |
103 | else { |
104 | System.out.println("Best: " + bestDesc); |
105 | System.out.println(s + ", score: " + formatDouble(bestScore, 2) + "%, l=" + l(bestDesc) + ", pivotL=" + pivotLength + "/" + fullGrabLength + (shortest100 == null ? "" : ", shortest100=" + shortest100.l())); |
106 | } |
107 | } |
108 | S desc; |
109 | try { |
110 | desc = grabFromQueue(newProducts); |
111 | } catch e { |
112 | print("Production failed: " + exceptionToStringShort(e)); |
113 | continue; |
114 | } |
115 | Renderer p; |
116 | try { |
117 | p = makeRenderer(desc); |
118 | } catch { |
119 | print("Can't unstructure: " + desc); |
120 | continue; |
121 | } |
122 | |
123 | BWImage rendering = render(p, bw); |
124 | double pixelScore = 100*(1-diff(bw, rendering)); |
125 | double score = formula(desc, pixelScore); |
126 | |
127 | if (bestDesc == null || p != null && score > bestScore) { |
128 | //System.out.println("New best! " + score); |
129 | bestDesc = desc; |
130 | bestScore = score; |
131 | bestRendering = rendering; |
132 | best = p; |
133 | if (pixelScore >= 100 && (shortest100 == null || shortest100.l() > l(desc))) { |
134 | shortest100 = new Best(desc, pixelScore, rendering); |
135 | saveTextFile(getProgramFile("shortest100.txt"), bw.getWidth() + " " + bw.getHeight() + " " + desc); |
136 | } |
137 | imageSurface.setImage(bestRendering.getBufferedImage()); |
138 | } |
139 | |
140 | if (solved()) { |
141 | print("Solved! l=" + l(bestDesc)); |
142 | print(bestDesc); |
143 | break; |
144 | } |
145 | } |
146 | } |
147 | |
148 | bool solved() { |
149 | ret bestScore >= 100.0; |
150 | } |
151 | |
152 | BufferedImage descToImage(S desc) { |
153 | try { |
154 | ret makeRenderer(desc).render(bw.getWidth(), bw.getHeight()).getBufferedImage(); |
155 | } catch { |
156 | fail(desc); |
157 | } |
158 | } |
159 | } |
160 | |
161 | static class FullGrab extends Renderer { |
162 | int dw, dh; |
163 | byte[] data; |
164 | |
165 | BWImage render(int w, int h) { |
166 | if (w != dw || h != dh) |
167 | fail("size: \*w*/ \*h*/ \*dw*/ \*dh*/"); |
168 | ret new BWImage(w, h, data); |
169 | } |
170 | } |
171 | |
172 | static class HRepeat extends Renderer { |
173 | int width; |
174 | S inner; |
175 | |
176 | BWImage render(int w, int h) { |
177 | BWImage img = new BWImage(w, h); |
178 | BWImage clip = makeRenderer(inner).render(width, h); |
179 | for (int x = 0; x < w; x += width) |
180 | copy(clip, 0, 0, img, x, 0, width, h); |
181 | ret img; |
182 | } |
183 | } |
184 | |
185 | static S fullGrab(BWImage img) { |
186 | DynamicObject d = new DynamicObject("FullGrab"); |
187 | int w = img.getWidth(), h = img.getHeight(); |
188 | d.put("dw", w); |
189 | d.put("dh", h); |
190 | byte[] data = new byte[w*h]; |
191 | for (int y = 0; y < h; y++) |
192 | for (int x = 0; x < w; x++) |
193 | data[y*w+x] = img.getByte(x, y); |
194 | d.put("data", data); |
195 | ret structure(d); |
196 | } |
197 | |
198 | static S hrepeat(BWImage img, int width) { |
199 | int h = img.getHeight(); |
200 | BWImage clip = img.clip(0, 0, width, h); |
201 | ret structure(dynamicObject("HRepeat", "width", width, "inner", fullGrab(clip))); |
202 | } |
203 | |
204 | static S varyFloat(S s) { |
205 | L<S> tok = javaTok(s); |
206 | int i = tok.indexOf("f"); |
207 | if (i < 0) null; |
208 | float f = Float.parseFloat(unquote(tok.get(i+2))); |
209 | f = (float) (f+random(-0.1, 0.1)); |
210 | tok.set(i+2, quote(str(f))); |
211 | ret join(tok); |
212 | } |
213 | |
214 | static BWImage render(Renderer p, BWImage original) { |
215 | ret p.render(original.getWidth(), original.getHeight()); |
216 | } |
217 | |
218 | static interface Reproducer { |
219 | public S reproduce(BWImage original); |
220 | } |
221 | |
222 | static class Solid extends Renderer { |
223 | float col; |
224 | |
225 | BWImage render(int w, int h) { |
226 | ret new BWImage(w, h, col); |
227 | } |
228 | } |
229 | |
230 | static class RandomSolid implements Reproducer { |
231 | int n = -1; |
232 | public S reproduce(BWImage original) { |
233 | ++n; |
234 | DynamicObject p = new DynamicObject("Solid"); |
235 | if (n % 2 == 0) { |
236 | p.put("col", randomBrightness()); |
237 | } else { |
238 | p.put("col", probeRandomPixel(original)); |
239 | } |
240 | ret structure(p); |
241 | } |
242 | } |
243 | |
244 | static abstract class Renderer { |
245 | abstract BWImage render(int w, int h); |
246 | } |
247 | |
248 | static Renderer makeRenderer(S desc) { |
249 | ret (Renderer) unstructure(desc); |
250 | } |
251 | |
252 | static BufferedImage render(S fullDesc) { |
253 | if (fullDesc == null) null; |
254 | new Matches m; |
255 | assertTrue(jmatchStart("* *", fullDesc, m)); |
256 | int w = m.psi(0), h = m.psi(1); |
257 | S desc = m.unq(2); |
258 | ret makeRenderer(desc).render(w, h).getBufferedImage(); |
259 | } |
260 | |
261 | static S shortest100() { |
262 | ret loadTextFile(getProgramFile("shortest100.txt")); |
263 | } |
264 | |
265 | static BufferedImage renderShortest100() { |
266 | ret render(shortest100()); |
267 | } |
Began life as a copy of #1004545
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, ddnzoavkxhuk, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1004551 |
Snippet name: | Reproduce Image 4 (with class Reproducing) |
Eternal ID of this version: | #1004551/1 |
Text MD5: | aab8ce0320808195f71e45d0d3ffe72c |
Transpilation MD5: | f2dcafe1888ea6848cb4f49afbd564c5 |
Author: | stefan |
Category: | javax / a.i. |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-08-21 02:15:43 |
Source code size: | 6905 bytes / 267 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 568 / 953 |
Referenced in: | [show references] |