woletee commited on
Commit
ded89f7
·
1 Parent(s): de94fdd

this is the commit for adding the gp interface

Browse files
app.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request
2
+ from markupsafe import Markup
3
+
4
+ import os
5
+ import glob
6
+ from gp1 import run_task # Make sure run_task returns all required data
7
+
8
+ app = Flask(__name__)
9
+
10
+ # Helper function to render a grid as HTML using CSS classes
11
+ def render_grid(grid):
12
+ html = '<div class="grid">'
13
+ for row in grid:
14
+ html += '<div class="grid-row">'
15
+ for cell in row:
16
+ html += f'<div class="cell color-{cell}"></div>'
17
+ html += '</div>'
18
+ html += '</div>'
19
+ return Markup(html)
20
+
21
+ @app.route('/', methods=['GET', 'POST'])
22
+ def index():
23
+ task_folder = './training/'
24
+ task_files = sorted(glob.glob(os.path.join(task_folder, '*.json')))
25
+ task_names = [os.path.basename(f) for f in task_files]
26
+
27
+ result = None
28
+
29
+ if request.method == 'POST':
30
+ selected_task = request.form.get('task')
31
+ task_path = os.path.join(task_folder, selected_task)
32
+
33
+ # run_task should return: best_program, correct, input_grid, target_grid, output_grid
34
+ best_program, correct, input_grid, target_grid, output_grid = run_task(task_path)
35
+
36
+ result = {
37
+ "task": selected_task,
38
+ "program": best_program,
39
+ "success": correct,
40
+ "input": input_grid,
41
+ "target": target_grid,
42
+ "output": output_grid
43
+ }
44
+
45
+ return render_template('index.html', tasks=task_names, result=result, render_grid=render_grid)
46
+
47
+ if __name__ == '__main__':
48
+ app.run(debug=True)
dsl.py ADDED
@@ -0,0 +1,680 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from typing import Tuple, List
3
+
4
+ # Define Count as an alias for int
5
+ Count = int
6
+ from scipy.ndimage import binary_dilation
7
+ from scipy import ndimage
8
+ from typing import Callable
9
+
10
+ class GridList(list):
11
+ pass
12
+
13
+ class PrimitiveException(Exception):
14
+ pass
15
+
16
+ # Simple Grid class
17
+ class Grid:
18
+ def __init__(self, grid: np.ndarray, position: Tuple[int, int]=(0, 0)):
19
+ self.grid = grid
20
+ self.position = position
21
+
22
+ @property
23
+ def size(self):
24
+ return self.grid.shape
25
+
26
+ def newgrid(self, grid: np.ndarray, position=None):
27
+ if position is None:
28
+ position = self.position
29
+ return Grid(grid, position)
30
+
31
+ def count(self):
32
+ return np.count_nonzero(self.grid)
33
+
34
+ Colour = int
35
+
36
+ def primitive_assert(condition, message="Assertion failed"):
37
+ if not condition:
38
+ raise ValueError(message)
39
+
40
+ # DSL primitives
41
+ def rot90(g: Grid) -> Grid:
42
+ return g.newgrid(np.rot90(g.grid))
43
+
44
+ def rot180(g: Grid) -> Grid:
45
+ return g.newgrid(np.rot90(g.grid, 2))
46
+
47
+ def ic_compress2(g: Grid) -> Grid:
48
+ keep_rows = np.any(g.grid, axis=1)
49
+ keep_cols = np.any(g.grid, axis=0)
50
+ return g.newgrid(g.grid[keep_rows][:, keep_cols])
51
+
52
+ def flipy(g: Grid) -> Grid:
53
+ return g.newgrid(np.flip(g.grid, axis=1))
54
+
55
+ def mirrorX(g: Grid) -> Grid:
56
+ return Grid(np.hstack((g.grid, np.fliplr(g.grid))))
57
+
58
+ def mirrorY(g: Grid) -> Grid:
59
+ return Grid(np.vstack((g.grid, np.flipud(g.grid))))
60
+
61
+ def overlay(g: Grid, h: Grid) -> Grid:
62
+ if g.size == h.size:
63
+ newgrid = Grid(g.grid.copy())
64
+ newgrid.grid[h.grid != 0] = h.grid[h.grid != 0]
65
+ return newgrid
66
+ else:
67
+ xpos = min(g.position[0], h.position[0])
68
+ ypos = min(g.position[1], h.position[1])
69
+ xsize = max(g.position[0]+g.size[0], h.position[0]+h.size[0]) - xpos
70
+ ysize = max(g.position[1]+g.size[1], h.position[1]+h.size[1]) - ypos
71
+
72
+ newgrid = Grid(np.zeros((xsize, ysize)), position=(xpos, ypos))
73
+ newgrid.grid[g.position[0]-xpos:g.position[0]-xpos+g.size[0],
74
+ g.position[1]-ypos:g.position[1]-ypos+g.size[1]] = g.grid
75
+
76
+ mask = np.nonzero(h.grid)
77
+ slice = newgrid.grid[h.position[0]-xpos:h.position[0]-xpos+h.size[0],
78
+ h.position[1]-ypos:h.position[1]-ypos+h.size[1]]
79
+ slice[mask] = h.grid[mask]
80
+ return newgrid
81
+
82
+ def set_bg(c: Colour, g: Grid) -> Grid:
83
+ primitive_assert(c != 0, "background with 0 has no effect")
84
+ grid = np.copy(g.grid)
85
+ grid[grid == 0] = c
86
+ return g.newgrid(grid)
87
+ def ic_composegrowing(l: List[Grid]) -> Grid:
88
+ xpos = min([g.position[0] for g in l])
89
+ ypos = min([g.position[1] for g in l])
90
+ xsize = max([g.position[0]+g.size[0] for g in l]) - xpos
91
+ ysize = max([g.position[1]+g.size[1] for g in l]) - ypos
92
+
93
+ newgrid = Grid(np.zeros((xsize, ysize)), position=(xpos, ypos))
94
+ sorted_list = sorted(l, key=lambda g: g.count(), reverse=True)
95
+
96
+ for g in sorted_list:
97
+ xstart = g.position[0] - xpos
98
+ ystart = g.position[1] - ypos
99
+ slice = newgrid.grid[xstart:xstart+g.size[0], ystart:ystart+g.size[1]]
100
+ mask = np.nonzero(g.grid)
101
+ slice[mask] = g.grid[mask]
102
+
103
+ return newgrid
104
+
105
+ def ic_splitall(g: Grid) -> GridList:
106
+ colours = np.unique(g.grid)
107
+ ret = []
108
+ for colour in colours:
109
+ if colour:
110
+ labeled_grid, _ = ndimage.label(g.grid == colour)
111
+ objects = ndimage.find_objects(labeled_grid)
112
+ ret += [g.newgrid(g.grid[obj], position=(obj[0].start, obj[1].start)) for obj in objects]
113
+ return ret
114
+
115
+ def ic_connect_kernel(g: Grid, x: bool, y: bool) -> Grid:
116
+ """
117
+ Implements a generic connect (not a primitive)
118
+ x and y control whether it is enabled in the horizontal and vertical directions
119
+
120
+ Connect works as follows:
121
+ Two cells in the same row/column are connected iff:
122
+ - they are both non-zero
123
+ - they have the same value c
124
+ - there are only zeros in between them
125
+ Connect fills in the zero values in-between with c.
126
+ Note that vertical connection happens after horizontal connection and "overrides" it.
127
+
128
+ This function is SLOW
129
+ TODO: Verify this actually works because I'm not confident
130
+ """
131
+ ret = np.zeros_like(g.grid)
132
+
133
+ if x:
134
+ for row in range(g.grid.shape[0]):
135
+ last = last_value = -1
136
+ for col in range(g.grid.shape[1]):
137
+ if g.grid[row, col]:
138
+ if g.grid[row, col] == last_value:
139
+ ret[row, last+1:col] = last_value
140
+ last_value = g.grid[row, col]
141
+ last = col
142
+
143
+ if y:
144
+ for col in range(g.grid.shape[1]):
145
+ last = last_value = -1
146
+ for row in range(g.grid.shape[0]):
147
+ if g.grid[row, col]:
148
+ if g.grid[row, col] == last_value:
149
+ ret[last+1:row, col] = last_value
150
+ last_value = g.grid[row, col]
151
+ last = row
152
+
153
+ return g.newgrid(ret)
154
+
155
+ def ic_connectY(g: Grid) -> Grid:
156
+ return ic_connect_kernel(g, False, True)
157
+
158
+ def ic_connectX(g: Grid) -> Grid:
159
+ return ic_connect_kernel(g, True, False)
160
+
161
+ def ic_compress2(g: Grid) -> Grid:
162
+ """Deletes any black rows/columns in the grid"""
163
+ keep_rows = np.any(g.grid, axis=1)
164
+ keep_cols = np.any(g.grid, axis=0)
165
+
166
+ return g.newgrid(g.grid[keep_rows][:, keep_cols])
167
+
168
+ def ic_compress3(g: Grid) -> Grid:
169
+ """
170
+ Keep any rows/columns which differ in any way from the previous row/column
171
+ The first row/column is always kept.
172
+ """
173
+ keep_rows = np.ones(g.grid.shape[0], dtype=bool)
174
+ keep_cols = np.ones(g.grid.shape[1], dtype=bool)
175
+
176
+ for row in range(1, g.grid.shape[0]):
177
+ if np.all(g.grid[row] == g.grid[row-1]):
178
+ keep_rows[row] = False
179
+
180
+ for col in range(1, g.grid.shape[1]):
181
+ if np.all(g.grid[:, col] == g.grid[:, col-1]):
182
+ keep_cols[col] = False
183
+
184
+ return g.newgrid(g.grid[keep_rows][:, keep_cols])
185
+
186
+ def ic_erasecol(c: Colour, g: Grid) -> Grid:
187
+ "Remove a specified colour from the grid, keeping others intact"
188
+ primitive_assert(c != 0, "erasecol with 0 has no effect")
189
+ grid = np.copy(g.grid)
190
+ grid[grid == c] = 0
191
+ return g.newgrid(grid)
192
+ def rarestcol(g: Grid) -> Colour:
193
+ """
194
+ Returns the least common colour, excluding black.
195
+ Excludes any colours with zero count.
196
+ """
197
+ counts = np.bincount(g.grid.ravel())[1:]
198
+ counts[counts == 0] = 9999
199
+ return np.argmin(counts)+1
200
+
201
+ def left_half(g: Grid) -> Grid:
202
+ primitive_assert(g.size[1] > 1, "Grid is too small to crop")
203
+ return g.newgrid(g.grid[:, :g.grid.shape[1]//2])
204
+
205
+ def right_half(g: Grid) -> Grid:
206
+ primitive_assert(g.size[1] > 1, "Grid is too small to crop")
207
+ new_position = (g.position[0], g.position[1] + g.grid.shape[1]//2 + g.grid.shape[1]%2)
208
+ return g.newgrid(g.grid[:, -g.grid.shape[1]//2:], position=new_position)
209
+
210
+ def top_half(g: Grid) -> Grid:
211
+ primitive_assert(g.size[0] > 1, "Grid is too small to crop")
212
+ return g.newgrid(g.grid[:g.grid.shape[0]//2])
213
+ def repeatX(g: Grid) -> Grid:
214
+ """
215
+ Repeat the grid g horizontally, with no gaps
216
+ """
217
+ return Grid(np.tile(g.grid, (1, 2)), position=g.position)
218
+ def flipx(g: Grid) -> Grid:
219
+ return g.newgrid(np.flip(g.grid, axis=0))
220
+ # Your custom primitive function
221
+ def ic_pickunique(l: List[Grid]) -> Grid:
222
+ """
223
+ Given a list of grids, return the one which has a unique colour unused by any other grid.
224
+ If there are no such grids or more than one, terminate.
225
+ """
226
+ counts = np.zeros(10)
227
+ uniques = [np.unique(g.grid) for g in l]
228
+ for u in uniques:
229
+ counts[u] += 1
230
+
231
+ colour_mask = counts == 1
232
+ ccount = np.sum(colour_mask)
233
+ if not ccount:
234
+ raise PrimitiveException("pickunique: no unique grids")
235
+
236
+ for g, u in zip(l, uniques):
237
+ if np.sum(colour_mask[u]) == ccount:
238
+ return g
239
+
240
+ raise PrimitiveException("pickunique: no unique grids (2)")
241
+ def countToXY(c: int, col: Colour) -> Grid:
242
+ """
243
+ Given a count (integer) and a colour, create a square grid of size c×c filled with the given colour.
244
+ """
245
+ return Grid(np.full((c, c), col, dtype=int))
246
+ # Primitive definitions
247
+ def gravity(g: Grid, dx=False, dy=False) -> Grid:
248
+ assert dx or dy
249
+
250
+ pieces = ic_splitall(g)
251
+
252
+ # Sort pieces by gravity direction
253
+ pieces = sorted(pieces,
254
+ key=lambda g: -(g.position[0]*dy + g.position[1]*dx))
255
+
256
+ # Start with empty grid
257
+ newgrid = Grid(np.zeros(g.size))
258
+
259
+ # Iterate over pieces
260
+ for p in pieces:
261
+ while True:
262
+ # Move piece by gravity direction
263
+ p.position = (p.position[0]+dy, p.position[1]+dx)
264
+
265
+ # Check bounds
266
+ if (p.position[0] < 0 or p.position[0]+p.size[0] > g.size[0] or
267
+ p.position[1] < 0 or p.position[1]+p.size[1] > g.size[1]):
268
+ p.position = (p.position[0]-dy, p.position[1]-dx)
269
+ break
270
+
271
+ # Collision check
272
+ slice = newgrid.grid[
273
+ p.position[0]:p.position[0]+p.size[0],
274
+ p.position[1]:p.position[1]+p.size[1]
275
+ ]
276
+
277
+ if slice[p.grid != 0].any():
278
+ p.position = (p.position[0]-dy, p.position[1]-dx)
279
+ break
280
+
281
+ # Composite piece
282
+ newgrid = overlay(newgrid, p)
283
+
284
+ return newgrid
285
+
286
+ # Wrapper primitive: gravity to the right
287
+ def gravity_right(g: Grid) -> Grid:
288
+ return gravity(g, dx=1)
289
+ struct8 = np.array([[1, 1, 1],
290
+ [1, 1, 1],
291
+ [1, 1, 1]], dtype=int)
292
+
293
+ def split8(g: Grid) -> List[Grid]:
294
+ """
295
+ Find all objects using 8-connected structuring element.
296
+ Each colour is separated.
297
+ """
298
+ colours = np.unique(g.grid)
299
+ ret = []
300
+ for colour in colours:
301
+ if colour:
302
+ objects = ndimage.find_objects(ndimage.label(g.grid == colour, structure=struct8)[0])
303
+ ret += [g.newgrid(g.grid[obj], offset=(obj[0].start, obj[1].start)) for obj in objects]
304
+ return ret
305
+ def ic_makeborder(g: Grid) -> Grid:
306
+ """
307
+ Return a new grid which is the same as the input, but with a border of 1s around it.
308
+ Only elements which are 0 in the original grid are set to 1 in the new grid.
309
+ 8-connected structuring element used to determine border positions.
310
+ """
311
+
312
+ binary_grid = g.grid > 0
313
+ output_grid = np.zeros_like(g.grid)
314
+
315
+ grown_binary_grid = binary_dilation(binary_grid, structure=np.ones((3, 3)))
316
+ output_grid[grown_binary_grid & ~binary_grid] = 1
317
+
318
+ return g.newgrid(output_grid)
319
+ def ic_filtercol(c: Colour, g: Grid) -> Grid:
320
+ "Remove all colours except the selected colour"
321
+ primitive_assert(c != 0, "filtercol with 0 has no effect")
322
+
323
+ grid = np.copy(g.grid) # Do we really need to copy? old one thrown away anyway
324
+ grid[grid != c] = 0
325
+ return g.newgrid(grid)
326
+ def ic_invert(g: Grid) -> Grid:
327
+ """
328
+ Replaces all colours with zeros, and replaces zeros with the most common colour.
329
+ """
330
+ mode = np.argmax(np.bincount(g.grid.ravel())[1:]) + 1 # skip counting 0
331
+ grid = np.zeros_like(g.grid)
332
+ grid[g.grid == 0] = mode
333
+ return g.newgrid(grid)
334
+ def logical_and(g: Grid, h: Grid) -> Grid:
335
+ """
336
+ Logical AND between two grids. Use the colour of the first argument.
337
+ Logical OR is given by overlay.
338
+ """
339
+ primitive_assert(g.size == h.size, "logical_and: grids must be the same size")
340
+
341
+ mask = np.logical_and(g.grid != 0, h.grid != 0)
342
+ return g.newgrid(np.where(mask, g.grid, 0))
343
+
344
+ struct4 = np.array([[0,1,0],
345
+ [1,1,1],
346
+ [0,1,0]], dtype=int)
347
+
348
+ def fillobj(c: Colour, g: Grid) -> Grid:
349
+ """
350
+ Fill in any closed objects in the grid with a specified colour.
351
+ Uses 4-connectedness to determine closed objects.
352
+ """
353
+ primitive_assert(c != 0, "fill with 0 has no effect")
354
+
355
+ binhole = ndimage.binary_fill_holes(g.grid != 0, structure=struct4)
356
+ newgrid = np.copy(g.grid)
357
+ newgrid[binhole & (g.grid == 0)] = c
358
+
359
+ return g.newgrid(newgrid)
360
+ def topcol(g: Grid) -> Colour:
361
+ """
362
+ Returns the most common colour in the grid, excluding black (0).
363
+ Equivalent to majCol in icecuber.
364
+ """
365
+ return np.argmax(np.bincount(g.grid.ravel())[1:]) + 1
366
+ def rarestcol(g: Grid) -> Colour:
367
+ """
368
+ Returns the least common colour in the grid, excluding black.
369
+ Colours with zero occurrences are ignored.
370
+ """
371
+ counts = np.bincount(g.grid.ravel())[1:]
372
+ counts[counts == 0] = 9999
373
+ return np.argmin(counts) + 1
374
+ def gravity_down(g: Grid) -> Grid:
375
+ return gravity(g, dy=1)
376
+ def setcol(c: Colour, g: Grid) -> Grid:
377
+ """
378
+ Set all pixels in the grid to the specified colour.
379
+ Originally named colShape in icecuber.
380
+ """
381
+ primitive_assert(c != 0, "setcol with 0 has no effect")
382
+
383
+ grid = np.zeros_like(g.grid)
384
+ grid[np.nonzero(g.grid)] = c
385
+ return g.newgrid(grid)
386
+ def ic_embed(img: Grid, shape: Grid) -> Grid:
387
+ """
388
+ Embeds a grid into a larger shape defined by a second argument (zero-padded).
389
+ If the image is larger than the shape, it is cropped.
390
+ """
391
+ ret = np.zeros_like(shape.grid)
392
+
393
+ xoffset = shape.position[0] - img.position[0]
394
+ yoffset = shape.position[1] - img.position[1]
395
+
396
+ xsize = min(img.grid.shape[0], shape.grid.shape[0] - xoffset)
397
+ ysize = min(img.grid.shape[1], shape.grid.shape[1] - yoffset)
398
+
399
+ ret[xoffset:xoffset+xsize, yoffset:yoffset+ysize] = img.grid[:xsize, :ysize]
400
+ return shape.newgrid(ret)
401
+
402
+ def rot270(g: Grid) -> Grid:
403
+ """
404
+ Rotate a grid by 270 degrees.
405
+ """
406
+ return g.newgrid(np.rot90(g.grid, k=3))
407
+ def mapSplit8(f: Callable[[Grid], Grid], g: Grid) -> Grid:
408
+ """
409
+ Split grid g into objects using 8-connectedness,
410
+ apply function f to each object, and then reassemble.
411
+ """
412
+ pieces = split8(g)
413
+ processed_pieces = [f(piece) for piece in pieces]
414
+ return ic_composegrowing(processed_pieces)
415
+ from collections import Counter
416
+ def pickcommon(l: List[Grid]) -> Grid:
417
+ """
418
+ Given a list of grids, return the grid that appears most frequently (by exact match).
419
+ """
420
+ primitive_assert(len(l) > 0, "pickcommon: list is empty")
421
+ hashes = [hash(g.grid.data.tobytes()) for g in l]
422
+ most_common_hash = Counter(hashes).most_common(1)[0][0]
423
+ return l[hashes.index(most_common_hash)]
424
+ def swapxy(g: Grid) -> Grid:
425
+ return g.newgrid(g.grid.T)
426
+
427
+ def topcol(g: Grid) -> Colour:
428
+ """
429
+ Returns the most common colour, excluding black.
430
+ majCol in icecuber.
431
+ """
432
+ return np.argmax(np.bincount(g.grid.ravel())[1:])+1
433
+ def setcol(c: Colour, g: Grid) -> Grid:
434
+ """
435
+ Set all pixels in the grid to the specified colour.
436
+ This was named colShape in icecuber.
437
+ """
438
+ primitive_assert(c != 0, "setcol with 0 has no effect")
439
+
440
+ grid = np.zeros_like(g.grid)
441
+ grid[np.nonzero(g.grid)] = c
442
+ return g.newgrid(grid)
443
+ def get_bg(c: Colour, g: Grid) -> Grid:
444
+ """
445
+ Return a grid of all the background pixels in g, coloured c
446
+ Essentially same as invert.
447
+ """
448
+ return Grid(np.where(g.grid == 0, c, 0))
449
+ def rarestcol(g: Grid) -> Colour:
450
+ """
451
+ Returns the least common colour, excluding black.
452
+ Excludes any colours with zero count.
453
+ """
454
+ counts = np.bincount(g.grid.ravel())[1:]
455
+ counts[counts == 0] = 9999
456
+ return np.argmin(counts)+1
457
+ def ic_fill(g: Grid) -> Grid:
458
+ """
459
+ Returns a grid with all closed objects filled in with the most common colour
460
+ Note that like Icecuber, this also colours everything not connected to the border with the most common colour
461
+ i.e. the result is a single colour
462
+ """
463
+ return setcol(topcol(g), fillobj(1, g))
464
+ def ic_center(g: Grid) -> Grid:
465
+ # TODO: Figure out why this is useful
466
+ w,h = g.size
467
+
468
+ newsize = ((w + 1) % 2 + 1, (h + 1) % 2 + 1)
469
+ newgrid = np.ones(newsize)
470
+ newpos = (
471
+ g.position[0] + (newsize[0] - w) / 2,
472
+ g.position[1] + (newsize[1] - h) / 2
473
+ )
474
+
475
+ return Grid(newgrid, newpos)
476
+ def countToY(c: Count, col: Colour) -> Grid:
477
+ """
478
+ Create a vertical (1×c) grid filled with the given colour.
479
+ """
480
+ return Grid(np.full((1, c), col, dtype=int))
481
+
482
+ def countPixels(g: Grid) -> Count:
483
+ """
484
+ Count the number of non-zero pixels in the grid.
485
+ """
486
+ return np.count_nonzero(g.grid)
487
+ def ic_splitcols(g: Grid) -> List[Grid]:
488
+ """
489
+ Split a grid into multiple grids, each with a single colour.
490
+ """
491
+ ret = []
492
+ for colour in np.unique(g.grid):
493
+ if colour:
494
+ ret.append(g.newgrid(g.grid == colour))
495
+ return ret
496
+ def grid_split(g: Grid) -> GridList:
497
+ # Get rows and columns that are filled with a single color
498
+ row_colors = [row[0] for row in g.grid if np.all(row == row[0])]
499
+ col_colors = [col[0] for col in g.grid.T if np.all(col == col[0])]
500
+
501
+ colors = row_colors + col_colors
502
+ primitive_assert(len(colors) > 0, "No uniform rows or columns found")
503
+
504
+ # Find the most common such color
505
+ color = np.argmax(np.bincount(colors))
506
+
507
+ # Now split along rows and columns with this color
508
+ horizontal_splits = []
509
+ current = []
510
+ for row in g.grid:
511
+ if np.all(row == color):
512
+ if current:
513
+ horizontal_splits.append(np.stack(current))
514
+ current = []
515
+ else:
516
+ current.append(row)
517
+ if current:
518
+ horizontal_splits.append(np.stack(current))
519
+
520
+ # Convert each resulting piece to Grid
521
+ result = []
522
+ for h in horizontal_splits:
523
+ if h.shape[0] > 0:
524
+ result.append(Grid(h))
525
+
526
+ return GridList(result)
527
+
528
+
529
+
530
+ def arc_assert(boolean, message=None):
531
+ if not boolean:
532
+ # print('ValueError')
533
+ raise ValueError(message)
534
+
535
+ def _get(l):
536
+ def get(l, i):
537
+ arc_assert(i >= 0 and i < len(l))
538
+ return l[i]
539
+
540
+ return lambda i: get(l, i)
541
+
542
+ def stack_no_crop(l: GridList) -> Grid:
543
+ """
544
+ Stack same-size grids with masking — first grids drawn underneath later ones.
545
+ """
546
+ primitive_assert(len(l) > 0, "Empty GridList in stack_no_crop")
547
+
548
+ shape = l[0].grid.shape
549
+ for g in l:
550
+ primitive_assert(g.grid.shape == shape, "Mismatched grid shapes in stack_no_crop")
551
+
552
+ stackedgrid = np.zeros(shape, dtype=int)
553
+ for g in l:
554
+ stackedgrid += g.grid * (stackedgrid == 0)
555
+
556
+ return Grid(stackedgrid)
557
+
558
+ def overlay(g1: Grid, g2: Grid) -> Grid:
559
+ """
560
+ Mask overlay of g2 on top of g1.
561
+ """
562
+ primitive_assert(g1.grid.shape == g2.grid.shape, "Overlay shape mismatch")
563
+ result = g1.grid.copy()
564
+ result[g2.grid != 0] = g2.grid[g2.grid != 0]
565
+ return Grid(result)
566
+ def _objects2(g: Grid) -> Callable[[bool], Callable[[bool], GridList]]:
567
+ """
568
+ Extract connected components (objects) from grid.
569
+ Options:
570
+ - connect_diagonals: whether to connect diagonally
571
+ - separate_colors: whether to segment by color
572
+ """
573
+
574
+ def inner(connect_diagonals: bool):
575
+ def inner2(separate_colors: bool):
576
+ structure = ndimage.generate_binary_structure(2, 2 if connect_diagonals else 1)
577
+ components = []
578
+
579
+ if separate_colors:
580
+ colors = np.unique(g.grid)
581
+ colors = colors[colors != 0]
582
+ for c in colors:
583
+ mask = (g.grid == c).astype(int)
584
+ labeled, num = ndimage.label(mask, structure)
585
+ for i in range(1, num + 1):
586
+ submask = (labeled == i).astype(int) * c
587
+ components.append(Grid(submask))
588
+ else:
589
+ mask = (g.grid != 0).astype(int)
590
+ labeled, num = ndimage.label(mask, structure)
591
+ for i in range(1, num + 1):
592
+ submask = (labeled == i).astype(int) * g.grid
593
+ components.append(Grid(submask))
594
+
595
+ return GridList(components)
596
+
597
+ return inner2
598
+ return inner
599
+
600
+ def _objects(g: Grid) -> GridList:
601
+ connect_diagonals = False
602
+ separate_colors = True
603
+ return _objects2(g)(connect_diagonals)(separate_colors)
604
+ def move_down(g: Grid) -> Grid:
605
+ """
606
+ Moves the first extracted object down by one row and overlays it back.
607
+ """
608
+ objects = _objects(g)
609
+ primitive_assert(len(objects) > 0, "No objects found to move.")
610
+
611
+ obj = objects[0]
612
+ newg = Grid(np.copy(g.grid))
613
+ newg.grid[obj.grid != 0] = 0
614
+
615
+ moved_obj = Grid(np.roll(obj.grid, 1, axis=0), position=obj.position)
616
+
617
+ return overlay(newg, moved_obj)
618
+ def draw_line(g: Grid, angle: int) -> Grid:
619
+ """
620
+ Draw a line from some starting condition in the grid in the given direction.
621
+ Supported angles: 0 (right), 90 (up), 180 (left), 270 (down)
622
+ """
623
+ # For example, draw a line from top-left corner in given direction
624
+ new_grid = np.copy(g.grid)
625
+ h, w = new_grid.shape
626
+
627
+ if angle == 0: # Right
628
+ new_grid[0, :] = 1
629
+ elif angle == 90: # Up
630
+ new_grid[:, 0] = 1
631
+ elif angle == 180: # Left
632
+ new_grid[-1, :] = 1
633
+ elif angle == 270: # Down
634
+ new_grid[:, -1] = 1
635
+ else:
636
+ primitive_assert(False, f"Unsupported angle: {angle}")
637
+
638
+ return Grid(new_grid)
639
+ def draw_line_slant_up(g: Grid) -> Grid:
640
+ """
641
+ Extracts first object and draws a 45-degree line from it.
642
+ """
643
+ objects = _objects(g)
644
+ primitive_assert(len(objects) > 0, "No objects found in draw_line_slant_up.")
645
+ obj = objects[0]
646
+ return draw_line(g)(obj)(45)
647
+ def draw_line_slant_down(g: Grid) -> Grid:
648
+ """
649
+ Automatically extracts the first object from the grid and draws a 315-degree slant.
650
+ """
651
+ objects = _objects(g)
652
+ primitive_assert(len(objects) > 0, "No objects found in draw_line_slant_down.")
653
+ obj = objects[0]
654
+ return draw_line(g)(obj)(315)
655
+
656
+ def _place_into_grid(objects):
657
+ grid = np.zeros(objects[0].input_grid.shape, dtype=int)
658
+ # print('grid: {}'.format(grid))
659
+ for obj in objects:
660
+ # print('obj: {}'.format(obj))
661
+ # note: x, y, w, h should be flipped in reality. just go with it
662
+ y, x = obj.position
663
+ # print('x, y: {}'.format((x, y)))
664
+ h, w = obj.grid.shape
665
+ g_h, g_w = grid.shape
666
+ # may need to crop the grid for it to fit
667
+ # if negative, crop out the first parts
668
+ o_x, o_y = max(0, -x), max(0, -y)
669
+ # if negative, start at zero instead
670
+ x, y = max(0, x), max(0, y)
671
+ # this also affects the width/height
672
+ w, h = w - o_x, h - o_y
673
+ # if spills out sides, crop out the extra
674
+ w, h = min(w, g_w - x), min(h, g_h - y)
675
+ # print('x, y = {}, {}, o_x, o_y = {}, {}, w, h = {}, {}'.format(x, y,
676
+ # o_x, o_y, w, h))
677
+
678
+ grid[y:y+h, x:x+w] = obj.grid[o_y: o_y + h, o_x: o_x + w]
679
+
680
+ return Grid(grid)
gp1.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import sys, os, json
3
+ from deap import base, creator, gp, tools, algorithms
4
+ from dsl import *
5
+ import glob
6
+
7
+ from dsl import _objects
8
+
9
+ # Custom type definition (DEAP compatibility)
10
+ class GridList(list):
11
+ pass
12
+
13
+ # DEAP GP Setup
14
+ creator.create("FitnessMax", base.Fitness, weights=(1.0,))
15
+ creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMax)
16
+
17
+ pset = gp.PrimitiveSetTyped("MAIN", [Grid], Grid)
18
+
19
+ # Basic Grid primitives (all your previously defined primitives)
20
+ pset.addPrimitive(ic_compress2, [Grid], Grid)
21
+ pset.addPrimitive(flipy, [Grid], Grid)
22
+ pset.addPrimitive(rot90, [Grid], Grid)
23
+ pset.addPrimitive(rot180, [Grid], Grid)
24
+ pset.addPrimitive(mirrorX, [Grid], Grid)
25
+ pset.addPrimitive(mirrorY, [Grid], Grid)
26
+ pset.addPrimitive(overlay, [Grid, Grid], Grid)
27
+ pset.addPrimitive(set_bg, [int, Grid], Grid)
28
+ pset.addPrimitive(ic_connectY, [Grid], Grid)
29
+ pset.addPrimitive(ic_connectX, [Grid], Grid)
30
+ pset.addPrimitive(ic_compress3, [Grid], Grid)
31
+ pset.addPrimitive(ic_erasecol, [int, Grid], Grid)
32
+ pset.addPrimitive(left_half, [Grid], Grid)
33
+ pset.addPrimitive(right_half, [Grid], Grid)
34
+ pset.addPrimitive(top_half, [Grid], Grid)
35
+ pset.addPrimitive(repeatX, [Grid], Grid)
36
+ pset.addPrimitive(flipx, [Grid], Grid)
37
+ pset.addPrimitive(setcol, [Colour, Grid], Grid)
38
+ pset.addPrimitive(ic_embed, [Grid, Grid], Grid)
39
+ pset.addPrimitive(rot270, [Grid], Grid)
40
+
41
+ # GridList-based primitives
42
+ pset.addPrimitive(ic_splitall, [Grid], GridList)
43
+ pset.addPrimitive(ic_composegrowing, [GridList], Grid)
44
+ pset.addPrimitive(lambda x: GridList([x]), [Grid], GridList, name="toGridList")
45
+ pset.addTerminal(GridList([]), GridList)
46
+ pset.addPrimitive(ic_pickunique, [GridList], Grid)
47
+ pset.addPrimitive(gravity_right, [Grid], Grid)
48
+ pset.addPrimitive(split8, [Grid], GridList)
49
+ pset.addPrimitive(ic_makeborder, [Grid], Grid)
50
+ pset.addPrimitive(ic_filtercol, [Colour, Grid], Grid)
51
+ pset.addPrimitive(ic_invert, [Grid], Grid)
52
+ pset.addPrimitive(logical_and, [Grid, Grid], Grid)
53
+ pset.addPrimitive(fillobj, [Colour, Grid], Grid)
54
+ pset.addPrimitive(topcol, [Grid], Colour)
55
+ pset.addPrimitive(rarestcol, [Grid], Colour)
56
+ pset.addPrimitive(gravity_down, [Grid], Grid)
57
+ pset.addPrimitive(pickcommon, [GridList], Grid)
58
+ pset.addPrimitive(swapxy, [Grid], Grid)
59
+ pset.addPrimitive(topcol, [Grid], Colour)
60
+ pset.addPrimitive(setcol, [Colour, Grid], Grid)
61
+ pset.addPrimitive(get_bg, [Grid], Colour)
62
+ pset.addPrimitive(rarestcol, [Grid], Colour)
63
+ pset.addPrimitive(ic_fill, [Colour, Grid], Grid)
64
+ pset.addPrimitive(ic_center, [Grid], Grid)
65
+ pset.addPrimitive(countToY, [Count, Colour], Grid)
66
+ pset.addPrimitive(countPixels, [Grid], Count)
67
+ pset.addPrimitive(ic_splitcols, [Grid], GridList)
68
+ pset.addPrimitive(grid_split, [Grid], GridList)
69
+ pset.addPrimitive(_objects, [Grid], GridList)
70
+ pset.addPrimitive(overlay, [Grid, Grid], Grid)
71
+ pset.addPrimitive(stack_no_crop, [GridList], Grid)
72
+ pset.addPrimitive(move_down, [Grid], Grid)
73
+ pset.addPrimitive(draw_line, [Grid, int], Grid)
74
+ pset.addPrimitive(draw_line_slant_up, [Grid, Grid], Grid)
75
+ pset.addPrimitive(draw_line_slant_down, [Grid], Grid)
76
+ pset.addPrimitive(rarestcol, [Grid], int)
77
+ pset.addPrimitive(lambda: 1, [], int, name="int_one")
78
+
79
+ # Integer terminals
80
+ for i in range(1, 10):
81
+ pset.addTerminal(i, int)
82
+
83
+
84
+ import operator # needed for operator.attrgetter
85
+
86
+ toolbox = base.Toolbox()
87
+ toolbox.register("compile", gp.compile, pset=pset)
88
+ toolbox.register("select", tools.selTournament, tournsize=3)
89
+
90
+ # Use leaf-biased crossover to avoid excessive tree growth
91
+ toolbox.register("mate", gp.cxOnePointLeafBiased, termpb=0.1)
92
+
93
+ # Mutation setup remains the same
94
+ toolbox.register("expr_mut", gp.genFull, min_=0, max_=2)
95
+ toolbox.register("mutate", gp.mutUniform, expr=toolbox.expr_mut, pset=pset)
96
+
97
+ # Explicitly limit tree height to avoid memory errors
98
+ MAX_TREE_HEIGHT = 17 # recommended limit
99
+ toolbox.decorate("mate", gp.staticLimit(operator.attrgetter("height"), MAX_TREE_HEIGHT))
100
+ toolbox.decorate("mutate", gp.staticLimit(operator.attrgetter("height"), MAX_TREE_HEIGHT))
101
+
102
+ # Population initialization (unchanged)
103
+ toolbox.register("population", tools.initRepeat, list,
104
+ lambda: creator.Individual(gp.genHalfAndHalf(pset, min_=1, max_=3)))
105
+
106
+ def evaluate_task(individual, task):
107
+ func = toolbox.compile(expr=individual)
108
+ total = 0
109
+ for example in task['train']:
110
+ inp = Grid(np.array(example["input"]))
111
+ tgt = Grid(np.array(example["output"]))
112
+ try:
113
+ out = func(inp)
114
+ if out.grid.shape == tgt.grid.shape:
115
+ total += np.sum(out.grid == tgt.grid)
116
+ except:
117
+ pass
118
+ return (total,)
119
+
120
+ toolbox.register("evaluate", evaluate_task)
121
+
122
+ # Folder containing your tasks
123
+ training_folder = "./training/"
124
+ task_files = glob.glob(training_folder + "*.json")
125
+
126
+ results = []
127
+
128
+ # Evaluate each task separately
129
+ for task_file in task_files:
130
+ task_name = os.path.basename(task_file)
131
+ print(f"Processing {task_name}")
132
+
133
+ with open(task_file, 'r') as f:
134
+ task = json.load(f)
135
+
136
+ # GP initialization per task
137
+ pop = toolbox.population(n=150)
138
+ hof = tools.HallOfFame(1)
139
+
140
+ for gen in range(250): # Adjust number of generations if needed
141
+ offspring = algorithms.varAnd(pop, toolbox, cxpb=0.5, mutpb=0.2)
142
+ fits = toolbox.map(lambda ind: toolbox.evaluate(ind, task), offspring)
143
+
144
+ for fit, ind in zip(fits, offspring):
145
+ ind.fitness.values = fit
146
+
147
+ hof.update(offspring)
148
+ pop = toolbox.select(offspring, k=len(pop))
149
+
150
+ # Evaluate best individual on the test set
151
+ best_ind = hof[0]
152
+ func = toolbox.compile(expr=best_ind)
153
+
154
+ correct = False
155
+ try:
156
+ for test_case in task["test"]:
157
+ test_inp = Grid(np.array(test_case["input"]))
158
+ expected_out = np.array(test_case["output"])
159
+ output_grid = func(test_inp).grid
160
+ if np.array_equal(output_grid, expected_out):
161
+ correct = True
162
+ else:
163
+ correct = False
164
+ break
165
+ except:
166
+ correct = False
167
+
168
+ results.append({
169
+ "task_name": task_name,
170
+ "best_program": str(best_ind),
171
+ "solution_found": correct
172
+ })
173
+
174
+ print(f"{task_name} completed. Solution found: {correct}")
175
+
176
+ # Save summary results to JSON
177
+ with open("tasks_results_summary.json", "w") as f:
178
+ json.dump(results, f, indent=2)
179
+
180
+ print("All tasks processed. Results saved to tasks_results_summary.json.")
181
+ # Put everything you already have here...
182
+ # And then add this at the bottom:
183
+ def run_task(task_path):
184
+ with open(task_path, 'r') as f:
185
+ task = json.load(f)
186
+
187
+ pop = toolbox.population(n=150)
188
+ hof = tools.HallOfFame(1)
189
+
190
+ for gen in range(250):
191
+ offspring = algorithms.varAnd(pop, toolbox, cxpb=0.5, mutpb=0.2)
192
+ fits = toolbox.map(lambda ind: toolbox.evaluate(ind, task), offspring)
193
+
194
+ for fit, ind in zip(fits, offspring):
195
+ ind.fitness.values = fit
196
+
197
+ hof.update(offspring)
198
+ pop = toolbox.select(offspring, k=len(pop))
199
+
200
+ best_ind = hof[0]
201
+ func = toolbox.compile(expr=best_ind)
202
+
203
+ # We'll just use the first test example for visual output
204
+ test_example = task["test"][0]
205
+ input_grid = np.array(test_example["input"])
206
+ target_grid = np.array(test_example["output"])
207
+
208
+ try:
209
+ output_grid = func(Grid(input_grid)).grid
210
+ correct = np.array_equal(output_grid, target_grid)
211
+ except:
212
+ output_grid = np.zeros_like(input_grid)
213
+ correct = False
214
+
215
+ return str(best_ind), correct, input_grid.tolist(), target_grid.tolist(), output_grid.tolist()
static/styles.css ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ font-family: Arial, sans-serif;
3
+ background-color: #111;
4
+ color: white;
5
+ text-align: center;
6
+ }
7
+
8
+ h1, h2, h3 {
9
+ color: #FFD700;
10
+ }
11
+
12
+ .grid-container {
13
+ display: flex;
14
+ justify-content: center;
15
+ gap: 50px;
16
+ margin-bottom: 30px;
17
+ }
18
+
19
+ .grid-wrapper {
20
+ background-color: #222;
21
+ padding: 15px;
22
+ border-radius: 10px;
23
+ box-shadow: 0 0 10px #fff3;
24
+ }
25
+
26
+ .grid {
27
+ display: inline-block;
28
+ }
29
+
30
+ .grid-row {
31
+ display: flex;
32
+ }
33
+
34
+ .cell {
35
+ width: 30px;
36
+ height: 30px;
37
+ border: 1px solid #333;
38
+ }
39
+
40
+ /* ARC Color Mapping: You can customize these */
41
+ /* You can customize these */
42
+ .color-0 { background-color: #000000; } /* black */
43
+ .color-1 { background-color: #0074D9; } /* strong blue */
44
+ .color-2 { background-color: #FF4136; } /* vivid red */
45
+ .color-3 { background-color: #2ECC40; } /* bright green */
46
+ .color-4 { background-color: #FFDC00; } /* yellow */
47
+ .color-5 { background-color: #AAAAAA; } /* gray */
48
+ .color-6 { background-color: #F012BE; } /* hot pink */
49
+ .color-7 { background-color: #FF851B; } /* orange */
50
+ .color-8 { background-color: #7FDBFF; } /* light blue */
51
+ .color-9 { background-color: #870C25; } /* dark red */
52
+ .color-10 { background-color: #FFFFFF; } /* white */
53
+
54
+
templates/index.html ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Task Solver</title>
6
+ <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
7
+ </head>
8
+ <body>
9
+ <h1>Genetic Programming Task Solver</h1>
10
+
11
+ <form method="POST">
12
+ <label for="task">Select a task:</label>
13
+ <select name="task" id="task" required>
14
+ <option disabled selected value="">-- Choose a task --</option>
15
+ {% for t in tasks %}
16
+ <option value="{{ t }}">{{ t }}</option>
17
+ {% endfor %}
18
+ </select>
19
+ <button type="submit">Solve</button>
20
+ </form>
21
+
22
+ {% if result %}
23
+ <h2>Result for: {{ result.task }}</h2>
24
+
25
+ <div class="grid-container">
26
+ <div class="grid-wrapper">
27
+ <h3>Input</h3>
28
+ {{ render_grid(result.input) }}
29
+ </div>
30
+ <div class="grid-wrapper">
31
+ <h3>Target Output</h3>
32
+ {{ render_grid(result.target) }}
33
+ </div>
34
+ <div class="grid-wrapper">
35
+ <h3>Generated Output</h3>
36
+ {{ render_grid(result.output) }}
37
+ </div>
38
+ </div>
39
+
40
+ <p><strong>Best Program:</strong> {{ result.program }}</p>
41
+ <p><strong>Solution Found:</strong> {{ result.success }}</p>
42
+ {% endif %}
43
+ </body>
44
+ </html>
training/00d62c1b (3).json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"train": [{"input": [[0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0], [0, 3, 0, 3, 0, 0], [0, 0, 3, 0, 3, 0], [0, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0]], "output": [[0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0], [0, 3, 4, 3, 0, 0], [0, 0, 3, 4, 3, 0], [0, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0]]}, {"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 3, 0, 0, 0, 0, 0], [0, 0, 0, 3, 0, 3, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0, 3, 0, 0, 0], [0, 0, 0, 0, 0, 3, 0, 3, 0, 0], [0, 0, 0, 3, 0, 3, 3, 0, 0, 0], [0, 0, 3, 3, 3, 0, 0, 0, 0, 0], [0, 0, 0, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 3, 0, 0, 0, 0, 0], [0, 0, 0, 3, 0, 3, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0, 3, 0, 0, 0], [0, 0, 0, 0, 0, 3, 4, 3, 0, 0], [0, 0, 0, 3, 0, 3, 3, 0, 0, 0], [0, 0, 3, 3, 3, 0, 0, 0, 0, 0], [0, 0, 0, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]}, {"input": [[0, 0, 0, 0, 0, 3, 0, 0, 0, 0], [0, 0, 0, 0, 3, 0, 0, 0, 0, 0], [0, 3, 3, 0, 3, 3, 0, 3, 0, 0], [3, 0, 0, 3, 0, 0, 3, 0, 3, 0], [0, 0, 0, 3, 0, 0, 3, 3, 0, 0], [0, 0, 0, 3, 0, 0, 3, 0, 0, 0], [0, 0, 0, 3, 0, 0, 3, 0, 0, 0], [0, 0, 0, 0, 3, 3, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[0, 0, 0, 0, 0, 3, 0, 0, 0, 0], [0, 0, 0, 0, 3, 0, 0, 0, 0, 0], [0, 3, 3, 0, 3, 3, 0, 3, 0, 0], [3, 0, 0, 3, 4, 4, 3, 4, 3, 0], [0, 0, 0, 3, 4, 4, 3, 3, 0, 0], [0, 0, 0, 3, 4, 4, 3, 0, 0, 0], [0, 0, 0, 3, 4, 4, 3, 0, 0, 0], [0, 0, 0, 0, 3, 3, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]}, {"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 3, 3, 0, 0, 0, 0], [0, 0, 3, 0, 0, 3, 0, 0, 0, 0], [0, 0, 3, 0, 0, 3, 0, 3, 0, 0], [0, 0, 3, 3, 3, 3, 3, 3, 3, 0], [0, 0, 0, 3, 0, 0, 0, 0, 3, 0], [0, 0, 0, 3, 0, 0, 0, 3, 3, 0], [0, 0, 0, 3, 3, 0, 0, 3, 0, 3], [0, 0, 0, 3, 0, 3, 0, 0, 3, 0], [0, 0, 0, 0, 3, 0, 0, 0, 0, 0]], "output": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 3, 3, 3, 0, 0, 0, 0], [0, 0, 3, 4, 4, 3, 0, 0, 0, 0], [0, 0, 3, 4, 4, 3, 0, 3, 0, 0], [0, 0, 3, 3, 3, 3, 3, 3, 3, 0], [0, 0, 0, 3, 0, 0, 0, 0, 3, 0], [0, 0, 0, 3, 0, 0, 0, 3, 3, 0], [0, 0, 0, 3, 3, 0, 0, 3, 4, 3], [0, 0, 0, 3, 4, 3, 0, 0, 3, 0], [0, 0, 0, 0, 3, 0, 0, 0, 0, 0]]}, {"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 3, 3, 3, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0], [0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 3, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 3, 0, 0, 3, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 3, 0, 0, 3, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 3, 3, 3, 3, 4, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 4, 4, 4, 3, 0, 0, 0, 0], [0, 0, 0, 0, 3, 0, 0, 0, 3, 4, 4, 4, 4, 4, 4, 3, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 4, 4, 4, 3, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 4, 4, 4, 3, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 3, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 3, 3, 4, 4, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 3, 3, 0, 0, 3, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 3, 0, 0, 3, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 4, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]}], "test": [{"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 0, 0], [0, 0, 0, 0, 0, 0, 3, 3, 0, 3, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0], [0, 0, 3, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 3, 4, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 3, 4, 4, 4, 4, 3, 4, 4, 3, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 4, 4, 4, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 3, 4, 4, 4, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 0, 0], [0, 0, 0, 0, 0, 0, 3, 3, 4, 3, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0], [0, 0, 3, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 3, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]}]}
training/1cf80156.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"train": [{"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0], [0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0], [0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[0, 2, 2, 2], [0, 0, 2, 0], [2, 2, 2, 0], [2, 0, 2, 0]]}, {"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[1, 0, 0], [1, 1, 0], [0, 1, 0], [1, 1, 1], [0, 0, 1]]}, {"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 8, 0, 8, 0, 0, 0, 0, 0], [0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[0, 8, 0, 8, 0], [8, 8, 8, 8, 0], [0, 0, 0, 8, 8]]}], "test": [{"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0], [0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0], [0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0], [0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[0, 0, 6, 6, 6, 6], [0, 0, 6, 0, 0, 0], [6, 0, 6, 0, 0, 0], [6, 6, 6, 6, 0, 0]]}]}
training/8a004b2b.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"train": [{"input": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 4, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 4, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 8, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[4, 0, 0, 0, 0, 0, 4], [0, 2, 2, 3, 3, 0, 0], [0, 2, 2, 3, 3, 0, 0], [0, 3, 3, 8, 8, 0, 0], [0, 3, 3, 8, 8, 0, 0], [0, 0, 0, 0, 0, 0, 0], [4, 0, 0, 0, 0, 0, 4]]}, {"input": [[0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0], [0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 3, 3, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0], [0, 3, 3, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0], [0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0], [0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4]]}, {"input": [[0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0], [0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0], [0, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 3, 3, 3, 1, 1, 1, 0], [0, 0, 0, 0, 3, 3, 3, 1, 1, 1, 0], [0, 0, 0, 0, 3, 3, 3, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4]]}], "test": [{"input": [[4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 3, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "output": [[4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], [4, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 4]]}]}