Skip to main content

arc_agi/
runner.rs

1use std::str::FromStr;
2use std::hash::{DefaultHasher, Hash, Hasher};
3use peak_alloc::PeakAlloc;
4#[global_allocator]
5static PEAK: PeakAlloc = PeakAlloc;
6use strum::IntoEnumIterator;
7use std::panic;
8use std::panic::RefUnwindSafe;
9use std::collections::{BTreeSet, BTreeMap};
10use pathfinding::prelude::Matrix;
11use array_tool::vec::{Uniq, Join};
12use crate::cats::Colour::*;
13use crate::cats::GridCategory::*;
14use crate::cats::Direction::*;
15use crate::cats::Transformation::*;
16use crate::cats::*;
17use crate::examples::*;
18use crate::experiments::*;
19use crate::rules::*;
20//use crate::oldrules::*;
21use crate::grid::*;
22use crate::shape::*;
23use crate::cell::*;
24use crate::data::*;
25
26pub fn runner(data: &str, task_name: &str, experiment: &str, trans: &str, all: bool) {
27    //eprintln!("{data} {task_name} {experiment} {trans} {all}");
28    let start = std::time::Instant::now();
29    let tdata = load_files(data);
30    let is_test = data == "test";
31    let mut cnt = 0;
32    let mut output: BTreeMap<String, Vec<OutputData>> = BTreeMap::new();
33    let mut cap_cats: BTreeMap<GridCategory, i32> = BTreeMap::new();
34    let mut cap_todo: BTreeMap<GridCategory, i32> = BTreeMap::new();
35    let mut rule_tasks: BTreeMap<usize, Vec<String>> = BTreeMap::new();
36    let mut done: BTreeSet<String> = BTreeSet::new();
37    let mut tries: usize = 0;
38    let mut cat_hash: BTreeMap<u64, usize> = BTreeMap::new();
39
40    // Main processing outer loop
41    for (file_name, data) in tdata.iter() {
42        let task = file_name.to_string();
43
44        // already done or just one???
45        if done.contains(&task) || (!task_name.is_empty() && task_name != "all" && task != task_name) {
46            continue;
47        }
48
49        let mut examples = Examples::new(data);
50
51        // Do some shapes overay others?
52        if examples.cat.contains(&OverlayInSame) || examples.cat.contains(&OverlayOutSame) {
53            examples = Examples::new_cons(data);
54        }
55        println!("{task}: {:?}", examples.cat);
56
57        let transform = if trans == "all" || trans == "NoTrans" {
58            NoTrans
59        } else if let Ok(tr) = Transformation::from_str(trans) {
60            examples = examples.transformation(tr);
61
62            tr
63        } else {
64            NoTrans
65        };
66
67        let mut hasher = DefaultHasher::new();
68        examples.cat.hash(&mut hasher);
69        let hash = hasher.finish();
70        //println!("Hash is {:x}", hasher.finish());
71        *cat_hash.entry(hash).or_insert(0) += 1;
72
73        // Base pass with no transformations
74        let rule = pass(all, &task, experiment, &examples, transform, is_test, &mut output, &mut cap_cats, &mut cap_todo, &mut done, &mut tries);
75
76        if done.contains(&task) {
77            if let Some(rule) = rule {
78                if rule != usize::MAX {
79                    rule_tasks.entry(rule).or_default().push(task.clone());
80                }
81            }
82        }
83
84        // Experimental - needs more work!
85        if trans == "all" {
86            // Now check for transformed grids to make closures more generic
87            for transform in Transformation::iter() {
88                if transform == NoTrans || transform >= MirrorRowRotate90 { continue; }
89                //println!("{:?}", transform);
90
91                let ex_copy = examples.transformation(transform);
92
93                let _rule = pass(all, &task, experiment, &ex_copy, transform, is_test, &mut output, &mut cap_cats, &mut cap_todo, &mut done, &mut tries);
94            }
95        }
96
97        cnt += 1;
98    }
99//println!("{cat_hash:?}");
100
101    println!("Totals: {cap_cats:?}");
102
103    let cap_done: BTreeMap<GridCategory, i32> = cap_cats
104        .iter()
105        .map(|(cat, i)| {
106            if let Some(j) = cap_todo.get(cat) {
107                (*cat, *i - j)
108            } else {
109                (*cat, *i)
110            }
111        })
112        .collect();
113
114    if is_test {
115        create_output(true, &output);
116    }
117
118    println!("Complete: {cap_done:?}");
119    //println!("{done:?}");
120    if rule_tasks.len() > 0 {
121        format(&rule_tasks);
122        println!("Generalisation Ratio: {:.4}", done.len() as f64 / rule_tasks.len() as f64);
123    }
124    println!("Done = {}, To Do = {}, tries = {tries}", done.len(), cnt - done.len());
125
126    let timing = start.elapsed().as_secs() as f64 + start.elapsed().subsec_millis() as f64 / 1000.0;
127
128    println!("Elapsed time: {timing} secs");
129    println!("Used memory : {:.2} Mb", PEAK.current_usage_as_mb());
130}
131
132fn pass(all: bool, task: &str, experiment: &str, examples: &Examples, trans: Transformation, is_test: bool, output: &mut BTreeMap<String, Vec<OutputData>>, cap_cats: &mut BTreeMap<GridCategory, i32>, cap_todo: &mut BTreeMap<GridCategory, i32>, done: &mut BTreeSet<String>, tries: &mut usize) -> Option<usize> {
133    let cat = &examples.cat;
134    let targets: Vec<Grid> = examples.tests.iter().map(|test| test.output.grid.clone()).collect();
135
136    // used by many tasks
137    // 60a26a3e 50f325b5 : find shape in Grid
138    let colour_diffs = examples.io_colour_diff();
139    let all_colour_diffs = examples.io_all_colour_diff();
140    let colour_common = examples.io_colour_common();
141
142    let gc = BlankIn;
143    if all || cat.contains(&gc) { // 2 done
144        *cap_cats.entry(gc).or_insert(0) += 1;
145
146        let colour = examples.examples[0].output.grid.colour;
147
148        let func = &|ex: &Example| {
149            let odd = ex.cat.contains(&InOutSquareSameSizeOdd);
150            let mut grid;
151
152            if odd {
153                // TODO: Might be improved by using permutation of output grid?
154                grid = ex.input.grid.clone();
155
156                for (r, c) in grid.cells.keys() {
157                    if r % 2 == 0 || c % 2 == 0 || r == grid.cells.rows - 1 || c == grid.cells.columns - 1 {
158                        grid.cells[(r,c)].colour = colour;
159                    }
160                }
161            } else {
162                let sq = ex.cat.contains(&InOutSquareSameSize);
163
164                grid = ex.input.grid.do_circle(colour, sq);
165            }
166
167            grid
168        };
169
170        if let Some(rule) = run_experiment(task, 187, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
171
172        *cap_todo.entry(gc).or_insert(0) += 1;
173    }
174
175    let gc = BlackPatches;
176    if all || cat.contains(&gc) { // 3?
177        *cap_cats.entry(gc).or_insert(0) += 1;
178
179        // TODO: 981571dc.json and af22c60d.json mirrored
180        // 1e97544e.json e95e3d8e.json e95e3d8e.json 0dfd9992.json + test c3f564a4.json 29ec7d0e.json
181        let func = &|ex: &Example| {
182            if ex.input.black.is_empty() || !ex.input.grid.is_square() || ex.input.grid.size() < 16 * 16 {
183                return Grid::trivial();
184            }
185
186            // Split up any adjacent black patches
187            fn pop_bp(grid: &Grid, black_patches: &Shapes, out: &mut Shapes) {
188                for bp in black_patches.shapes.iter() {
189                    if grid.cells[(bp.orow,bp.ocol+bp.cells.columns-1)].colour != Black { 
190                        let sg = grid.subgrid(bp.orow, bp.cells.rows, bp.ocol, bp.cells.columns);
191                        let ss = sg.to_shapes_coloured();
192
193                        for s in ss.shapes.iter() {
194                            let b = if s.orow == 0 {
195                                if bp.orow + s.cells.rows >= grid.cells.rows || bp.ocol + s.cells.columns + 1 >= grid.cells.columns {
196                                    return;
197                                }
198                                let g = grid.subgrid(bp.orow, s.cells.rows, bp.ocol, s.cells.columns + 1);
199                                g.as_shape().to_position(bp.orow, bp.ocol)
200                            } else {
201                                if bp.orow + s.orow + s.cells.rows >= grid.cells.rows || bp.ocol + s.cells.columns + s.cells.columns + 1 >= grid.cells.columns {
202                                    return;
203                                }
204                                let g = grid.subgrid(bp.orow + s.orow, s.cells.rows, bp.ocol + s.cells.columns, s.cells.columns + 1);
205
206                                g.as_shape().to_position(bp.orow + s.orow, bp.ocol + s.cells.columns)
207                            };
208
209                            out.shapes.push(b);
210                        }
211                    } else {
212                        out.shapes.push(bp.clone());
213                    }
214                }
215            }
216
217            let mut grid = ex.input.grid.clone();
218            let bp_in = ex.input.black.clone();
219            let mut black_patches: Shapes = ex.input.black.clone_base();
220
221            pop_bp(&grid, &bp_in, &mut black_patches);
222
223            for it in 0 .. 4 {   // may need more that one iteration
224                'second:
225                for bp in black_patches.shapes.iter() {
226                    let r1 = if bp.orow > 0 { bp.orow - 1 } else { bp.orow };
227                    let r2 = if bp.orow + bp.cells.rows < grid.cells.rows { bp.orow + bp.cells.rows + 1 } else { bp.orow + bp.cells.rows };
228                    let c1 = if bp.ocol > 0 { bp.ocol - 1 } else { bp.ocol };
229                    let c2 = if bp.ocol + bp.cells.columns < grid.cells.columns { bp.ocol + bp.cells.columns + 1 } else { bp.ocol + bp.cells.columns };
230                    let m = grid.cells.slice(r1 .. r2, c1 .. c2);
231
232                    if let Ok(m) = m {
233                        let s = Shape::new(bp.orow, bp.ocol, &m);
234//s.show();
235                        let l = c2 - c1;
236                        let fw = m.windows(l).next().unwrap();
237                        let sc: Vec<_> = fw.iter().map(|c| c.colour).collect();
238                        for w in grid.cells.windows(l) {
239                            let fc: Vec<_> = w.iter().map(|c| c.colour).collect();
240                            if sc == fc && (fw[0].row != w[0].row || fw[0].col != w[0].col) {
241                                let patch = grid.get_patch(w[0].row, w[0].col, m.rows, m.columns);
242                                //if patch.is_full() && s.same_patch(&patch) {
243                                if s.same_patch(&patch) {
244                                    let sor = if s.orow > 0 { s.orow - 1 } else { s.orow };
245                                    let soc = if s.ocol > 0 { s.ocol - 1 } else { s.ocol };
246
247                                    grid.fill_patch_mut(&patch, sor, soc);
248
249                                    continue 'second;
250                                }
251                            }
252                        }
253                    } else {
254                        return Grid::trivial();
255                    }
256                }
257                if it % 2 == 0 {
258                    grid = ex.input.grid.rot_180();
259                    let bp_in = black_patches.clone();
260                    black_patches = grid.find_black_patches();
261                    pop_bp(&grid, &bp_in, &mut black_patches);
262                } else {
263                    grid = grid.rot_180();
264                }
265                if grid.full() {
266                    break
267                }
268            }
269//grid.show();
270
271            grid
272        };
273
274        if let Some(rule) = run_experiment(task, 292, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
275
276        let func = &|ex: &Example| {
277            if ex.input.black.is_empty() || !ex.input.grid.is_square() || ex.input.grid.size() < 20 * 20 {
278                return Grid::trivial();
279            }
280
281            let mut grid = ex.input.grid.clone();
282
283            grid.fill_border();
284
285            let mut pr = 0;
286            let mut pc = 0;
287            let mut lc = 0;     // if all else fails break the loop!
288
289            loop {
290                let black = grid.find_black_patches();
291
292                if black.is_empty() || lc >= 10 {
293                    break;
294                }
295
296                for p in black.shapes.iter() {
297                    let ra = if p.ocol == 0 { 
298                        Vec::new()
299                    } else if let Ok(xs) = grid.cells.slice(p.orow .. p.orow+p.cells.rows, p.ocol-1 .. p.ocol) {
300                        let xa: Vec<_> = xs.values().map(|c| c.colour).collect();
301                        if Colour::single_colour_vec(&xa) {
302                            Vec::new()
303                        } else {
304                            xa
305                        }
306
307                    } else {
308                        Vec::new()
309                    };
310                    let ca = if p.orow == 0 {
311                        Vec::new()
312                    } else if let Ok(ys) = grid.cells.slice(p.orow-1 .. p.orow, p.ocol .. p.ocol+p.cells.columns) {
313                        let ya: Vec<_> = ys.values().map(|c| c.colour).collect();
314                        if Colour::single_colour_vec(&ya) {
315                            Vec::new()
316                        } else {
317                            ya
318                        }
319                    } else {
320                        Vec::new()
321                    };
322                    if !ra.is_empty() && ra.len() >= ca.len() {
323                        let (xo, yo) = grid.find_row_seq(p.orow, p.ocol, &ra, p.cells.columns);
324                        if xo == usize::MAX && yo == usize::MAX || pr == xo && pc == yo {
325                            return Grid::trivial();
326                        }
327                        for r in 0 .. p.cells.rows {
328                            for c in 0 .. p.cells.columns {
329                                if grid.cells[(p.orow+r,p.ocol+c)].colour == Black && xo+r < grid.cells.rows && yo+1+c < grid.cells.columns {
330                                    grid.cells[(p.orow+r,p.ocol+c)] = grid.cells[(xo+r,yo+1+c)].clone();
331                                }
332                            }
333                        }
334
335                        pr = xo;
336                        pc = yo;
337                    }
338                    else if !ca.is_empty() {
339                        let (xo, yo) = grid.find_col_seq(p.orow, p.ocol, &ca, p.cells.rows);
340                        if xo == usize::MAX && yo == usize::MAX || pr == xo && pc == yo {
341                            return Grid::trivial();
342                        }
343                        for r in 0 .. p.cells.rows {
344                            for c in 0 .. p.cells.columns {
345                                if grid.cells[(p.orow+r,p.ocol+c)].colour == Black && xo+1+r < grid.cells.rows && yo+c < grid.cells.columns {
346                                    grid.cells[(p.orow+r,p.ocol+c)] = grid.cells[(xo+1+r,yo+c)].clone();
347                                }
348                            }
349                        }
350
351                        pr = xo;
352                        pc = yo;
353                    } else {
354                        return Grid::trivial();
355                    }
356                }
357                lc += 1;
358            }
359//grid.show();
360            
361            grid
362        };
363
364        if let Some(rule) = run_experiment(task, 382, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
365
366        if !examples.examples[0].input.black.is_empty() && !examples.examples[0].output.shapes.shapes.is_empty() {
367            let mut ccm = examples.examples[0].output.grid.as_shape().cell_colour_cnt_map();
368            // assume grid background and border shapes same colour for all tests
369            let bg = examples.examples[0].output.grid.cells[(0,0)].colour;
370            let border = examples.examples[0].output.shapes.shapes[0].colour;
371
372            ccm.remove(&bg);
373            ccm.remove(&border);
374
375            let func = |ex: &Example| {
376                if ccm.len() != 1 || !ex.input.black.shapes[0].is_square() {
377                    return Grid::trivial();
378                }
379
380                // Assume square
381                let side = ex.input.black.shapes[0].cells.rows;
382                let Some((inner, _)) = ccm.first_key_value() else { todo!() };
383                let mut grid = ex.input.grid.clone();
384
385                for s in ex.input.black.shapes.iter() {
386                    if s.orow == 0 || s.ocol == 0 {
387                        return Grid::trivial();
388                    }
389                    if s.orow <= 2 || s.ocol <= 2 || s.orow >= grid.cells.rows - side - 2 || s.ocol >= grid.cells.columns - side - 2 {
390                        grid.flood_fill_mut(s.orow, s.ocol, NoColour, border);
391                    } else {
392                        grid.flood_fill_mut(s.orow, s.ocol, NoColour, *inner);
393                    }
394                }
395//grid.show();
396
397                grid
398            };
399
400            if let Some(rule) = run_experiment(task, 418, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
401        }
402
403        let func = |ex: &Example| {
404            if colour_diffs.len() != 1 {
405                return Grid::trivial();
406            }
407            let colour = colour_diffs[0];
408            let g = &ex.input.grid;
409            let mut grid = g.clone();
410
411            grid.recolour_mut(Black, colour);
412
413            let shapes = grid.to_shapes_sq();
414
415            for s in shapes.shapes.iter() {
416                if s.is_pixel() && s.colour == colour {
417                    grid.cells[(s.orow, s.ocol)].colour = Black;
418                }
419            }
420
421            grid
422        };
423
424        let (rs, cs) = examples.examples[0].output.grid.dimensions();
425
426        if let Some(rule) = run_experiment(task, 444, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
427
428        let func = |ex: &Example| {
429            if !ex.cat.contains(&NxNIn(15)) || !ex.cat.contains(&NxNOut(3)) || !colour_diffs.is_empty() {
430                return Grid::trivial();
431            }
432
433            let mut grid = Grid::new(rs, cs, ex.input.grid.colour);
434
435            for s in ex.input.black.shapes.iter() {
436                grid.cells[(s.orow / 5,s.ocol / 5)].colour = Black;
437            }
438//grid.show();
439
440            grid
441        };
442
443        if let Some(rule) = run_experiment(task, 461, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
444
445        let func = |ex: &Example| {
446            if ex.input.shapes.shapes.is_empty() {
447                return Grid::trivial();
448            }
449
450            let mut shapes = ex.input.shapes.clone_base();
451
452            for s in ex.input.shapes.shapes.iter() {
453                let (dir,_) = s.has_arm(5);
454
455                if dir == Other {
456                    let sn = s.recolour(Black, s.colour);
457
458                    shapes.shapes.push(sn.clone());
459                }
460            }
461
462            for s in ex.input.shapes.shapes.iter() {
463                let (dir,len) = s.has_arm(5);
464
465                if dir == Other {
466                    continue;
467                }
468
469                let sn = match dir {
470                    Up => {
471                        let s = s.subshape(len, s.cells.rows - len, 0, s.cells.columns);
472
473                        if s.orow >= len {
474                            s.to_position(s.orow - len, s.ocol)
475                        } else {
476                            return Grid::trivial();
477                        }
478                    },
479                    Down => {
480                        let s = s.subshape(0, s.cells.rows - len, 0, s.cells.columns);
481                        s.to_position(s.orow + len, s.ocol)
482                    },
483                    Left => {
484                        let s = s.subshape(0, s.cells.rows, len, s.cells.columns - len);
485                        if s.ocol >= len {
486                            s.to_position(s.orow, s.ocol - len)
487                        } else {
488                            return Grid::trivial();
489                        }
490                    },
491                    Right => {
492                        let s = s.subshape(0, s.cells.rows, 0, s.cells.columns - len);
493                        s.to_position(s.orow, s.ocol + len)
494                    },
495                    _ => todo!(),   // Should never happen!
496                };
497
498                shapes.shapes.push(sn.clone());
499            }
500
501            shapes.to_grid()
502        };
503
504        if let Some(rule) = run_experiment(task, 522, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
505
506        // TODO BlackPatches okay but cannot find test!!!
507        let func = |ex: &Example| {
508            if !ex.cat.contains(&OverlayInDiff) || !ex.cat.contains(&OverlayOutDiff) || ex.input.black.shapes.len() != 1 {
509                return Grid::trivial();
510            }
511
512            let g = &ex.input.grid;
513            let black = &ex.input.black.shapes[0];
514            let mut grid = ex.input.grid.clone();
515
516            for (r, c) in g.cells.keys() {
517                if g.cells[(r,c)].colour == Black {
518                    if g.cells[(g.cells.rows - r - 1,c)].colour != Black {
519                        grid.cells[(r,c)].colour = g.cells[(g.cells.rows - r - 1,c)].colour;
520                    } else {
521                        grid.cells[(r,c)].colour = g.cells[(r,g.cells.columns - c - 1)].colour;
522                    }
523                }
524            }
525
526//ex.output.grid.show();
527            grid = grid.subgrid(black.orow, black.cells.rows, black.ocol, black.cells.columns);
528//grid.show();
529
530            grid
531        };
532
533        if let Some(rule) = run_experiment(task, 551, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
534
535        if colour_diffs.len() == 2 {
536            for i in 0 .. 2 {
537                let func = |ex: &Example| {
538                    if ex.input.shapes.shapes.is_empty() {
539                        return Grid::trivial();
540                    }
541                    let mut shapes = ex.input.shapes.clone();
542        //println!("{colour_diffs:?}");
543
544                    for s in ex.input.shapes.shapes.iter() {
545                        let (dir, _) = s.has_arm(1);
546                        let mut ns = if dir == Up || dir == Down {
547                            let colour = colour_diffs[if i == 0 { 0 } else { 1 }];
548                            s.mirrored_r().recolour(s.colour, colour)
549                        } else if dir == Left || dir == Right {
550                            let colour = colour_diffs[if i == 1 { 0 } else { 1 }];
551                            s.mirrored_c().recolour(s.colour, colour)
552                        } else {
553                            s.clone()
554                        };
555
556                        match dir {
557                            Left => ns.to_position_mut(s.orow, s.ocol + s.cells.columns + 1),
558                            Right => if s.ocol > s.cells.columns {
559                                ns.to_position_mut(s.orow, s.ocol - s.cells.columns - 1)
560                            } else {
561                                return Grid::trivial();
562                            },
563                            Down => if s.orow > s.cells.rows {
564                                ns.to_position_mut(s.orow - s.cells.rows - 1, s.ocol)
565                            } else {
566                                return Grid::trivial();
567                            },
568                            Up => ns.to_position_mut(s.orow + s.cells.rows + 1, s.ocol),
569                            _ => (),
570                        }
571
572                        shapes.shapes.push(ns);
573                    }
574        //shapes.trim_to_grid().show();
575
576                    shapes.trim_to_grid()
577                };
578
579                if let Some(rule) = run_experiment(task, 597, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
580            }
581        }
582
583        // Should work, bug in data
584        let func = |ex: &Example| {
585            if ex.input.shapes.shapes.is_empty() || colour_common.len() != 3 {
586                return Grid::trivial();
587            }
588            let mut colour_common = colour_common.clone();
589            let mut orig_colour = NoColour;
590
591            let (div_colour, mut shapes) = ex.input.grid.full_dim_split(&ex.input.shapes);
592
593            colour_common.retain(|&c| c != div_colour);
594
595            for s in shapes.shapes.iter_mut() {
596                if orig_colour == NoColour {
597                    colour_common.retain(|&c| c != s.colour);
598                    orig_colour = s.colour;
599                }
600
601                if colour_common.is_empty() {
602                    return Grid::trivial();
603                }
604
605                if s.colour == div_colour {
606                    break
607                }
608
609                s.recolour_mut(colour_common[0], orig_colour);
610            }
611
612            shapes.to_grid()
613        };
614
615        if let Some(rule) = run_experiment(task, 633, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
616
617        let func = |ex: &Example| {
618            if ex.input.shapes.shapes.is_empty() {
619                return Grid::trivial();
620            }
621
622            let mut cc = ex.input.shapes.colour_cnt();
623            let mut shapes = ex.input.shapes.clone_base();
624
625            for s in ex.input.shapes.shapes.iter() {
626                if !s.is_pixel() {
627                    cc.remove(&s.colour);
628                }
629            }
630
631            for s in ex.input.shapes.shapes.iter() {
632                if !s.is_pixel() {
633                    let mut ns = s.clone();
634                    let bg_cnt = s.bg_count();
635                    let colour: Vec<_> = cc.iter().filter(|&(&c,&s)|c != ns.colour && (s == if bg_cnt % 2 == 0 { bg_cnt / 2 } else { bg_cnt / 2 + 1})).collect();
636                    
637                    if colour.len() != 1 {
638                        return Grid::trivial();
639                    }
640
641                    // Every other pixel set
642                    let mut toddle = true;
643
644                    for ((r, c), cell) in ns.cells.items_mut() {
645                        if cell.colour == Black {
646                            // reset per line
647                            if r % 2 == 0 && c <= 1 {
648                                toddle = false;
649                            }
650                            if toddle {
651                                cell.colour = *colour[0].0;
652                            }
653                            toddle = !toddle;
654                        }
655                    }
656
657                    shapes.shapes.push(ns);
658                }
659            }
660
661//shapes.to_grid().show();
662            shapes.to_grid()
663        };
664
665        if let Some(rule) = run_experiment(task, 683, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
666
667        let func = |ex: &Example| {
668            if ex.input.shapes.shapes.is_empty() {
669                return Grid::trivial();
670            }
671
672            let mut shapes = ex.input.shapes.clone();
673
674            shapes.shapes.sort_by(|a, b| {
675                let (_, a_cc) = a.colour_cnt(true);
676                let (_, b_cc) = b.colour_cnt(true);
677
678                a_cc.cmp(&b_cc)
679            });
680
681            let mut pos = 0;
682
683            for s in shapes.shapes.iter_mut() {
684                if s.cells.rows > s.cells.columns {
685                    s.to_position_mut(s.orow, pos);
686
687                    pos += s.cells.columns + 1;
688                } else {
689                    s.to_position_mut(pos, s.ocol);
690
691                    pos += s.cells.rows + 1;
692                }
693            }
694
695            shapes.to_grid()
696        };
697
698        if let Some(rule) = run_experiment(task, 716, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
699
700        let func = |ex: &Example| {
701            if colour_diffs.len() != 1 {
702                return Grid::trivial();
703            }
704
705            ex.input.grid.rip(colour_diffs[0])
706        };
707
708        if let Some(rule) = run_experiment(task, 726, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
709
710        let func = |ex: &Example| {
711            let ss = ex.input.coloured_shapes.split_size(12);
712
713            if !colour_diffs.is_empty() && ss.shapes.len() < 2 {
714                return Grid::trivial();
715            }
716
717            let mut shapes = ex.input.coloured_shapes.clone_base();
718            let mut last_size = usize::MAX;
719
720            for s in ss.shapes.iter() {
721                if s.size() > 12 {
722                    let s = s.shrink_border_n(3);
723
724                    if s.size() == 0 || last_size != usize::MAX && last_size != s.size() {
725                        return Grid::trivial();
726                    }
727
728                    if last_size == usize::MAX {
729                        last_size = s.size();
730                    }
731
732                    shapes.shapes.push(s);
733                }
734            }
735            shapes.shapes.sort();
736//shapes.show();
737
738            let shape = shapes.majority_cell();
739
740            if shape.size() == 0 {
741                return Grid::trivial();
742            }
743
744            let (rrep, crep) = shapes.find_repeats();
745            let (rgap, cgap) = shapes.find_gaps();
746
747            shape.fit_chequer(rrep, crep, shapes.shapes[0].orow, shapes.shapes[0].ocol, rgap, cgap, ex.input.grid.cells.rows, ex.input.grid.cells.columns, &|s, _, _| s.clone()).to_grid()
748        };
749
750        if let Some(rule) = run_experiment(task, 768, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
751
752        let func = |ex: &Example| {
753            let pixels = ex.input.shapes.get_pixels();
754            let mut all_shapes = ex.input.shapes.clone();
755
756            if !colour_diffs.is_empty() || pixels.shapes.len() * 2 != all_shapes.shapes.len() {
757                return Grid::trivial();
758            }
759            let mut i = 0;
760
761            for ss in ex.input.shapes.shapes.iter() {
762                if !ss.is_pixel() {
763                    let mut shapes = ss.get_joined();
764
765                    for s in shapes.shapes.iter_mut() {
766                        s.fill_centre_mut(pixels.shapes[i].colour);
767
768                        all_shapes.shapes.push(s.clone());
769                    }
770
771                    i += 1;
772                }
773            }
774//all_shapes.to_grid_transparent().show();
775
776            all_shapes.to_grid_transparent()
777        };
778
779        if let Some(rule) = run_experiment(task, 797, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
780
781        let func = |ex: &Example| {
782            if colour_diffs.len() != 1 || ex.input.shapes.len() < 2 {
783                return Grid::trivial();
784            }
785
786            let (rg, cg) = ex.input.shapes.find_gaps();
787            let ss = &ex.input.shapes.shapes;
788            let mut grid = ex.input.grid.clone();
789
790            for (r, c) in (ss[ss.len() - 1].orow + rg + 1 .. grid.cells.rows).step_by(rg + 1).zip((ss[ss.len() - 1].ocol + cg + 1 .. grid.cells.columns).step_by(cg + 1)) {
791                grid.cells[(r,c)].colour = colour_diffs[0];
792            }
793//grid.show();
794
795            grid
796        };
797
798        if let Some(rule) = run_experiment(task, 816, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
799
800        let func = |ex: &Example| {
801            if ex.input.shapes.len() != 5 {
802                return Grid::trivial();
803            }
804            let in_shapes = ex.input.shapes.clone();
805            let rows = in_shapes.shapes[1].cells.rows;
806            let cols = in_shapes.shapes[1].cells.columns;
807            let (cr, cc) = in_shapes.shapes[0].mid_pixel();
808
809            let mut shapes = Shapes::new_sized(rows * 2, cols * 2);
810
811            for s in in_shapes.shapes.iter() {
812                if s.size() != ex.input.shapes.size() {
813                    let ns = if s.orow < cr && s.ocol < cc {
814                        s.to_position(0, 0)
815                    } else if s.orow < cr && s.ocol >= cc {
816                        s.to_position(0, cols)
817                    } else if s.orow >= cr && s.ocol < cc {
818                        s.to_position(rows, 0)
819                    } else {
820                        s.to_position(rows, cols)
821                    };
822
823                    shapes.shapes.push(ns);
824                }
825            }
826//shapes.to_grid().show();
827
828            shapes.to_grid()
829        };
830
831        if let Some(rule) = run_experiment(task, 849, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
832
833        let func = |ex: &Example| {
834            if colour_diffs.len() != 1 {
835                return Grid::trivial();
836            }
837
838            let mut grid = ex.input.grid.clone();
839            let (min_r, min_c, max_r, max_c) = grid.corners();
840            let (r,c) = grid.centre_of_symmetry();
841
842            if r == 0 || c == 0 || r >= grid.cells.rows - 1 || c >= grid.cells.columns - 1 {
843                return Grid::trivial();
844            }
845
846            grid.cells[(r,c)].colour = colour_diffs[0];
847            grid.cells[(r-1,c-1)].colour = grid.cells[(min_r,min_c)].colour;
848            grid.cells[(r-1,c+1)].colour = grid.cells[(min_r,max_c)].colour;
849            grid.cells[(r+1,c-1)].colour = grid.cells[(max_r,min_c)].colour;
850            grid.cells[(r+1,c+1)].colour = grid.cells[(max_r,max_c)].colour;
851
852            grid
853        };
854
855        if let Some(rule) = run_experiment(task, 873, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
856
857        let out_csm = examples.colour_shape_map(true);
858        let cam = examples.colour_attachment_map(true);
859
860        let func = |ex: &Example| {
861            if all_colour_diffs.len() != 1 {
862                return Grid::trivial();
863            }
864            let (div_colour, mut shapes) = ex.input.grid.full_dim_split(&ex.input.shapes);
865
866            shapes.shapes.sort_by(|a, b| (a.ocol,a.orow).cmp(&(b.ocol,b.orow)));
867
868            let mut start = Shape::trivial();
869            let mut div = Shape::trivial();
870
871            for s in shapes.shapes.iter() {
872                if s.is_pixel() {
873                    start = s.clone();
874                } else if s.cells.rows == ex.input.grid.cells.rows {
875                    div = s.clone();
876                }
877            }
878
879            let mut new_shapes = Shapes::new_sized(ex.input.grid.cells.rows, div.ocol);
880            let mut r = 1;
881
882            if start.ocol <= div.ocol {
883                return Grid::trivial();
884            }
885
886            let mut c = start.ocol - div.ocol - 1;
887
888            start.to_position_mut(0, c);
889            new_shapes.shapes.push(start.clone());
890
891            for s in shapes.shapes.iter() {
892                if !s.is_pixel() && s.colour != div_colour {
893                    if let Some(os) = out_csm.get(&s.colour) {
894                        if let Some(left) = cam.get(&s.colour) {
895                            let ns;
896
897                            if *left {
898                                ns = os.to_position(r, c);
899                                c += os.cells.columns - 1;
900                            } else {
901                                if c < os.cells.columns - 1 {
902                                    return Grid::trivial();
903                                }
904
905                                c -= os.cells.columns - 1;
906                                ns = os.to_position(r, c);
907                            };
908
909                            new_shapes.shapes.push(ns);
910                            r += os.cells.rows;
911                        }
912                    }
913                }
914            }
915
916//new_shapes.to_grid().show();
917            new_shapes.to_grid()
918        };
919
920        if let Some(rule) = run_experiment(task, 938, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
921
922        let func = |ex: &Example| {
923            if !all_colour_diffs.is_empty() {
924                return Grid::trivial();
925            }
926
927            let (div_colour, mut shapes) = ex.input.grid.full_dim_split(&ex.input.shapes);
928            let div = shapes.find_by_colour(div_colour);
929            let mut grid = ex.input.grid.clone();
930
931            // get the sort order right!
932            for s in shapes.shapes.iter() {
933                if s.colour != div_colour {
934                    if div.orow == ex.input.grid.cells.rows - 1 && div.cells.rows == 1 {
935                        shapes.shapes.sort_by(|a, b| a.orow.cmp(&b.orow));
936                    } else if div.ocol == ex.input.grid.cells.columns - 1 && div.cells.columns == 1 {
937                        shapes.shapes.sort_by(|a, b| a.ocol.cmp(&b.ocol));
938                    } else if div.orow == 0 && div.cells.rows == 1 {
939                        shapes.shapes.sort_by(|a, b| b.orow.cmp(&a.orow));
940                    } else {
941                        shapes.shapes.sort_by(|a, b| b.ocol.cmp(&a.ocol));
942                    }
943                    break;
944                }
945            }
946
947            for s in shapes.shapes.iter() {
948                if s.colour != div_colour {
949                    if div.orow == ex.input.grid.cells.rows - 1 && div.cells.rows == 1 {
950                        for r in s.orow .. ex.input.grid.cells.rows - 1 {
951                            for c in 0 .. s.cells.columns {
952                                grid.cells[(r,c+s.ocol)].colour = s.colour;
953                            }
954                        }
955                    } else if div.ocol == ex.input.grid.cells.columns - 1 && div.cells.columns == 1 {
956                        for r in 0 .. s.cells.rows {
957                            for c in s.ocol .. ex.input.grid.cells.columns - 1 {
958                                grid.cells[(r+s.orow,c)].colour = s.colour;
959                            }
960                        }
961                    } else if div.orow == 0 && div.cells.rows == 1 {
962                        for r in (1 ..= s.orow).rev() {
963                            for c in s.ocol .. s.ocol + s.cells.columns {
964                                grid.cells[(r,c)].colour = s.colour;
965                            }
966                        }
967                    } else {
968                        for r in s.orow .. s.orow + s.cells.rows {
969                            for c in (1 ..= s.ocol).rev() {
970                                grid.cells[(r,c)].colour = s.colour;
971                            }
972                        }
973                    }
974                }
975            }
976
977//grid.show();
978            grid
979        };
980
981        if let Some(rule) = run_experiment(task, 999, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
982
983        let func = |ex: &Example| {
984            let mut shapes = ex.input.shapes.clone_base();
985
986            for s in ex.input.shapes.shapes.iter() {
987                for s2 in ex.input.shapes.shapes.iter() {
988                    if s != s2 && s.container(&s2) {
989                        let (s_r, _) = s.centre_of_exact();
990                        let (s2_r, _) = s2.centre_of_exact();
991                        shapes.shapes.push(s.clone());
992                        shapes.shapes.push(s2.clone());
993
994                        let sm = if s_r == s2_r {
995                            let sm = s2.mirrored_c();
996
997                            if sm.ocol + sm.cells.columns * 2 + 1 < s.ocol + s.cells.columns {
998                                let extra = if s.cells.columns % 2 != 0 { 1 } else { 0 };
999                                sm.to_position(sm.orow, s.ocol + s.cells.columns / 2 + extra)
1000                            } else {
1001                                sm.to_position(sm.orow, s.ocol + sm.cells.columns)
1002                            }
1003                        } else {
1004                            let sm = s2.mirrored_r();
1005
1006                            if sm.orow + sm.cells.rows * 2 + 1 < s.orow + s.cells.rows {
1007                                let extra = if s.cells.rows % 2 != 0 { 1 } else { 0 };
1008                                sm.to_position(s.orow + s.cells.rows / 2 + extra, sm.ocol)
1009                            } else {
1010                                sm.to_position(s.orow + sm.cells.rows, sm.ocol)
1011                            }
1012                        };
1013
1014                        shapes.shapes.push(sm);
1015                    }
1016                }
1017            }
1018
1019            shapes.to_grid()
1020        };
1021
1022        if let Some(rule) = run_experiment(task, 1040, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1023
1024        let func = |ex: &Example| {
1025            if !colour_diffs.is_empty() {
1026                return Grid::trivial();
1027            }
1028            let sc = ex.input.shapes.size_cnt();
1029            if sc.len() != 1 {
1030                return Grid::trivial();
1031            }
1032            let Some((_, n)) = sc.first_key_value() else { todo!() };
1033            // TODO: strict assumption, make more generic
1034            if *n != 4 {
1035                return Grid::trivial();
1036            }
1037            let (rs, cs) = ex.input.shapes.shapes[0].dimensions();
1038            if rs != cs {
1039                return Grid::trivial();
1040            }
1041
1042            let mut shapes = Shapes::new_sized(rs * 2 + 1, cs * 2 + 1);
1043
1044            let corners = ex.input.shapes.all_corners();
1045
1046            let mut row = 0;
1047            let mut col = 0;
1048
1049            for (i, (r, c)) in corners.iter().enumerate() {
1050                let s = ex.input.shapes.nearest_shape(*r, *c);
1051
1052                shapes.shapes.push(s.to_position(row, col));
1053
1054                match i {
1055                    0 => col = cs + 1,
1056                    1 => row = rs + 1,
1057                    2 => col = 0,
1058                    3 => row = 0,
1059                    _ => todo!(),
1060                }
1061            }
1062
1063            shapes.to_grid()
1064        };
1065
1066        if let Some(rule) = run_experiment(task, 1084, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1067
1068        let func = |ex: &Example| {
1069            if all_colour_diffs.len() != 1 {
1070                return Grid::trivial();
1071            }
1072            let sc = ex.input.shapes.size_cnt();
1073            if sc.len() != 2 || ex.input.shapes.shapes.len() < 3 || all_colour_diffs.len() != 1 {
1074                return Grid::trivial();
1075            }
1076
1077            let mut grid = Grid::new(2, 2, Black);
1078
1079            let corners = ex.input.shapes.all_corners();
1080
1081            for s in ex.input.shapes.shapes.iter() {
1082                if s.colour != all_colour_diffs[0] {
1083                    match s.nearest_point_idx(&corners) {
1084                        0 => grid.cells[(0,0)].colour = s.colour,
1085                        1 => grid.cells[(0,1)].colour = s.colour,
1086                        2 => grid.cells[(1,1)].colour = s.colour,
1087                        3 => grid.cells[(1,0)].colour = s.colour,
1088                        _ => todo!(),
1089                    }
1090                }
1091            }
1092
1093//grid.show();
1094            grid
1095        };
1096
1097        if let Some(rule) = run_experiment(task, 1121, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1098
1099        let func = |ex: &Example| {
1100            if !colour_diffs.is_empty() {
1101                return Grid::trivial();
1102            }
1103
1104            let ccm = ex.input.shapes.shape_colour_cnt_map();
1105
1106            let mut grid = Grid::new(ex.input.grid.cells.rows, ex.input.grid.cells.columns, Black);
1107
1108            let mut box_tlr = 0;
1109            let mut box_tlc = 0;
1110
1111            for (col, sv) in ccm.iter() {
1112                if sv.len() == 1 {
1113                    box_tlr = sv[0].orow;
1114                    box_tlc = sv[0].ocol;
1115                    let box_brr = box_tlr + sv[0].cells.rows;
1116                    let box_brc = box_tlc + sv[0].cells.columns;
1117
1118                    grid.fill_patch_coord_mut(box_tlr, box_tlc, box_brr - box_tlr, box_brc - box_tlc, *col);
1119                }
1120            }
1121
1122            for (col, sv) in ccm.iter() {
1123                if sv.len() > 1 {
1124                    let (mut tlr, mut tlc, brr, brc) = Shapes::new_shapes(&sv).corners();
1125                    
1126                    let rlen = brr - tlr - 1;
1127                    let clen = brc - tlc - 1;
1128
1129                    tlr = tlr.max(box_tlr);
1130                    tlc = tlc.max(box_tlc);
1131
1132                    if grid.cells.rows < tlr + rlen || grid.cells.columns < tlc + clen {
1133                        return Grid::trivial();
1134                    }
1135
1136                    grid.fill_patch_coord_mut(tlr, tlc, rlen, clen, *col);
1137                }
1138            }
1139//grid.show();
1140
1141            grid
1142        };
1143
1144        if let Some(rule) = run_experiment(task, 1168, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1145
1146        let func = |ex: &Example| {
1147            if ex.input.shapes.shapes.len() < 5 {
1148                return Grid::trivial();
1149            }
1150
1151            let mut shapes = ex.input.shapes.clone();
1152            let idx = &ex.input.shapes.shapes[0];
1153            let mut colour = NoColour;
1154
1155            for s in ex.input.shapes.shapes.iter() {
1156                if s.size() == 1 && s.orow < idx.cells.rows && s.ocol < idx.cells.columns {
1157                    colour = s.colour;
1158                }
1159            }
1160
1161            for s in shapes.shapes.iter_mut() {
1162                if s.colour == colour && (s.orow >= idx.cells.rows || s.ocol >= idx.cells.columns) {
1163                    s.force_recolour_mut(Black);
1164                }
1165            }
1166
1167            shapes.to_grid()
1168        };
1169
1170        if let Some(rule) = run_experiment(task, 1194, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1171
1172        let func = |ex: &Example| {
1173            let colours = Uniq::uniq(&colour_common, all_colour_diffs.clone());
1174            if ex.input.shapes.shapes.len() < 2 || colour_diffs.len() != 1 || colours.len() != 1 {
1175                return Grid::trivial();
1176            }
1177
1178            let (tlr, tlc, brr, brc) = ex.input.shapes.corners();
1179            let mut grid = ex.input.grid.clone();
1180
1181            grid.draw_mut(Down, 0, tlc, colours[0]);
1182            grid.draw_mut(Down, 0, brc - 1, colours[0]);
1183            grid.draw_mut(Right, tlr, 0, colours[0]);
1184            grid.draw_mut(Right, brr - 1, 0, colours[0]);
1185
1186            grid.flood_fill_mut(tlr + 1, tlc + 1, NoColour, colour_diffs[0]);
1187
1188//grid.show();
1189            grid
1190        };
1191
1192        if let Some(rule) = run_experiment(task, 1216, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1193
1194        if colour_diffs.len() == 1 {
1195            let mut gap = 0;
1196
1197            for (i, s) in examples.examples[0].output.shapes.shapes.iter().enumerate() {
1198                if i == 0 && s.colour == colour_diffs[0] {
1199                    continue;
1200                } else if s.colour == colour_diffs[0] {
1201                    gap = i;
1202                    break;
1203                }
1204            }
1205
1206            let func = |ex: &Example| {
1207                if ex.input.shapes.shapes.len() < 2 || gap == 0 {
1208                    return Grid::trivial();
1209                }
1210
1211                let mut shapes = ex.input.shapes.clone();
1212
1213                for (i, s) in shapes.shapes.iter_mut().enumerate() {
1214                    if i % gap == 0 {
1215                        s.force_recolour_mut(colour_diffs[0]);
1216                    }
1217                }
1218
1219//shapes.to_grid().show();
1220                shapes.to_grid()
1221            };
1222
1223            if let Some(rule) = run_experiment(task, 1247, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1224        }
1225
1226        let func = |ex: &Example| {
1227            if ex.input.shapes.shapes.len() < 4 {
1228                return Grid::trivial();
1229            }
1230
1231            let mut grid = ex.input.grid.clone();
1232            let mut shapes: BTreeMap<Colour, Vec<&Shape>> = BTreeMap::new();
1233
1234            for s in ex.input.shapes.shapes.iter() {
1235                if s.size() != ex.input.grid.size() {
1236                    shapes.entry(s.colour).and_modify(|sv| sv.push(s)).or_insert(vec![s]);
1237                }
1238            }
1239
1240            for (_colour, shapes) in shapes.iter() {
1241                let origins = Shapes::origins(shapes);
1242
1243                if origins.is_empty() {
1244                    return Grid::trivial();
1245                }
1246
1247                for (i, (r, c)) in origins.iter().enumerate() {
1248                    if !Shapes::contains_origin(shapes, *r, *c) {
1249                        let posn = if i == 0 { 3 } else { i - 1 };
1250
1251                        if posn >= shapes.len() {
1252                            return Grid::trivial();
1253                        }
1254
1255                        let s = if posn % 2 == 0 {
1256                            shapes[posn].mirrored_c()
1257                        } else {
1258                            shapes[posn].mirrored_r()
1259                        };
1260
1261                        let s = s.to_position(*r, *c);
1262
1263                        grid.copy_shape_to_grid_mut(&s);
1264                    }
1265                }
1266            }
1267//grid.show();
1268            grid
1269        };
1270
1271        if let Some(rule) = run_experiment(task, 1295, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1272
1273        let func = |ex: &Example| {
1274            if ex.input.shapes.shapes.len() < 10 || colour_common.len() < 5 {
1275                return Grid::trivial();
1276            }
1277
1278            let mut cc: BTreeMap<Colour, usize> = BTreeMap::new();
1279            let mut corners: Vec<Shape> = Vec::new();
1280
1281            for s in ex.input.shapes.shapes.iter() {
1282                if s.size() == 4 {
1283                    *cc.entry(s.colour).or_insert(0) += 1;
1284                    corners.push(s.clone());
1285                }
1286            }
1287
1288            let (_, max_col) = if let Some(col) = cc.iter().map(|(&c, &n)| (n, c)).max() {
1289                col
1290            } else {
1291                (0, NoColour)
1292            };
1293            let (_, min_col) = if let Some(col) = cc.iter().map(|(&c, &n)| (n, c)).min() {
1294                col
1295            } else {
1296                (0, NoColour)
1297            };
1298            let (tlr, tlc, brr, brc) = Shapes::vec_corners(&corners);
1299            let mut grid = ex.input.grid.clone();
1300
1301            if brr - tlr < 2 || brc - tlc < 2 || brr == tlr || brc == tlc || tlr == 0 || tlc == 0 || grid.cells.columns == brc || grid.cells.rows == brr {
1302                return Grid::trivial();
1303            }
1304
1305            let centre = Shape::new_sized_coloured_position(tlr, tlc, brr - tlr, brc - tlc, max_col);
1306            let scentre = Shape::new_sized_coloured_position(tlr + 1, tlc + 1, brr - tlr - 2, brc - tlc - 2, min_col);
1307            let left = Shape::new_sized_coloured_position(tlr, 0, brr - tlr, tlc, min_col);
1308            let right = Shape::new_sized_coloured_position(tlr, brc, brr - tlr, grid.cells.columns - brc, min_col);
1309            let up = Shape::new_sized_coloured_position(0, tlc, tlr, brc - tlc, min_col);
1310            let down = Shape::new_sized_coloured_position(brr, tlc, grid.cells.rows - brr, brc - tlc, min_col);
1311            grid.copy_shape_to_grid_mut(&centre);
1312            grid.copy_shape_to_grid_mut(&scentre);
1313            grid.copy_shape_to_grid_mut(&left);
1314            grid.copy_shape_to_grid_mut(&right);
1315            grid.copy_shape_to_grid_mut(&up);
1316            grid.copy_shape_to_grid_mut(&down);
1317
1318            for s in ex.input.shapes.shapes.iter() {
1319                if s.size() == 1 && grid.cells[(s.orow,s.ocol)].colour == min_col {
1320                    //grid.copy_shape_to_grid_mut(&s);
1321                    if s.orow <= tlr && (s.orow == 0 || grid.cells[(s.orow-1,s.ocol)].colour == min_col) {
1322                        grid.draw_bg_mut(Up, s.orow, s.ocol, s.colour, min_col);
1323                    } else if s.orow >= brr && (s.orow == grid.cells.rows - 1 || grid.cells[(s.orow+1,s.ocol)].colour == min_col) {
1324                        grid.draw_bg_mut(Down, s.orow, s.ocol, s.colour, min_col);
1325                    } else if s.ocol <= tlc && (s.ocol == 0 || grid.cells[(s.orow,s.ocol-1)].colour == min_col) {
1326                        grid.draw_bg_mut(Left, s.orow, s.ocol, s.colour, min_col);
1327                    } else if s.ocol >= brc {
1328                        grid.draw_bg_mut(Right, s.orow, s.ocol, s.colour, min_col);
1329                    }
1330                }
1331            }
1332            grid
1333        };
1334
1335        if let Some(rule) = run_experiment(task, 1359, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1336
1337        let func = |ex: &Example| {
1338            if ex.input.shapes.shapes.len() < 5 || ex.input.coloured_shapes.shapes.len() != ex.input.shapes.shapes.len() {
1339                return Grid::trivial();
1340            }
1341
1342            let ccm = ex.input.shapes.shape_colour_cnt_map();
1343            let r = ccm.len();
1344            let c = if let Some(c) = ccm.iter().map(|(_,vs)| vs.len()).max() {
1345                c
1346            } else {
1347                0
1348            };
1349
1350            if c == 0 {
1351                return Grid::trivial();
1352            }
1353
1354            let mut grid = Grid::new(r, c, Black);
1355            let mut i = 0;
1356
1357            let mut cs: Vec<(usize, Colour)> = ccm.iter().map(|(colour,vs)| (vs.len(), *colour)).collect();
1358
1359            cs.sort_by(|a, b| b.cmp(a));
1360
1361            for (len, colour) in cs.iter() {
1362                for j in 0 .. *len {
1363                    grid.cells[(i, c - len + j)].colour = *colour;
1364                }
1365
1366                i += 1;
1367            }
1368
1369//grid.show();
1370            grid
1371        };
1372
1373        if let Some(rule) = run_experiment(task, 1397, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1374
1375        let func = |ex: &Example| {
1376            if ex.input.coloured_shapes.shapes.len() < 2 {
1377                return Grid::trivial();
1378            }
1379            let mut posn = 0;
1380            let mut horizontal = true;
1381            let mut shapes = ex.input.coloured_shapes.clone();
1382
1383            for s in ex.input.coloured_shapes.shapes.iter() {
1384                if s.orow == 0 && s.cells.rows == ex.input.grid.cells.rows {
1385                    horizontal = false;
1386                    posn = s.ocol;
1387
1388                } else if s.ocol == 0 && s.cells.columns == ex.input.grid.cells.columns {
1389                    horizontal = true;
1390                    posn = s.orow;
1391                } 
1392            }
1393
1394            for s in ex.input.coloured_shapes.shapes.iter() {
1395                if (s.orow != 0 || s.cells.rows != ex.input.grid.cells.rows) && (s.ocol != 0 || s.cells.columns != ex.input.grid.cells.columns) {
1396                    let ccm = s.cell_colour_cnt_map();
1397
1398                    if ccm.len() != 2 {
1399                        return Grid::trivial();
1400                    }
1401
1402                    let colours: Vec<Colour> = ccm.iter().map(|(c, _)| *c).collect();
1403                    shapes.shapes.push(s.toddle_colour(colours[0], colours[1]));
1404
1405                    let s = if horizontal {
1406                        if posn > s.orow {
1407                            s.mirrored_r().to_position(posn + 2, s.ocol)
1408                        } else {
1409                            if posn < s.cells.rows + 1 {
1410                                return Grid::trivial();
1411                            }
1412
1413                            s.mirrored_r().to_position(posn - 1 - s.cells.rows, s.ocol)
1414                        }
1415                    } else {
1416                        if posn > s.ocol {
1417                            s.mirrored_c().to_position(s.orow, posn + 2)
1418                        } else {
1419                            if posn < s.cells.columns + 1 {
1420                                return Grid::trivial();
1421                            }
1422
1423                            s.mirrored_c().to_position(s.orow, posn - 1 - s.cells.columns)
1424                        }
1425                    };
1426
1427                    shapes.shapes.push(s);
1428                }
1429            }
1430
1431//shapes.to_grid().show();
1432            shapes.to_grid()
1433        };
1434
1435        if let Some(rule) = run_experiment(task, 1459, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1436
1437        let func = |ex: &Example| {
1438            if ex.input.coloured_shapes.shapes.len() < 2 || all_colour_diffs.len() != 1 {
1439                return Grid::trivial();
1440            }
1441            let shapes = ex.input.grid.recolour(Black, NoColour).to_shapes();
1442            let mut shape = Shape::trivial();
1443            let mut bg = Shape::trivial();
1444            let mut pixel1 = Shape::trivial();
1445            let mut pixel2 = Shape::trivial();
1446
1447            for s in shapes.shapes.iter() {
1448                if s.size() == ex.input.grid.size() {
1449                    continue;
1450                }
1451                if s.size() > 1 && s.colour != NoColour {
1452                    shape = s.clone();
1453                } else if s.is_pixel() {
1454                    if pixel1 == Shape::trivial() {
1455                        pixel1 = s.clone();
1456                    } else {
1457                        pixel2 = s.clone();
1458                    };
1459                } else if s.size() > 1 && s.colour == NoColour && s.colour_cnt(false).1 + 1 == s.size() {
1460                    bg = s.clone();
1461                }
1462            }
1463            if pixel1.colour != pixel2.colour {
1464                return Grid::trivial();
1465            }
1466
1467            let mut grid = Grid::new(bg.cells.rows, bg.cells.columns, Black);
1468
1469            let (pixel, shape_pixel) = if pixel1.contained_by(&bg) {
1470                (&pixel1, pixel2)
1471            } else {
1472                (&pixel2, pixel1)
1473            };
1474
1475            if pixel.orow < bg.orow || pixel.ocol < bg.ocol {
1476                return Grid::trivial();
1477            }
1478
1479            let r = pixel.orow - bg.orow;
1480            let c = pixel.ocol - bg.ocol;
1481
1482            if shape_pixel.orow < shape.orow || shape_pixel.ocol < shape.ocol {
1483                return Grid::trivial();
1484            }
1485
1486            let sr = shape_pixel.orow - shape.orow;
1487            let sc = shape_pixel.ocol - shape.ocol;
1488
1489            if r < sr || c < sc {
1490                return Grid::trivial();
1491            }
1492
1493            grid.copy_shape_to_grid_position_mut(&shape, r - sr, c - sc);
1494            grid.copy_shape_to_grid_position_mut(&pixel, r, c);
1495
1496//grid.show();
1497            grid
1498        };
1499
1500        if let Some(rule) = run_experiment(task, 1524, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1501
1502        let (out_r, out_c) = examples.examples[0].output.grid.dimensions();
1503
1504        let func = |ex: &Example| {
1505            if ex.input.shapes.shapes.len() < 20 {
1506                return Grid::trivial();
1507            }
1508
1509            let mut cnt = 0;
1510            let mut ms = &Shape::trivial();
1511
1512            for s in ex.input.shapes.shapes.iter() {
1513                if s.size() > 4 {
1514                    let (_, n) = if let Some(n) = s.cell_colour_cnt_map().pop_first() {
1515                        n
1516                    } else {
1517                        (NoColour, 0)
1518                    };
1519                    if n > cnt {
1520                        cnt = n;
1521                        ms = &s;
1522                    }
1523                }
1524            }
1525            let grid = Grid::new(out_r, out_c, ms.colour);
1526
1527//grid.show();
1528            grid
1529        };
1530
1531        if let Some(rule) = run_experiment(task, 1555, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1532
1533        let mut colour = NoColour;
1534
1535        for s in examples.examples[0].input.black.shapes.iter() {
1536            if s.is_square() {
1537                colour = examples.examples[0].output.grid.find_axis_colour(&s);
1538            }
1539        }
1540
1541        let func = |ex: &Example| {
1542            if ex.input.black.shapes.len() != 1 || colour == NoColour {
1543                return Grid::trivial();
1544            }
1545            let mut grid = ex.input.grid.clone();
1546            let patch = &ex.input.black.shapes[0];
1547
1548            for r in 0 .. grid.cells.rows {
1549                for c in patch.ocol .. patch.ocol + patch.cells.columns {
1550                    if grid.cells[(r,c)].colour != colour {
1551                        grid.cells[(r,c)].colour = Black;
1552                    }
1553                }
1554            }
1555
1556            for c in 0 .. grid.cells.columns {
1557                for r in patch.orow .. patch.orow + patch.cells.rows {
1558                    if grid.cells[(r,c)].colour != colour {
1559                        grid.cells[(r,c)].colour = Black;
1560                    }
1561                }
1562            }
1563
1564            grid
1565        };
1566
1567        if let Some(rule) = run_experiment(task, 1591, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1568
1569        let func = |ex: &Example| {
1570            if colour_diffs.len() != 1 {
1571                return Grid::trivial();
1572            }
1573
1574            let mut grid = ex.input.grid.clone();
1575
1576            for s in ex.input.shapes.shapes.iter() {
1577                grid.draw_mc_mut(Up, s.orow, s.ocol, s.colour);
1578                grid.draw_mc_mut(Down, s.orow, s.ocol, s.colour);
1579                grid.draw_mc_mut(Left, s.orow, s.ocol, s.colour);
1580                grid.draw_mc_mut(Right, s.orow, s.ocol, s.colour);
1581            }
1582
1583            for s in ex.input.shapes.shapes.iter() {
1584                grid.recolour_mut(s.colour + ToBlack, colour_diffs[0]);
1585            }
1586
1587//grid.show();
1588            grid
1589        };
1590
1591        if let Some(rule) = run_experiment(task, 1592, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1592
1593        let func = |ex: &Example| {
1594            if all_colour_diffs.len() != 1 {
1595                return Grid::trivial();
1596            }
1597
1598            let mut grid = ex.input.grid.clone();
1599
1600            for s in ex.input.shapes.shapes.iter() {
1601                if s.is_pixel() {
1602                    let colour = ex.input.grid.shape_in_line(&s);
1603
1604                    if colour != NoColour {
1605                        grid.flood_fill_bg_mut(s.orow, s.ocol, NoColour, all_colour_diffs[0], s.colour);
1606                    } else {
1607                        grid.flood_fill_bg_mut(s.orow, s.ocol, NoColour, Black, s.colour);
1608                    }
1609                }
1610            }
1611
1612//grid.show();
1613            grid
1614        };
1615
1616        if let Some(rule) = run_experiment(task, 1593, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1617
1618        let func = |ex: &Example| {
1619            if ex.input.shapes.shapes.len() < 6 {
1620                return Grid::trivial();
1621            }
1622
1623            let mut shapes = ex.input.shapes.clone_base();
1624
1625            for s in ex.input.shapes.shapes.iter() {
1626                if s.hollow() {
1627                    let mut cc: BTreeMap<Colour, usize> = BTreeMap::new();
1628                    let mut pix = Shape::trivial();
1629
1630                    for s2 in ex.input.shapes.shapes.iter() {
1631                        if s2.is_pixel() && s2.contained_by(&s) {
1632                            *cc.entry(s2.colour).or_insert(0) += 1;
1633                            pix = s2.clone();
1634                        }
1635                    }
1636                    if let Some((_,c)) = cc.iter().map(|(k,v)| (v, k)).max() {
1637                        let ss = s.flood_fill(pix.orow - s.orow, pix.ocol - s.ocol, NoColour, *c);
1638
1639                        shapes.shapes.push(ss);
1640                    }
1641                } else if !s.is_pixel() {
1642                        shapes.shapes.push(s.clone());
1643                }
1644            }
1645
1646//shapes.to_grid().show();
1647            shapes.to_grid()
1648        };
1649
1650        if let Some(rule) = run_experiment(task, 1593, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1651
1652        let func = |ex: &Example| {
1653            let in_shapes = ex.input.coloured_shapes.clone();
1654            let mut shapes = in_shapes.clone();
1655            let mut cnt = usize::MAX;
1656            let mut del_shape = Shape::trivial();
1657
1658            for s in in_shapes.shapes.iter() {
1659                let n = s.pixels_in_shape();
1660
1661                if n == 0 {
1662                    return Grid::trivial();
1663                }
1664
1665                if cnt > n {
1666                    cnt = n;
1667                    del_shape = s.clone();
1668                }
1669            }
1670 
1671            shapes.shapes.retain(|s| *s != del_shape);
1672
1673            shapes.to_grid()
1674        };
1675
1676        if let Some(rule) = run_experiment(task, 1594, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1677
1678        let func = |ex: &Example| {
1679            if colour_diffs.len() != 1 {
1680                return Grid::trivial();
1681            }
1682
1683            let centres = ex.input.shapes.centre_of();
1684            let mut grid = ex.input.grid.clone();
1685            // Only 1 direction or will skip too far
1686            let mut pairs: Vec<(usize, usize)> = Vec::new();
1687
1688            for (r1, c1) in centres.keys() {
1689                for (r2, c2) in centres.keys() {
1690                    if r1 != r2 && c1 != c2 {
1691                        let l1 = (*r1 as isize - *r2 as isize).abs() as usize;
1692                        let l2 = (*c1 as isize - *c2 as isize).abs() as usize;
1693
1694                        if l1 == l2 && !pairs.contains(&(l1, l2)) {
1695                            let dir = Grid::calc_direction(*r1, *c1, *r2, *c2);
1696                            if dir != Other && !pairs.contains(&(l1, l2)) {
1697                                let (r, c) = grid.skip_to(dir, *r1, *c1);
1698                                grid.draw_term_mut(dir, r, c, colour_diffs[0]);
1699                            }
1700                            pairs.push((l1, l2));
1701                        }
1702                    }
1703                }
1704            }
1705
1706//grid.show();
1707            grid
1708        };
1709
1710        if let Some(rule) = run_experiment(task, 1595, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1711
1712        let func = |ex: &Example| {
1713            if colour_diffs.len() != 1 {
1714                return Grid::trivial();
1715            }
1716
1717            let mut grid = ex.input.grid.clone();
1718
1719            for s in ex.input.shapes.shapes.iter() {
1720                let (dir, r, c) = s.find_a_border_break();
1721
1722                grid.draw_term_mut(dir, r, c, colour_diffs[0]);
1723                grid.flood_fill_mut(s.orow + s.cells.rows / 2, s.ocol + s.cells.columns / 2, NoColour, colour_diffs[0]);
1724            }
1725
1726//grid.show();
1727            grid
1728        };
1729
1730        if let Some(rule) = run_experiment(task, 1596, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1731
1732        let func = |ex: &Example| {
1733            if all_colour_diffs.len() != 1 {
1734                return Grid::trivial();
1735            }
1736
1737            let mut grid = ex.input.shapes.biggest_shape().to_grid();
1738            let mut template = Shape::trivial();
1739            let mut idx = Shape::trivial();
1740
1741            for s in ex.input.coloured_shapes.shapes.iter() {
1742                if s.is_square() {
1743                    template = s.to_origin();
1744                } else if s.dimensions() != grid.dimensions() {
1745                    idx = s.clone();
1746                }
1747            }
1748
1749            for s in idx.to_grid().to_shapes_sq().shapes.iter() {
1750                if s.colour != grid.colour {
1751                    let factor = grid.cells.rows as f64 / idx.cells.rows as f64 ;
1752
1753                    template.recolour_mut(all_colour_diffs[0], grid.colour);
1754                    template.to_position_mut((s.orow as f64 * factor) as usize, (s.ocol as f64 * factor) as usize);
1755                    grid.copy_shape_to_grid_mut(&template);
1756                }
1757            }
1758
1759//grid.show();
1760            grid
1761        };
1762
1763        if let Some(rule) = run_experiment(task, 1597, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1764
1765        let func = |ex: &Example| {
1766            if all_colour_diffs.is_empty() || !ex.input.grid.is_square() {
1767                return Grid::trivial();
1768            }
1769
1770            let mut template = Shape::trivial();
1771
1772            for s in ex.input.shapes.shapes.iter() {
1773                if s.colour != Black && s.ocol != 0 {
1774                    template = s.clone();
1775                }
1776            }
1777
1778            let bg = ex.input.grid.has_bg_grid_not_sq();
1779            let mut colour = NoColour;
1780            let mut shapes = ex.input.shapes.clone_base();
1781
1782            shapes.shapes.push(Shape::new_sized_coloured(ex.input.grid.cells.rows, ex.input.grid.cells.columns, bg));
1783
1784            for s in ex.input.shapes.shapes.iter() {
1785                if colour != s.colour && s.colour != Black && s.colour != template.colour {
1786                    colour = s.colour;
1787                }
1788
1789                template.to_position_mut(s.orow, s.ocol);
1790                shapes.shapes.push(template.recolour(template.colour, colour));
1791
1792            }
1793
1794//shapes.to_grid().show();
1795            shapes.to_grid()
1796        };
1797
1798        if let Some(rule) = run_experiment(task, 1598, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1799
1800        let func = |ex: &Example| {
1801            if !all_colour_diffs.is_empty() {
1802                return Grid::trivial();
1803            }
1804
1805            let mut templates: Vec<Shape> = Vec::new();
1806
1807            for s in ex.input.coloured_shapes.shapes.iter() {
1808                if !s.is_pixel() {
1809                    templates.push(s.clone());
1810                }
1811            }
1812
1813            if templates.is_empty() || templates[0].cells.rows != 1 || templates[0].cells.columns == 1 {
1814                return Grid::trivial();
1815            }
1816
1817            let mut shapes = ex.input.shapes.clone_base();
1818
1819            for s in ex.input.coloured_shapes.shapes.iter() {
1820                if templates.contains(s) {
1821                    shapes.shapes.push(s.clone());
1822                } else {
1823                    let mut c = 0;
1824                    let mut template = Shape::trivial();
1825
1826                    templates.iter().for_each(|t| {
1827                        let cp = t.colour_position(s.colour);
1828
1829                        if cp.len() > 0 {
1830                            let (_, cc) = cp[0];
1831
1832                            c = cc;
1833                            template = t.clone();
1834                        }
1835                    });
1836
1837                    let new_template = if s.ocol > c {
1838                        template.to_position(s.orow, s.ocol - c)
1839                    } else {
1840                        let sc = c - s.ocol;
1841                        let sub_temp = template.subshape(0, template.cells.rows, sc, template.cells.columns - sc);
1842                        sub_temp.to_position(s.orow, 0)
1843                    };
1844
1845                    shapes.shapes.push(new_template);
1846                }
1847            }
1848
1849//shapes.to_grid().show();
1850            shapes.to_grid()
1851        };
1852
1853        if let Some(rule) = run_experiment(task, 1599, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1854
1855        let func = |ex: &Example| {
1856            if colour_diffs.len() != 1 || ex.input.shapes.shapes.len() < 4 {
1857                return Grid::trivial();
1858            }
1859
1860            let mut rv: BTreeSet<usize> = BTreeSet::new();
1861            let mut cv: BTreeSet<usize> = BTreeSet::new();
1862
1863            for s in ex.input.coloured_shapes.shapes.iter() {
1864                rv.insert(s.orow);
1865                cv.insert(s.ocol);
1866            }
1867
1868            let mut shapes = ex.input.shapes.clone();
1869            let mut template = ex.input.shapes.shapes[0].clone();
1870            let cts = ex.input.shapes.coords_to_shape();
1871
1872            for r in rv.iter() {
1873                for c in cv.iter() {
1874                    if !cts.contains_key(&(*r, *c)) {
1875                        template.recolour_mut(template.colour, colour_diffs[0]);
1876                        template.to_position_mut(*r, *c);
1877
1878                        shapes.shapes.push(template.clone());
1879                    }
1880                }
1881            }
1882
1883//shapes.to_grid().show();
1884            shapes.to_grid()
1885        };
1886
1887        if let Some(rule) = run_experiment(task, 1600, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1888
1889        let func = |ex: &Example| {
1890            // Might have been neater using coloured shapes!
1891            if !colour_diffs.is_empty() {
1892                return Grid::trivial();
1893            }
1894
1895            let mut pixels: Vec<Shape> = Vec::new();
1896            let mut horizontal: Vec<Shape> = Vec::new();
1897            let mut vertical: Vec<Shape> = Vec::new();
1898
1899            for s in ex.input.shapes.shapes.iter() {
1900                if s.is_pixel() {
1901                    pixels.push(s.clone());
1902                } else if s.is_horizontal_line() {
1903                    horizontal.push(s.clone());
1904                } else if s.is_vertical_line() {
1905                    vertical.push(s.clone());
1906                }
1907            }
1908
1909            let mut pshapes: Vec<(Shape,Shape)> = Vec::new();
1910
1911            for s in ex.input.shapes.shapes.iter() {
1912                if !s.is_pixel() && !s.is_line() {
1913                    for p in pixels.iter() {
1914                        if p.contained_by(&s) {
1915                            pshapes.push((p.clone(), s.clone()));
1916                        }
1917                    }
1918                }
1919            }
1920
1921            let mut shapes = ex.input.shapes.clone_base();
1922            let mut used: Vec<&Shape> = Vec::new();
1923
1924            for (p, s) in pshapes.iter() {
1925                for h in horizontal.iter() {
1926                    if h.adjacent_r_or_c(&s) && !used.contains(&h) {
1927                        let diff = (p.orow as isize - h.orow as isize).abs() as usize;
1928                        let ms;
1929                        let mp;
1930
1931                        if h.above(&p) {
1932                            ms = s.mirrored_r().to_position(s.orow + s.cells.rows + 1, s.ocol);
1933                            mp = p.to_position(h.orow + diff, p.ocol);
1934                        } else {
1935                            if s.orow <= s.cells.rows || h.orow < diff {
1936                                return Grid::trivial();
1937                            }
1938
1939                            ms = s.mirrored_r().to_position(s.orow - s.cells.rows - 1, s.ocol);
1940                            mp = p.to_position(h.orow - diff, p.ocol);
1941                        }
1942                        shapes.shapes.push(s.clone());
1943                        shapes.shapes.push(p.clone());
1944                        shapes.shapes.push(ms);
1945                        shapes.shapes.push(mp);
1946                        shapes.shapes.push(h.clone());
1947
1948                        used.push(h);
1949                    }
1950                }
1951                for v in vertical.iter() {
1952                    if v.adjacent_r_or_c(&s) && !used.contains(&v){
1953                        let diff = (p.ocol as isize - v.ocol as isize).abs() as usize;
1954                        let ms;
1955                        let mp;
1956
1957                        if v.left(&p) {
1958                            ms = s.mirrored_c().to_position(s.orow, s.ocol + s.cells.columns + 1);
1959                            mp = p.to_position(p.orow, v.ocol + diff);
1960                        } else {
1961                            if s.ocol <= s.cells.columns || v.ocol < diff {
1962                                return Grid::trivial();
1963                            }
1964
1965                            ms = s.mirrored_c().to_position(s.orow, s.ocol - s.cells.columns - 1);
1966                            mp = p.to_position(p.orow, v.ocol - diff);
1967                        }
1968
1969                        shapes.shapes.push(s.clone());
1970                        shapes.shapes.push(p.clone());
1971                        shapes.shapes.push(ms);
1972                        shapes.shapes.push(mp);
1973                        shapes.shapes.push(v.clone());
1974
1975                        used.push(v);
1976                    }
1977                }
1978            }
1979
1980//shapes.to_grid().show();
1981            shapes.to_grid()
1982        };
1983
1984        if let Some(rule) = run_experiment(task, 1601, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
1985
1986        *cap_todo.entry(gc).or_insert(0) += 1;
1987    }
1988    let gc = InToSquaredOut;
1989    if all || cat.contains(&gc) {
1990        *cap_cats.entry(gc).or_insert(0) += 1;
1991
1992        if let Some(rule) = run_experiment(task, 1599, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.grid.in_to_squared_out(), output) { return Some(rule); };
1993
1994        *cap_todo.entry(gc).or_insert(0) += 1;
1995    }
1996    let gc = BGGridInBlack;
1997    if all || cat.contains(&gc) && !cat.contains(&BGGridOutBlack) {
1998        *cap_cats.entry(gc).or_insert(0) += 1;
1999
2000        if let Some(rule) = run_experiment(task, 1607, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.find_min().to_grid(), output) { return Some(rule); };
2001
2002        if let Some(rule) = run_experiment(task, 1609, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.find_max_colour_count().to_grid(), output) { return Some(rule); };
2003
2004        if let Some(rule) = run_experiment(task, 1611, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.has_mirror_r().to_grid(), output) { return Some(rule); };
2005
2006        if let Some(rule) = run_experiment(task, 1613, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.has_mirror_c().to_grid(), output) { return Some(rule); };
2007        //if let Some(rule) = run_experiment_examples(&file, 1000, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_overlay(&exs), output) { return Some(rule); };
2008
2009        //-if let Some(rule) = run_experiment_examples(&file, 1010, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_shape_fill(&exs), output) { return Some(rule); };
2010
2011        let func = |ex: &Example| {
2012            if ex.input.coloured_shapes.shapes.len() != 1 || ex.input.coloured_shapes.shapes[0].dimensions() != (3, 3) {
2013                return Grid::trivial();
2014            }
2015
2016            let mut grid = ex.input.grid.clone();
2017            let ss = &ex.input.coloured_shapes.shapes[0];
2018
2019            for c in ss.cells.values() {
2020                match (c.row - ss.orow, c.col - ss.ocol) {
2021                    (0, 0) => grid.draw_mut(UpLeft, c.row, c.col, c.colour),
2022                    (0, 1) => grid.draw_mut(Up, c.row, c.col, c.colour),
2023                    (0, 2) => grid.draw_mut(UpRight, c.row, c.col, c.colour),
2024                    (1, 0) => grid.draw_mut(Left, c.row, c.col, c.colour),
2025                    (1, 1) => (),
2026                    (1, 2) => grid.draw_mut(Right, c.row, c.col, c.colour),
2027                    (2, 0) => grid.draw_mut(DownLeft, c.row, c.col, c.colour),
2028                    (2, 1) => grid.draw_mut(Down, c.row, c.col, c.colour),
2029                    (2, 2) => grid.draw_mut(DownRight, c.row, c.col, c.colour),
2030                    _ => todo!()
2031                }
2032            }
2033//grid.show();
2034
2035            grid
2036        };
2037
2038        if let Some(rule) = run_experiment(task, 1645, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2039
2040        let func = |ex: &Example| {
2041            if ex.input.shapes.shapes.len() < 3 || !ex.input.shapes.shapes[0].is_pixel() || !ex.input.shapes.shapes[1].is_pixel() {
2042                return Grid::trivial();
2043            }
2044
2045            let cpm = ex.input.grid.cell_colour_posn_map();
2046            let mut grid = ex.input.grid.clone();
2047
2048            for (c, vp) in cpm.iter() {
2049                if vp.len() == 2 {
2050                    let (_, c1) = vp[0];
2051                    let (r2, _) = vp[1];
2052
2053                    grid.cells[(r2,c1)].colour = *c;
2054                }
2055            }
2056
2057            grid.connect_dots();
2058
2059            grid
2060        };
2061
2062        if let Some(rule) = run_experiment(task, 1669, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2063
2064        let func = |ex: &Example| {
2065            if colour_diffs.len() != 1 {
2066                return Grid::trivial();
2067            }
2068
2069            let colour = colour_diffs[0];
2070            let grid = &ex.input.grid;
2071            let mut shapes = ex.input.shapes.clone_base();
2072
2073            // TODO Fix hard coding
2074            for s in ex.input.shapes.shapes.iter() {
2075                if s.orow == 0 {
2076                    return Grid::trivial();
2077                }
2078                if s.cells.columns > 1 && s.cells[(0,1)].colour == Black {
2079                    shapes.shapes.push(s.flood_fill(0, 1, NoColour, colour));
2080                    shapes.shapes.push(Shape::new_sized_coloured_position(s.orow - 1, s.ocol + 1, 1, grid.cells.columns - s.ocol, colour));
2081                } else if s.cells.columns > 2 && s.cells[(0,2)].colour == Black {
2082                    shapes.shapes.push(s.flood_fill(0, 2, NoColour, colour));
2083                    shapes.shapes.push(Shape::new_sized_coloured_position(s.orow- 1, 0, 1, s.ocol + 3, colour));
2084                } else {
2085                    return Grid::trivial();
2086                }
2087            }
2088
2089//shapes.to_grid().show();
2090            shapes.to_grid()
2091        };
2092
2093        if let Some(rule) = run_experiment(task, 1667, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2094
2095        *cap_todo.entry(gc).or_insert(0) += 1;
2096    }
2097
2098    let gc = SingleColourOut2xIn;
2099    if all || cat.contains(&gc) { // 3?
2100        *cap_cats.entry(gc).or_insert(0) += 1;
2101
2102        if let Some(rule) = run_experiment_tries(task, 1678, experiment, trans, is_test, examples, &targets, done, tries, &|ex, _, n| mirror_only(ex, n), output) { return Some(rule); };
2103
2104        *cap_todo.entry(gc).or_insert(0) += 1;
2105    }
2106
2107    let gc = SymmetricOut;
2108    if all || cat.contains(&gc) { // 3?
2109        *cap_cats.entry(gc).or_insert(0) += 1;
2110
2111        let func = |ex: &Example| {
2112            let xc = ex.input.shapes.shapes.iter().filter(|s| s.orow == 0).count();
2113
2114            if xc == 0 {
2115                return Grid::trivial();
2116            }
2117
2118            Grid::new(ex.input.shapes.len() / xc, xc, ex.input.shapes.shapes[0].colour)
2119        };
2120
2121        if let Some(rule) = run_experiment(task, 1697, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2122
2123        *cap_todo.entry(gc).or_insert(0) += 1;
2124    }
2125    let gc = InOutSameShapes;
2126    if all || cat.contains(&gc) {
2127        *cap_cats.entry(gc).or_insert(0) += 1;
2128
2129        let func = &|ex: &Example| {
2130            let mut border = Shape::trivial();
2131            let mut colours: BTreeSet<Colour> = BTreeSet::new();
2132            let border_colour = ex.input.shapes.biggest_shape().colour;
2133
2134            for s in ex.input.shapes.shapes.iter() {
2135                if s.colour == border_colour {
2136                    border = s.clone();
2137                } else {
2138                    colours.insert(s.colour);
2139                }
2140            }
2141
2142            if colours.len() != 2 || border == Shape::trivial() {
2143                return Grid::trivial();
2144            }
2145            let sg = ex.input.grid.subgrid(border.orow, border.cells.rows, border.ocol, border.cells.columns);
2146            let colours: Vec<&Colour> = colours.iter().collect();
2147//
2148            if *colours[0] == NoColour || *colours[1] == NoColour {
2149                return Grid::trivial();
2150            }
2151
2152            let s = sg.toddle_colour(*colours[0], *colours[1]);
2153
2154            let mut shapes = Shapes::new_sized(ex.input.grid.cells.rows, ex.input.grid.cells.columns);
2155
2156            shapes.shapes.push(ex.input.grid.as_shape());
2157            shapes.shapes.push(s.as_shape());
2158//shapes.to_grid().show();
2159
2160            shapes.to_grid()
2161        };
2162
2163        if let Some(rule) = run_experiment(task, 1739, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2164
2165        let common_colour = examples.io_common_row_colour();
2166
2167        let func = |ex: &Example| {
2168            if ex.input.shapes.is_empty() || !ex.cat.contains(&InSameCountOut) {
2169                return Grid::trivial();
2170            }
2171
2172            let mut shapes = ex.input.shapes.clone();
2173            let mut row = 0;
2174
2175            for s in shapes.shapes.iter() {
2176                if s.colour == common_colour {
2177                    row = s.orow;
2178
2179                    break;
2180                }
2181            }
2182
2183            for s in shapes.shapes.iter_mut() {
2184                s.to_position_mut(row, s.ocol);
2185            }
2186//shapes.to_grid().show();
2187
2188            shapes.to_grid()
2189        };
2190
2191        if let Some(rule) = run_experiment(task, 1767, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2192
2193        let func = |ex: &Example| {
2194            if ex.input.shapes.shapes.is_empty() {
2195                return Grid::trivial();
2196            }
2197
2198            let mut grid = ex.input.grid.clone();
2199
2200            for s in ex.input.shapes.shapes.iter() {
2201                if s.is_pixel() {
2202                    if s.orow > 0 && grid.cells[(s.orow-1,s.ocol)].colour == Black {
2203                        grid.flood_fill_mut(s.orow-1, s.ocol, NoColour, s.colour);
2204                    }
2205                    if s.ocol > 0 && grid.cells[(s.orow,s.ocol-1)].colour == Black {
2206                        grid.flood_fill_mut(s.orow, s.ocol-1, NoColour, s.colour);
2207                    }
2208                    if s.orow < grid.cells.rows - 1 && grid.cells[(s.orow+1,s.ocol)].colour == Black {
2209                        grid.flood_fill_mut(s.orow+1, s.ocol, NoColour, s.colour);
2210                    }
2211                    if s.ocol < grid.cells.columns - 1 && grid.cells[(s.orow,s.ocol+1)].colour == Black {
2212                        grid.flood_fill_mut(s.orow, s.ocol+1, NoColour, s.colour);
2213                    }
2214                }
2215            }
2216
2217//grid.show();
2218            grid
2219        };
2220
2221        if let Some(rule) = run_experiment(task, 1797, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2222
2223        if colour_diffs.len() == 2 {
2224            let first = &examples.examples[0].input.grid.to_shapes_sq().shapes[0];
2225            let first_colour = examples.examples[0].output.shapes.shapes[0].colour;
2226            let second_colour = if colour_diffs[0] == first_colour {
2227                colour_diffs[1]
2228            } else {
2229                colour_diffs[0]
2230            };
2231            let (rs, cs) = examples.examples[0].output.grid.dimensions();
2232
2233            let func = |ex: &Example| {
2234                if ex.input.shapes.shapes.is_empty() || rs.max(cs) != rs.min(cs) * 2 {
2235                    return Grid::trivial();
2236                }
2237
2238                let (mut s1,mut s2) = if rs < cs {
2239                    (Shape::new_sized_coloured(rs, rs, Black),
2240                    Shape::new_sized_coloured_position(0, rs, rs, rs, Black))
2241                } else {
2242                    (Shape::new_sized_coloured(cs, cs, Black),
2243                    Shape::new_sized_coloured_position(cs, 0, cs, cs, Black))
2244                };
2245
2246                let mut size0 = 0;
2247                let mut size1 = 0;
2248
2249                for s in ex.input.grid.to_shapes_sq().shapes.iter() {
2250                    if first.same_pixel_positions(s, false) {
2251                        size0 += 1;
2252                    } else {
2253                        size1 += 1;
2254                    }
2255                }
2256                
2257                s1.fill_corners_mut(size0, first_colour);
2258                s2.fill_corners_mut(size1, second_colour);
2259
2260//Shapes::new_shapes(&[s1.clone(), s2.clone()]).to_grid().show();
2261                Shapes::new_shapes(&[s1.clone(), s2.clone()]).to_grid()
2262            };
2263
2264            if let Some(rule) = run_experiment(task, 1840, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2265        }
2266
2267        let func = |ex: &Example| {
2268            if !colour_diffs.is_empty() {
2269                return Grid::trivial();
2270            }
2271            let mut shapes = ex.input.shapes.clone_base();
2272
2273            let mut shape1 = Shape::trivial();
2274            let mut shape2 = Shape::trivial();
2275
2276            for s in ex.input.shapes.shapes.iter() {
2277                if shape1 == Shape::trivial() {
2278                    shape1 = s.clone();
2279                } else if s.equals(&shape1) != Same {
2280                    shape2 = s.clone();
2281                }
2282            }
2283            for s in ex.input.shapes.shapes.iter() {
2284                let ms = if s.equals(&shape1) == Same {
2285                    shape2.to_position(s.orow, s.ocol)
2286                } else {
2287                    shape1.to_position(s.orow, s.ocol)
2288                };
2289
2290                shapes.shapes.push(ms);
2291            }
2292
2293            shapes.to_grid()
2294        };
2295
2296        if let Some(rule) = run_experiment(task, 1872, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2297
2298        let func = |ex: &Example| {
2299            if ex.input.shapes.shapes.len() < 10 || ex.input.shapes.shapes.len() == ex.input.coloured_shapes.shapes.len(){
2300                return Grid::trivial();
2301            }
2302            let mut shapes = ex.input.shapes.clone_base();
2303
2304            let mut idx = Shape::trivial();
2305
2306            for s in ex.input.coloured_shapes.shapes.iter() {
2307                if s.colour == Mixed {
2308                    idx = s.clone();
2309                } else {
2310                    shapes.shapes.push(s.clone());
2311                }
2312            }
2313
2314            for (cell, s) in idx.cells.values().zip(shapes.shapes.iter_mut()) {
2315                s.recolour_mut(s.colour, cell.colour);
2316            }
2317
2318            shapes.shapes.push(idx.clone());
2319
2320            shapes.to_grid()
2321        };
2322
2323        if let Some(rule) = run_experiment(task, 1899, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2324
2325        let func = |ex: &Example| {
2326            if !all_colour_diffs.is_empty() {
2327                return Grid::trivial();
2328            }
2329
2330            let mut shapes = ex.input.shapes.clone();
2331            let smallest = ex.input.shapes.smallest();
2332            let largest = ex.input.shapes.largest();
2333            let edge = if smallest.cells.rows != smallest.cells.columns {
2334                smallest.cells.rows.max(smallest.cells.columns) / 2
2335            } else {
2336                smallest.cells.rows
2337            };
2338
2339            if largest.orow < edge || largest.ocol < edge {
2340                return Grid::trivial();
2341            }
2342
2343            let enclosing = Shape::new_sized_coloured_position(largest.orow - edge, largest.ocol - edge, largest.cells.rows + edge * 2, largest.cells.columns + edge * 2, smallest.colour);
2344
2345            shapes.shapes.insert(0, enclosing);
2346
2347//shapes.to_grid().show();
2348            shapes.to_grid()
2349        };
2350
2351        if let Some(rule) = run_experiment(task, 1927, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2352
2353        let func = |ex: &Example| {
2354            if !all_colour_diffs.is_empty() {
2355                return Grid::trivial();
2356            }
2357
2358            let mut shapes = ex.input.coloured_shapes.clone_base();
2359
2360            for s in ex.input.coloured_shapes.shapes.iter() {
2361                let cc = s.cell_colours();
2362                if cc.len() != 2 {
2363                    return Grid::trivial();
2364                }
2365
2366                shapes.shapes.push(s.toddle_colour(cc[0], cc[1]));
2367            }
2368
2369            shapes.to_grid()
2370        };
2371
2372        if let Some(rule) = run_experiment(task, 1948, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2373
2374        let func = |ex: &Example| {
2375            if !colour_diffs.is_empty() {
2376                return Grid::trivial();
2377            }
2378
2379            let mut shapes = ex.input.shapes.clone();
2380//shapes.show();
2381
2382            for s in shapes.shapes.iter_mut() {
2383                for (i, r) in (0 .. s.cells.rows).rev().enumerate() {
2384                    for c in 0 .. s.cells.columns {
2385                        let cell = &mut s.cells[(r,c)];
2386
2387                        if cell.col >= i {
2388                            cell.col -= i;
2389                        } else {
2390                            cell.colour = Black;
2391                        }
2392                    }
2393                }
2394            }
2395
2396//shapes.to_grid().show();
2397            shapes.to_grid()
2398        };
2399
2400        if let Some(rule) = run_experiment(task, 1988, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2401
2402        let func = |ex: &Example| {
2403            if !colour_diffs.is_empty() {
2404                return Grid::trivial();
2405            }
2406
2407            let mut shapes = ex.input.grid.to_shapes();
2408            let mut even = true;
2409            let mut bg = NoColour;
2410
2411            for s in shapes.shapes.iter_mut() {
2412                if s.size() != ex.input.grid.size() {
2413                    if even {
2414                        if s.ocol == 0 {
2415                            return Grid::trivial();
2416                        }
2417                        s.to_position_mut(s.orow, s.ocol - 1);
2418                    } else {
2419                        s.to_position_mut(s.orow, s.ocol + 1);
2420                    }
2421
2422                    even = !even;
2423                } else {
2424                    bg = s.colour;
2425                }
2426            }
2427
2428            let mut grid = shapes.to_grid();
2429
2430            grid.recolour_mut(Black, bg);
2431
2432            grid
2433        };
2434
2435        if let Some(rule) = run_experiment(task, 2026, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2436
2437        let func = |ex: &Example| {
2438            if colour_diffs.is_empty() {
2439                return Grid::trivial();
2440            }
2441            let bg = ex.input.grid.majority_colour();
2442            let mut grid = ex.input.grid.clone();
2443            let mut cc: Vec<usize> = Vec::new();
2444
2445            for cell in grid.cells.values() {
2446                if cell.colour != bg {
2447                    cc.push(cell.col);
2448                }
2449            }
2450
2451            cc.sort();
2452
2453            let cc = cc.unique();
2454
2455            for cell in grid.cells.values_mut() {
2456                if cell.colour != bg {
2457                    if let Some(ncolour) = cc.iter().position(|n| *n == cell.col) {
2458                        cell.colour = Colour::from_usize(ncolour + 1);
2459                    }
2460                }
2461            }
2462
2463//grid.show();
2464            grid
2465        };
2466
2467        if let Some(rule) = run_experiment(task, 2027, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2468
2469        let func = |ex: &Example| {
2470            if colour_diffs.len() != 1 {
2471                return Grid::trivial();
2472            }
2473
2474            let mut grid = ex.input.grid.clone();
2475            let mut cc: Vec<Colour> = Vec::new();
2476
2477            for s in ex.input.shapes.shapes.iter() {
2478                if s.ocol == 0 || s.ocol == grid.cells.columns {
2479                    return Grid::trivial();
2480                }
2481                // Down
2482                let mut r = s.orow + s.cells.rows;
2483                let mut cm = s.ocol - 1;
2484                let mut cp = s.ocol + 1;
2485                let mut l = s.cells.rows;
2486                let mut outleft = false;
2487
2488                while r < grid.cells.rows { 
2489                    if grid.cells.rows - r <= l {
2490                        l = grid.cells.rows - r;
2491                    }
2492
2493                    for rr in r .. r  + l {
2494                        if !cc.contains(&s.colour) {
2495                            if !outleft {
2496                                if grid.cells[(rr, cm)].colour != Black {
2497                                    grid.cells[(rr, cm)].colour = colour_diffs[0];
2498                                } else {
2499                                    grid.cells[(rr, cm)].colour = s.colour;
2500                                }
2501                            }
2502                        } else {
2503                            if cp < grid.cells.columns {
2504                                if grid.cells[(rr, cp)].colour != Black {
2505                                    grid.cells[(rr, cp)].colour = colour_diffs[0];
2506                                } else {
2507                                    grid.cells[(rr, cp)].colour = s.colour;
2508                                }
2509                            }
2510                        }
2511                    }
2512                    
2513                    if cm > 0 {
2514                        cm -= 1;
2515                    } else if cm == 0 {
2516                        outleft = true;
2517                    }
2518                    cp += 1;
2519                    r += l;
2520                }
2521
2522                // Up
2523                let mut r = s.orow;
2524                let mut cm = s.ocol - 1;
2525                let mut cp = s.ocol + 1;
2526                let mut l = s.cells.rows;
2527                let mut outleft = false;
2528
2529                while r > 0 { 
2530                    if r <= l {
2531                        l = r;
2532                    }
2533
2534                    for rr in r - l .. r {
2535                        if !cc.contains(&s.colour) {
2536                            if !outleft {
2537                                if grid.cells[(rr, cm)].colour != Black {
2538                                    grid.cells[(rr, cm)].colour = colour_diffs[0];
2539                                } else {
2540                                    grid.cells[(rr, cm)].colour = s.colour;
2541                                }
2542                            }
2543                        } else {
2544                            if cp < grid.cells.columns {
2545                                if grid.cells[(rr, cp)].colour != Black {
2546                                    grid.cells[(rr, cp)].colour = colour_diffs[0];
2547                                } else {
2548                                    grid.cells[(rr, cp)].colour = s.colour;
2549                                }
2550                            }
2551                        }
2552                    }
2553                    
2554                    if cm > 0 {
2555                        cm -= 1;
2556                    } else if cm == 0 {
2557                        outleft = true;
2558                    }
2559                    cp += 1;
2560                    r -= if r >= l { l } else { r };
2561                }
2562
2563                cc.push(s.colour);
2564            }
2565
2566//grid.show();
2567            grid
2568        };
2569
2570        if let Some(rule) = run_experiment(task, 2028, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2571
2572        // TODO : factor out gravity into grid function
2573        let func = |ex: &Example| {
2574            if !colour_diffs.is_empty() || ex.input.shapes.shapes.len() < 4 {
2575                return Grid::trivial();
2576            }
2577
2578            let grid = &ex.input.grid;
2579            let mut shapes = ex.input.grid.to_shapes_sq();
2580            let mut new_shapes = shapes.clone_base();
2581
2582            shapes.shapes.sort_by(|a, b| (a.ocol,a.orow).cmp(&(b.ocol,b.orow)));
2583
2584            let mut posns: BTreeMap<usize,usize> = (0 .. grid.cells.rows)
2585                .map(|r| (r, grid.cells.columns))
2586                .collect();
2587
2588            for s in shapes.shapes.iter().rev() {
2589                let c = if let Some(c) = posns.get(&s.orow) { *c } else { 0 };
2590
2591                // find min over shape
2592                let mut cs = c;
2593
2594                for r in s.orow .. s.orow + s.cells.rows {
2595                    if let Some(c) = posns.get(&r) {
2596                        cs = cs.min(*c);
2597                    };
2598                }
2599
2600                if cs < s.cells.columns {
2601                    return Grid::trivial();
2602                }
2603
2604                new_shapes.shapes.push(s.to_position(s.orow, cs - s.cells.columns));
2605
2606                // now update position
2607                for r in s.orow .. s.orow + s.cells.rows {
2608                    let mut blanks = 0;
2609                    let grid = new_shapes.to_grid();
2610
2611                    // Don't count blanks
2612                    for c2 in cs - s.cells.columns .. c {
2613                        if grid.cells[(r,c2)].colour != Black {
2614                            break;
2615                        }
2616                        blanks += 1;
2617                    }
2618                    *posns.entry(r).or_insert(cs) = cs + blanks - s.cells.columns;
2619                }
2620            }
2621
2622            new_shapes.to_grid()
2623        };
2624
2625        if let Some(rule) = run_experiment(task, 2029, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2626
2627        *cap_todo.entry(gc).or_insert(0) += 1;
2628    }
2629
2630    let gc = BGGridOutBlack;
2631    if all || cat.contains(&gc) {
2632        *cap_cats.entry(gc).or_insert(0) += 1;
2633
2634        if all || cat.contains(&IdenticalNoColours) {
2635            let func = &|ex: &Example| {
2636                if ex.input.shapes.shapes.len() % 2 != 0 || ex.input.shapes.shapes.len() == ex.input.coloured_shapes.shapes.len() {
2637                    return Grid::trivial();
2638                }
2639                let mut shapes = ex.input.shapes.clone_base();
2640
2641                for shape in ex.input.coloured_shapes.shapes.iter() {
2642                    let inner_shapes = shape.to_shapes();
2643                    let mut small = inner_shapes.smallest();
2644                    let mut large = inner_shapes.largest();
2645
2646                    if shape.cells.rows != shape.cells.columns || inner_shapes.len() != 2 || !large.can_contain(&small) {
2647                        return Grid::trivial();
2648                    }
2649
2650                    let small_colour = small.colour;
2651
2652                    small.recolour_mut(small_colour, large.colour);
2653                    large.recolour_mut(large.colour, small_colour);
2654
2655                    // Assume rows == columns for small
2656                    let enclose = large.surround(small.cells.rows, small.colour, false, false);
2657
2658                    shapes.shapes = [shapes.shapes, vec![large, small, enclose]].concat();
2659                }
2660//shapes.show();
2661
2662                shapes.to_grid()
2663            };
2664
2665            if let Some(rule) = run_experiment(task, 1988, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2666
2667            let func = |ex: &Example| {
2668                let mut read_shapes = ex.input.shapes.clone();
2669                let mut shapes = ex.input.shapes.clone_base();
2670                let mut row = 0;
2671                let mut col = 0;
2672
2673                read_shapes.shapes.sort_by(|a, b| a.ocol.cmp(&b.ocol));
2674
2675                for s in read_shapes.shapes.iter() {
2676                    shapes.shapes.push(s.to_position(row, col));
2677
2678                    row += s.cells.rows - 1;
2679                    col += s.cells.columns - 1;
2680                }
2681
2682//shapes.to_grid().show();
2683                shapes.to_grid()
2684            };
2685
2686            if let Some(rule) = run_experiment(task, 2009, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2687        }
2688
2689        let func = &|ex: &Example| {
2690            let rows = ex.input.grid.cells.rows;
2691            let cols = ex.input.grid.cells.columns;
2692            let h = ex.input.grid.cell_colour_cnt_map();
2693//print!("{h:?} -> ");
2694//let h2 = ex.input.grid.cell_colour_cnt_map();
2695//println!("{h2:?}");
2696            let mut grid = Grid::new(rows, cols, Black);
2697
2698            for (col, size) in h.iter() {
2699                let c = Colour::to_usize(*col) - 1;
2700
2701                if *size >= rows || c >= cols {
2702                    return Grid::trivial();
2703                }
2704
2705                for r in 0 .. *size {
2706                    let r = rows - r - 1;
2707
2708                    grid.cells[(r,c)].row = r;
2709                    grid.cells[(r,c)].col = c;
2710                    grid.cells[(r,c)].colour = *col;
2711                }
2712            }
2713
2714            grid
2715        };
2716
2717        if let Some(rule) = run_experiment(task, 2040, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2718
2719        let func = |gi: &Example| {
2720//gi.input.shapes.show();
2721            let mut rc: Vec<(usize, usize, Colour)> = Vec::new();
2722            let mut colour = NoColour;
2723            let mut shapes = gi.input.shapes.clone();
2724
2725            for s in gi.input.shapes.shapes.iter() {
2726                if colour == NoColour {
2727                    colour = s.colour;
2728                }
2729                if colour != s.colour {
2730                    rc.push((s.cells[(0,0)].row, s.cells[(0,0)].col, s.colour));
2731
2732                    break;
2733                }
2734            }
2735
2736            for ss in shapes.shapes.iter_mut() {
2737                for (rr, cc, colour) in rc.iter() {
2738                    if ss.cells[(0,0)].row == *rr || ss.cells[(0,0)].col == *cc {
2739                        ss.colour = *colour;
2740
2741                        for i in ss.cells.keys() {
2742                            ss.cells[i].colour = *colour;
2743                        }
2744                    }
2745                }
2746            }
2747//shapes.to_grid().show();
2748
2749            shapes.to_grid()
2750        };
2751
2752        if let Some(rule) = run_experiment(task, 2075, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2753
2754        let func = |ex: &Example| {
2755            if !ex.input.grid.is_square() || colour_diffs.len() != 1 || all_colour_diffs.len() != 1 {
2756                return Grid::trivial();
2757            }
2758
2759            let (rs, cs) = ex.input.grid.dimensions();
2760            let r = (rs as f32).sqrt().abs() as usize;
2761            let c = (cs as f32).sqrt().abs() as usize;
2762            let grid_shapes = ex.input.grid.to_shapes_from_grid();
2763            let mut base = Shape::trivial();
2764            let mut shapes = grid_shapes.clone_base();
2765
2766            for s in grid_shapes.shapes.iter() {
2767                if s.colour != all_colour_diffs[0] && s.colour != Black {
2768                    if base == Shape::trivial() {
2769                        base = s.clone().to_origin();
2770                    } else if base.equals(s) != Same {
2771                        return Grid::trivial();
2772                    }
2773                }
2774            }
2775
2776            if base.size() < 4 {
2777                return Grid::trivial();
2778            }
2779
2780            let shape = base.clone();
2781
2782            for s in grid_shapes.shapes.iter() {
2783                if s.colour != all_colour_diffs[0] && s.colour != Black {
2784                    let pr = s.orow / r;
2785                    let pc = s.ocol / c;
2786
2787                    if pr >= s.cells.rows || pc >= s.cells.columns {
2788                        return Grid::trivial();
2789                    }
2790
2791                    let mut ns = s.clone();
2792
2793                    ns.cells[(pr,pc)].colour = colour_diffs[0];
2794                    base.cells[(pr,pc)].colour = Black;
2795                    shapes.shapes.push(ns);
2796                }
2797            }
2798
2799            for cell in base.cells.values() {
2800                if cell.colour != Black {
2801                    let pr = cell.row * r + cell.row;
2802                    let pc = cell.col * c + cell.col;
2803                    let mut ns = shape.clone();
2804
2805                    ns.cells[(cell.row,cell.col)].colour = colour_diffs[0];
2806                    shapes.shapes.push(ns.to_position(pr, pc));
2807                }
2808            }
2809
2810//shapes.to_grid().show();
2811            shapes.to_grid()
2812        };
2813
2814        if let Some(rule) = run_experiment(task, 2224, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2815
2816        *cap_todo.entry(gc).or_insert(0) += 1;
2817    }
2818    let gc = FullyPopulatedOut;
2819    if all || cat.contains(&gc) {
2820        *cap_cats.entry(gc).or_insert(0) += 1;
2821
2822        if let Some(rule) = run_experiment(task, 2083, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.find_sub_max().to_grid(), output) { return Some(rule); };
2823
2824        if let Some(rule) = run_experiment(task, 2085, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.largest().to_grid(), output) { return Some(rule); };
2825//target.show();
2826//ans.show();
2827
2828        if let Some(rule) = run_experiment(task, 2089, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.find_sub_min().to_grid(), output) { return Some(rule); };
2829
2830        let common_colours = examples.find_output_colours();
2831
2832        for colour in common_colours {
2833            if let Some(rule) = run_experiment(task, 2094, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.cell_colour_cnts(colour).to_grid(), output) { return Some(rule); };
2834        }
2835
2836        if let Some(rule) = run_experiment(task, 2097, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.find_sub_largest_count().to_grid(), output) { return Some(rule); };
2837
2838        let func = |ex: &Example| {
2839            let mut cnt = 0;
2840            let mut shapes: Vec<Shape> = Vec::new();
2841
2842            for s in ex.input.shapes.shapes.iter() {
2843                if s.size() >= 9 && s.colour != Mixed && s.dense() {
2844                    cnt += 1;
2845
2846                    shapes.push(s.clone())
2847                }
2848            }
2849
2850            let height = cnt / 3;
2851
2852            if height == 0 {
2853                return Grid::trivial();
2854            }
2855
2856            let mut grid = Grid::new(height, 3, Black);
2857            let mut r = 0;
2858
2859            // Get right ordering by munging row coord then sorting
2860            for (i, s) in shapes.iter_mut().enumerate() {
2861                if i > 0 && (i % 3) == 0 {
2862                    r += 1;
2863                }
2864
2865                s.orow = r;
2866            }
2867
2868            shapes.sort_by(|a, b| (a.orow, a.ocol).cmp(&(b.orow, b.ocol)));
2869//println!("{} by {}", ex.input.grid.cells.rows, ex.input.grid.cells.columns);
2870
2871            for (i, s) in shapes.iter().enumerate() {
2872                let r = i / 3;
2873                let c = i % 3;
2874//println!("{:?} {i} {}/{} -> {}/{}", s.colour, s.orow, s.ocol, x, y);
2875
2876                if r >= grid.cells.rows || c >= grid.cells.columns {
2877                    return Grid::trivial();
2878                }
2879
2880                grid.colour = s.colour;
2881
2882                grid.cells[(r,c)].row = i / 3;
2883                grid.cells[(r,c)].col = i / height;
2884                grid.cells[(r,c)].colour = s.colour;
2885            }
2886//grid.show();
2887
2888            grid
2889        };
2890
2891        if let Some(rule) = run_experiment(task, 2152, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2892
2893        let func = |ex: &Example| {
2894            if !ex.input.grid.is_square() {
2895                return Grid::trivial();
2896            }
2897
2898            let colours = ex.input.grid.find_colour_row_order();
2899            let len = colours.len();
2900
2901            if len == 0 {
2902                return Grid::trivial();
2903            }
2904            let colours: BTreeMap<usize, Colour> = colours.iter()
2905                .map(|(k,&v)| (k % len, v))
2906                .collect();
2907
2908            let mut grid = ex.input.grid.clone();
2909
2910            for ((r, c), cell) in ex.input.grid.cells.items() {
2911                if cell.colour == Black {
2912                    let idx = (r + c) % len;
2913
2914                    if let Some(colour) = colours.get(&idx) {
2915                        grid.cells[(r,c)].colour = *colour;
2916                    }
2917                }
2918            }
2919//grid.show();
2920
2921            grid
2922        };
2923
2924        if let Some(rule) = run_experiment(task, 2185, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2925
2926        let ex = &examples.examples[0];
2927        let in_colour = ex.output.grid.get_diff_colour(&ex.input.grid);
2928        let out_colour = ex.input.grid.get_diff_colour(&ex.output.grid);
2929
2930        let func = |ex: &Example| {
2931            ex.input.grid.recolour(in_colour, out_colour)
2932        };
2933
2934        if let Some(rule) = run_experiment(task, 2195, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2935
2936        let func = |ex: &Example| {
2937            let mut colours = ex.input.shapes.find_shape_colours();
2938
2939            let mut width = 0;
2940            let mut first = true;
2941
2942            for s in ex.input.shapes.shapes.iter() {
2943                if !first && s.ocol == 0 {
2944                    break;
2945                }
2946
2947                first = false;
2948                width += 1;
2949            }
2950
2951            if colours.len() % 2 == 1 && (colours.len() + 1) % width == 0 {
2952                let mut ps = Shape::trivial();
2953                
2954                for (n, s) in ex.input.shapes.shapes.iter().enumerate() {
2955                    if s.cells.rows > ps.cells.rows {
2956                        if ps.cells.rows > 0 {
2957                            if n + n + 1 > colours.len() {
2958                                return Grid::trivial();
2959                            }
2960
2961                            colours.insert(n + n + 1, s.colour);
2962
2963                            break;
2964                        }
2965                        ps = s.clone();
2966                    }
2967                }
2968            }
2969
2970            if width == 0 {
2971                return Grid::trivial();
2972            }
2973
2974            let mut grid = Grid::new(colours.len() / width, width, Black);
2975
2976            for (i, cell) in grid.cells.values_mut().enumerate() {
2977                cell.colour = colours[i];
2978            }
2979
2980            grid
2981        };
2982
2983        if let Some(rule) = run_experiment(task, 2244, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
2984
2985        let (rs, cs) = examples.examples[0].output.grid.dimensions();
2986
2987        let func = |ex: &Example| {
2988            if ex.input.shapes.shapes.is_empty() {
2989                return Grid::trivial();
2990            }
2991
2992            let (div_colour, shapes) = ex.input.grid.full_dim_split(&ex.input.shapes);
2993
2994            let mut colours: BTreeMap<Colour, Vec::<usize>> = BTreeMap::new();
2995
2996            for s in shapes.shapes.iter() {
2997                if s.colour != div_colour {
2998                    colours.entry(s.colour).and_modify(|size| size.push(s.size())).or_insert(vec![s.size()]);
2999                }
3000            }
3001
3002            let mut colour = NoColour;
3003
3004            for (k,v) in colours.iter() {
3005                if v.len() != 2 {
3006                    return Grid::trivial();
3007                }
3008
3009                if v[1] > v[0] + 2 {
3010                    colour = *k;
3011                    break;
3012                } else if v[0] + 2 == v[1] {
3013                    colour = *k;
3014                }
3015            }
3016
3017            if colour == NoColour {
3018                return Grid::trivial();
3019            }
3020
3021            Grid::new(rs, cs, colour)
3022        };
3023
3024        // 67b4a34d - merge
3025        if let Some(rule) = run_experiment(task, 2286, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3026
3027        /* Subsumed by 1193!
3028        let func = |ex: &Example| {
3029            let shape = ex.input.shapes.largest_solid();
3030            let other = if shape.orow > shape.ocol {
3031                ex.input.grid.subgrid(shape.orow, shape.cells.rows, ex.input.grid.cells.columns - (shape.ocol + shape.cells.columns), shape.cells.columns).mirrored_cols()
3032            } else {
3033                ex.input.grid.subgrid(ex.input.grid.cells.rows - (shape.orow + shape.cells.rows), shape.cells.rows, shape.ocol, shape.cells.columns).mirrored_rows()
3034            };
3035//other.show();
3036
3037            other
3038        };
3039
3040        if let Some(rule) = run_experiment(task, 2301, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3041
3042        // 0934a4d8 - merge
3043        let func = |ex: &Example| {
3044            let shape = ex.input.shapes.largest_solid();
3045            let cs = ex.input.grid.col_skew();
3046            let rs = ex.input.grid.row_skew();
3047
3048            let other = if shape.ocol < cs as usize {
3049                ex.input.grid.subgrid(0, shape.cells.columns, shape.orow, shape.cells.rows).rot_rect_270().mirrored_rows()
3050            } else if shape.orow < rs as usize {    // Needs checking
3051                ex.input.grid.subgrid(shape.orow, shape.cells.rows, 0, shape.cells.columns).rot_rect_90().mirrored_cols()
3052            } else if shape.orow < shape.ocol {
3053                ex.input.grid.subgrid(shape.orow, shape.cells.rows, ex.input.grid.cells.columns - (shape.ocol + shape.cells.columns) + cs as usize, shape.cells.columns).mirrored_cols()
3054            } else {
3055                ex.input.grid.subgrid(ex.input.grid.cells.rows - (shape.orow + shape.cells.rows) + rs as usize, shape.cells.rows, shape.ocol, shape.cells.columns).mirrored_rows()
3056            };
3057//other.show();
3058
3059            other
3060        };
3061
3062        if let Some(rule) = run_experiment(task, 2323, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3063        */
3064
3065        let func = |ex: &Example| {
3066            if all_colour_diffs.is_empty() {
3067                return Grid::trivial();
3068            }
3069
3070            let mut grid = ex.input.grid.clone();
3071            for i in 0 .. 2 {
3072                let shapes = grid.find_colour_patches(all_colour_diffs[0]);
3073
3074                for shape in shapes.shapes.iter() {
3075                    let g = if i == 0 {
3076                        let cpos = ex.input.grid.cells.columns - (shape.ocol + shape.cells.columns);
3077                        ex.input.grid.subgrid(shape.orow, shape.cells.rows, cpos, shape.cells.columns).mirrored_cols()
3078
3079                    } else {
3080                        let rpos = ex.input.grid.cells.rows - (shape.orow + shape.cells.rows);
3081                        ex.input.grid.subgrid(rpos, shape.cells.rows, shape.ocol, shape.cells.columns).mirrored_rows()
3082                    };
3083
3084                    grid.copy_to_position_mut(&g, shape.orow, shape.ocol);
3085                }
3086            }
3087            
3088            grid
3089        };
3090
3091        if let Some(rule) = run_experiment(task, 2352, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3092
3093        let func = |ex: &Example| {
3094            if all_colour_diffs.is_empty() || !ex.input.grid.is_square() {
3095                return Grid::trivial();
3096            }
3097
3098            let mut grid = ex.input.grid.clone();
3099            let shapes = grid.find_colour_patches(all_colour_diffs[0]);
3100            let gr = grid.cells.rows;
3101            let gc = grid.cells.columns;
3102
3103            for shape in shapes.shapes.iter() {
3104                for cell in shape.cells.values() {
3105                    if grid.cells[(cell.row,cell.col)].colour == shape.colour {
3106                        if grid.cells[(gr - cell.row - 1,cell.col)].colour != shape.colour {
3107                            grid.cells[(cell.row,cell.col)].colour = grid.cells[(gr - cell.row - 1,cell.col)].colour;
3108                        } else if grid.cells[(cell.row,gc - cell.col - 1)].colour != shape.colour {
3109                            grid.cells[(cell.row,cell.col)].colour = grid.cells[(cell.row,gc - cell.col - 1)].colour;
3110                        } else if grid.cells[(gr - cell.row - 1,gc - cell.col - 1)].colour != shape.colour {
3111                            grid.cells[(cell.row,cell.col)].colour = grid.cells[(gr - cell.row - 1,gc - cell.col - 1)].colour;
3112                        } else if grid.cells[(cell.col,cell.row)].colour != shape.colour {
3113                            grid.cells[(cell.row,cell.col)].colour = grid.cells[(cell.col,cell.row)].colour;
3114//                        } else {
3115//println!("--- {} {} {:?}", cell.row, cell.col, cell.colour);
3116                        }
3117                    }
3118                }
3119            }
3120//grid.show();
3121            
3122            grid
3123        };
3124
3125        if let Some(rule) = run_experiment(task, 2386, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3126
3127        let func = |ex: &Example| {
3128            if !ex.input.grid.is_square() {
3129                return Grid::trivial();
3130            }
3131
3132            let cnt = ex.input.grid.cell_colour_cnt_map();
3133            let grid = ex.input.grid.scale_up(cnt.len());
3134            
3135            grid
3136        };
3137
3138        if let Some(rule) = run_experiment(task, 2399, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3139
3140        let func = |ex: &Example| {
3141            if all_colour_diffs.is_empty() || !ex.input.grid.is_square() {
3142                return Grid::trivial();
3143            }
3144
3145            let mut grid = ex.input.grid.clone();
3146            let gr = grid.cells.rows;
3147            let gc = grid.cells.columns;
3148            let rs = ex.input.grid.row_skew();
3149            let cs = ex.input.grid.col_skew();
3150            let rr = gr + rs as usize - 1;
3151            let cr = gc + cs as usize - 1;
3152
3153            if rs != cs {
3154                return Grid::trivial();
3155            }
3156
3157            let shapes = grid.find_colour_patches(all_colour_diffs[0]);
3158
3159            for shape in shapes.shapes.iter() {
3160                let new_shape = if cs > 0 && (shape.ocol as isize) < cs {
3161                    grid.populate_skew_edge_lr(&shape, all_colour_diffs[0])
3162                } else {
3163                    shape.clone()
3164                };
3165                let new_shape = if rs > 0 && (shape.orow as isize) < rs {
3166                    grid.populate_skew_edge_tb(&new_shape, all_colour_diffs[0])
3167                } else {
3168                    new_shape
3169                };
3170
3171                for cell in shape.cells.values() {
3172                    let r = cell.row;
3173                    let c = cell.col;
3174
3175                    if grid.cells[(cell.row,cell.col)].colour == shape.colour {
3176                        if r > gr / 2 && grid.cells[(rr - r,c)].colour != shape.colour {
3177                            grid.cells[(r,c)].colour = grid.cells[(rr - r,c)].colour;
3178                        } else if c > gr / 2 && grid.cells[(r,cr - c)].colour != shape.colour {
3179                            grid.cells[(r,c)].colour = grid.cells[(r,cr - c)].colour;
3180                        } else if rr >= r && cr >= c && rr - r < gr && cr - c < gc && grid.cells[(rr - r,cr - c)].colour != shape.colour {
3181                            grid.cells[(r,c)].colour = grid.cells[(rr - r,cr - c)].colour;
3182                        } else if grid.cells[(c,r)].colour != shape.colour {
3183                            if r + rs as usize >= grid.cells.rows || c + cs as usize >= grid.cells.columns {
3184                                return Grid::trivial();
3185                            }
3186
3187                            grid.cells[(r,c)].colour = grid.cells[(r + rs as usize,c + cs as usize)].colour;
3188                        }
3189                    }
3190                }
3191                let shape = grid.subgrid(shape.orow, shape.cells.rows, shape.ocol, shape.cells.columns).as_shape();
3192                let grid = new_shape.copy_not_colour(&shape, all_colour_diffs[0]).to_grid();
3193
3194//grid.show();
3195                return grid;
3196            }
3197            
3198            Grid::trivial()
3199        };
3200
3201        if let Some(rule) = run_experiment(task, 2471, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3202
3203        let dir = ex.output.shapes.border_gravity();
3204
3205        let func = |ex: &Example| {
3206            if !all_colour_diffs.is_empty() || colour_common.len() < 3 {
3207                return Grid::trivial();
3208            }
3209
3210            let conts = ex.input.shapes.group_containers();
3211            let mut shapes = ex.input.shapes.clone_base();
3212
3213            for (k, v) in conts.iter() {
3214                let nk = k.recolour(Black, v[0].colour);
3215                let nk = if let Some(dir) = dir.get(&k.colour) {
3216                    match dir {
3217                        Up => nk.gravity_up_colour(k.colour),
3218                        Down => nk.gravity_down_colour(k.colour),
3219                        Left => nk.gravity_left_colour(k.colour),
3220                        Right => nk.gravity_right_colour(k.colour),
3221                        _ => todo!(),
3222                    }
3223                } else {
3224                    return Grid::trivial();
3225                };
3226
3227                shapes.shapes.push(nk);
3228            }
3229
3230            shapes.to_grid()
3231        };
3232
3233        if let Some(rule) = run_experiment(task, 2503, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3234
3235        let mut out_colour: Vec<_> = examples.examples[0].output.grid.cell_colour_cnt_map()
3236            .into_iter()
3237            .map(|(k,v)| (v,k))
3238            .collect();
3239        out_colour.sort();
3240        out_colour.reverse();
3241        let out_colour: Vec<_> = out_colour.into_iter().map(|(_,v)| v).collect();
3242        // testing function
3243        let func = |ex: &Example| {
3244            if colour_diffs.len() != 3 || out_colour.len() != 5 {
3245                return Grid::trivial();
3246            }
3247
3248            let mut shapes = ex.input.shapes.clone_base();
3249
3250            for s in ex.input.shapes.shapes.iter() {
3251                if s.size() == ex.input.grid.size() {
3252                    shapes.shapes.push(s.clone());
3253                    continue;
3254                }
3255                if s.colour == out_colour[0] {
3256                    continue;
3257                }
3258                let mut s = s.add_hugging_border(colour_diffs[0]);
3259
3260                s.flood_fill_border_mut(NoColour, out_colour[0]);
3261                s.recolour_mut(Black, out_colour[4]);
3262
3263                if s.contains_colour(out_colour[4]) {
3264                    s.recolour_mut(out_colour[1], out_colour[3]);
3265                }
3266
3267                shapes.shapes.push(s);
3268            }
3269
3270//grid.show();
3271            shapes.to_grid_colour_transparent(out_colour[0])
3272        };
3273
3274        if let Some(rule) = run_experiment(task, 2544, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3275
3276        let func = |ex: &Example| {
3277            if all_colour_diffs.len() != 1 {
3278                return Grid::trivial();
3279            }
3280
3281            let mut h: BTreeMap<(Colour, u32), usize> = BTreeMap::new();
3282
3283            for s in ex.input.shapes.shapes.iter() {
3284                *h.entry((s.colour, Shape::sid(&s.cells, false))).or_insert(0) += 1;
3285            }
3286
3287            let mut colour = NoColour;
3288
3289            for s in ex.input.shapes.shapes.iter() {
3290                if let Some(cnt) = h.get(&(s.colour, Shape::sid(&s.cells, false))) {
3291                    if *cnt > 1 && s.size() > 1 {
3292                        colour = s.colour;
3293                        break;
3294                    }
3295                }
3296            }
3297
3298            let colours = Uniq::uniq(&colour_common, all_colour_diffs.clone());
3299            let colours = Uniq::uniq(&colours, vec![colour]);
3300
3301            if colours.len() != 1 {
3302                return Grid::trivial();
3303            }
3304
3305            for s in ex.input.shapes.shapes.iter() {
3306                if let Some(cnt) = h.get(&(s.colour, Shape::sid(&s.cells, false))) {
3307                    if s.colour == colour && *cnt == 1 {
3308                        return s.recolour(Black, colours[0]).add_border(colours[0]).to_grid();
3309                    }
3310                }
3311            }
3312
3313            Grid::trivial()
3314        };
3315
3316        if let Some(rule) = run_experiment(task, 2586, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3317
3318        let func = |ex: &Example| {
3319            let mut bg = ex.input.grid.has_bg_grid_not_sq();
3320
3321            if bg == NoColour { // is this necessary
3322                bg = Black;
3323            }
3324
3325            let mut colour = NoColour;
3326            let mut min_r = usize::MAX;
3327            let mut min_c = usize::MAX;
3328            let mut max_r = 0;
3329            let mut max_c = 0;
3330
3331            for s in ex.input.shapes.shapes.iter() {
3332                if s.is_full() {
3333                    colour = s.colour;
3334                }
3335            }
3336
3337            for s in ex.input.shapes.shapes.iter() {
3338                if s.colour == colour {
3339                    min_r = min_r.min(s.orow);
3340                    min_c = min_c.min(s.ocol);
3341                    max_r = max_r.max(s.orow + s.cells.rows - 1);
3342                    max_c = max_c.max(s.ocol + s.cells.columns - 1);
3343                }
3344            }
3345
3346            for s in ex.input.shapes.shapes.iter() {
3347                if s.colour != colour && s.orow >= min_r && s.orow <= max_r && s.ocol >= min_c && s.ocol <= max_c {
3348//s.recolour(Black, bg).to_grid().show();
3349                    return s.recolour(Black, bg).to_grid();
3350                }
3351            }
3352
3353            Grid::trivial()
3354        };
3355
3356        if let Some(rule) = run_experiment(task, 2626, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3357
3358        let func = |ex: &Example| {
3359            let bg = ex.output.grid.has_bg_grid_not_sq();
3360
3361            if all_colour_diffs.len() != 1 || ex.input.grid.cells.rows < 4 || ex.input.grid.cells.columns < 4 {
3362                return Grid::trivial();
3363            }
3364
3365            let colour1 = ex.input.grid.cells[(1,1)].colour;
3366            let colour2 = ex.input.grid.cells[(2,2)].colour;
3367            let colour3 = ex.input.grid.cells[(3,3)].colour;
3368
3369            if colour1 == bg {
3370                return Grid::trivial();
3371            }
3372
3373            let mut grid = ex.input.grid.clone();
3374
3375            for ((r, c), cell) in ex.input.grid.cells.items() {
3376                if cell.colour == all_colour_diffs[0] {
3377                    grid.cells[(r, c)].colour = bg;
3378                }
3379                let one = colour1 != bg && colour2 == bg && colour3 != bg;
3380                let two = colour1 != bg && colour2 == bg && colour3 == bg;
3381                let three = colour1 != bg && colour2 != bg && colour3 == bg;
3382
3383                if one && r % 2 == 1 && c % 2 == 1 ||
3384                   two && r % 3 == 1 && c % 3 == 1 ||
3385                   three && (r % 3 == 1 || r % 3 == 2) && (c % 3 == 1 || c % 3 == 2) {
3386                    grid.cells[(r, c)].colour = colour1;
3387                }
3388            }
3389            
3390//grid.show();
3391            grid
3392        };
3393
3394        if let Some(rule) = run_experiment(task, 2664, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3395
3396        let func = |ex: &Example| {
3397            if ex.input.shapes.shapes.len() < 3 {
3398                return Grid::trivial();
3399            }
3400
3401            let mut shapes = ex.input.shapes.clone();
3402
3403            for (i, s) in ex.input.shapes.shapes.iter().enumerate() {
3404                if s.size() == ex.input.grid.size() {
3405                    shapes.shapes.remove(i);
3406                }
3407            }
3408
3409            shapes.shapes.sort_by(|a, b| b.size().cmp(&a.size()));
3410
3411            let mut new_shapes = Shapes::new_sized(shapes.shapes[0].cells.rows, shapes.shapes[0].cells.columns);
3412
3413            for s in shapes.shapes.iter() {
3414                let mut ns = s.to_origin();
3415
3416                ns.force_recolour_mut(s.colour);
3417
3418                new_shapes.shapes.push(ns);
3419            }
3420
3421//new_shapes.to_grid().show();
3422            new_shapes.to_grid()
3423        };
3424
3425        if let Some(rule) = run_experiment(task, 2695, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3426
3427        let func = |ex: &Example| {
3428            if ex.input.shapes.shapes.is_empty() || colour_diffs.len() != 1 {
3429                return Grid::trivial();
3430            }
3431
3432            let bg = ex.input.grid.majority_colour();
3433
3434            let mut grid = ex.input.grid.clone();
3435
3436            for s in ex.input.shapes.shapes.iter() {
3437                if s.dimensions() != ex.input.grid.dimensions() {
3438                    let (dir, r, c) = s.has_border_break();
3439
3440                    if s.orow == ex.input.grid.cells.rows - 1 || s.ocol == ex.input.grid.cells.columns - 1 {
3441                        return Grid::trivial();
3442                    }
3443
3444                    grid.draw_bg_mut(dir, r, c, colour_diffs[0], bg);
3445                    grid.flood_fill_bg_mut(s.orow + 1, s.ocol + 1, NoColour, bg, colour_diffs[0]);
3446                }
3447            }
3448
3449//grid.show();
3450            grid
3451        };
3452
3453        if let Some(rule) = run_experiment(task, 2723, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3454
3455        let func = |ex: &Example| {
3456            if colour_diffs.len() != 1 {
3457                return Grid::trivial();
3458            }
3459            let mut grid = ex.input.grid.clone();
3460
3461            for r in 0 .. grid.cells.rows {
3462                for c in 0 .. grid.cells.columns {
3463                    if grid.cells[(r,c)].colour == grid.colour && c > 0 && grid.cells[(r,c-1)].colour == Black {
3464                        grid.cells[(r,c-1)].colour = grid.colour;
3465                        break;
3466                    }
3467                }
3468                for c in (0 .. grid.cells.columns).rev() {
3469                    if grid.cells[(r,c)].colour == grid.colour {
3470                        grid.cells[(r,c)].colour = Black;
3471                        break;
3472                    }
3473                }
3474            }
3475
3476            grid.recolour_mut(Black, colour_diffs[0]);
3477
3478//grid.show();
3479            grid
3480        };
3481
3482        if let Some(rule) = run_experiment(task, 2752, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3483
3484        let func = |ex: &Example| {
3485            if !all_colour_diffs.is_empty()  || ex.input.shapes.len() < 3 || ex.input.shapes.len() > 20 {
3486                return Grid::trivial();
3487            }
3488
3489            let mut shapes = ex.input.shapes.clone();
3490
3491            shapes.shapes.sort_by(|a, b| a.size().cmp(&b.size()));
3492
3493            let mut size = 0;
3494
3495            for s in shapes.shapes.iter() {
3496                if size == 0 {
3497                    size += s.cells.rows.max(s.cells.columns);
3498                } else {
3499                    size += 2;
3500                }
3501            }
3502
3503            let mut grid = Grid::new(size, size, Black);
3504
3505            shapes.shapes.sort_by(|a, b| b.size().cmp(&a.size()));
3506
3507            for (i, s) in shapes.shapes.iter().enumerate() {
3508                for r in i .. size {
3509                    for c in i .. size {
3510                        grid.cells[(r, c)].colour = s.colour;
3511                    }
3512                }
3513                size -= 1;
3514            }
3515
3516//grid.show();
3517            grid
3518        };
3519
3520        if let Some(rule) = run_experiment(task, 2790, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3521
3522        let func = |ex: &Example| {
3523            if !all_colour_diffs.is_empty() {
3524                return Grid::trivial();
3525            }
3526
3527            let bg_colour = ex.input.shapes.largest().colour;
3528            let mut largest = ex.input.coloured_shapes.largest().to_grid();
3529
3530            for s in ex.input.coloured_shapes.shapes.iter() {
3531                if s.dimensions() != largest.dimensions() {
3532                    let colour = s.minority_colour();
3533                    let (r, c) = s.to_origin().find_colour_pixel_coords(colour);
3534                    let (lr, lc) = largest.find_colour_pixel_coords(colour);
3535
3536                    if lr > 0 || lc > 0 {
3537                        if lr < r || lc < c {
3538                            return Grid::trivial();
3539                        }
3540
3541                        largest.copy_shape_to_grid_position_mut(s, lr - r, lc - c);
3542                    }
3543                }
3544            }
3545
3546            largest.recolour_mut(Black, bg_colour);
3547
3548//largest.show();
3549            largest
3550        };
3551
3552        if let Some(rule) = run_experiment(task, 2818, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3553
3554        let func = |ex: &Example| {
3555            let pred = |solver: &Grid, r, c, colour| !solver.used_in_row(r, colour) && !solver.used_in_col(c, colour);
3556
3557            let mut grid = ex.input.grid.clone();
3558
3559            grid.solve(&pred);
3560
3561//grid.show();
3562            grid
3563        };
3564
3565        if let Some(rule) = run_experiment(task, 2819, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3566
3567        *cap_todo.entry(gc).or_insert(0) += 1;
3568    }
3569    let gc = MirrorCIn;
3570    if all || cat.contains(&gc) || cat.contains(&MirrorCOut) {
3571        *cap_cats.entry(gc).or_insert(0) += 1;
3572
3573        let func = |ex: &Example| {
3574            if ex.input.shapes.shapes.is_empty() {
3575                return Grid::trivial();
3576            }
3577
3578            let mut row = ex.input.shapes.shapes[0].orow;
3579            let mut shapes = ex.input.shapes.clone();
3580
3581            for s in shapes.shapes.iter_mut().rev() {
3582                s.to_position_mut(row, s.ocol);
3583                row += s.cells.rows;
3584            }
3585
3586            shapes.to_grid()
3587        };
3588
3589        if let Some(rule) = run_experiment(task, 2842, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3590
3591        // Also done by 142
3592        let func = |ex: &Example| {
3593            if ex.input.shapes.shapes.is_empty() {
3594                return Grid::trivial();
3595            }
3596
3597            let shapes = ex.input.grid.to_shapes_cons();
3598            let mut new_shapes = shapes.clone_base();
3599
3600            for s in shapes.shapes.iter() {
3601                let ns = s.mirrored_r();
3602
3603                new_shapes.shapes.push(ns);
3604            }
3605
3606            new_shapes.to_grid()
3607        };
3608
3609        if let Some(rule) = run_experiment(task, 2862, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3610
3611        *cap_todo.entry(gc).or_insert(0) += 1;
3612    }
3613    let gc = MirrorROut;
3614    if all || cat.contains(&gc) || cat.contains(&MirrorCOut) {
3615        *cap_cats.entry(gc).or_insert(0) += 1;
3616
3617        let func = |gi: &Example| {
3618            if gi.input.coloured_shapes.len() != 1 {
3619                return Grid::trivial();
3620            }
3621
3622            let s = gi.input.grid.as_shape();
3623
3624            let rows = s.cells.rows;
3625            let cols = s.cells.columns;
3626            let mut shapes = Shapes::new_sized(rows * 2, cols * 2);
3627
3628            shapes.shapes.push(s.mirrored_r().mirrored_c());
3629            shapes.shapes.push(s.mirrored_c().translate_absolute(rows, 0));
3630            shapes.shapes.push(s.mirrored_r().translate_absolute(0, cols));
3631            shapes.shapes.push(s.translate_absolute(rows, cols));
3632
3633//shapes.to_grid().show();
3634            shapes.to_grid()
3635        };
3636
3637        if let Some(rule) = run_experiment(task, 2890, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3638
3639        let func = |ex: &Example| {
3640            let bg = ex.input.grid.max_colour();
3641            let shapes = ex.input.grid.to_shapes_sq();
3642            let shapes = shapes.colour_groups_to_shapes(bg);
3643
3644            shapes.to_grid()
3645        };
3646
3647        if let Some(rule) = run_experiment(task, 2900, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3648
3649        *cap_todo.entry(gc).or_insert(0) += 1;
3650    }
3651    let gc = Div9In;
3652    if all || cat.contains(&gc) && !cat.contains(&Div9Out) { 
3653        *cap_cats.entry(gc).or_insert(0) += 1;
3654
3655        //-if let Some(rule) = run_experiment_examples(&file, 1020, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_9_in_out(&exs), output) { return Some(rule); };
3656        //
3657        let out_colours = examples.find_all_output_colours();
3658        let (rs, cs) = examples.examples[0].output.grid.dimensions();
3659
3660        if out_colours.len() == 2 && examples.examples[0].input.grid.is_3x3() {
3661            let func = |ex: &Example| {
3662               if ex.input.grid.cells[(0,1)].colour == Black && ex.input.grid.cells[(2,1)].colour == Black {
3663                   Grid::new(rs,cs,out_colours[0])
3664               } else {
3665                   Grid::new(rs,cs,out_colours[1])
3666               }
3667            };
3668
3669            if let Some(rule) = run_experiment(task, 2922, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3670        }
3671
3672        *cap_todo.entry(gc).or_insert(0) += 1;
3673    }
3674    let gc = Div9Out;
3675    if all || cat.contains(&Is3x3In) && cat.contains(&gc) && !cat.contains(&Div9In){ 
3676        *cap_cats.entry(gc).or_insert(0) += 1;
3677
3678        let func = |ex: &Example| {
3679            if colour_common.len() != 9 || !ex.input.grid.cells.is_square() {
3680                return Grid::trivial();
3681            }
3682            let div = ex.input.grid.cells.rows.isqrt();
3683            let mut cells: BTreeMap<(usize,usize),Colour> = BTreeMap::new();
3684
3685            for cell in ex.input.grid.cells.values() {
3686                if cell.colour != Black {
3687                    cells.insert((cell.row / div, cell.col), cell.colour);
3688                }
3689            }
3690            let mut grid = Grid::new(3, 3, Black);
3691
3692            for (cell, colour) in grid.cells.values_mut().zip(cells.values()) {
3693                cell.colour = *colour;
3694            }
3695
3696//grid.show();
3697            grid
3698        };
3699
3700        if let Some(rule) = run_experiment(task, 2923, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3701
3702        *cap_todo.entry(gc).or_insert(0) += 1;
3703    }
3704    let gc = Div9In;
3705    if all || cat.contains(&gc) && cat.contains(&Is3x3Out) && !cat.contains(&Div9Out) { 
3706        *cap_cats.entry(gc).or_insert(0) += 1;
3707
3708        //-if let Some(rule) = run_experiment_examples(&file, 1030, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_mirror(&exs), output) { return Some(rule); };
3709
3710        //-if let Some(rule) = run_experiment_examples(&file, 1040, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_double(&exs), output) { return Some(rule); };
3711
3712        //-if let Some(rule) = run_experiment_examples(&file, 1050, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_expand_3x3(&exs), output) { return Some(rule); };
3713
3714        if let Some(rule) = run_experiment(task, 2943, experiment, trans, is_test, examples, &targets, done, tries, &|ex| repeat_pattern(&ex, Black), output) { return Some(rule); };
3715
3716        let func = |ex: &Example| {
3717            let colour = if ex.input.grid.colour == Mixed {
3718                ex.input.grid.find_max_colour()
3719            } else {
3720                ex.input.grid.colour
3721            };
3722
3723            repeat_pattern(ex, colour)
3724        };
3725
3726        if let Some(rule) = run_experiment(task, 2955, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3727
3728        let func = |ex: &Example| {
3729            let colour = if ex.input.grid.colour == Mixed {
3730                ex.input.grid.find_min_colour()
3731            } else {
3732                ex.input.grid.colour
3733            };
3734
3735            repeat_pattern(ex, colour)
3736        };
3737
3738        if let Some(rule) = run_experiment(task, 2967, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3739
3740        if let Some(rule) = run_experiment_colours(task, 2969, experiment, is_test, examples, &targets, done, &|ex, colour| repeat_pattern(ex, colour), output) { return Some(rule); };
3741
3742        /*
3743        let func = |ex: &Example| {
3744            if !cat.contains(&InLessThanOut) {
3745                return Grid::trivial();
3746            }
3747            let colour = if ex.input.grid.colour == Mixed {
3748                ex.input.grid.find_max_colour()
3749            } else {
3750                ex.input.grid.colour
3751            };
3752            let shape = ex.input.grid.as_shape();
3753            let (rs, cs) = ex.input.grid.dimensions();
3754
3755            let shapes = shape.chequer(rs, cs, &|r,c| ex.input.grid.cells[(r / rs,c / cs)].colour == colour, &|s| s.clone(), true);
3756
3757            shapes.to_grid()
3758        };
3759
3760        if let Some(rule) = run_experiment(task, 2989, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3761
3762        let func = |ex: &Example| {
3763            if !cat.contains(&InLessThanOut) {
3764                return Grid::trivial();
3765            }
3766            let colour = if ex.input.grid.colour == Mixed {
3767                ex.input.grid.find_min_colour()
3768            } else {
3769                ex.input.grid.colour
3770            };
3771            let shape = ex.input.grid.as_shape();
3772            let (rs, cs) = ex.input.grid.dimensions();
3773
3774            let shapes = shape.chequer(rs, cs, &|r,c| ex.input.grid.cells[(r / rs,c / cs)].colour == colour, &|s| s.clone(), true);
3775
3776            shapes.to_grid()
3777        };
3778
3779        if let Some(rule) = run_experiment(task, 3008, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3780
3781        if examples.examples[0].input.grid.size().pow(2) == examples.examples[0].output.grid.size() {
3782            let func = |ex: &Example| {
3783                let (colour, _) = ex.input.grid.as_shape().colour_cnt(false);
3784
3785                repeat_pattern(ex, colour)
3786            };
3787
3788            if let Some(rule) = run_experiment(task, 3017, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3789
3790            let shapes_out = examples.examples[0].output.coloured_shapes.shapes.len();
3791            let h = examples.examples[0].input.grid.cell_colour_cnt_map();
3792            let colours: Vec<Colour> = h.iter().filter(|(_, &v)| v == shapes_out).map(|(&k,_)| k).collect();
3793
3794            let func = |ex: &Example| {
3795                if colours.len() != 1 {
3796                    return Grid::trivial();
3797                }
3798
3799                repeat_pattern(ex, colours[0])
3800            };
3801
3802            if let Some(rule) = run_experiment(task, 3031, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3803        }
3804        */
3805        *cap_todo.entry(gc).or_insert(0) += 1;
3806    }
3807    let gc = IdenticalNoPixels;
3808    if all || cat.contains(&gc) { // 164
3809        *cap_cats.entry(gc).or_insert(0) += 1;
3810
3811        /*
3812        let func = |ex: &Example| {
3813            let grid = &ex.input.grid;
3814            if grid.cells.rows != grid.cells.columns {
3815                return Grid::trivial();
3816            }
3817
3818            let shapes = &ex.input.shapes.shapes;
3819            let trivial = Shape::trivial();
3820            let mut border1: &Shape = &trivial;
3821            let mut border2: &Shape = &trivial;
3822            let mut x = false;
3823//ex.input.shapes.show();
3824
3825            for s in shapes {
3826                if s.size() == 1 {
3827                    continue;
3828                }
3829                if s.orow == 0 && s.cells.columns == grid.cells.columns {
3830                    x = true;
3831                    border1 = s;
3832                } else if s.orow == grid.cells.rows - 1 && s.cells.columns == grid.cells.columns {
3833                    x = true;
3834                    border2 = s;
3835                } else if s.ocol == 0 && s.cells.rows == grid.cells.rows {
3836                    border1 = s;
3837                } else if s.ocol == grid.cells.columns - 1 && s.cells.rows == grid.cells.rows {
3838                    border2 = s;
3839                }
3840            }
3841
3842            let mut new_shapes = ex.input.shapes.clone();
3843
3844            for s in new_shapes.shapes.iter_mut() {
3845                if s.size() == 1 {
3846                    if x && s.distance_x(border1) < s.distance_x(border2) || !x && s.distance_y(border1) < s.distance_y(border2){
3847                        s.force_recolour_mut(border1.colour);
3848                    } else {
3849                        s.force_recolour_mut(border2.colour);
3850                    }
3851                }
3852            }
3853println!("139 --- {file}");
3854
3855            new_shapes.to_grid()
3856        };
3857        */
3858
3859        // Not working???
3860        //if let Some(rule) = run_experiment(file, 139, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3861
3862        let func = |ex: &Example| {
3863            let grid = &ex.input.grid;
3864            if grid.cells.rows != grid.cells.columns {  // Must be square
3865                return Grid::trivial();
3866            }
3867            // Do manually as will miss shapes starting in 0,0!
3868            let shapes = grid.to_shapes();
3869
3870            if shapes.shapes.is_empty() {
3871                return Grid::trivial();
3872            }
3873
3874            let x_axis = shapes.shapes[0].height() > 1;
3875
3876            let borders: Vec<_> = shapes.shapes.iter().filter(|s| s.size() > 1).collect();
3877            if borders.len() != 2 {
3878                return Grid::trivial();
3879            }
3880
3881            let c1 = borders[0].colour;
3882            let c2 = borders[1].colour;
3883
3884            let mut new_grid = grid.clone();
3885
3886            for s in ex.input.shapes.shapes.iter() {
3887                if s.size() == 1 {
3888                    if x_axis {
3889                        new_grid.cells[(s.orow, s.ocol)].colour = if s.ocol < grid.cells.columns / 2 { c1 } else { c2 };
3890                    } else {
3891                        new_grid.cells[(s.orow, s.ocol)].colour = if s.orow < grid.cells.rows / 2 { c1 } else { c2 };
3892                    }
3893                }
3894            }
3895//new_grid.show();
3896
3897            new_grid
3898        };
3899
3900        if let Some(rule) = run_experiment(task, 3129, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3901
3902        // Also done by 126
3903        let func = |ex: &Example| {
3904            let mut grid = ex.input.grid.clone();
3905
3906            for (r, c) in ex.input.grid.cells.keys() {
3907                if ex.input.grid.cells[(r, 0)].colour != Black && grid.cells[(r, c)].colour != Black {
3908                    grid.cells[(r, c)].colour = ex.input.grid.cells[(r, 0)].colour;
3909                }
3910            }
3911            
3912            grid
3913        };
3914
3915        if let Some(rule) = run_experiment(task, 3144, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3916
3917        let out_colours = examples.find_output_colours();
3918
3919        let func = |ex: &Example| {
3920            if out_colours.len() != 1 {
3921                return Grid::trivial();
3922            }
3923
3924            let mut shapes = ex.input.shapes.clone();
3925            // get them in right order to alternate
3926            shapes.shapes.sort_by_key(|a| a.size());
3927            let mut toddle = false;
3928
3929            for shape in shapes.shapes.iter_mut() {
3930                for cell in shape.cells.values_mut() {
3931                    if cell.colour != Black {
3932                        if toddle {
3933                            cell.colour = out_colours[0];
3934                        }
3935                        toddle = !toddle;
3936                    }
3937                }
3938            }
3939            // reverse order to lay on top on one another
3940            shapes.shapes.sort_by_key(|b| std::cmp::Reverse(b.size()));
3941
3942//shapes.to_grid().show();
3943            shapes.to_grid()
3944        };
3945
3946        if let Some(rule) = run_experiment(task, 3175, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3947
3948        let func = |ex: &Example| {
3949            if colour_diffs.len() != 1 {
3950                return Grid::trivial();
3951            }
3952
3953            let mut shapes = ex.input.grid.to_shapes_sq();
3954
3955            for shape in shapes.shapes.iter_mut() {
3956                if shape.is_pixel() {
3957                    shape.force_recolour_mut(colour_diffs[0]);
3958                }
3959            }
3960
3961//shapes.to_grid().show();
3962            shapes.to_grid()
3963        };
3964
3965        if let Some(rule) = run_experiment(task, 3194, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3966
3967        let func = |ex: &Example| {
3968            if colour_diffs.len() != 1 {
3969                return Grid::trivial();
3970            }
3971
3972            let mut shapes = ex.input.grid.to_shapes_sq();
3973
3974            shapes.shapes.sort_by(|a, b| (a.ocol, a.orow).cmp(&(b.ocol, b.orow)));
3975
3976            let mut toddle = ex.input.grid.cells.columns % 2 != 0;
3977
3978            for shape in shapes.shapes.iter_mut() {
3979                if toddle {
3980                    shape.force_recolour_mut(colour_diffs[0]);
3981                }
3982                toddle = !toddle;
3983            }
3984
3985//shapes.to_grid().show();
3986            shapes.to_grid()
3987        };
3988
3989        if let Some(rule) = run_experiment(task, 3218, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
3990
3991        let ex = &examples.examples[0];
3992        let smallest = ex.input.shapes.smallest();
3993        let in_colour = smallest.colour;
3994
3995        if ex.output.grid.height() >= ex.input.grid.height() && ex.output.grid.width() >= ex.input.grid.width() {
3996            let out_colour = ex.output.grid.cells[(smallest.orow,smallest.ocol)].colour;
3997            let mut diag_colour = colour_diffs.clone();
3998
3999            diag_colour.retain(|&c| c != out_colour);
4000
4001            // testing function
4002            let func = |ex: &Example| {
4003                if diag_colour.len() != 1 {
4004                    return Grid::trivial();
4005                }
4006
4007                let mut grid = ex.input.grid.clone();
4008                let bg = grid.has_bg_grid_not_sq();
4009
4010                for s in ex.input.shapes.shapes.iter() {
4011                    if s.is_pixel() {
4012                        grid.draw_bg_mut(Up, s.orow, s.ocol, in_colour, bg);
4013                        grid.draw_bg_mut(Down, s.orow, s.ocol, in_colour, bg);
4014                        grid.draw_bg_mut(Left, s.orow, s.ocol, in_colour, bg);
4015                        grid.draw_bg_mut(Right, s.orow, s.ocol, in_colour, bg);
4016                    }
4017                }
4018                
4019                let mut shapes = Shapes::new_sized(grid.cells.rows, grid.cells.columns);
4020
4021                shapes.shapes.push(grid.as_shape());
4022
4023                for s in ex.input.shapes.shapes.iter() {
4024                    if s.is_pixel() {
4025                        let ns = s.recolour(in_colour, out_colour);
4026
4027                        shapes.shapes.push(ns);
4028
4029                        let surround = s.surround(1, diag_colour[0], false, true);
4030
4031                        shapes.shapes.push(surround);
4032                    }
4033                }
4034
4035//shapes.to_grid().show();
4036                shapes.to_grid()
4037            };
4038
4039            if let Some(rule) = run_experiment(task, 3268, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4040        }
4041
4042        let func = |ex: &Example| {
4043            if ex.input.shapes.shapes.is_empty() {
4044                return Grid::trivial();
4045            }
4046
4047            let mut shapes = ex.input.shapes.clone();
4048            let mut index: Shape = Shape::trivial();
4049
4050            for s in ex.input.coloured_shapes.shapes.iter() {
4051                if s.size() < 10 && (s.cells.rows == 1 || s.cells.columns == 1) {
4052                    if s.cells.rows > 1 {
4053                        // normalise index
4054                        index = s.to_grid().rot_rect_270().as_shape();
4055                    } else {
4056                        index = s.clone();
4057                    }
4058                    break;
4059                }
4060            }
4061
4062            if index == Shape::trivial() {
4063                return Grid::trivial();
4064            }
4065
4066            let idx_len = index.cells.columns;
4067
4068            for s in ex.input.coloured_shapes.shapes.iter() {
4069                if s.size() < 10 {
4070                    continue;
4071                }
4072                // Does it lean right or left!
4073                let right = s.cells[(s.cells.rows - 1,0)].colour == Black;
4074                let size = if right {   // Assume it's square!
4075                    let mut i: usize = 0;
4076
4077                    for _ in 0 .. s.cells.rows {
4078                        if s.cells[(i,0)].colour == Black {
4079                            break;
4080                        }
4081                        i += 1;
4082                    }
4083                    
4084                    i
4085                } else {
4086                    let mut i: usize = 0;
4087
4088                    for _ in (0 .. s.cells.rows).rev() {
4089                        if s.cells[(i,s.cells.columns - 1)].colour == Black {
4090                            break;
4091                        }
4092                        i += 1;
4093                    }
4094
4095                    i
4096                };
4097
4098                let mut idx = 0;
4099                let mut ns = s.clone();
4100
4101                // Now do the real work
4102                for i in 0 .. s.cells.rows - size + 1 {
4103                    for pos in 0 .. size {
4104                        if i + pos >= s.cells.rows || i + pos >= s.cells.columns {
4105                            return Grid::trivial();
4106                        }
4107                        let colour = index.cells[(0,idx)].colour;
4108                        if right {
4109                            ns.cells[(i+pos,i+pos)].colour = colour;
4110
4111                            for inc in 1 .. size {
4112                                if i+pos+inc < s.cells.rows {
4113                                    ns.cells[(i+pos+inc,i+pos)].colour = colour;
4114                                }
4115                                if i+pos+inc < s.cells.columns {
4116                                    ns.cells[(i+pos,i+pos+inc)].colour = colour;
4117                                }
4118                            }
4119                        } else {
4120                            ns.cells[(i+pos,s.cells.columns-1-pos-i)].colour = colour;
4121                            for inc in 1 .. size {
4122                                if i+pos+inc < s.cells.rows {
4123                                    ns.cells[(i+pos+inc,s.cells.columns-1-pos-i)].colour = colour;
4124                                }
4125                                if i+pos+inc < s.cells.columns {
4126                                    ns.cells[(i+pos,s.cells.columns-1-pos-i-inc)].colour = colour;
4127                                }
4128                            }
4129                        }
4130                    };
4131
4132                    idx = (idx + 1) % idx_len;
4133                }
4134
4135                shapes.shapes.push(ns);
4136            }
4137
4138//shapes.to_grid().show();
4139            shapes.to_grid()
4140        };
4141
4142        if let Some(rule) = run_experiment(task, 3371, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4143
4144        let func = |ex: &Example| {
4145            if ex.input.shapes.shapes.len() < 3 || ex.input.shapes.shapes.len() % 2 == 0 {
4146                return Grid::trivial();
4147            }
4148
4149            let mut shapes = ex.input.shapes.clone();
4150            let mut rs: Vec<&Shape> = Vec::new();
4151            let mut ss: Vec<&Shape> = Vec::new();
4152
4153            for s in ex.input.shapes.shapes.iter() {
4154                if s.size() == 1 {
4155                    rs.push(&s);
4156                }
4157            }
4158
4159            for s in ex.input.coloured_shapes.shapes.iter() {
4160                if s.size() > 1 && !s.has_border() {
4161                    ss.push(&s);
4162                }
4163            }
4164
4165            //rs.sort();
4166            //ss.sort();
4167
4168            for (s, m) in rs.iter().zip(ss.iter()) {
4169                shapes.shapes.push(m.recolour(m.colour, s.colour));
4170            }
4171
4172//shapes.to_grid().show();
4173            shapes.to_grid()
4174        };
4175
4176        if let Some(rule) = run_experiment(task, 3405, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4177
4178        let out_colours = examples.examples[0].output.grid.cell_colour_cnt_map();
4179        let func = |ex: &Example| {
4180            if all_colour_diffs.len() != 2 || out_colours.len() != 3 {
4181                return Grid::trivial();
4182            }
4183            let mut colour_order: Vec<(usize,Colour)> = out_colours.iter().map(|(k, v)| (*v, *k)).collect();
4184            colour_order.sort();
4185            let colours: Vec<Colour> = colour_order.iter().map(|(_, c)| *c).collect();
4186            let mut shapes = ex.input.shapes.clone();
4187
4188            for s in shapes.shapes.iter_mut() {
4189                for i in 1 ..= s.cells.rows.max(s.cells.columns) / 2 {
4190                    let colour = colours[if i % 2 == 0 { 0 } else { 1 }];
4191                    s.nest_mut(i, colour);
4192                }
4193            }
4194
4195//shapes.to_grid().show();
4196            shapes.to_grid()
4197        };
4198
4199        if let Some(rule) = run_experiment(task, 3406, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4200
4201        *cap_todo.entry(gc).or_insert(0) += 1;
4202    }
4203    let gc = Is3x3In;
4204    if all || cat.contains(&gc) && cat.contains(&Is3x3Out) { 
4205        *cap_cats.entry(gc).or_insert(0) += 1;
4206
4207//println!("#### {file}");
4208        //-if let Some(rule) = run_experiment_examples(&file, 1060, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_mirror(&exs), output) { return Some(rule); };
4209
4210        let func = |gi: &Example| {
4211            let mut big: Shape = Shape::trivial();
4212            let mut n = 0;
4213
4214            if gi.input.grid.cells.rows != 9 || gi.input.grid.cells.columns != 9 {
4215                return Grid::trivial();
4216            }
4217
4218            for s in &gi.input.shapes.shapes {
4219                if s.size() > 1 {
4220                    if s.cells.rows > 3 || s.cells.columns > 3 {
4221                        return Grid::trivial();
4222                    }
4223                    if s.cells.rows == 3 && s.cells.columns == 3 {
4224                        if big != Shape::trivial() {
4225                            return Grid::trivial();
4226                        }
4227                        big = s.clone();
4228                    } else if s.cells.rows == 2 && s.cells.columns == 3 {
4229                        let mut m = Matrix::new(3, 3, Cell::new(0, 0, 0));
4230                        for c in 1 .. 3 {
4231                            m[(0,c)].row = 0;
4232                            m[(0,c)].col = c;
4233                        }
4234                        for r in 1 .. 3 {
4235                            for c in 0 .. 3 {
4236                                m[(r,c)].row = r;
4237                                m[(r,c)].col = c;
4238                                m[(r,c)].colour = s.cells[(r-1,c)].colour;
4239                            }
4240                        }
4241                        big = Shape::new(0, 0, &m);
4242                    } else if s.cells.rows == 3 && s.cells.columns == 2 {
4243                        let mut m = Matrix::new(3, 3, Cell::new(0, 0, 0));
4244                        for r in 1 .. 3 {
4245                            m[(r,0)].row = r;
4246                            m[(r,0)].col = 0;
4247                        }
4248                        for r in 0 .. 3 {
4249                            for c in 1 .. 3 {
4250                                m[(r,c)].row = r;
4251                                m[(r,c)].col = c;
4252                                m[(r,c)].colour = s.cells[(r,c-1)].colour;
4253                            }
4254                        }
4255                        big = Shape::new(0, 0, &m);
4256                    }
4257                } else {
4258                    n += 1;
4259                }
4260            }
4261//big.show();
4262
4263            let rows = big.cells.rows;
4264            let cols = big.cells.columns;
4265//println!("{rows}/{cols}");
4266            let mut shapes = Shapes::new_sized(rows, cols * n);
4267            let big = big.to_origin();
4268
4269            shapes.shapes.push(big.clone());
4270//shapes.show();
4271
4272            for i in 1 .. n {
4273                shapes.shapes.push(big.translate_absolute(0, cols * i));
4274            }
4275//println!("{:?}", shapes);
4276
4277            shapes.to_grid()
4278        };
4279
4280        if let Some(rule) = run_experiment(task, 3486, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4281
4282        let func = |ex: &Example| {
4283            if ex.input.shapes.shapes.len() < 5 {
4284                return Grid::trivial();
4285            }
4286
4287            //let mut one = Shape::trivial();
4288            let mut two = Shape::trivial();
4289            let mut three = Shape::trivial();
4290            let mut other = Shape::trivial();
4291            let mut shapes = Shapes::trivial();
4292            let mut rows = 0;
4293
4294            for (i, s) in ex.input.shapes.shapes.iter().enumerate() {
4295                if s.ocol == 0 && s.cells.columns == ex.input.grid.cells.columns {
4296                    if s.orow < 1 || ex.input.grid.cells.rows < s.orow - 1 {
4297                        return Grid::trivial();
4298                    }
4299                    rows = ex.input.grid.cells.rows - s.orow - 1;
4300                    shapes = Shapes::new_sized(rows, ex.input.grid.cells.columns);
4301                    continue;
4302                }
4303
4304                match i {
4305                    //0 => one = s.clone(),
4306                    0 => (),
4307                    1 => two = s.clone(),
4308                    2 => three = s.clone(),
4309                    _ => {
4310                        other = s.clone();
4311
4312                        break
4313                    },
4314                }
4315            }
4316
4317            if other == Shape::trivial() || shapes == Shapes::trivial() || two == Shape::trivial() {
4318                return Grid::trivial();
4319            }
4320
4321            shapes.shapes.push(other.to_position(other.orow - (ex.input.grid.cells.rows - rows), other.ocol));
4322
4323            if two.cells[(0,0)].colour == Black {
4324                shapes.shapes.push(three.to_position(other.orow - (ex.input.grid.cells.rows - rows) - other.cells.rows, other.ocol));
4325            } else {
4326                shapes.shapes.push(three.to_position(other.orow - (ex.input.grid.cells.rows - rows) + other.cells.rows, other.ocol));
4327            }
4328
4329//shapes.to_grid().show();
4330            shapes.to_grid()
4331        };
4332
4333        if let Some(rule) = run_experiment(task, 3487, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4334
4335        *cap_todo.entry(gc).or_insert(0) += 1;
4336    }
4337    let gc = InOutSquareSameSize;
4338    if all || cat.contains(&gc) { // 164
4339        *cap_cats.entry(gc).or_insert(0) += 1;
4340
4341        if all || cat.contains(&InSameCountOut) || cat.contains(&InSameCountOutColoured) {
4342            //if let Some(rule) = run_experiment_examples(&file, 1070, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_shape_substitute(&exs), output) { return Some(rule); };
4343
4344            let func = |ex: &Example| {
4345                let biggest = ex.input.coloured_shapes.biggest_shape();
4346                if biggest.size() != ex.input.grid.size() {
4347                    return Grid::trivial();
4348                }
4349                let (idx, dir) = ex.input.grid.corner_idx();
4350                if dir == Other {
4351                    return Grid::trivial();
4352                }
4353                let mut shapes = Shapes::new_from_shape(&biggest);
4354                let body = ex.input.grid.corner_body(dir.inverse());
4355                let four = body.split_4();
4356
4357                if four.is_empty() {
4358                    return Grid::trivial();
4359                }
4360
4361                four.iter().zip(idx.cells.values())
4362                    .for_each(|(s,c)| shapes.add(&s.recolour(s.colour, c.colour).as_shape()));
4363
4364                shapes.to_grid()
4365            };
4366
4367            if let Some(rule) = run_experiment(task, 3520, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4368
4369            let func = |ex: &Example| {
4370                if ex.input.shapes.shapes.len() > 20 {
4371                    return Grid::trivial();
4372                }
4373
4374                let mut shapes = ex.input.shapes.clone_base();
4375
4376                //for s in &ex.input.shapes.consolidate_shapes().shapes {
4377                for s in &ex.input.shapes.shapes {
4378                    shapes.shapes.push(s.mirrored_r());
4379                }
4380//shapes.to_grid().show();
4381
4382                shapes.to_grid()
4383            };
4384
4385            // evaluation only
4386            if let Some(rule) = run_experiment(task, 3539, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4387        }
4388
4389        if all || cat.contains(&InLessCountOut) {
4390            // see 045e512c.json TODO MORE
4391            let s1 = examples.all(false);
4392            let s2 = examples.all_coloured(true);
4393
4394            let func = |ex: &Example| {
4395                if s1.len() != s2.len() {
4396                    return Grid::trivial();
4397                }
4398                let sc: BTreeMap<Shape, Shape> = s1.iter().zip(s2.iter()).map(|(s1, s2)| (s1.to_origin(), s2.to_origin())).collect();
4399
4400                //let mut shapes = ex.input.shapes.clone_base();
4401                let mut shapes = ex.input.shapes.clone_base();
4402
4403                for s in ex.input.shapes.shapes.iter() {
4404                    match sc.get(&s.to_origin()) {
4405                        Some(ns) => {
4406                            shapes.shapes.push(ns.to_position(s.orow, s.ocol));
4407                        },
4408                        None => (),
4409                    }
4410                }
4411
4412                shapes.to_grid()
4413            };
4414
4415            if let Some(rule) = run_experiment(task, 3568, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4416
4417            /*
4418            // see 626c0bcc.json    map_coloured_shapes_to_shape
4419            let s1: Vec<Shape> = s2.iter().map(|s| s.recolour(s.colour, s1[0].colour)).collect();
4420s1.iter().for_each(|s| s.show());
4421
4422            let func = |ex: &Example| {
4423                let sc: BTreeMap<Shape, Shape> = s1.iter().zip(s2.iter()).map(|(s1, s2)| (s1.to_origin(), s2.to_origin())).collect();
4424
4425                let mut shapes = ex.input.shapes.clone_base();
4426
4427                for s in ex.input.shapes.shapes.iter() {
4428                    match sc.get(&s.to_origin()) {
4429                        Some(ns) => {
4430                            shapes.shapes.push(ns.to_position(s.orow, s.ocol));
4431                        },
4432                        None => (),
4433                    }
4434                }
4435
4436                shapes.to_grid()
4437            };
4438
4439            if let Some(rule) = run_experiment(task, 3569, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4440            */
4441        }
4442
4443        // 0ca9ddb6 4258a5f9 913fb3ed 95990924 b60334d2 test
4444        if let Some(rule) = run_experiment_tries(task, 3572, experiment, trans, is_test, examples, &targets, done, tries, &|ex, _, n| transform_only(ex, n), output) { return Some(rule); };
4445        //-if let Some(rule) = run_experiment_examples(&file, 1100, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_mirror(&exs), output) { return Some(rule); };
4446
4447        let func = |ex: &Example| {
4448            let mut grid = ex.input.grid.clone();
4449
4450            for s in ex.input.shapes.shapes.iter() {
4451                if s.size() == 1 {
4452                    grid.cells[(ex.input.grid.cells.rows - 1,s.ocol)].colour = s.colour;
4453                    grid.cells[(s.orow,s.ocol)].colour = Black;
4454                }
4455            }
4456
4457            grid
4458        };
4459
4460        if let Some(rule) = run_experiment(task, 3588, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4461
4462        let func = &|ex: &Example| {
4463            fn do_diag(grid: &mut Grid, s: &Shape) {
4464                grid.draw_mut(FromUpLeft, s.orow, s.ocol,s.cells[(s.cells.rows-1,0)].colour);
4465                grid.draw_mut(FromUpRight, s.orow, s.ocol + s.cells.columns, s.cells[(0,0)].colour);
4466                grid.draw_mut(FromDownRight, s.orow + s.cells.rows-1, s.ocol + s.cells.columns-1, s.cells[(0,s.cells.columns-1)].colour);
4467                grid.draw_mut(FromDownLeft, s.orow + s.cells.rows, s.ocol, s.cells[(s.cells.rows-1,s.cells.columns-1)].colour);
4468            }
4469
4470            let mut grid = ex.input.grid.clone();
4471//ex.input.shapes.show();
4472
4473            for s in ex.input.coloured_shapes.shapes.iter() {
4474                if s.cells.rows != 8 || s.cells.columns != 6 {
4475                    return Grid::trivial();
4476                }
4477//s.show();
4478                if s.size() > 16 {
4479                    // TODO: Parameterise it
4480                    let ss1 = s.subshape_remain(0, 4, 0, 6).shrink_coloured();
4481                    let ss2 = s.subshape_remain(4, 4, 0, 6).shrink_coloured();
4482
4483                    do_diag(&mut grid, &ss1);
4484                    do_diag(&mut grid, &ss2);
4485                } else {
4486                    // Rotated 90 degrees
4487                    do_diag(&mut grid, s);
4488                }
4489            }
4490//grid.show();
4491
4492            grid
4493        };
4494
4495        if let Some(rule) = run_experiment(task, 3623, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4496
4497        let func = |ex: &Example| {
4498            if colour_diffs.len() != 1 {
4499                return Grid::trivial();
4500            }
4501            let colour = colour_diffs[0];
4502            let g = &ex.input.grid;
4503            let mut grid = g.clone();
4504
4505            for ((r, c), cell) in g.cells.items() {
4506                if c > grid.cells.columns / 2 {
4507                    continue;
4508                }
4509
4510                if cell.colour != Black && cell.colour == g.cells[(r, g.cells.columns - 1 - c)].colour {
4511                    grid.cells[(r, c)].colour = colour;
4512                    grid.cells[(r, g.cells.columns - 1 - c)].colour = colour;
4513                }
4514            }
4515
4516            grid
4517        };
4518
4519        if let Some(rule) = run_experiment(task, 3647, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4520
4521        let func = |ex: &Example| {
4522            if ex.input.shapes.shapes.is_empty() {
4523                return Grid::trivial();
4524            }
4525
4526            let g = &ex.input.grid;
4527            let s = &ex.input.shapes.shapes[0];
4528
4529            if s.cells.rows < 2 || s.cells.columns < 2 {
4530                return Grid::trivial();
4531            }
4532
4533            let border = s.colour;
4534            let idx = g.subgrid(0, s.cells.rows - 1, 0, s.cells.columns - 1);
4535            let mut idx = idx.as_shape();
4536
4537            if idx.cells.rows < 2 || idx.cells.columns < 2 {
4538                return Grid::trivial();
4539            }
4540
4541            let (r, c) = g.find_patch(&idx);
4542
4543            if r == 0 && c == 0 {
4544                return Grid::trivial();
4545            }
4546
4547            idx.to_position_mut(r, c);
4548
4549            let idx = idx.add_border(border);
4550            let mut shapes = g.as_shapes();
4551
4552            shapes.shapes.push(idx);
4553//shapes.to_grid().show();
4554
4555            shapes.to_grid()
4556        };
4557
4558        if let Some(rule) = run_experiment(task, 3686, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4559
4560        let min_colour = examples.examples[0].output.grid.minority_colour();
4561
4562        let func = |ex: &Example| {
4563            if colour_diffs.len() != 2 {
4564                return Grid::trivial();
4565            }
4566
4567            let mut other_colour = colour_diffs.clone();
4568
4569            other_colour.retain(|&x| x != min_colour);
4570
4571            let bg = ex.input.grid.colour;
4572            let (min_r, min_c, max_r, max_c) = ex.input.shapes.corners();
4573            let mut grid = ex.input.grid.clone();
4574
4575            // Inside box is simple
4576            for r in min_r .. max_r {
4577                for c in min_c .. max_c {
4578                    if grid.cells[(r,c)].colour == Black {
4579                        grid.cells[(r,c)].colour = other_colour[0];
4580                    }
4581                }
4582            }
4583
4584            // Outside box is harder
4585            for r in min_r .. max_r {
4586                for c in min_c .. max_c {
4587                    if grid.cells[(r,c)].colour == other_colour[0] {
4588                        for rr in r .. grid.cells.rows {
4589                            if grid.cells[(rr,c)].colour == bg {
4590                                break;
4591                            } else if grid.cells[(rr,c)].colour != other_colour[0] {
4592                                grid.cells[(rr,c)].colour = min_colour;
4593                            }
4594                        }
4595                        for cc in c .. grid.cells.columns {
4596                            if grid.cells[(r,cc)].colour == bg {
4597                                break;
4598                            } else if grid.cells[(r,cc)].colour != other_colour[0] {
4599                                grid.cells[(r,cc)].colour = min_colour;
4600                            }
4601                        }
4602                        for rr in (0 ..= r).rev() {
4603                            if grid.cells[(rr,c)].colour == bg {
4604                                break;
4605                            } else if grid.cells[(rr,c)].colour != other_colour[0] {
4606                                grid.cells[(rr,c)].colour = min_colour;
4607                            }
4608                        }
4609                        for cc in (0 ..= c).rev() {
4610                            if grid.cells[(r,cc)].colour == bg {
4611                                break;
4612                            } else if grid.cells[(r,cc)].colour != other_colour[0] {
4613                                grid.cells[(r,cc)].colour = min_colour;
4614                            }
4615                        }
4616                    }
4617                }
4618            }
4619
4620//grid.show();
4621            grid
4622        };
4623
4624        if let Some(rule) = run_experiment(task, 3752, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4625
4626        let func = |ex: &Example| {
4627            if ex.input.coloured_shapes.shapes.len() != 1 {
4628                return Grid::trivial();
4629            }
4630
4631            let ccm = ex.input.coloured_shapes.shapes[0].cell_colour_cnt_map();
4632            let mut grid = ex.input.grid.clone();
4633            let div_colour = if let Some((_, colour)) = ccm.iter().map(|(c,n)| (n, c)).max() {
4634                *colour
4635            } else {
4636                NoColour
4637            };
4638            if let Some((_, colour)) = ccm.iter().filter(|&(&c, _)| c != div_colour).map(|(c,n)| (n, c)).max() {
4639                grid.cells[(ex.input.grid.cells.rows-1, ex.input.grid.cells.columns / 2)].colour = *colour;
4640            }
4641
4642//grid.show();
4643            grid
4644        };
4645
4646        if let Some(rule) = run_experiment(task, 3774, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4647
4648        let func = |ex: &Example| {
4649            let shapes = ex.input.grid.to_shapes_coloured_sq();
4650            let ss = &shapes.shapes;
4651
4652            if !all_colour_diffs.is_empty() || ss.len() != 9 {
4653                return Grid::trivial();
4654            }
4655
4656            let mut ns = shapes.clone_base();
4657            let ps = &mut ns.shapes;
4658
4659            for s in shapes.shapes.iter() {
4660                match s.pixel_position(ex.input.grid.minority_colour()) {
4661                    UpLeft => ps.push(s.to_position(ss[0].orow, ss[0].ocol)),
4662                    Up => ps.push(s.to_position(ss[1].orow, ss[1].ocol)),
4663                    UpRight => ps.push(s.to_position(ss[2].orow, ss[2].ocol)),
4664                    Left => ps.push(s.to_position(ss[3].orow, ss[3].ocol)),
4665                    Middle => ps.push(s.to_position(ss[4].orow, ss[4].ocol)),
4666                    Right => ps.push(s.to_position(ss[5].orow, ss[5].ocol)),
4667                    DownLeft => ps.push(s.to_position(ss[6].orow, ss[6].ocol)),
4668                    Down => ps.push(s.to_position(ss[7].orow, ss[7].ocol)),
4669                    DownRight => ps.push(s.to_position(ss[8].orow, ss[8].ocol)),
4670                    _ => ()
4671                }
4672            }
4673
4674//ns.to_grid().show();
4675            ns.to_grid()
4676        };
4677
4678        if let Some(rule) = run_experiment(task, 3775, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4679
4680        let func = |ex: &Example| {
4681            if !colour_diffs.is_empty() {
4682                return Grid::trivial();
4683            }
4684
4685            let colour = ex.input.grid.minority_colour();
4686            //let mut shapes = ex.input.shapes.clone();
4687            let mut shapes = ex.input.grid.to_shapes();
4688            let mut idxes: Vec<Shape> = Vec::new();
4689
4690            for s in shapes.shapes.iter() {
4691                if s.colour == colour {
4692                    idxes.push(s.clone());
4693                }
4694            }
4695
4696            shapes.shapes.insert(0, ex.input.grid.as_shape());
4697
4698            for s in shapes.shapes.iter_mut() {
4699                for idx in idxes.iter() {
4700                    if s.colour != colour && s.equal_shape(&idx) {
4701                        s.recolour_mut(s.colour, idx.colour);
4702                    }
4703                }
4704            }
4705
4706//shapes.to_grid_transparent().show();
4707            shapes.to_grid_transparent()
4708        };
4709
4710        if let Some(rule) = run_experiment(task, 3776, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4711
4712        *cap_todo.entry(gc).or_insert(0) += 1;
4713    }
4714    let gc = InOutSquare;
4715    if all || cat.contains(&gc) { // 27
4716        *cap_cats.entry(gc).or_insert(0) += 1;
4717
4718        //if let Some(rule) = run_experiment_examples(&file, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_shape_fill(&exs), output) { return Some(rule); };
4719
4720        //-if let Some(rule) = run_experiment_examples(&file, 1050, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_expand_3x3(&exs), output) { return Some(rule); };
4721
4722        let func = |ex: &Example| {
4723            if !ex.input.grid.is_square() {
4724                return Grid::trivial();
4725            }
4726
4727            let height = ex.input.grid.height();
4728            let width = ex.input.grid.width();
4729
4730            let mut shapes = Shapes::new_sized(height * 2, width * 2);
4731
4732            let shape = ex.input.grid.as_shape();
4733            shapes.shapes.push(shape);
4734
4735            let shape = ex.input.grid.as_shape_position(0, width).rotated_270();
4736            shapes.shapes.push(shape);
4737
4738            let shape = ex.input.grid.as_shape_position(height, 0).rotated_180();
4739            shapes.shapes.push(shape);
4740
4741            let shape = ex.input.grid.as_shape_position(height, width).rotated_90();
4742            shapes.shapes.push(shape);
4743
4744            shapes.to_grid()
4745        };
4746        if let Some(rule) = run_experiment(task, 3810, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4747
4748        // TODO: Combine 160 and 162
4749        let func = |ex: &Example| {
4750            if !ex.input.grid.is_square() {
4751                return Grid::trivial();
4752            }
4753
4754            let height = ex.input.grid.height();
4755            let width = ex.input.grid.width();
4756
4757            let mut shapes = Shapes::new_sized(height * 2, width * 2);
4758
4759            let shape = ex.input.grid.as_shape_position(height, width);
4760            shapes.shapes.push(shape);
4761
4762            let shape = ex.input.grid.as_shape_position(0, width).mirrored_r();
4763            shapes.shapes.push(shape);
4764
4765            let shape = ex.input.grid.as_shape_position(height, 0).mirrored_c();
4766            shapes.shapes.push(shape);
4767
4768            let shape = ex.input.grid.as_shape().mirrored_r().mirrored_c();
4769            shapes.shapes.push(shape);
4770
4771            shapes.to_grid()
4772        };
4773        if let Some(rule) = run_experiment(task, 3837, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4774
4775        let func = &|ex: &Example| {
4776            if ex.input.coloured_shapes.shapes.len() != 1 || !ex.input.coloured_shapes.shapes[0].is_square() || ex.input.coloured_shapes.shapes[0].size() != 36 {
4777                return Grid::trivial();
4778            }
4779
4780            let shape = &ex.input.coloured_shapes.shapes[0];
4781            let ss = shape.subshape(0, 3, 0, 3);
4782
4783            ss.to_grid()
4784        };
4785
4786        if let Some(rule) = run_experiment(task, 3850, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4787
4788        *cap_todo.entry(gc).or_insert(0) += 1;
4789//a.show();
4790    }
4791    let gc = InOutSameSize;
4792    if all || cat.contains(&gc) { // 97
4793        *cap_cats.entry(gc).or_insert(0) += 1;
4794
4795        /* Causes problems probably not
4796        //if let Some(rule) = run_experiment_examples(&file, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_shape_fill(&exs), output) { return Some(rule); };
4797
4798        //if let Some(rule) = run_experiment_examples(&file, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_overlay(&exs), output) { return Some(rule); };
4799
4800        // 5
4801        if all || cat.contains(&InSameCountOut) {
4802            //if let Some(rule) = run_experiment_examples(&file, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_move_together(&exs), output) { return Some(rule); };
4803        }
4804        */
4805
4806        if cat.contains(&IsPanelledROut) {
4807            let func = |ex: &Example| {
4808                let grid_shape = ex.input.grid.as_shape();
4809                let colour = grid_shape.majority_colour();
4810                let bg_shapes = ex.input.grid.to_shapes_base_bg(colour);
4811                let not_empty: Vec<Shape> = bg_shapes.shapes.iter().filter(|s| !s.is_empty()).cloned().collect();
4812
4813                if not_empty.len() != 1 {
4814                    return Grid::trivial();
4815                }
4816
4817                let mut shapes = ex.input.shapes.clone_base();
4818
4819                shapes.shapes.push(grid_shape);
4820
4821                for s in &bg_shapes.shapes {
4822                    if s.is_empty() {
4823                        shapes.shapes.push(not_empty[0].copy_into(s));
4824                    } else {
4825                        shapes.shapes.push(s.clone());
4826                    }
4827                }
4828//shapes.to_grid().show();
4829
4830                shapes.to_grid()
4831            };
4832
4833            if let Some(rule) = run_experiment(task, 3897, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4834        }
4835
4836        //if let Some(rule) = run_experiment(file, 150, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.toddle_colours().to_grid(), output) { return Some(rule); };
4837
4838        // Clunky and not very generic 42918530 in eval
4839        let func = |gi: &Example| {
4840            let mut h: BTreeMap<Colour, Shape> = BTreeMap::new();
4841            let mut size = 0;
4842
4843            for s in gi.input.shapes.shapes.iter() {
4844//s.show();
4845                if size == 0 {
4846                    size = s.size();
4847                }
4848                if size != 25 {
4849                    return Grid::trivial();
4850                } else if s.size() < size {
4851                    if let Some(ls) = h.get(&s.colour) {
4852                        let mut ls = ls.clone();
4853
4854                        if s.contained_by(&ls) {
4855//println!("heer {:?}", s.move_in(ls));
4856//s.move_in(ls).show();
4857                            if s.size() == 1 && size == 25 {
4858                                ls.cells[(2, 2)].colour = s.colour;
4859//ls.show();
4860                                h.insert(s.colour, ls.clone());
4861                                continue;
4862                            }
4863                        }
4864                    }
4865                    return Grid::trivial();
4866                }
4867                if let Some(shape) = h.get(&s.colour) {
4868                    if shape.pixels() <= s.pixels() {
4869                        h.insert(s.colour, s.clone());
4870                    }
4871                } else {
4872                    h.insert(s.colour, s.clone());
4873                }
4874            }
4875
4876            let mut shapes = Shapes::new_sized(gi.input.shapes.nrows, gi.input.shapes.ncols);
4877
4878            for s in gi.input.shapes.shapes.iter() {
4879                if s.size() < size { continue; }
4880//s.show_summary();
4881                if let Some(shape) = h.get(&s.colour) {
4882                    if shape.pixels() >= s.pixels() {
4883                        let mut new_shape = s.clone();
4884//shape.show_summary();
4885                        for ((r, c), cell) in shape.cells.items() {
4886                            if r >= new_shape.cells.rows || c >= new_shape.cells.columns {
4887                                return Grid::trivial();
4888                            }
4889                            new_shape.cells[(r,c)].colour = cell.colour;
4890                        }
4891                        shapes.add(&new_shape);
4892                    } else {
4893                        shapes.add(shape);
4894                    }
4895                }
4896            }
4897//println!("{:?}", h);
4898//shapes.to_grid().show();
4899            shapes.to_grid()
4900        };
4901
4902        if let Some(rule) = run_experiment(task, 3966, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4903
4904        if !cat.contains(&FullyPopulatedIn) {
4905            let func = |gi: &Example| {
4906                let mut si = gi.clone();
4907                let mut dr = 0;
4908                let mut dc = 0;
4909
4910                for s in &gi.input.shapes.shapes {
4911                    if dr == 0 {
4912                        dr = s.orow;
4913                    } else if s.orow % dr != 0 {
4914                        return Grid::trivial();
4915                    }
4916                    if dc == 0 {
4917                        dc = s.ocol;
4918                    } else if s.ocol % dc != 0 {
4919                        return Grid::trivial();
4920                    }
4921//println!("{} {}", s.ox, s.oy);
4922                }
4923
4924                if dr != 0 && dc != 0 {
4925                    return Grid::trivial();
4926                }
4927
4928                si.input.shapes.shapes.sort_by_key(|b| std::cmp::Reverse(b.pixels()));
4929
4930                for (i, s) in si.input.shapes.shapes.iter_mut().enumerate() {
4931                    s.orow = i * dr;
4932                    s.ocol = i * dc;
4933
4934                    for (r, c) in s.cells.keys() {
4935                        s.cells[(r, c)].row = s.orow + r;
4936                        s.cells[(r, c)].col = s.ocol + c;
4937                    }
4938                }
4939//si.input.shapes.to_grid().show();
4940
4941                si.input.shapes.to_grid()
4942            };
4943
4944            if let Some(rule) = run_experiment(task, 4008, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4945        }
4946
4947        let func = |gi: &Example| {
4948            if gi.input.shapes.is_empty() || gi.input.shapes.len() > 21 {
4949                return Grid::trivial();
4950            }
4951
4952            let mut colours: Vec<Colour> = Vec::new();
4953            let mut si = gi.input.shapes.clone();
4954
4955            let mut full_size = false;
4956
4957            for s in si.shapes.iter() {
4958                if s.size() == gi.input.grid.size() {
4959                    full_size = true;
4960                }
4961                if s.size() == 1 {
4962                    colours.push(s.colour);
4963                }
4964            }
4965
4966            if colours.is_empty() || !full_size {
4967                return Grid::trivial();
4968            }
4969
4970            let mut i = 0;
4971
4972            for s in si.shapes.iter_mut() {
4973                if s.size() != 1 && s.size() != gi.input.grid.size() {
4974                    if i >= colours.len() {
4975                        return Grid::trivial();
4976                    }
4977                    s.mut_recolour(s.colour, colours[i]);
4978                    
4979                    /* Not Necessary
4980                    if !s.is_square() {
4981                        s.cells = s.make_square().cells;
4982                    }
4983                    */
4984                    i += 1;
4985                }
4986            }
4987
4988            // Should not be necessary???
4989            si.shapes.sort_by_key(|b| std::cmp::Reverse(b.size()));
4990
4991            si.to_grid()
4992        };
4993
4994        if let Some(rule) = run_experiment(task, 4058, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
4995
4996        let func = &|ex: &Example| {
4997            let mut grid = ex.input.grid.clone();
4998            let cnts = ex.input.shapes.shape_colour_cnt_map();
4999
5000            for a_colour in Colour::all_colours().iter() {
5001                if let Some(cs) = cnts.get(a_colour) {
5002                    if cs.len() == 2 || cs.len() == 4 {
5003                        let size = cs[0].size();
5004                        if cs.len() == 2 || cs.iter().filter(|s| s.size() == 1).count() == size {
5005                            // Now draw the lines
5006                            let v = Vec::from_iter(cs);
5007
5008                            grid.draw_lines(&v, cs.len() == 2, true);
5009                        }
5010                    }
5011                }
5012            }
5013//grid.show();
5014
5015            grid
5016        };
5017
5018        if let Some(rule) = run_experiment(task, 4082, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5019
5020        let func = |ex: &Example| {
5021            if !ex.cat.contains(&NoShapesIn(5)) || !ex.cat.contains(&NoShapesOut(6)) || colour_diffs.is_empty() {
5022                return Grid::trivial();
5023            }
5024
5025            let shapes = &ex.input.shapes;
5026            let corners = shapes.corners();
5027
5028            if corners.0 == 0 || corners.1 == 0 || corners.2 == 0 || corners.3 == 0 {
5029                return Grid::trivial();
5030            }
5031
5032            let centre = (corners.0 + (corners.2 - corners.0) / 2, corners.1 + (corners.3 - corners.1) / 2);
5033
5034            let mut dist = f32::MAX;
5035
5036            for s in shapes.shapes.iter() {
5037                let d = s.distance_from(centre.0, centre.1);
5038
5039                if s.orow > corners.0 && s.orow < corners.2 && s.ocol > corners.1 && s.ocol < corners.3 && d < dist {
5040                    dist = d;
5041                }
5042            }
5043
5044            let mut grid = ex.input.grid.clone();
5045//return Grid::trivial();
5046
5047            for s in shapes.shapes.iter() {
5048                if s.orow == corners.0 {
5049                    grid.draw_line_row_coords(corners.0, corners.1 - 1, corners.0, corners.3, s.colour, true, false, 1);
5050                } else if s.orow == corners.2 - 1 {
5051                    grid.draw_line_row_coords(corners.2 - 1, corners.1 - 1, corners.2 - 1, corners.3, s.colour, true, false, 1);
5052                } else if s.ocol == corners.1 {
5053                    grid.draw_line_col_coords(corners.0, corners.1, corners.2 - 1, corners.1, s.colour, true, false, 1);
5054                } else if s.ocol == corners.3 - 1 {
5055                    grid.draw_line_col_coords(corners.0, corners.3 - 1, corners.2 - 1, corners.3 - 1, s.colour, true, false, 1);
5056                } else {
5057                    grid.draw_line_row_coords(s.orow, corners.1, s.orow, corners.3 - 1, colour_diffs[0], false, false, 1);
5058                    grid.draw_line_col_coords(corners.0, s.ocol, corners.2 - 1, s.ocol, colour_diffs[0], false, false, 1);
5059                }
5060            }
5061
5062//grid.show();
5063            grid
5064        };
5065
5066        if let Some(rule) = run_experiment(task, 4124, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5067
5068        let func = |ex: &Example| {
5069            if ex.input.shapes.shapes.is_empty() {
5070                return Grid::trivial();
5071            }
5072            let border = ex.input.shapes.shapes.iter()
5073                .map(|s| s.cells.rows.max(s.cells.columns))
5074                .max().unwrap() * 2;
5075            let mut grid = ex.input.grid.add_border(border);
5076
5077            for s in ex.input.shapes.shapes.iter() {
5078                let mut tlr = s.orow + border + s.cells.rows;
5079                let mut tlc = s.ocol + border - s.cells.columns;
5080
5081                //while tlr < grid.cells.rows && tlc >= s.cells.columns {
5082                while tlr < grid.cells.rows && tlc >= s.cells.columns {
5083                    grid.copy_shape_to_grid_position_mut(s, tlr, tlc);
5084
5085                    tlr += s.cells.rows;
5086                    tlc -= s.cells.columns;
5087                }
5088
5089                let mut brr = s.orow + s.cells.rows + border;
5090                let mut brc = s.ocol + s.cells.columns + border;
5091
5092                while brr < grid.cells.rows && brc < grid.cells.columns {
5093                    grid.copy_shape_to_grid_position_mut(s, brr, brc);
5094
5095                    brr += s.cells.rows;
5096                    brc += s.cells.columns;
5097                }
5098            }
5099
5100            grid = grid.remove_border(border);
5101//grid.show();
5102
5103            grid
5104        };
5105
5106        if let Some(rule) = run_experiment(task, 4164, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5107
5108        let func = |ex: &Example| {
5109            if ex.input.shapes.shapes.is_empty() {
5110                return Grid::trivial();
5111            }
5112
5113            let mut grid = ex.input.grid.clone();
5114            let mut pixels: Vec<Shape> = Vec::new();
5115
5116            for s in ex.input.shapes.shapes.iter() {
5117                if s.is_pixel() && s.on_edge(&grid) {
5118                    pixels.push(s.clone());
5119                }
5120            }
5121
5122            if pixels.len() % 2 != 0 {
5123                return Grid::trivial();
5124            }
5125
5126            for s in pixels.iter() {
5127                if s.orow == 0 || s.orow == grid.cells.rows - 1 {
5128                    continue;
5129                }
5130                    
5131                let os = s.find_same_row(&pixels);
5132
5133                if os != Shape::trivial() {
5134//println!("row {}/{} -> {}/{}", s.orow, s.ocol, os.orow, os.ocol);
5135                    grid.draw_line_row(s, &os, s.colour, true, true);
5136                }
5137            }
5138            for s in pixels.iter() {
5139                if s.ocol == 0 || s.ocol == grid.cells.columns - 1 {
5140                    continue;
5141                }
5142                    
5143                let os = s.find_same_col(&pixels);
5144
5145                if os != Shape::trivial() {
5146                    grid.draw_line_col(s, &os, s.colour, true, true);
5147                }
5148            }
5149
5150//grid.show();
5151            grid
5152        };
5153
5154        if let Some(rule) = run_experiment(task, 4212, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5155
5156        let func = |ex: &Example| {
5157            if !colour_diffs.is_empty() || ex.input.shapes.shapes.len() < 3 {
5158                return Grid::trivial();
5159            }
5160
5161            let rep = ex.input.shapes.shapes[0].cells.rows;
5162            let mut grid = ex.input.grid.clone();
5163            let (_, _, max_r, _) = grid.corners();
5164
5165            for i in (max_r .. grid.cells.rows - rep).step_by(rep) {
5166                for r in 0 .. rep {
5167                    for c in 1 .. grid.cells.columns {
5168                        grid.cells[(i + r + 1,c)].colour = grid.cells[(r,c)].colour;
5169                    }
5170                }
5171            }
5172
5173//grid.show();
5174
5175            grid
5176        };
5177
5178        if let Some(rule) = run_experiment(task, 4236, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5179
5180        let func = |ex: &Example| {
5181            if colour_diffs.len() != 1 {
5182                return Grid::trivial();
5183            }
5184            let mut shapes = ex.input.grid.to_shapes_sq();
5185
5186            for s in shapes.shapes.iter_mut() {
5187                if s.size() < 3 {
5188                    s.force_recolour_mut(colour_diffs[0]);
5189                }
5190            }
5191
5192//shapes.to_grid_transparent().show();
5193            shapes.to_grid_transparent()
5194        };
5195
5196        if let Some(rule) = run_experiment(task, 4254, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5197
5198        let func = |ex: &Example| {
5199            let mut grid = ex.input.grid.clone();
5200
5201            for c in 0 .. grid.cells.columns {
5202                if grid.cells[(grid.cells.rows-1,c)].colour != Black {
5203                    let mut colour = grid.cells[(grid.cells.rows-1,c)].colour;
5204
5205                    for r in (0 .. grid.cells.rows).rev() {
5206                        let col = grid.cells[(r,c)].colour;
5207
5208                        if col != Black && col != colour {
5209                            colour = col;
5210                        } else if col == Black {
5211                            grid.cells[(r,c)].colour = colour;
5212                        }
5213                    }
5214                }
5215            }
5216
5217            grid
5218        };
5219
5220        if let Some(rule) = run_experiment(task, 4278, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5221
5222        if examples.examples[0].input.grid.cells.columns != examples.examples[0].input.grid.cells.rows {
5223            let n = examples.examples[0].input.grid.cells.columns / examples.examples[0].input.grid.cells.rows;
5224            let s_to_s = examples.split_n_map_horizontal(n);
5225//println!("{}", s_to_s.len());
5226
5227            let func = |ex: &Example| {
5228                let globc = &ex.input.grid.cells;
5229
5230                if globc.columns % globc.rows != 0 || s_to_s.is_empty() {
5231                    return Grid::trivial();
5232                }
5233                let mut grid = ex.input.grid.clone();
5234                let reps = grid.split_n_horizontal(n);
5235//println!("n = {n} {} {}", reps.len(), ex.input.grid.cells.columns / ex.input.grid.cells.rows);
5236
5237                for (i, s) in reps.iter().enumerate() {
5238                    let os = s.to_origin();
5239
5240                    if let Some(ns) = s_to_s.get(&os) {
5241                        grid.copy_to_position_mut(&ns, 0, i * s.cells.columns);
5242                    }
5243                }
5244//ex.output.grid.show();
5245//grid.show();
5246
5247                grid
5248            };
5249
5250            if let Some(rule) = run_experiment(task, 4304, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5251
5252            let n = examples.examples[0].input.grid.cells.rows / examples.examples[0].input.grid.cells.columns;
5253            let s_to_s = examples.split_n_map_vertical(n);
5254
5255            let func = |ex: &Example| {
5256                let globc = &ex.input.grid.cells;
5257
5258                if globc.rows % globc.columns != 0 || s_to_s.is_empty() {
5259                    return Grid::trivial();
5260                }
5261                let mut grid = ex.input.grid.clone();
5262                let reps = grid.split_n_vertical(n);
5263
5264                for (i, s) in reps.iter().enumerate() {
5265                    let os = s.to_origin();
5266
5267                    if let Some(ns) = s_to_s.get(&os) {
5268                        grid.copy_to_position_mut(&ns, i * s.cells.rows, 0);
5269                    }
5270                }
5271
5272                grid
5273            };
5274
5275            if let Some(rule) = run_experiment(task, 4328, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5276        }
5277
5278        let func = |ex: &Example| {
5279            if ex.input.coloured_shapes.shapes.len() != 3 {
5280                return Grid::trivial();
5281            }
5282
5283            let cnt = ex.input.coloured_shapes.shapes[0].size();
5284            let r = ex.input.coloured_shapes.shapes[1].orow;
5285
5286            if cnt > r {
5287                return Grid::trivial();
5288            }
5289
5290            let cc = ex.input.coloured_shapes.shapes[2].cell_colour_cnt_map();
5291            let mut grid = ex.input.grid.clone();
5292
5293            for cell in ex.input.coloured_shapes.shapes[2].cells.values() {
5294                if let Some(n) = cc.get(&cell.colour) {
5295                    if *n == cnt {
5296                        for i in 1 ..= cnt {
5297                            grid.cells[(r - i, cell.col)].colour = cell.colour;
5298                        }
5299                    }
5300                }
5301            }
5302
5303            grid
5304        };
5305
5306        if let Some(rule) = run_experiment(task, 4359, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5307
5308        let func = |ex: &Example| {
5309            if ex.input.coloured_shapes.shapes.len() < 2 {
5310                return Grid::trivial();
5311            }
5312            let mut shapes = ex.input.coloured_shapes.clone();
5313            let mut gr = 0;
5314            let mut gc = 0;
5315            let mut colour = NoColour;
5316
5317            for s in ex.input.coloured_shapes.shapes.iter() {
5318                if s.size() == 1 {
5319                    gr = s.orow;
5320                    gc = s.ocol;
5321                    colour = s.colour;
5322                }
5323            }
5324
5325            for s in ex.input.coloured_shapes.shapes.iter() {
5326                if s.size() > 1 {
5327                    for ((r, c), cell) in s.cells.items() {
5328                        if gr < r || gc < c {
5329                             return Grid::trivial();
5330                        }
5331                        if cell.colour == colour {
5332                            shapes.shapes.push(s.to_position(gr - r, gc - c).recolour(colour, Black));
5333                        }
5334                    }
5335                }
5336            }
5337
5338//shapes.to_grid().show();
5339            shapes.to_grid()
5340        };
5341
5342        if let Some(rule) = run_experiment(task, 4395, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5343
5344        let func = |ex: &Example| {
5345            if colour_diffs.len() != 1 || ex.input.grid.height() < 8 || ex.input.grid.width() < 8 {
5346                return Grid::trivial();
5347            }
5348            let mut grid = ex.input.grid.clone();
5349
5350            grid.colour_squares(colour_diffs[0]);
5351
5352            grid
5353        };
5354
5355        if let Some(rule) = run_experiment(task, 4408, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5356
5357        // aa18de87 but not 3490cc26
5358        let func = |ex: &Example| {
5359            if colour_diffs.len() != 1 || ex.input.shapes.shapes.len() != ex.input.coloured_shapes.shapes.len() {
5360                return Grid::trivial();
5361            }
5362            let mut grid = ex.input.grid.clone();
5363
5364            grid.connect_dots_colour_pairs(colour_diffs[0]);
5365
5366            grid
5367        };
5368
5369        if let Some(rule) = run_experiment(task, 4422, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5370
5371        let func = |ex: &Example| {
5372            let mut shapes = ex.input.shapes.clone();
5373
5374            for s in ex.input.shapes.shapes.iter() {
5375                if !s.is_pixel() {
5376                    let pixels = ex.input.shapes.pixels_in_shapes(&s);
5377
5378                    if pixels.is_empty() {
5379                        return Grid::trivial();
5380                    }
5381
5382                    let colour = pixels[0].colour;
5383                    let n = pixels.len();
5384
5385                    if n == 0 || s.orow < n || s.ocol < n {
5386                        return Grid::trivial();
5387                    }
5388
5389                    let ns = Shape::new_sized_coloured_position(s.orow - n, s.ocol - n, s.cells.rows + n * 2, s.cells.columns + n * 2, colour);
5390
5391                    shapes.shapes.insert(0, ns);
5392                }
5393            }
5394
5395//shapes.to_grid().show();
5396            shapes.to_grid()
5397        };
5398
5399        if let Some(rule) = run_experiment(task, 4423, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5400
5401        // Assumes this is true for first test?
5402        let min_colour = examples.examples[0].input.grid.minority_colour();
5403        let func = |ex: &Example| {
5404            if !colour_diffs.is_empty() {
5405                return Grid::trivial();
5406            }
5407
5408            let bg = ex.input.grid.majority_colour();
5409            let all_colours = ex.input.grid.cell_colours();
5410            let colours = Uniq::uniq(&all_colours, vec![min_colour, bg]);
5411            let diag_colour = if colours.is_empty() {
5412                NoColour
5413            } else {
5414                colours[0]
5415            };
5416            let mut grid = ex.input.grid.clone();
5417
5418            for s1 in ex.input.shapes.shapes.iter() {
5419                for s2 in ex.input.shapes.shapes.iter() {
5420                    if s1 != s2 && s1.is_diagonal(s2) {
5421                        let dir = s1.which_direction(s2);
5422
5423                        if s1.colour == s2.colour && s1.colour == min_colour {
5424                            let r = if s1.orow == 0 { 0 } else { 1 };
5425                            let c = if s1.ocol == 0 { 0 } else { 1 };
5426
5427                            match dir {
5428                                DownRight => grid.draw_bg_mc_term_other_mut(dir, s1.orow + 1, s1.ocol + 1, s1.colour, bg, false, true, diag_colour),
5429                                DownLeft => grid.draw_bg_mc_term_other_mut(dir, s1.orow + 1, s1.ocol - c, s1.colour, bg, false, true, diag_colour),
5430                                UpRight => grid.draw_bg_mc_term_other_mut(dir, s1.orow - r, s1.ocol + 1, s1.colour, bg, false, true, diag_colour),
5431                                UpLeft => grid.draw_bg_mc_term_other_mut(dir, s1.orow - r, s1.ocol - c, s1.colour, bg, false, true, diag_colour),
5432                                _ => (),
5433                            }
5434                        }
5435                    }
5436                }
5437            }
5438
5439            for s1 in ex.input.shapes.shapes.iter() {
5440                for s2 in ex.input.shapes.shapes.iter() {
5441                    if s1 != s2 && s1.is_diagonal(s2) {
5442                        let dir = s1.which_direction(s2);
5443
5444                        if s1.colour != s2.colour && s1.colour != min_colour {
5445                            let r = if s1.orow == 0 { 0 } else { 1 };
5446                            let c = if s1.ocol == 0 { 0 } else { 1 };
5447                            let dir_rot = dir.rot();
5448
5449                            match dir_rot {
5450                                DownRight => 
5451                                    grid.draw_bg_mut(dir_rot, s1.orow + 1, s1.ocol + 1, s1.colour, bg),
5452                                DownLeft => 
5453                                    grid.draw_bg_mut(dir_rot, s1.orow + 1, s1.ocol - c, s1.colour, bg),
5454                                UpRight => 
5455                                    grid.draw_bg_mut(dir_rot, s1.orow - r, s1.ocol + 1, s1.colour, bg),
5456                                UpLeft => 
5457                                    grid.draw_bg_mut(dir_rot, s1.orow - r, s1.ocol - c, s1.colour, bg),
5458                                _ => (),
5459                            }
5460                        }
5461                    }
5462                }
5463            }
5464
5465//grid.show();
5466            grid
5467        };
5468
5469        if let Some(rule) = run_experiment(task, 4424, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5470
5471        let sam = if colour_common.len() != 2 || examples.examples[0].input.shapes.shapes.len() % 2 != 0 {
5472            BTreeMap::new()
5473        } else {
5474            // This is expensive
5475            examples.shape_adjacency_map()
5476        };
5477
5478        let func = |ex: &Example| {
5479            if sam.is_empty() || colour_common.len() != 2 || ex.input.shapes.shapes.len() % 2 != 0 {
5480                return Grid::trivial();
5481            }
5482
5483            let mut shapes = ex.input.shapes.clone_base();
5484
5485            for (s, colour) in sam.iter() {
5486                let es = s.find_equal_shape(&ex.input.shapes);
5487                let touching = es.find_touching(&ex.input.shapes);
5488
5489                if touching != Shape::trivial() {
5490                    shapes.shapes.push(touching.recolour(touching.colour, *colour));
5491                }
5492            }
5493
5494//shapes.to_grid().show();
5495            shapes.to_grid()
5496        };
5497
5498        if let Some(rule) = run_experiment(task, 4425, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5499
5500        *cap_todo.entry(gc).or_insert(0) += 1;
5501    }
5502    let gc = Double;
5503    if all || cat.contains(&gc) {
5504        *cap_cats.entry(gc).or_insert(0) += 1;
5505
5506        //-if let Some(rule) = run_experiment_examples(&file, 1110, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_double(&exs), output) { return Some(rule); };
5507
5508        let func = |gi: &Example| {
5509            /*
5510            if gi.input.shapes.shapes.len() != 1 {
5511                return Grid::trivial();
5512            }
5513            */
5514
5515            let s = &gi.input.grid.as_shape();
5516            let s = s.toddle_colour(Black, s.colour);
5517            let rows = s.cells.rows;
5518            let cols = s.cells.columns;
5519            let mut shapes = Shapes::new_sized(rows * 2, cols * 2);
5520
5521            shapes.shapes.push(s.clone());
5522            shapes.shapes.push(s.translate_absolute(rows, 0));
5523            shapes.shapes.push(s.translate_absolute(0, cols));
5524            shapes.shapes.push(s.translate_absolute(rows, cols));
5525
5526            shapes.to_grid()
5527        };
5528
5529        if let Some(rule) = run_experiment(task, 4453, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5530
5531        /*
5532        // TODO Important 10fcaaa3
5533        let common_colour = examples.find_output_colours();
5534
5535        let func = |ex: &Example| {
5536            if common_colour.is_empty() {
5537                return Grid::trivial();
5538            }
5539
5540            let s = &ex.input.grid.as_shape();
5541            let rows = s.cells.rows;
5542            let cols = s.cells.columns;
5543            let mut shapes = Shapes::new_sized(rows * 2, cols * 2);
5544
5545            shapes.shapes.push(s.clone());
5546            shapes.shapes.push(s.translate_absolute(rows, 0));
5547            shapes.shapes.push(s.translate_absolute(0, cols));
5548            shapes.shapes.push(s.translate_absolute(rows, cols));
5549
5550            let mut copy = shapes.clone_base();
5551
5552            for s in shapes.to_grid().to_shapes_sq().shapes.iter() {
5553                let enclose = s.new9(true, common_colour[0]);
5554
5555                copy.shapes.push(enclose);
5556            }
5557            for s in shapes.to_grid().to_shapes_sq().shapes.iter() {
5558                copy.shapes.push(s.clone());
5559            }
5560//ex.output.grid.show();
5561//ex.output.grid.diff(&copy.trim_to_grid()).unwrap().show_full();
5562//copy.trim_to_grid().show();
5563
5564            copy.trim_to_grid()
5565        };
5566
5567        if let Some(rule) = run_experiment(file, 191, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5568        */
5569
5570    let colours = examples.io_colour_diff();
5571
5572    let func = |ex: &Example| {
5573        if colours.len() != 1 {
5574            return Grid::trivial();
5575        }
5576
5577        let grid = ex.input.grid.dup_right().dup_down();
5578        let shapes = grid.as_pixel_shapes();
5579
5580        let mut shapes = Shapes::new_given(grid.cells.rows, grid.cells.columns, &shapes.shapes);
5581
5582        shapes = shapes.embellish(colours[0]);
5583
5584        for s in grid.to_shapes_sq().shapes.iter() {
5585            shapes.shapes.push(s.clone());
5586        }
5587        
5588        shapes.to_grid_transparent()
5589    };
5590
5591    if let Some(rule) = run_experiment(task, 4515, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5592
5593        *cap_todo.entry(gc).or_insert(0) += 1;
5594    }
5595    let gc = InLessThanOut;
5596    if all || cat.contains(&gc) {
5597        *cap_cats.entry(gc).or_insert(0) += 1;
5598
5599        let (in_rs, in_cs) = examples.examples[0].input.grid.dimensions();
5600        let (out_rs, out_cs) = examples.examples[0].output.grid.dimensions();
5601        let rs = out_rs / in_rs;
5602        let cs = out_cs / in_cs;
5603
5604        let func = |ex: &Example| {
5605            // TODO: Derive the predicate and function before hand
5606            ex.input.grid.as_shape().chequer(rs, cs, &|r,_| r == ex.input.grid.cells.rows, &|s| s.mirrored_c(), false).to_grid()
5607        };
5608
5609        if let Some(rule) = run_experiment(task, 4533, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5610
5611        let func = |ex: &Example| {
5612            // TODO: Derive the predicate and function before hand
5613            let shape = ex.input.grid.as_shape();
5614
5615            shape.chequer(rs, cs, &|r,c| shape.cells[(r / rs,c / cs)].colour != Black, &|s| s.invert_colour(), true).to_grid()
5616        };
5617
5618        if let Some(rule) = run_experiment(task, 4542, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5619
5620        let func = |ex: &Example| {
5621            let shape = ex.input.grid.as_shape();
5622
5623            let has_band = |r,c| {
5624                match ex.input.shapes.has_band() {
5625                    (Down, pos) => r == pos * rs,
5626                    (Right, pos) => c == pos * cs,
5627                    _ => false,
5628                }
5629            };
5630
5631            shape.chequer(rs, cs, &has_band, &|s| s.clone(), true).to_grid()
5632        };
5633
5634        if let Some(rule) = run_experiment(task, 4558, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5635
5636        let shapes = examples.examples[0].output.grid.template_shapes(&examples.examples[0].input.grid);
5637
5638        if !shapes.shapes.is_empty()  {
5639            if let Some(rule) = run_experiment(task, 4563, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.grid.fill_template(&shapes.shapes[0]), output) { return Some(rule); };
5640        }
5641
5642        let func = |ex: &Example| {
5643            if ex.input.shapes.shapes.is_empty() {
5644                return Grid::trivial();
5645            }
5646
5647            let shape = &ex.input.shapes.shapes[0].to_origin();
5648            let (rs, cs) = shape.dimensions();
5649            let mr = rs.max(cs);
5650            let dim = rs.max(cs) * 2 + rs.min(cs);
5651            let mut shapes = Shapes::new_sized(dim, dim);
5652
5653            shapes.shapes.push(shape.to_position(mr, 0));
5654            shapes.shapes.push(shape.rotate_90_pos(1, 0, mr));
5655            shapes.shapes.push(shape.rotate_90_pos(2, mr, rs + cs));
5656            shapes.shapes.push(shape.rotate_90_pos(3, rs + cs, mr));
5657
5658//shapes.to_grid().show();
5659            shapes.to_grid()
5660        };
5661
5662        if let Some(rule) = run_experiment(task, 4586, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5663
5664        let func = |ex: &Example| {
5665            if !cat.contains(&InLessThanOut) {
5666                return Grid::trivial();
5667            }
5668
5669            let shape = ex.input.grid.as_shape();
5670            let (rs, cs) = shape.dimensions();
5671            let mut grid = Grid::new(rs * rs, cs * cs, Black);
5672            let max_colour = ex.input.grid.find_max_colour();
5673
5674            for (or, r) in (0 .. rs * rs).step_by(rs).enumerate() {
5675                for (oc, c) in (0 .. cs * cs).step_by(cs).enumerate() {
5676                    if or >= shape.cells.rows || oc >= shape.cells.columns {
5677                        return Grid::trivial();
5678                    }
5679                    if shape.cells[(or,oc)].colour == max_colour {
5680                        grid.copy_shape_to_grid_position_mut(&shape, r, c);
5681                    }
5682                }
5683            }
5684
5685//grid.show();
5686            grid
5687        };
5688
5689        if let Some(rule) = run_experiment(task, 4613, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5690
5691        let func = |ex: &Example| {
5692            if ex.input.shapes.shapes.is_empty() || !cat.contains(&InLessThanOut) || colour_diffs.len() != 1 {
5693                return Grid::trivial();
5694            }
5695
5696            let (lrs, lcs) = ex.input.grid.dimensions();
5697            let mut shape = ex.input.grid.as_shape();
5698
5699            for ((r, c), cell) in shape.clone().cells.items() {
5700                if cell.colour != Black {
5701                    if r > 0 && c > 0 {
5702                        shape.cells[(r - 1, c - 1)].colour = colour_diffs[0];
5703                    } else if r == 0 && c > 0 && lrs <= shape.cells.rows && shape.cells[(lrs - 1, c - 1)].colour == Black {
5704                        shape.cells[(lrs - 1, c - 1)].colour = colour_diffs[0];
5705                    } else if r > 0 && c == 0 && lcs <= shape.cells.columns && shape.cells[(r - 1, lcs - 1)].colour == Black {
5706                        shape.cells[(r - 1, lcs - 1)].colour = colour_diffs[0];
5707                    }
5708                }
5709            }
5710
5711            shape.chequer(rs, cs, &|_,_| true, &|s| s.clone(), false).to_grid()
5712        };
5713
5714        if let Some(rule) = run_experiment(task, 4638, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5715
5716        let func = |ex: &Example| {
5717            let g = &ex.input.grid;
5718
5719            if ex.input.shapes.shapes.is_empty() || !cat.contains(&InLessThanOut) || out_rs % g.height() != 0 || out_cs % g.width() != 0 {
5720                return Grid::trivial();
5721            }
5722
5723            let grid = if g.cells.rows > g.cells.columns {
5724                g.as_shape().chequer(1, cs, &|r,_| r % (g.cells.rows * 2) == 0, &|s| s.mirrored_c(), false).to_grid()
5725            } else {
5726                g.as_shape().chequer(1, cs, &|_,c| c % (g.cells.columns * 2) == 0, &|s| s.mirrored_c(), false).to_grid()
5727            };
5728
5729            grid
5730        };
5731
5732        if let Some(rule) = run_experiment(task, 4656, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5733
5734        let func = |ex: &Example| {
5735            if !cat.contains(&InLessThanOut) {
5736                return Grid::trivial();
5737            }
5738
5739            let shape = ex.input.grid.as_shape().recolour(ex.input.grid.colour, Black).add_border(ex.input.grid.colour);
5740            let (in_rs, in_cs) = shape.dimensions();
5741            let rs = (out_rs + 4) / in_rs;
5742            let cs = (out_cs + 4) / in_cs;
5743            let grid = Grid::new(in_rs, in_cs, ex.input.grid.colour);
5744
5745            grid.as_shape().chequer(rs, cs, &|_,_| true, &|_| shape.clone(), false).to_grid().trim(out_rs, out_cs)
5746        };
5747
5748        if let Some(rule) = run_experiment(task, 4672, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5749
5750        let func = |ex: &Example| {
5751            if colour_diffs.len() != 1 || colour_common.len() != 2 || !cat.contains(&InLessThanOut) {
5752                return Grid::trivial();
5753            }
5754
5755            let colour = colour_diffs[0];
5756            let grid = &ex.input.grid;
5757
5758            if grid.free_border(Left) {
5759                grid.mirror_right_func(&|g| g.invert_colour_new(colour))
5760            } else if grid.free_border(Right) {
5761                grid.mirror_left_func(&|g| g.invert_colour_new(colour))
5762            } else if grid.free_border(Up) {
5763                grid.mirror_down_func(&|g| g.invert_colour_new(colour))
5764            } else {
5765                grid.mirror_up_func(&|g| g.invert_colour_new(colour))
5766            }
5767        };
5768
5769        if let Some(rule) = run_experiment(task, 4693, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5770
5771        let func = |ex: &Example| {
5772            if !ex.input.grid.is_square() || !colour_diffs.is_empty() || colour_common.len() != 1 || !cat.contains(&InLessThanOut) {
5773                return Grid::trivial();
5774            }
5775
5776            let (rs, cs) = ex.input.grid.dimensions();
5777            let grid = ex.input.grid.scale_up(ex.input.grid.height());
5778            let mut grid = grid.resize_inc(ex.input.grid.height());
5779
5780            for ((r, c), cell) in ex.input.grid.cells.items() {
5781                if cell.colour != Black {
5782                    if r == 0 && c == 0 {
5783                        grid.copy_to_position_mut(&ex.input.grid, 0, cs);
5784                        grid.copy_to_position_mut(&ex.input.grid, rs, 0);
5785                    } else if r == 0 && c == cs - 1 {
5786                        grid.copy_to_position_mut(&ex.input.grid, rs, grid.cells.columns - cs);
5787                    } else if r == rs - 1 && c == 0 {
5788                        grid.copy_to_position_mut(&ex.input.grid, r * rs * 2 - rs, 0);
5789                    } else {
5790                        if r == 0 {
5791                            grid.copy_to_position_mut(&ex.input.grid, 0, c * cs * 2);
5792                        }
5793                        if c == 0 {
5794                            grid.copy_to_position_mut(&ex.input.grid, r * rs * 2, 0);
5795                        }
5796                    }
5797
5798                    if r == rs - 1 {
5799                        grid.copy_to_position_mut(&ex.input.grid, grid.cells.rows - rs, c * cs + c + (cs - c));
5800                    }
5801                    if c == cs - 1 {
5802                        grid.copy_to_position_mut(&ex.input.grid, r * rs + r + (rs - r), grid.cells.columns - cs);
5803                    }
5804                }
5805            }
5806
5807//grid.show();
5808            grid
5809        };
5810
5811        if let Some(rule) = run_experiment(task, 4735, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5812
5813        let func = |ex: &Example| {
5814            if !cat.contains(&InLessThanOut) {
5815                return Grid::trivial();
5816            }
5817
5818            let grid = &ex.input.grid;
5819            let toddle = grid.toddle_colour(Black, grid.colour);
5820
5821            toddle.as_shape().chequer(rs, cs, &|r,c| toddle.cells[(r / rs,c / cs)].colour != Black, &|s| s.clone(), true).to_grid()
5822        };
5823
5824        if let Some(rule) = run_experiment(task, 4748, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5825
5826        let func = |ex: &Example| {
5827            if !cat.contains(&InLessThanOut) {
5828                return Grid::trivial();
5829            }
5830
5831            let grid = &ex.input.grid;
5832            let cnt = grid.cell_colour_cnt_map().len();
5833
5834            grid.as_shape().chequer(cnt, cnt, &|_,_| true, &|s| s.clone(), true).to_grid()
5835        };
5836
5837        if let Some(rule) = run_experiment(task, 4761, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5838
5839        let colour = examples.examples[0].input.grid.max_colour();
5840        let colour2 = examples.examples[1].input.grid.max_colour();
5841        
5842        // testing function
5843        let func = |ex: &Example| {
5844            if !cat.contains(&InLessThanOut) || colour != colour2 {
5845                return Grid::trivial();
5846            }
5847
5848            let grid = &ex.input.grid;
5849            let (rs, cs) = grid.dimensions();
5850            let grid = grid.as_shape().chequer(rs, cs, &|r,c| grid.cells[(r/ rs,c / cs)].colour == colour, &|s| s.clone(), true).to_grid();
5851
5852//grid.show();
5853            grid.clone()
5854        };
5855
5856        if let Some(rule) = run_experiment(task, 4780, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5857
5858        let (out_rs, out_cs) = examples.examples[0].output.grid.dimensions();
5859        let all_colour_diffs = examples.io_all_colour_diff();
5860        
5861        let func = |ex: &Example| {
5862            if !cat.contains(&InLessThanOut) || all_colour_diffs.len() != 1 {
5863                return Grid::trivial();
5864            }
5865            let shapes = ex.input.grid.to_shapes_base_bg(all_colour_diffs[0]);
5866
5867            let in_shape = shapes.shapes[0].scale_down(2);
5868            let (in_rs, in_cs) = in_shape.dimensions();
5869
5870            if in_rs == 0 || in_cs == 0 || shapes.shapes.len() != 2 || out_rs % (in_rs * 2) != 0 || out_cs % (in_cs * 2) != 0 {
5871                return Grid::trivial();
5872            }
5873
5874            let rs = out_rs / in_rs;
5875            let cs = out_cs / in_cs;
5876
5877            let grid = in_shape.chequer(rs, cs, &|r,c| shapes.shapes[1].cells[(r / (rs / 2), c / (cs / 2))].colour != Black, &|s| s.clone(), true).to_grid();
5878
5879//grid.show();
5880            grid.clone()
5881        };
5882
5883        if let Some(rule) = run_experiment(task, 4808, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5884
5885        let func = |ex: &Example| {
5886            if !cat.contains(&InLessThanOut) || !colour_diffs.is_empty() {
5887                return Grid::trivial();
5888            }
5889            let shape = ex.input.grid.as_shape();
5890
5891            let grid = shape.chequer(rs, cs, &|_,c| c % (in_rs * 2) != 0, &|s| s.mirrored_c(), false).to_grid();
5892
5893            grid.clone()
5894        };
5895
5896        if let Some(rule) = run_experiment(task, 4821, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5897
5898        let func = |ex: &Example| {
5899            if !cat.contains(&InLessThanOut) || colour_diffs.len() != 1 {
5900                return Grid::trivial();
5901            }
5902            let (in_rs, in_cs) = ex.input.grid.dimensions();
5903            let dim = in_rs.max(in_cs);
5904            let mut grid = Grid::new(dim, dim, Black);
5905            let mut c_pos = 0;
5906            let mut colour = ex.input.grid.colour;
5907
5908            for c in 0 .. dim {
5909                if ex.input.grid.cells[(0,c)].colour != Black {
5910                    colour = ex.input.grid.cells[(0,c)].colour;
5911                    c_pos = c;
5912                    break;
5913                }
5914            }
5915
5916            grid.cells[(0,c_pos)].colour = colour;
5917
5918            let mut left = c_pos;
5919            let mut right = c_pos;
5920            let mut pos = 0;
5921
5922            for r in 1 .. dim {
5923                if left > 0 {
5924                    left -= 1;
5925                    grid.cells[(r,left)].colour = colour;
5926                }
5927                if right < grid.cells.rows - 1 {
5928                    right += 1;
5929                    grid.cells[(r,right)].colour = colour;
5930                }
5931
5932                if r > 0 && r % 2 == 0 && grid.cells[(r,left)].colour == colour {
5933                    grid.draw_bg_mut(DownRight, r, left, colour_diffs[0], Black);
5934                    if r + 1 >= left {
5935                        pos = r + 1 - left;
5936                    }
5937                }
5938
5939                if left == 0 {
5940                    break;
5941                }
5942            }
5943
5944            // Not entirely happy with this!
5945            for r in (pos + 3 .. dim).step_by(4) {
5946                grid.draw_bg_mut(DownRight, r, 0, colour_diffs[0], Black);
5947            }
5948
5949//grid.show();
5950            grid
5951        };
5952
5953        if let Some(rule) = run_experiment(task, 4878, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5954
5955        let func = |ex: &Example| {
5956            if !cat.contains(&InLessThanOut) || !colour_diffs.is_empty() {
5957                return Grid::trivial();
5958            }
5959
5960            let shape = ex.input.grid.as_shape();
5961            let action = &|s: &Shape, r: usize, c: usize| {
5962                let r_edge = r == 0 || r == s.cells.rows * rs - rs;
5963                let c_edge = c == 0 || c == s.cells.columns * cs - cs;
5964
5965                if r_edge && c_edge {
5966                    s.rotated_180()
5967                } else if r_edge && !c_edge {
5968                    s.mirrored_r()
5969                } else if !r_edge && c_edge {
5970                    s.mirrored_c()
5971                } else {
5972                    s.clone()
5973                }
5974            };
5975
5976            shape.combined_chequer(rs, cs, &action).to_grid()
5977        };
5978
5979        if let Some(rule) = run_experiment(task, 4904, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5980
5981        /* Does not work yet c92b942c
5982        let rule = examples.derive_missing_rule();
5983
5984        let func = |ex: &Example| {
5985            if !cat.contains(&InLessThanOut) || colour_diffs.len() != 2 {
5986                return Grid::trivial();
5987            }
5988
5989            let grid = ex.input.grid.apply_missing_rule(&rule);
5990//rule.show_full();
5991//grid.show_full();
5992            let grid = grid.as_shape().checker(rs, cs, &|_,_| true, &|s| s.clone(), false).to_grid();
5993//grid.show();
5994
5995            grid
5996        };
5997
5998        if let Some(rule) = run_experiment(file, 819, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
5999        */
6000
6001        if let Some(rule) = run_experiment(task, 4926, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.grid.extend_border(), output) { return Some(rule); };
6002
6003        let func = |ex: &Example| {
6004            if !cat.contains(&InLessThanOut) || colour_diffs.len() != 1 {
6005                return Grid::trivial();
6006            }
6007
6008            let mut grid = ex.input.grid.scale_up(2);
6009            let shapes = grid.to_shapes();
6010
6011            for s in shapes.shapes.iter() {
6012                let mr = s.cells.rows - 1;
6013                let mc = s.cells.columns - 1;
6014
6015                grid.draw_mut(UpLeft, s.cells[(0,0)].row, s.cells[(0,0)].col, colour_diffs[0]);
6016                grid.draw_mut(DownRight, s.cells[(mr,mc)].row, s.cells[(mr,mc)].col, colour_diffs[0]);
6017            }
6018
6019            grid
6020        };
6021
6022        if let Some(rule) = run_experiment(task, 4947, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6023
6024        let func = |ex: &Example| {
6025            if !cat.contains(&InLessThanOut) || colour_diffs.len() != 1 {
6026                return Grid::trivial();
6027            }
6028
6029            let rows = ex.input.grid.cells.rows;
6030            let cols = ex.input.grid.cells.columns;
6031            let mut grid = ex.input.grid.as_shape().chequer(rs, cs, &|r,c| r == 0 && c == 0 || r == rows && c == cols , &|s| s.clone(), true).to_grid();
6032            let shapes = grid.to_shapes();
6033
6034            for s in shapes.shapes.iter().skip(1).step_by(2) {
6035                if s.orow > 0 {
6036                    grid.draw_mut(Right, s.orow - 1, 0, colour_diffs[0]);
6037                }
6038            }
6039//grid.show();
6040
6041            grid
6042        };
6043
6044        if let Some(rule) = run_experiment(task, 4967, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6045
6046        if let Some(rule) = run_experiment(task, 4969, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.grid.scale_up(ex.input.grid.height()), output) { return Some(rule); };
6047
6048        *cap_todo.entry(gc).or_insert(0) += 1;
6049    }
6050    let gc = SingleShapeOut;
6051    if all || cat.contains(&gc) {
6052        *cap_cats.entry(gc).or_insert(0) += 1;
6053
6054        if all || cat.contains(&SingleShapeIn) {
6055            //if let Some(rule) = run_experiment_examples(&file, 1120, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_overlay(&exs), output) { return Some(rule); };
6056
6057            //if let Some(rule) = run_experiment_examples(&file, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_move_same_colour(&exs), output) { return Some(rule); };
6058
6059            let func = |gi: &Grid, go: &Grid, n: &mut usize| {
6060                let grid = gi.recolour(gi.colour, go.colour);
6061
6062                move_only(&grid, n)
6063            };
6064
6065            if let Some(rule) = run_experiment_tries(task, 4988, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6066
6067            let func = |gi: &Example| {
6068                if gi.input.coloured_shapes.shapes.is_empty() {
6069                    return Grid::trivial();
6070                }
6071
6072                gi.input.coloured_shapes.shapes[0].to_origin().to_grid()
6073            };
6074
6075            if let Some(rule) = run_experiment(task, 4998, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6076        }
6077
6078        if all || !cat.contains(&SingleShapeIn) {
6079            let r = examples.examples[0].output.grid.cells.rows;
6080            let c = examples.examples[0].output.grid.cells.columns;
6081
6082            if r == 1 || c == 1 {
6083                let colour = examples.examples[0].output.grid.colour;
6084
6085                let func = |ex: &Example| {
6086                    let mut i = 0;
6087                    let mut grid = Grid::new(r, c, Black);
6088
6089                    for s in ex.input.shapes.shapes.iter() {
6090                        if i >= c {
6091                            return Grid::trivial();
6092                        }
6093                        if s.colour == colour && s.size() > 1 {
6094                            if r == 1 {
6095                                grid.cells[(0, i)].colour = colour;
6096                            } else {
6097                                grid.cells[(i, 0)].colour = colour;
6098                            }
6099                            i += 1;
6100                        }
6101                    }
6102
6103                    grid
6104                };
6105
6106                if let Some(rule) = run_experiment(task, 5029, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6107            }
6108        }
6109
6110        *cap_todo.entry(gc).or_insert(0) += 1;
6111    } 
6112    let gc = OutLessThanIn;
6113    // Default shape parser sometimes gets it wrong!
6114    if all || cat.contains(&gc) { 
6115        *cap_cats.entry(gc).or_insert(0) += 1;
6116
6117        if let Some(rule) = run_experiment(task, 5040, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.hollow_cnt_unique().to_grid(), output) { return Some(rule); };
6118
6119        if let Some(rule) = run_experiment(task, 5042, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.first().to_grid(), output) { return Some(rule); };
6120
6121        //if let Some(rule) = run_experiment(task, 5044, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.last().to_grid(), output) { return Some(rule); };
6122
6123        let func = |ex: &Example| {
6124            for s in &ex.input.shapes.shapes {
6125                if !s.is_mirror_r() && !s.is_mirror_c() {
6126                    return s.to_grid();
6127                }
6128            }
6129
6130            Grid::trivial()
6131        };
6132
6133        if let Some(rule) = run_experiment(task, 5056, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6134
6135        let func = |ex: &Example| {
6136            for s in &ex.input.shapes.shapes {
6137                if s.is_mirror_r() || s.is_mirror_c() {
6138                    return s.to_grid();
6139                }
6140            }
6141
6142            Grid::trivial()
6143        };
6144
6145        if let Some(rule) = run_experiment(task, 5068, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6146
6147        let func = |ex: &Example| {
6148            let bordered = ex.input.shapes.border_only();
6149
6150            if bordered == Shape::trivial() {
6151                return Grid::trivial();
6152            }
6153
6154            ex.input.grid.subgrid(bordered.orow + 1, bordered.cells.rows - 2, bordered.ocol + 1, bordered.cells.columns - 2)
6155        };
6156
6157        if let Some(rule) = run_experiment(task, 5080, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6158
6159        let func = |ex: &Example| {
6160            if !cat.contains(&OutLessThanIn) {
6161                return Grid::trivial();
6162            }
6163
6164            let sc = ex.input.coloured_shapes.shape_counts();
6165
6166            if let Some(max) = sc.values().max() {
6167                let sid: Vec<_> = sc.iter().filter(|&(_,&v)| v == *max).map(|(k,_)| k).collect();
6168                for s in ex.input.coloured_shapes.shapes.iter() {
6169                    let this_sid = Shape::sid(&s.cells, true);
6170
6171                    if *sid[0] == this_sid {
6172                        return s.to_grid();
6173                    }
6174                }
6175            }
6176
6177            Grid::trivial()
6178        };
6179
6180        if let Some(rule) = run_experiment(task, 5103, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6181
6182        let func = |ex: &Example| {
6183            let colour = ex.input.grid.mid_div_colour();
6184            let ns = ex.input.grid.to_shapes_base_bg(colour);
6185
6186            if ns.shapes.len() != 2 {
6187                return Grid::trivial();
6188            }
6189
6190            let mut nns = Shapes::new_sized(ns.shapes[0].cells.rows, ns.shapes[0].cells.columns);
6191
6192            for s in ns.shapes.clone().iter() {
6193                nns.shapes.push(s.to_origin());
6194            }
6195
6196            if nns.to_grid_transparent().is_full() {  
6197                nns.to_grid_transparent()
6198            } else {
6199                ns.shapes[0].to_grid()
6200            }
6201        };
6202
6203        if let Some(rule) = run_experiment(task, 5126, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6204
6205        let func = |ex: &Example| {
6206            if !colour_diffs.is_empty() || ex.input.shapes.shapes.len() < 3 {
6207                return Grid::trivial();
6208            }
6209            let big = ex.input.shapes.largest();
6210            let mut horizontal = true;
6211            let mut r = usize::MAX;
6212
6213            for s in ex.input.shapes.shapes.iter() {
6214                if s.is_pixel() {
6215                    if r == usize::MAX {
6216                        r = s.orow;
6217                    } else if r != s.orow {
6218                        horizontal = false;
6219                    }
6220                }
6221            }
6222
6223            let cnt = ex.input.shapes.shapes.len() - 1;
6224            let mut shapes = if horizontal {
6225                Shapes::new_sized(big.cells.rows, big.cells.columns * cnt)
6226            } else {
6227                Shapes::new_sized(big.cells.rows * cnt, big.cells.columns)
6228            };
6229            let mut offset = 0;
6230
6231            for s in ex.input.shapes.shapes.iter() {
6232                if *s != big {
6233                    let mut shape = big.clone();
6234
6235                    shape.recolour_mut(big.colour, s.colour);
6236
6237                    if horizontal {
6238                        shape.to_position_mut(0, offset);
6239                        offset += big.cells.rows;
6240                    } else {
6241                        shape.to_position_mut(offset, 0);
6242                        offset += big.cells.columns;
6243                    };
6244
6245                    shapes.shapes.push(shape);
6246                }
6247            }
6248
6249//shapes.to_grid().show();
6250            shapes.to_grid()
6251        };
6252
6253        if let Some(rule) = run_experiment(task, 5176, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6254
6255        let func = |ex: &Example| {
6256            if !colour_diffs.is_empty() {
6257                return Grid::trivial();
6258            }
6259
6260            // Default shape parser sometimes gets it wrong!
6261            let colour = ex.input.grid.to_shapes().full_extent().colour;
6262
6263            Grid::new(1, 1, colour)
6264        };
6265
6266        if let Some(rule) = run_experiment(task, 5189, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6267
6268        // testing function
6269        let func = |ex: &Example| {
6270            if !colour_diffs.is_empty() {
6271                return Grid::trivial();
6272            }
6273            let s = ex.input.shapes.largest();
6274
6275            if s.cells.rows <= 3 || s.cells.columns <= 3 {
6276                return Grid::trivial();
6277            }
6278
6279            let s = s.shrink_border();
6280
6281            let grid = ex.input.grid.subgrid(s.orow + 1, s.cells.rows - 2, s.ocol + 1, s.cells.columns - 2);
6282//grid.show();
6283
6284            grid
6285        };
6286
6287        if let Some(rule) = run_experiment(task, 5210, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6288
6289        let (rs, cs) = examples.examples[0].output.grid.dimensions();
6290
6291        let func = |ex: &Example| {
6292            if all_colour_diffs.len() != 1 {
6293                return Grid::trivial();
6294            }
6295            let mut shape = Shape::trivial();
6296            let mut ocol = 0;
6297            let mut left = false;
6298            let mut width = 0;
6299            let mut winc = 0;
6300            let mut wider = false;
6301
6302            let grid = ex.input.grid.recolour(all_colour_diffs[0], Black);
6303
6304            for s in grid.to_shapes_coloured().shapes.iter() {
6305                if s.colour != all_colour_diffs[0] {
6306                    left = s.ocol > ocol;
6307                    ocol = s.ocol;
6308                    if width < s.cells.columns {
6309                        winc = s.cells.columns - width;
6310                        width = s.cells.columns;
6311                        wider = true;
6312                    } else {
6313                        wider = false;
6314                    }
6315
6316                    shape = s.clone();
6317                }
6318            }
6319
6320            let mut new_shape = shape.clone();
6321            let mut shapes = Shapes::new_sized(rs, cs);
6322
6323            if left {
6324                ocol += 1;
6325            } else if wider {
6326                new_shape = Shape::new_sized_coloured_position(shape.ocol, shape.orow, shape.cells.rows, shape.cells.columns + winc, shape.colour);
6327            } else {
6328                let mut c1 = NoColour;
6329                let mut cc = 0;
6330
6331                'outer:
6332                for r in 0 .. shape.cells.rows {
6333                    for c in 0 .. shape.cells.columns {
6334                        let cell = &shape.cells[(r,c)];
6335                        if c1 == NoColour && cell.colour != Black {
6336                            c1 = cell.colour;
6337                        } else if c1 != NoColour && cell.colour != Black {
6338                            if c == 0 {
6339                                return Grid::trivial();
6340                            }
6341
6342                            cc = c - 1;
6343                            break 'outer;
6344                        }
6345                    }
6346                }
6347
6348                new_shape = shape.clone();
6349
6350                for r in 0 .. shape.cells.rows {
6351                    let cell = &mut new_shape.cells[(r,cc)];
6352                    if cell.colour != Black {
6353                        cell.colour = c1;
6354                    }
6355                }
6356            }
6357
6358            let orow = if shape.cells.rows == 1 { 1 } else { 0 };
6359
6360            new_shape.to_position_mut(orow, ocol);
6361
6362            shapes.shapes.push(new_shape);
6363
6364//shapes.to_grid().show();
6365            shapes.to_grid()
6366        };
6367
6368        if let Some(rule) = run_experiment(task, 5291, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6369
6370        let func = |ex: &Example| {
6371            if all_colour_diffs.len() != 1 {
6372                return Grid::trivial();
6373            }
6374
6375            let colour = ex.input.grid.majority_colour();
6376            let mut pix = ex.input.shapes.clone_base();
6377            let mut rd = 0;
6378            let mut cd = 0;
6379            let mut big_r = 0;
6380            let mut big_c = 0;
6381            let mut max_r = 0;
6382            let mut max_c = 0;
6383
6384            for s in ex.input.shapes.shapes.iter() {
6385                if s.colour != colour {
6386                    if rd < s.orow || cd < s.ocol {
6387                        return Grid::trivial();
6388                    }
6389
6390                    pix.shapes.push(s.clone());
6391
6392                    rd += (rd as isize - s.orow as isize).abs() as usize;
6393                    cd += (cd as isize - s.ocol as isize).abs() as usize;
6394                } else {
6395                    big_r = big_r.max(s.cells.rows);
6396                    big_c = big_c.max(s.cells.columns);
6397                    max_r += s.cells.rows;
6398                    max_c += s.cells.columns;
6399                }
6400            }
6401
6402            let horizontal = rd < cd;
6403            let mut o_shapes = ex.input.shapes.clone();
6404            let mut shapes = if horizontal {
6405                o_shapes.shapes.sort_by(|a, b| (a.ocol,a.orow).cmp(&(b.ocol,b.orow)));
6406                Shapes::new_sized(big_r, max_c)
6407            } else {
6408                o_shapes.shapes.sort_by(|a, b| (a.orow,a.ocol).cmp(&(b.orow,b.ocol)));
6409                Shapes::new_sized(max_r, big_c)
6410            };
6411            let mut r = 0;
6412            let mut c = 0;
6413
6414            for s in o_shapes.shapes.iter() {
6415                if s.colour == colour {
6416                    let (cr, cc) = s.centre_of();
6417                    let near = pix.nearest_shape(cr, cc);
6418                    let ns = s.recolour(s.colour, near.colour).to_position(r, c);
6419                    if horizontal { c += big_c } else { r += big_r };
6420
6421                    shapes.shapes.push(ns);
6422                }
6423            }
6424
6425//shapes.to_grid().show();
6426            shapes.to_grid()
6427        };
6428
6429        if let Some(rule) = run_experiment(task, 5291, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6430
6431        let (gridr, gridc) = examples.examples[0].output.grid.dimensions();
6432        let func = |ex: &Example| {
6433            if colour_common.len() != 2 {
6434                return Grid::trivial();
6435            }
6436
6437            let mut grid = Grid::new(gridr, gridc, Black);
6438            let mut bg = NoColour;
6439
6440            for s in ex.input.shapes.shapes.iter() {
6441                if s.dimensions() == ex.input.grid.dimensions() {
6442                    bg = s.colour;
6443                }
6444            }
6445
6446            let scc = ex.input.shapes.shape_colour_cnt_map();
6447            let mut ccs: Vec<(Colour,usize)> = scc.iter().filter(|(k,_)| **k != bg).map(|(k,v)| (*k, v.len())).collect();
6448
6449            ccs.sort();
6450            ccs.reverse();
6451
6452            let mut r = 0;
6453            let mut c = 0;
6454
6455            for (col, sz) in ccs.iter() {
6456                for _ in 0 .. *sz {
6457                    if r >= grid.cells.rows || c >= grid.cells.columns {
6458                        return Grid::trivial();
6459                    }
6460                    grid.cells[(r,c)].colour = *col;
6461
6462                    if c + 1 == gridc {
6463                        c = 0;
6464                        r += 1;
6465                    } else {
6466                        c += 1;
6467                    }
6468                }
6469            }
6470
6471//grid.show();
6472            grid
6473        };
6474
6475        if let Some(rule) = run_experiment(task, 5292, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6476
6477        *cap_todo.entry(gc).or_insert(0) += 1;
6478    }
6479    let gc = SingleColouredShapeOut;
6480    if all || cat.contains(&gc) {
6481        *cap_cats.entry(gc).or_insert(0) += 1;
6482
6483        //if let Some(rule) = run_experiment_examples(&file, 1130, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_overlay(&exs), output) { return Some(rule); };
6484
6485        //if let Some(rule) = run_experiment_examples(&file, 1140, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_mirror(&exs), output) { return Some(rule); };
6486
6487        let edge_colour = examples.largest_shape_colour();
6488
6489        let func = |ex: &Example| {
6490            let h = ex.input.grid.cell_colour_cnt_map();
6491
6492            if let Some(colour) = h.iter().min_by(|(_, cnt1), (_, cnt2)| cnt1.cmp(cnt2)).map(|(k, _)| k) {
6493                let h = ex.input.shapes.shape_colour_cnt_map();
6494
6495                if let Some(vc) = h.get(colour) {
6496                    if vc.len() != 1 || vc[0].size() != 1 || vc[0].orow == 0 || vc[0].ocol == 0 || vc[0].orow >= ex.input.grid.cells.rows - 1 || vc[0].ocol >= ex.input.grid.cells.columns - 1 {
6497                        return Grid::trivial();
6498                    }
6499//println!("{:?}", vc[0]);
6500
6501                    let enclose = vc[0].surround(1, edge_colour, true, true);
6502//enclose.show();
6503                    let mut ss = ex.input.shapes.clone();
6504
6505                    ss.shapes = vec![enclose.clone(), vc[0].clone()];
6506
6507                    return ss.to_grid();
6508                }
6509            }
6510
6511            Grid::trivial()
6512        };
6513
6514        if let Some(rule) = run_experiment(task, 5330, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6515
6516        let func = |ex: &Example| {
6517            if ex.input.coloured_shapes.is_empty() {
6518                return Grid::trivial();
6519            }
6520
6521            let shape = if ex.input.coloured_shapes.len() == 1 {
6522                ex.input.coloured_shapes.shapes[0].clone()
6523            } else {
6524                ex.input.coloured_shapes.to_shape()
6525            };
6526
6527            let mut shapes = ex.input.coloured_shapes.clone();
6528
6529            shapes.shapes[0] = shape.make_symmetric();
6530
6531            shapes.to_grid()
6532        };
6533
6534        if let Some(rule) = run_experiment(task, 5350, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6535
6536        if cat.contains(&InLessCountOut) && cat.contains(&InOutSameSize) {
6537            let colour = examples.examples[0].output.grid.min_colour();
6538
6539            let func = |ex: &Example| {
6540                let consolidated = ex.input.grid.as_shape();
6541                let mut shapes = Shapes::new_from_shape(&consolidated);
6542                let consolidated = ex.input.shapes.to_shape();
6543                let s = consolidated.fill_lines(colour);
6544
6545                shapes.shapes.push(s);
6546
6547                shapes.to_grid()
6548            };
6549
6550            if let Some(rule) = run_experiment(task, 5366, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6551        }
6552
6553        if colour_diffs.len() == 1  {
6554            let (r, c) = examples.examples[0].output.grid.find_pixel(colour_diffs[0]);
6555
6556            let func = |ex: &Example| {
6557                if ex.input.shapes.shapes.is_empty() || colour_diffs.len() != 1  || ex.input.grid.cells.columns < ex.input.shapes.shapes.len() {
6558                    return Grid::trivial();
6559                }
6560
6561                let cs = ex.input.grid.cells.columns - ex.input.shapes.shapes.len();
6562                let mut shapes = Shapes::new_sized(cs + 1, cs);
6563                let mut row = r;
6564                let mut col = c;
6565
6566                for s in ex.input.shapes.shapes.iter() {
6567                    if s.width() == 2 {
6568                        if s.cells[(0,0)].colour != Black {
6569                            let ns = s.to_position(row, col);
6570
6571                            shapes.shapes.push(ns);
6572
6573                            row += 1;
6574                            col += 1;
6575                        } else if col > 0 {
6576                            let ns = s.to_position(row, col - 1);
6577
6578                            shapes.shapes.push(ns);
6579
6580                            row += 1;
6581                            col -= 1;
6582                        }
6583                    } else {
6584                        let ns = s.to_position(row + 1, col);
6585
6586                        shapes.shapes.push(ns);
6587
6588                        row += 2;
6589                    }
6590                }
6591
6592                let ns = Shape::new_sized_coloured_position(r, c, 1, 1, colour_diffs[0]);
6593                shapes.shapes.push(ns);
6594                
6595                shapes.to_grid_transparent()
6596            };
6597
6598            if let Some(rule) = run_experiment(task, 5414, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6599        }
6600
6601        *cap_todo.entry(gc).or_insert(0) += 1;
6602    } 
6603    let gc = NoShapesIn(1);
6604    if all || cat.contains(&gc) && cat.contains(&NoColouredShapesOut(1)) && !cat.contains(&NoShapesOut(1)) {
6605        *cap_cats.entry(gc).or_insert(0) += 1;
6606
6607        if cat.contains(&NoShapesIn(1)) && cat.contains(&NoShapesOut(6)) {
6608            // Important: all colour scan does not come back in correct order
6609            let in_colours = examples.examples[0].input.shapes.colours();
6610            let out_colours = examples.examples[0].output.shapes.colours();
6611            let colours = Uniq::uniq(&out_colours, in_colours);
6612
6613            let func = |ex: &Example| {
6614//ex.output.shapes.show();
6615                let mut grid = ex.input.grid.clone();
6616                let fb = ex.input.shapes.shapes[0].find_first_blacks();
6617//println!("{colours:?} {fb:?}");
6618                let mut j = 0;
6619
6620                for (i, (r, c)) in fb.iter().enumerate() {
6621                    // TODO better
6622                    if i != 0 && i != 2 && i != 6 && i != 8 {
6623                        grid = grid.flood_fill(*r, *c, NoColour, colours[j]);
6624                        j += 1;
6625                    }
6626                }
6627//grid.show();
6628
6629                grid
6630            };
6631
6632            if let Some(rule) = run_experiment(task, 5448, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6633        }
6634
6635        let min_colour = examples.examples[0].output.grid.find_min_colour();
6636        let max_colour = examples.examples[0].output.grid.find_max_colour();
6637
6638        let func = |ex: &Example| {
6639            let grid = ex.input.grid.recolour(Black, NoColour);
6640//grid.show();
6641            let mut shapes = grid.to_shapes();
6642            let mut min_size = usize::MAX;
6643            let mut max_size = 0;
6644
6645            for s in shapes.shapes.iter_mut() {
6646                if s.size() != grid.size() {
6647                    s.recolour_mut(NoColour, Black);
6648                    if s.size() > max_size {
6649                        max_size = s.size();
6650                    }
6651                    if s.size() < min_size {
6652                        min_size = s.size();
6653                    }
6654                }
6655            }
6656
6657            for s in shapes.shapes.iter_mut() {
6658                if s.size() == max_size {
6659                    s.recolour_mut(NoColour, max_colour);
6660                }
6661                if s.size() == min_size {
6662                    s.recolour_mut(NoColour, min_colour);
6663                }
6664            }
6665//shapes.show_summary();
6666//shapes.to_grid().show();
6667            shapes.to_grid()
6668        };
6669
6670        if let Some(rule) = run_experiment(task, 5486, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6671
6672        if cat.contains(&NoShapesIn(1)) && cat.contains(&NoShapesOut(2)) {
6673            let extra_colour = examples.examples[0].output.grid.find_min_colour();
6674
6675            let func = |ex: &Example| {
6676                if ex.input.shapes.shapes.is_empty() || !ex.input.grid.is_square() {
6677                    return Grid::trivial();
6678                }
6679                let colour = ex.input.grid.colour;
6680                let mut shapes = ex.input.shapes.clone();
6681                let shape = &ex.input.shapes.shapes[0];
6682                let shape = shape.to_square();
6683                let mut shape = shape.diff(&shape.rotated_90()).unwrap();
6684
6685                shape.recolour_mut(ToBlack + colour, extra_colour);
6686                shape.uncolour_mut();
6687
6688                shapes.shapes.push(shape);
6689//shapes.to_grid().show();
6690                
6691                shapes.to_grid()
6692            };
6693
6694            if let Some(rule) = run_experiment(task, 5510, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6695        }
6696
6697        if cat.contains(&NoShapesIn(1)) && cat.contains(&NoColouredShapesOut(1)) {
6698            let extra_colour = examples.examples[0].output.grid.find_min_colour();
6699
6700            let func = |ex: &Example| {
6701                if ex.input.shapes.shapes.is_empty() {
6702                    return Grid::trivial();
6703                }
6704                let mut shapes = ex.input.shapes.clone();
6705
6706                shapes.shapes[0].recolour_mut(Black, extra_colour);
6707//shapes.to_grid().show();
6708                
6709                shapes.to_grid()
6710            };
6711
6712            if let Some(rule) = run_experiment(task, 5528, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6713
6714            let func = |ex: &Example| {
6715                if ex.input.shapes.shapes.is_empty() && ex.input.shapes.shapes[0].cells.columns % 2 != 1 {
6716                    return Grid::trivial();
6717                }
6718
6719                let mut shape = ex.input.shapes.shapes[0].clone();
6720                let mid_r = shape.cells.rows / 2;
6721                let cols: Vec<usize> = (0 .. shape.cells.columns).filter(|&c| shape.cells[(mid_r, c)].colour == Black).collect();
6722
6723                if cols.is_empty() {
6724                    return Grid::trivial();
6725                }
6726
6727                let mut down = true;
6728
6729                for (i, &c) in cols.iter().enumerate() {
6730                    if i % 3 == 0 {
6731                        shape.flood_fill_mut(mid_r, c, NoColour, extra_colour);
6732                        down = !down;
6733                    }
6734                }
6735
6736                if cols.len() % 3 == 0 {
6737                    let r = if down { mid_r + 1 } else { mid_r - 1 };
6738                    let c = shape.cells.columns - 1;
6739
6740                    shape.flood_fill_mut(r, c, NoColour, extra_colour);
6741                }
6742
6743                shape.to_grid()
6744            };
6745
6746            if let Some(rule) = run_experiment(task, 5562, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6747
6748            let colours = examples.examples[0].output.grid.colours();
6749            let in_colour = examples.examples[0].input.grid.colour;
6750
6751/*
6752            if colours.len() == 4  {
6753                // 626c0bcc eval
6754                let func = |ex: &Example| {
6755println!("{colours:?} {in_colour:?} {:?}", ex.output.shapes.len());
6756println!("{:?}", ex.output.shapes.shapes[1]);
6757println!("{:?}", ex.input.shapes.shapes[0]);
6758println!("{:?}", ex.output.coloured_shapes.shapes[0]);
6759                    Grid::trivial()
6760                };
6761
6762                if let Some(rule) = run_experiment(file, 635, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6763            }
6764*/
6765
6766            let fill_colour = colours.iter().filter(|&(&k,_)| k != in_colour).map(|(k,v)| (v,k)).min().map(|(_,k)| k).unwrap();
6767
6768            if colours.len() == 3  {
6769                let bg_colour = colours.iter().filter(|&(&k,_)| k != in_colour).map(|(k,v)| (v,k)).max().map(|(_,k)| k).unwrap();
6770
6771                let func = |ex: &Example| {
6772                    if ex.input.shapes.shapes.is_empty() && ex.input.shapes.shapes[0].cells.columns % 2 != 1 {
6773                        return Grid::trivial();
6774                    }
6775
6776                    let mut shape = ex.input.grid.as_shape();
6777                    let rows = shape.cells.rows;
6778                    let cols = shape.cells.columns;
6779//shape.show();
6780
6781                    for r in 0 .. rows {
6782                        for c in 0 .. cols {
6783                            if (r == 0 || c == 0 || r == rows - 1 || c == cols - 1) && shape.cells[(r, c)].colour == Black {
6784                                shape.flood_fill_mut(r, c, NoColour, *bg_colour);
6785                            }
6786                        }
6787                    }
6788
6789                    shape.recolour_mut(Black, *fill_colour);
6790
6791//shape.show();
6792                    shape.to_grid()
6793                };
6794
6795                if let Some(rule) = run_experiment(task, 5611, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6796            }
6797
6798            if colours.len() == 2 {
6799                let func = |ex: &Example| {
6800                    if ex.input.shapes.shapes.is_empty() && ex.input.shapes.shapes[0].cells.columns % 2 != 1 || !ex.input.shapes.shapes[0].hollow() {
6801                        return Grid::trivial();
6802                    }
6803
6804                    let mut shapes = ex.input.shapes.clone();
6805//shapes.to_grid().show();
6806
6807                    let mut rects = ex.input.grid.find_rectangles();
6808//rects.show();
6809
6810                    for s in rects.shapes.iter_mut() {
6811                        s.recolour_mut(Black, *fill_colour);
6812                    }
6813//rects.show();
6814
6815                    shapes.merge_mut(&rects);
6816
6817//ex.output.grid.diff(&shapes.to_grid()).unwrap().show_full();
6818//ex.output.grid.show();
6819//shapes.to_grid().show();
6820
6821                    shapes.to_grid()
6822                };
6823
6824                if let Some(rule) = run_experiment(task, 5640, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6825            }
6826
6827            let func = |ex: &Example| {
6828                if ex.input.shapes.shapes.is_empty() {
6829                    return Grid::trivial();
6830                }
6831
6832                let mut grid = ex.input.grid.clone();
6833
6834                let mut nr = 1;
6835                for r in 1 .. grid.cells.rows {
6836                    if grid.cells[(r,0)].colour != grid.cells[(0,0)].colour {
6837                        nr += 1;
6838                    } else {
6839                        break;
6840                    }
6841                }
6842                let mut nc = 1;
6843                for c in 1 .. grid.cells.columns {
6844                    if grid.cells[(0,c)].colour != grid.cells[(0,0)].colour {
6845                        nc += 1;
6846                    } else {
6847                        break;
6848                    }
6849                }
6850                let mut tile = grid.subgrid(0, nr, 0, nc);
6851
6852                tile = tile.roll_right();
6853                grid.tile_mut(&tile);
6854//grid.show();
6855
6856                grid
6857            };
6858
6859            if let Some(rule) = run_experiment(task, 5675, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6860
6861            // a65b410d test and fails 5207a7b5 eval
6862            for inc in 1 ..= 1 {    // TODO Fix inc for > 1
6863                let func = |ex: &Example| {
6864                    if ex.input.shapes.shapes.len() != 1 || ex.input.shapes.shapes[0].size() >= ex.input.grid.size() || ex.input.shapes.shapes[0].is_pixel() || ex.input.shapes.shapes[0].ocol > 0 || !ex.input.shapes.is_line() {
6865                        return Grid::trivial();
6866                    }
6867
6868                    let top_colour = colours.iter().filter(|&(&k,_)| k != in_colour).map(|(k,v)| (v,k)).max().map(|(_,k)| k).unwrap();
6869                    let bottom_colour = colours.iter().filter(|&(&k,_)| k != in_colour).map(|(k,v)| (v,k)).min().map(|(_,k)| k).unwrap();
6870
6871                    let mut shapes = ex.input.shapes.clone();
6872                    let shape = &ex.input.shapes.shapes[0];
6873                    let rows = shape.cells.rows;
6874                    let cols = shape.cells.columns;
6875                    let bound = if inc == 1 { cols + shape.orow - 1
6876                    } else {
6877                        cols + shape.orow + inc
6878                    };
6879
6880                    for (i, c) in (0 ..= bound).rev().step_by(inc).enumerate() {
6881                        if i != shape.orow {
6882                            let colour = if i < shape.orow {
6883                                top_colour
6884                            } else {
6885                                bottom_colour
6886                            };
6887                            let s = Shape::new_sized_coloured_position(i, 0, rows, c + 1, *colour);
6888//println!("{i} {} {}", c + 1, c);
6889
6890                            shapes.shapes.push(s);
6891                        }
6892                    }
6893//ex.output.grid.show();
6894//println!("####");
6895//shapes.to_grid().show();
6896//shapes.to_grid().inverse_transform(trans).show();
6897
6898                    shapes.to_grid()
6899                };
6900
6901                if let Some(rule) = run_experiment(task, 5717, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6902            }
6903
6904            let func = |ex: &Example| {
6905                if ex.input.shapes.shapes.len() != 1 {
6906                    return Grid::trivial();
6907                }
6908
6909                let shape = &ex.input.shapes.shapes[0];
6910                let (dir, r, c) = shape.has_border_break();
6911                let mut grid = ex.input.grid.clone();
6912
6913                grid.draw_mut(dir, r, c, *fill_colour);
6914                grid.flood_fill_mut(r, c, NoColour, *fill_colour);
6915
6916//grid.show();
6917                grid
6918            };
6919
6920            if let Some(rule) = run_experiment(task, 5736, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6921
6922            let func = |ex: &Example| {
6923                if ex.input.shapes.shapes.len() != 1 {
6924                    return Grid::trivial();
6925                }
6926
6927                let shape = &ex.input.shapes.shapes[0];
6928                let mut grid = ex.input.grid.clone();
6929                let dist = grid.cells.columns - 1;
6930
6931                // TODO: This should be 4 functions on 4 rectangles
6932                let mut rfrom = shape.orow;
6933                let mut cfrom = shape.ocol;
6934                let mut odd = true;
6935
6936                while rfrom > 0 {
6937                    let dir = if odd { UpRight } else { UpLeft };
6938
6939                    grid.draw_mut(dir, rfrom, cfrom, in_colour);
6940
6941                    rfrom = rfrom.saturating_sub(dist);
6942                    cfrom = if cfrom == 0 { dist } else { 0 };
6943                    odd = !odd;
6944                }
6945
6946                grid = grid.recolour(Black, *fill_colour);
6947
6948//grid.show();
6949                grid
6950            };
6951
6952            if let Some(rule) = run_experiment(task, 5768, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
6953        }
6954//eprintln!("{file}");
6955
6956        /*
6957        eprintln!("{file} yes 4");
6958        examples.examples[0].input.shapes.show();
6959        examples.examples[0].output.shapes.show();
6960        examples.examples[0].output.coloured_shapes.show();
6961        //examples.examples[0].input.shapes.shapes[0].diff(&examples.examples[0].output.coloured_shapes.shapes[0]).unwrap().show_full();
6962        examples.examples[1].input.shapes.show();
6963        examples.examples[1].output.shapes.show();
6964        examples.examples[1].output.coloured_shapes.show();
6965        //eprintln!("{:?}", examples.examples[0].input.shapes.shapes);
6966        */
6967
6968        *cap_todo.entry(gc).or_insert(0) += 1;
6969    }
6970    /*
6971if cat.contains(&NoShapesOut(5)) && cat.contains(&ShapeMaxCntOut(4)) {
6972eprintln!("{file} yes 3");
6973}
6974let no = 1;
6975if cat.contains(&NoShapesIn(no)) && cat.contains(&NoShapesOut(no + 2)) {
6976eprintln!("yes");
6977}
6978if (cat.contains(&NoShapesIn(no)) || cat.contains(&NoShapesIn(no + no * 4))) && cat.contains(&NoShapesOut(no + no * 4)) {
6979eprintln!("yes 2");
6980}
6981if cat.contains(&InOutSameShapesColoured) && cat.contains(&InOutSameSize) && cat.contains(&ShapeMinCntIn(1)) && cat.contains(&ShapeMinCntOut(1)) {
6982let consolidated = examples.examples[0].input.shapes.consolidate_shapes();
6983//consolidated.show();
6984eprintln!("yes 3");
6985}
6986    */
6987    let gc = NoShapesIn(2);
6988    if all || cat.contains(&gc) {
6989        *cap_cats.entry(gc).or_insert(0) += 1;
6990
6991        let func = |ex: &Example| {
6992            if ex.input.shapes.shapes.len() != 2 || colour_diffs.len() != 1 {
6993                return Grid::trivial();
6994            }
6995            let mut shapes = ex.input.shapes.clone();
6996
6997            if shapes.shapes[0].orow + shapes.shapes[0].cells.rows + 1 == shapes.shapes[1].orow {
6998                if shapes.shapes[1].orow == 0 {
6999                    return Grid::trivial();
7000                }
7001                let s = Shape::new_sized_coloured_position(shapes.shapes[1].orow - 1, 0, 1, ex.input.grid.cells.columns, colour_diffs[0]);
7002
7003                shapes.shapes.push(s);
7004            } else {
7005                if shapes.shapes[1].ocol == 0 {
7006                    return Grid::trivial();
7007                }
7008                let s = Shape::new_sized_coloured_position(0, shapes.shapes[1].ocol - 1, ex.input.grid.cells.rows, 1, colour_diffs[0]);
7009
7010                shapes.shapes.push(s);
7011            }
7012
7013//shapes.to_grid().show();
7014            shapes.to_grid()
7015        };
7016
7017        if let Some(rule) = run_experiment(task, 5833, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7018
7019        let ss = examples.some(false, &|ss| ss.smallest());
7020        let sl = examples.some(true, &|ss| ss.largest());
7021        let sc: Vec<(Shape, Colour)> = ss.iter().zip(sl.iter()).map(|(s1, s2)| (s1.to_origin(), s2.colour)).collect();
7022
7023        let func = |ex: &Example| {
7024            let largest = ex.input.shapes.largest();
7025            let smallest = ex.input.shapes.smallest().to_origin();
7026            let mut shapes = ex.input.shapes.clone_base();
7027
7028            let pair: Vec<_> = sc.iter().filter(|(s, _)| s.equals(&smallest) == Same).collect();
7029
7030            if pair.len() == 0 {
7031                return Grid::trivial();
7032            }
7033
7034            shapes.shapes.push(largest.recolour(largest.colour, pair[0].1));
7035
7036// shapes.to_grid().show();
7037            shapes.to_grid()
7038        };
7039
7040        if let Some(rule) = run_experiment(task, 5856, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7041
7042        *cap_todo.entry(gc).or_insert(0) += 1;
7043    } 
7044    let gc = NoColouredShapesIn(2);
7045    if all || cat.contains(&gc) {
7046        *cap_cats.entry(gc).or_insert(0) += 1;
7047
7048        let func = |ex: &Example| {
7049           let idx = ex.input.coloured_shapes.smallest();
7050           let shape = ex.input.coloured_shapes.largest();
7051
7052           if idx.width() == 0 {
7053               return Grid::trivial();
7054           }
7055
7056           let mut big = idx.rotated_90().scale_up(shape.width() / idx.width());
7057
7058           big.to_position_mut(shape.orow, shape.ocol);
7059
7060           let mut shapes = ex.input.coloured_shapes.clone();
7061
7062           
7063           shapes.shapes.push(big);
7064//shapes.to_grid().show();
7065
7066           shapes.to_grid()
7067        };
7068
7069        if let Some(rule) = run_experiment(task, 5885, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7070
7071        let func = |ex: &Example| {
7072            if ex.input.coloured_shapes.len() != 2 || !ex.input.coloured_shapes.shapes[0].is_square() || ex.input.coloured_shapes.shapes[0].size() != 4 {
7073                return Grid::trivial();
7074            }
7075            let mut ns = ex.input.coloured_shapes.clone();
7076            let idx = &ex.input.coloured_shapes.shapes[0].cells;
7077
7078            let sm: BTreeMap<Colour, Colour> = idx.keys()
7079                .map(|(r,c)|
7080                    if r == 0 && c == 0 {
7081                        (idx[(r,c)].colour, idx[(r,c+1)].colour)
7082                    } else if r == 1 && c == 0 {
7083                        (idx[(r,c)].colour, idx[(r,c+1)].colour)
7084                    } else if r == 0 && c == 1 {
7085                        (idx[(r,c)].colour, idx[(r,c-1)].colour)
7086                    } else {
7087                        (idx[(r,c)].colour, idx[(r,c-1)].colour)
7088                    }
7089                )
7090            .collect();
7091
7092            ns.shapes[1].swap_colours(&sm);
7093
7094            ns.to_grid()
7095        };
7096
7097        if let Some(rule) = run_experiment(task, 5913, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7098
7099        *cap_todo.entry(gc).or_insert(0) += 1;
7100    }
7101
7102    let gc = NoColouredShapesIn(9);
7103    if all || cat.contains(&gc) && cat.contains(&NoColouredShapesOut(9)){ 
7104        *cap_cats.entry(gc).or_insert(0) += 1;
7105
7106        let colours: Vec<_> = examples.examples[0].input.grid.find_all_colours()
7107            .keys()
7108            .copied()
7109            .collect();
7110
7111        let order0 = [(0, 0), (0, 4), (0, 8), (4, 0), (4, 4), (4, 8), (8, 0), (8, 4), (8, 8)];
7112        let order1 = [(0, 8), (0, 4), (0, 0), (4, 8), (4, 4), (4, 0), (8, 8), (8, 4), (8, 0)];
7113        let order2 = [(8, 0), (8, 4), (8, 8), (4, 0), (4, 4), (4, 8), (0, 0), (0, 4), (0, 8)];
7114        let order3 = [(8, 8), (8, 4), (8, 0), (4, 8), (4, 4), (4, 0), (0, 8), (0, 4), (0, 0)];
7115
7116        for colour in colours.into_iter() {
7117            for order in [order0, order1, order2, order3] {
7118                // testing function
7119                let func = |ex: &Example| {
7120                    if ex.input.shapes.shapes.is_empty() {
7121                        return Grid::trivial();
7122                    }
7123                    let mut shapes = ex.input.grid.to_shapes_base_bg(Black);
7124
7125                    shapes.shapes.sort_by_key(|b| std::cmp::Reverse(b.cell_count_colour(colour)));
7126
7127                    let mut grid = Grid::new(ex.input.grid.cells.rows, ex.input.grid.cells.columns, Black);
7128
7129                    for ((r, c), s) in order.iter().zip(shapes.shapes.iter()) {
7130                        grid.copy_shape_to_grid_position_mut(s, *r, *c);
7131                    }
7132
7133                    grid
7134                };
7135
7136                if let Some(rule) = run_experiment(task, 5952, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7137            }
7138        }
7139
7140        *cap_todo.entry(gc).or_insert(0) += 1;
7141    }
7142    let gc = OutLessThanIn;
7143    if all || cat.contains(&gc) { 
7144        *cap_cats.entry(gc).or_insert(0) += 1;
7145
7146        if all || cat.contains(&SinglePixelOut) {
7147            let (rs, cs) = examples.examples[0].output.grid.dimensions();
7148
7149            let func = |gi: &Example| {
7150                if gi.input.shapes.shapes.is_empty() {
7151                    return Grid::trivial();
7152                }
7153
7154                let h = gi.input.shapes.shape_colour_cnt_map();
7155                let pair: Option<Vec<Shape>> = h.clone().into_values().filter(|p| p.len() == 2 && p[0].size() == p[1].size()).last();
7156                if let Some(pair) = pair {
7157                    // TODO fix coloured shape when mixed
7158                    for s in gi.input.coloured_shapes.shapes.iter() {
7159                        if s.is_contained(&pair[0]) && s.is_contained(&pair[1]) {
7160                            // find joining colour
7161                            let colour = h.keys().filter(|&&c| c != pair[0].colour && c != pair[1].colour).collect::<Vec<_>>();
7162
7163                            return Grid::new(rs, cs, *colour[0]);
7164                        }
7165                    }
7166                }
7167
7168                Grid::new(rs, cs, Black)
7169            };
7170
7171            if let Some(rule) = run_experiment(task, 5987, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7172        }
7173
7174        let func = |ex: &Example| {
7175            let scm = ex.input.shapes.shape_colour_cnt_map();
7176
7177            for v in scm.values() {
7178                if v.len() == 1 {
7179                    return v[0].to_grid();
7180                }
7181            }
7182
7183            Grid::trivial()
7184        };
7185
7186        if let Some(rule) = run_experiment(task, 6002, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7187
7188        if let Some(rule) = run_experiment(task, 6004, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.shapes.find_max().to_grid(), output) { return Some(rule); };
7189
7190        let colour = examples.examples[0].output.grid.colour;
7191
7192        // Use when divider 
7193        let func = |g: &Grid, _: &Grid, n: &mut usize| {
7194            let colour = g.mid_div_colour();
7195            let shapes = g.to_shapes_base_bg(colour);
7196            //let centre = g.centre_of();
7197            //let shapes = g.to_shapes_base_bg(ex.cells[centre].colour);
7198            if shapes.shapes.len() != 2 {
7199                return Grid::trivial();
7200            }
7201            let diff = shapes.shapes[0].diff(&shapes.shapes[1]);
7202
7203            if let Some(diff) = diff {
7204                diff_only(&diff.to_grid(), colour, n)
7205            } else {
7206                Grid::trivial()
7207            }
7208        };
7209
7210        if let Some(rule) = run_experiment_tries(task, 6026, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7211
7212        // Use when divider 
7213        let func = |g: &Grid, _: &Grid, n: &mut usize| {
7214            let colour = g.mid_div_colour();
7215            let shapes = g.to_shapes_base_bg(colour);
7216
7217            if shapes.shapes.len() != 2 || colour == NoColour || colour_diffs.is_empty() {
7218                return Grid::trivial();
7219            }
7220            let diff = shapes.shapes[0].diff(&shapes.shapes[1]);
7221
7222            if let Some(diff) = diff {
7223                diff_only(&diff.to_grid(), colour, n).recolour(colour, colour_diffs[0]).inverse_colour()
7224            } else {
7225                Grid::trivial()
7226            }
7227        };
7228
7229        if let Some(rule) = run_experiment_tries(task, 6045, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7230
7231        let func = |ex: &Example| {
7232            let shapes = ex.input.grid.split_2();
7233
7234            if shapes.len() != 2 || colour_diffs.is_empty() {
7235                return Grid::trivial();
7236            }
7237
7238            let g1 = shapes.shapes[0].to_grid();
7239            let g2 = shapes.shapes[1].to_grid();
7240            let grid = g1.diff_only_not(colour_diffs[0]).diff(&g2.diff_only_not(colour_diffs[0]));
7241
7242            match grid {
7243                Some(grid) => grid.diff_only_same(),
7244                None => Grid::trivial(),
7245            }
7246        };
7247
7248        if let Some(rule) = run_experiment(task, 6064, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7249
7250        // Use when divider - ops may be asymetric TODO: unduplicate
7251        let func = |gi: &Grid, _: &Grid, n: &mut usize| {
7252            let centre = gi.centre_of();
7253            let shapes = gi.to_shapes_base_bg(gi.cells[centre].colour);
7254            if shapes.is_empty() || shapes.shapes.len() != 2 {
7255                return Grid::trivial();
7256            }
7257            let diff = shapes.shapes[1].diff(&shapes.shapes[0]);
7258
7259            if let Some(diff) = diff {
7260                diff_only(&diff.to_grid(), colour, n)
7261            } else {
7262                Grid::trivial()
7263            }
7264        };
7265
7266        if let Some(rule) = run_experiment_tries(task, 6082, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7267
7268        // No divider
7269        let func = |gi: &Grid, _: &Grid, n: &mut usize| {
7270            let shapes = gi.split_2();
7271//shapes.show();
7272            if shapes.is_empty() || shapes.shapes.len() != 2 { return Grid::trivial(); }
7273            let diff = shapes.shapes[0].diff(&shapes.shapes[1]);
7274
7275            if let Some(diff) = diff {
7276                diff_only(&diff.to_grid(), colour, n)
7277            } else {
7278                Grid::trivial()
7279            }
7280        };
7281
7282        if let Some(rule) = run_experiment_tries(task, 6098, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7283
7284        let colours = examples.examples[0].input.grid.cell_colour_cnt_map();
7285        let colour = examples.examples[0].output.grid.colour;
7286
7287        if !colours.contains_key(&colour) {
7288            for (&in_colour, _) in colours.iter() {
7289                let func = |ex: &Example| {
7290                    let mut m = 0;
7291                    let mut size = 0;
7292
7293                    for s in &ex.input.shapes.shapes {
7294                        if s.colour == in_colour && s.size() > 1 {
7295                            if size > 1 && size != s.size() {
7296                                return Grid::trivial();
7297                            } 
7298                            size = s.size();
7299
7300                            m += 1;
7301                        }
7302                    }
7303                    let side = ex.output.grid.cells.rows;
7304
7305                    Grid::colour_every_nxn_for_m(colour, side, size, m)
7306                };
7307
7308                if let Some(rule) = run_experiment(task, 6123, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7309            }
7310        }
7311
7312        let (rs, cs) = examples.examples[0].output.grid.dimensions();
7313
7314        let func = |ex: &Example| {
7315            let mut colour = NoColour;
7316
7317            for s in &ex.input.shapes.shapes {
7318                if !s.is_full() {
7319                    colour = s.colour;
7320
7321                    break;
7322                }
7323            }
7324
7325            Grid::new(rs, cs, colour)
7326        };
7327
7328        if let Some(rule) = run_experiment(task, 6142, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7329
7330        // 3d31c5b3 281123b4
7331        for order in permutations(&[0,1,2,3]) {
7332            let func = |gi: &Example| {
7333                let shapes = gi.input.grid.split_4_inline(true);
7334                if shapes.is_empty() || shapes.shapes.len() != 4 {
7335                    return Grid::trivial();
7336                }
7337
7338                let mut diff = Some(shapes.shapes[*order[0]].clone());
7339
7340                for i in &order {
7341                    if let Some(new_diff) = diff {
7342                        let clear = new_diff.diff_only_transparent();
7343
7344                        diff = clear.diff(&shapes.shapes[**i]);
7345                    } else {
7346                        return Grid::trivial();
7347                    }
7348                }
7349                if let Some(new_diff) = diff {
7350                    new_diff.diff_only_transparent().to_grid()
7351                } else {
7352                    Grid::trivial()
7353                }
7354            };
7355
7356            if let Some(rule) = run_experiment(task, 6170, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7357        }
7358
7359        *cap_todo.entry(gc).or_insert(0) += 1;
7360    } 
7361    let gc = Div9Out;
7362    if all || cat.contains(&gc) { 
7363        *cap_cats.entry(gc).or_insert(0) += 1;
7364
7365        //if let Some(rule) = run_experiment_examples(&file, experiment, trans, is_test, examples, &targets, done, tries, &|exs| cat_div9(&exs), output) { return Some(rule); };
7366
7367        let colour_map = examples.find_colour_io_map();
7368
7369        let func = |ex: &Example| {
7370                let mut shapes = ex.input.shapes.clone();
7371                
7372                for s in shapes.shapes.iter_mut() {
7373                    if let Some(colour) = colour_map.get(&s.colour) {
7374                        s.recolour_mut(s.colour, *colour);
7375                    }
7376                }
7377
7378                shapes.to_grid()
7379        };
7380
7381        if let Some(rule) = run_experiment(task, 6195, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7382
7383        *cap_todo.entry(gc).or_insert(0) += 1;
7384    } 
7385    let gc = GravityDown;
7386    if all || cat.contains(&gc) || cat.contains(&GravityUp) { 
7387        *cap_cats.entry(gc).or_insert(0) += 1;
7388
7389        if let Some(rule) = run_experiment_tries(task, 6203, experiment, trans, is_test, examples, &targets, done, tries, &|ex, _, n| gravity_only(ex, n), output) { return Some(rule); };
7390
7391        let func = |ex: &Example| {
7392                let sccm = ex.input.shapes.shape_colour_cnt_map();
7393                let mut fill_colour = NoColour;
7394                let mut shapes = ex.input.shapes.clone_base();
7395                
7396                for (col, ss) in sccm.iter() {
7397                    if ss.len() == 1 {
7398                        shapes.shapes.push(ss[0].clone())
7399                    } else {
7400                        fill_colour = *col;
7401                    } 
7402                }
7403
7404                if shapes.shapes.is_empty() {
7405                    return Grid::trivial();
7406                }
7407
7408                let grid = shapes.to_grid();
7409
7410                grid.flood_fill(grid.cells.rows - 1, 0, NoColour, fill_colour)
7411        };
7412
7413        if let Some(rule) = run_experiment(task, 6227, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7414
7415        *cap_todo.entry(gc).or_insert(0) += 1;
7416    } 
7417    /*
7418    let gc = SingleColouredShapeIn;
7419    if all || cat.contains(&gc) && cat.contains(&SingleColouredShapeOut) {
7420        *cap_cats.entry(gc).or_insert(0) += 1;
7421
7422        // d631b094.json
7423        *cap_todo.entry(gc).or_insert(0) += 1;
7424    } 
7425    */
7426    let gc = SingleColourIn;
7427    if all || cat.contains(&gc) {
7428        *cap_cats.entry(gc).or_insert(0) += 1;
7429
7430        // ff28f65a.json
7431        if !cat.contains(&SingleColourOut) {
7432//println!("ffff");
7433//example.test.input.grid.show();
7434/*
7435            let func = |gi: &Grid, _: &Grid, n: &mut usize| {
7436                let shapes = gi.to_shapes_base_bg(gi.cells[(1,3)].colour);
7437                if shapes.len() < 2 { return Grid::trivial(); }
7438                let diff = shapes.shapes[0].diff(&shapes.shapes[1]).unwrap();
7439                let colour = examples.examples[0].output.grid.colour;
7440
7441                diff.to_grid().diff_only(colour, *n)
7442            };
7443
7444            if let Some(rule) = run_experiment_tries(file, 500, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7445*/
7446
7447            if !examples.examples.is_empty() && !examples.examples[0].input.shapes.shapes.is_empty() {
7448                // Global colour data for two rules
7449                let colour = examples.examples[0].input.shapes.shapes[0].colour;
7450                let mut new_colour = colour;
7451
7452                for s in examples.examples[0].output.shapes.shapes.iter() {
7453                    if colour != s.colour {
7454                        new_colour = s.colour;
7455
7456                        break;
7457                    }
7458                }
7459
7460                let func = |gi: &Example| {
7461                    if gi.input.shapes.is_empty() {
7462                        return Grid::trivial();
7463                    }
7464
7465                    let mut si = gi.input.shapes.clone();
7466
7467                    si.shapes.sort_by(|a, b| (a.ocol, a.orow).cmp(&(b.ocol, b.orow)));
7468                    let mut other = si.shapes.len() % 2 != 0;
7469
7470                    for s in si.shapes.iter_mut() {
7471                        if other {
7472                            s.mut_force_recolour(new_colour);
7473                        }
7474
7475                        other = !other;
7476                    }
7477
7478                    si.to_grid()
7479                };
7480
7481                if let Some(rule) = run_experiment(task, 6295, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7482
7483                let func = |gi: &Example| {
7484                    if gi.input.shapes.is_empty() {
7485                        return Grid::trivial();
7486                    }
7487
7488                    let mut si = gi.input.shapes.clone();
7489
7490                    for s in si.shapes.iter_mut() {
7491                        if s.pixels() >= 4 {
7492                            s.mut_recolour(colour, new_colour);
7493                        }
7494                    }
7495
7496                    si.to_grid()
7497                };
7498
7499                if let Some(rule) = run_experiment(task, 6313, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7500            }
7501
7502            let ccm = examples.find_hollow_cnt_colour_map();
7503
7504            let func = |ex: &Example| {
7505                if ex.input.shapes.is_empty() {
7506                    return Grid::trivial();
7507                }
7508
7509                let mut shapes = ex.input.shapes.clone();
7510
7511                for s in shapes.shapes.iter_mut() {
7512                    let (_, n) = s.hollow_colour_count();
7513                    
7514                    if let Some(colour) = ccm.get(&n) {
7515                        s.recolour_mut(s.colour, *colour);
7516                    }
7517                }
7518
7519//shapes.to_grid().show();
7520                shapes.to_grid()
7521            };
7522
7523            if let Some(rule) = run_experiment(task, 6337, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7524
7525            /* TODO 759f3fd3 translate_absolute_clip
7526            let sq_colour = if !examples.examples.is_empty() && !examples.examples[0].output.shapes.shapes.is_empty() {
7527                examples.examples[0].output.shapes.shapes[0].colour
7528            } else {
7529                NoColour
7530            };
7531
7532            let func = |ex: &Example| {
7533                if ex.input.shapes.len() != 4 || ex.input.shapes.shapes[0].colour != NoColour {
7534                    return Grid::trivial();
7535                }
7536                let shape = ex.input.grid.as_shape();
7537                let first = &ex.input.shapes.shapes[0];
7538                let x = first.cells.rows;
7539                let y = first.cells.columns;
7540                let mut shapes = Shapes::new_sized(shape.cells.rows, shape.cells.columns);
7541                
7542                for i in (5 .. shape.cells.rows * 2).step_by(2) {
7543                    if i > shape.cells.rows && i > shape.cells.columns {
7544                        break;
7545                    }
7546
7547                    let s = Shape::new_square(x, y, i, sq_colour);
7548//s.show_summary();
7549                    let s = s.translate_absolute_clip(x as isize - i as isize + 3, y as isize - i as isize + 3);
7550//println!("{:?}", s);
7551//s.show_summary();
7552                    shapes.shapes.push(s);
7553                }
7554
7555                shapes.shapes.reverse();
7556
7557                //shapes.shapes.push(shape.clone());
7558//shapes.show();
7559//shapes.trim_to_grid().show();
7560
7561                shapes.trim_to_grid()
7562            };
7563
7564            if let Some(rule) = run_experiment(file, 280, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7565            */
7566        }
7567
7568        let func = |ex: &Example| {
7569            if colour_diffs.len() != 1 || ex.input.shapes.shapes.is_empty() {
7570                return Grid::trivial();
7571            }
7572
7573            // Assume all shapes are the same size
7574            let (rs, cs) = ex.majority_dimensions();
7575            let mut grid = ex.input.grid.clone();
7576
7577            grid.recolour_mut(Black, colour_diffs[0]);
7578            grid.recolour_mut(all_colour_diffs[0], Black);
7579
7580            grid.background_border_mut();
7581
7582            grid.row_dividers_mut(rs);
7583            grid.col_dividers_mut(cs);
7584
7585            grid
7586        };
7587
7588        if let Some(rule) = run_experiment(task, 6402, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7589
7590        let out_colours = examples.examples[0].output.grid.cell_colour_cnt_map();
7591        let func = |ex: &Example| {
7592            if all_colour_diffs.len() != 2 || out_colours.len() != 3 {
7593                return Grid::trivial();
7594            }
7595            let mut colour_order: Vec<(usize,Colour)> = out_colours.iter().map(|(k, v)| (*v, *k)).collect();
7596            colour_order.sort();
7597            let colours: Vec<Colour> = colour_order.iter().map(|(_, c)| *c).collect();
7598            let mut grid = ex.input.grid.clone();
7599
7600            for s in ex.input.shapes.shapes.iter() {
7601                let mut r = s.cells.rows + 1;
7602
7603                for c in (0 .. s.ocol).rev() {
7604                    grid.draw_mut(Up, r, c, colours[2]);
7605
7606                    r += if grid.cells.rows - r <= 2 {
7607                        grid.cells.rows - r - 1
7608                    } else {
7609                        2
7610                    };
7611                }
7612
7613                if s.cells.rows < 2 + 1 {
7614                    return Grid::trivial();
7615                }
7616
7617                let mut r = s.cells.rows - 2 - 1;
7618
7619                for c in s.ocol + 1 .. grid.cells.columns {
7620                    grid.draw_mut(Up, r, c, colours[0]);
7621
7622                    if r < 2 {
7623                        break;
7624                    }
7625
7626                    r -= 2;
7627                }
7628            }
7629
7630//grid.show();
7631            grid
7632        };
7633
7634        if let Some(rule) = run_experiment(task, 6403, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7635
7636        *cap_todo.entry(gc).or_insert(0) += 1;
7637    } 
7638    let gc = SingleColourOut;
7639    if all || cat.contains(&gc) && !cat.contains(&SingleColourIn) {
7640        *cap_cats.entry(gc).or_insert(0) += 1;
7641
7642        if let Some(rule) = run_experiment(task, 6410, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.find_pixels_min().to_grid(), output) { return Some(rule); };
7643
7644        if let Some(rule) = run_experiment(task, 6412, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.find_pixels_max().to_grid(), output) { return Some(rule); };
7645
7646        if let Some(rule) = run_experiment(task, 6414, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.hollow_cnt_max().to_grid(), output) { return Some(rule); };
7647
7648        if let Some(rule) = run_experiment(task, 6416, experiment, trans, is_test, examples, &targets, done, tries, &|ex| ex.input.coloured_shapes.hollow_cnt_min().to_grid(), output) { return Some(rule); };
7649
7650        let out_colours = examples.find_output_colours();
7651
7652        if out_colours.len() == 1 {
7653            let in_colours = examples.find_input_colours().uniq(out_colours);
7654            if in_colours.len() == 2 {
7655                let func = |ex: &Example| {
7656                  let c1s = ex.input.grid.find_colour(in_colours[0]);
7657                  let c2s = ex.input.grid.find_colour(in_colours[1]);
7658                  let len = c1s.len();
7659                  if len == c2s.len() {
7660                      let c_dim = c1s[0].col == c2s[0].col;
7661                      let mut grid: Grid;
7662
7663                      if c_dim {
7664                          let width = c1s[0].row.min(c2s[0].row) - c1s[0].row.min(c2s[0].row) - 1; // assume all same
7665
7666                          grid = Grid::new(width, len, Black);
7667
7668                          for (c, (a, b)) in c1s.iter().zip(c2s.iter()).enumerate() {
7669                              for r in a.row + 1 .. b.row {
7670                                  grid.cells[(r - a.row - 1, c)].row = ex.input.grid.cells[(r,a.col)].row;
7671                                  grid.cells[(r - a.row - 1, c)].col = ex.input.grid.cells[(r,a.col)].col;
7672                                  grid.cells[(r - a.row - 1, c)].colour = ex.input.grid.cells[(r,a.col)].colour;
7673                              }
7674                          }
7675                      } else {
7676                          let height = c1s[0].col.max(c2s[0].col) - c1s[0].col.min(c2s[0].col) - 1; // assume all same
7677
7678                          grid = Grid::new(len, height, Black);
7679
7680                              for (r, (a, b)) in c1s.iter().zip(c2s.iter()).enumerate() {
7681                              for c in a.col + 1 .. b.col {
7682                                  grid.cells[(r, c - a.col - 1)].row = ex.input.grid.cells[(a.row,c)].row;
7683                                  grid.cells[(r, c - a.col - 1)].col = ex.input.grid.cells[(a.row,c)].col;
7684                                  grid.cells[(r, c - a.col - 1)].colour = ex.input.grid.cells[(a.row,c)].colour;
7685                              }
7686                          }
7687                      };
7688                      return grid;
7689                  }
7690
7691                  Grid::trivial()
7692                };
7693
7694                if let Some(rule) = run_experiment(task, 6462, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7695            }
7696        }
7697
7698        let (rs, cs) = examples.examples[0].output.grid.dimensions();
7699
7700        let func = |ex: &Example| {
7701            if ex.input.shapes.shapes.is_empty() {
7702                return Grid::trivial();
7703            }
7704
7705            let largest = ex.input.shapes.largest();
7706
7707            Grid::new(rs, cs, largest.colour)
7708        };
7709
7710        if let Some(rule) = run_experiment(task, 6478, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7711
7712        *cap_todo.entry(gc).or_insert(0) += 1;
7713    } 
7714
7715    // Special section for rules that might give false positives
7716    // These often solve the examples but not the final test(s)
7717    *cap_cats.entry(CatchAll).or_insert(0) += 1;
7718
7719    let func = |ex: &Example| {
7720        let largest = ex.input.coloured_shapes.largest();
7721
7722        if largest.cells.rows < 3 || largest.cells.columns < 3 {
7723            return Grid::trivial();
7724        }
7725
7726        let shape = largest.subshape(0, 3, 0, 3);
7727        let mut grid = ex.input.grid.clone();
7728
7729        for s in ex.input.coloured_shapes.shapes.iter() {
7730            if s.size() == 1 {
7731                if s.orow == 0 || s.ocol == 0 {
7732                    return Grid::trivial();
7733                }
7734                let new_shape = shape.translate_absolute(s.orow-1,s.ocol-1);
7735
7736                grid.copy_shape_to_grid_mut(&new_shape);
7737            }
7738        }
7739
7740        grid
7741    };
7742
7743    if let Some(rule) = run_experiment(task, 6511, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7744
7745    let out_shapes = examples.all_shapes_out();
7746    let out_shapes = out_shapes.shape_permutations();
7747
7748    let func = |ex: &Example| {
7749        let mut shapes = ex.input.shapes.clone();
7750
7751        for s1 in out_shapes.shapes.iter() {
7752            for s2 in shapes.shapes.iter_mut() {
7753                if s1.equal_shape(s2) {
7754                    s2.recolour_mut(s2.colour, s1.colour);
7755                    break;
7756                }
7757            }
7758        }
7759
7760        shapes.to_grid()
7761    };
7762
7763    if let Some(rule) = run_experiment(task, 6531, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7764
7765    let spc = examples.shape_pixels_to_colour();
7766
7767    let func = |ex: &Example| {
7768        let mut shapes = ex.input.shapes.clone();
7769
7770        for s in shapes.shapes.iter_mut() {
7771            if let Some(colour) = spc.get(&s.pixels()) {
7772                s.recolour_mut(s.colour, *colour);
7773            } else {
7774                return Grid::trivial();
7775            }
7776        }
7777
7778        shapes.to_grid()
7779    };
7780
7781    if let Some(rule) = run_experiment(task, 6549, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7782
7783    let func = |ex: &Example| {
7784        if ex.input.shapes.is_empty() {
7785            return Grid::trivial();
7786        }
7787        let mut shapes = ex.input.shapes.clone();
7788
7789        for s in shapes.shapes.iter_mut() {
7790            if !Colour::in_range(s.pixels()) {
7791                return Grid::trivial();
7792            }
7793
7794            s.recolour_mut(s.colour, Colour::from_usize(s.pixels()));
7795        }
7796//shapes.to_grid().show();
7797
7798        shapes.to_grid()
7799    };
7800
7801    if let Some(rule) = run_experiment(task, 6569, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7802
7803    let func = |ex: &Example| {
7804        let mut shapes = ex.input.shapes.clone();
7805
7806        for s1 in ex.input.shapes.shapes.iter() {
7807            for s2 in shapes.shapes.iter_mut() {
7808                if s1.equal_shape(s2) && s1.colour > s2.colour {
7809                    s2.recolour_mut(s2.colour, s1.colour);
7810
7811                    break;
7812                }
7813            }
7814        }
7815
7816        shapes.to_grid()
7817    };
7818
7819    if let Some(rule) = run_experiment(task, 6587, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7820
7821    // Cross example knowledge needed for closure
7822    let h = examples.bleached_io_map();
7823
7824    let func = |ex: &Example| {
7825        if let Some(grid) = h.get(&ex.input.grid.bleach().to_json()) {
7826            grid.clone()
7827        } else {
7828            Grid::trivial()
7829        }
7830    };
7831
7832    if let Some(rule) = run_experiment(task, 6600, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7833
7834    if (all || cat.contains(&InOutSameShapesColoured)) && !examples.examples[0].output.shapes.shapes.is_empty() {
7835        let mut pairs: BTreeMap<Shape, Shape> = BTreeMap::new();
7836
7837        for exs in examples.examples.iter() {
7838            let m = exs.output.shapes.contained_pairs();
7839            pairs.extend(m);
7840        }
7841
7842        let mut ssm: BTreeMap<usize, Colour> = BTreeMap::new();
7843
7844        for (ks, vs) in pairs.iter() {
7845            ssm.insert(ks.size(), vs.colour);
7846        }
7847
7848        let func = &|ex: &Example| {
7849            let mut shapes = ex.input.shapes.clone();
7850
7851            for s in shapes.shapes.iter_mut() {
7852                if let Some(colour) = ssm.get(&s.size()) {
7853                    let (r, c) = s.centre_of();
7854
7855                    s.flood_fill_mut(r - s.orow, c - s.ocol, NoColour, *colour);
7856                }
7857            }
7858
7859            shapes.to_grid()
7860        };
7861
7862        if let Some(rule) = run_experiment(task, 6630, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7863    }
7864
7865    let func = |ex: &Example| {
7866        let shape = ex.input.grid.as_shape().scale_up(2);
7867
7868        Shapes::new_shapes(&[shape]).to_grid()
7869    };
7870
7871    if let Some(rule) = run_experiment(task, 100000, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7872
7873    let func = &|ex: &Example| {
7874        let len = ex.input.shapes.shapes.len();
7875
7876//ex.input.grid.show();
7877        if len != 4 && len != 9 && len != 25 || !ex.input.shapes.shapes.is_empty() && (!ex.input.shapes.shapes[0].is_square() || ex.input.shapes.shapes[0].size() == 1) {
7878            return Grid::trivial();
7879        }
7880
7881        let mut n = usize::MAX;
7882        let mut posn = 0;
7883
7884        for (i, s) in ex.input.shapes.shapes.iter().enumerate() {
7885            let h = s.cell_colour_cnt_map();
7886            if n > h.len() {
7887                n = h.len();
7888                posn = i;
7889            }
7890        }
7891        let ans = ex.input.shapes.shapes[posn].clone();
7892        let mut shapes = ex.input.shapes.clone_base();
7893
7894        for (i, s) in ex.input.shapes.shapes.iter().enumerate() {
7895            if ans.size() != s.size() || ans.colour == NoColour  || i / ans.cells.rows >= ans.cells.rows  {
7896                return Grid::trivial();
7897            }
7898
7899            let colour = ans.cells[(i / ans.cells.rows, i % ans.cells.columns)].colour;
7900            let ns = s.force_recolour(colour);
7901            
7902            shapes.shapes.push(ns);
7903        }
7904
7905        if ans.cells.rows >= ex.input.grid.cells.rows || ans.cells.columns >= ex.input.grid.cells.columns {
7906            return Grid::trivial();
7907        }
7908
7909        let bg = ex.input.grid.cells[(ans.cells.rows,ans.cells.columns)].colour;
7910//shapes.to_grid_colour(bg).show();
7911
7912        shapes.to_grid_colour(bg)
7913    };
7914
7915    if let Some(rule) = run_experiment(task, 100010, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7916
7917    let in_colour = examples.examples[0].output.grid.get_diff_colour(&examples.examples[0].input.grid);
7918    let colour = examples.examples[0].io_colour_diff();
7919
7920    let func = |ex: &Example| {
7921        let mut shapes = ex.input.grid.to_shapes_sq();
7922
7923        for s in shapes.clone().shapes.iter_mut() {
7924            if !s.is_pixel() {
7925                shapes.shapes.push(s.recolour(in_colour, colour));
7926            }
7927        }
7928
7929        shapes.to_grid()
7930    };
7931
7932    if let Some(rule) = run_experiment(task, 100020, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7933
7934    let in_grid = &examples.examples[0].input.grid;
7935    let out_grid = &examples.examples[0].output.grid;
7936    
7937    let func = |ex: &Example| {
7938        if ex.input.shapes.shapes.is_empty() || NxNIn(0).gte_value(&NxNOut(0), &cat) {
7939            return Grid::trivial();
7940        }
7941
7942        let colour_map: BTreeMap<Colour,Colour> = in_grid.cells.values()
7943            .zip(ex.input.grid.cells.values())
7944            .map(|(k,v)| (k.colour,v.colour))
7945            .collect();
7946
7947        let mut grid = out_grid.clone();
7948
7949        for ((r, c), cell) in out_grid.cells.items() {
7950            match colour_map.get(&cell.colour) {
7951                Some(colour) => grid.cells[(r,c)].colour = *colour,
7952                None => return Grid::trivial()
7953            }
7954        }
7955
7956        grid
7957    };
7958
7959    if let Some(rule) = run_experiment(task, 100030, experiment, trans, is_test, examples, &targets, done, tries, &func, output) { return Some(rule); };
7960
7961    *cap_todo.entry(CatchAll).or_insert(0) += 1;
7962
7963    None
7964}
7965
7966#[allow(clippy::too_many_arguments)]
7967fn run_experiment(task: &str, experiment: usize, experiment_todo: &str, trans: Transformation, is_test: bool, examples: &Examples, targets: &[Grid], done: &mut BTreeSet<String>, tries: &mut usize, func: &(dyn Fn(&Example) -> Grid + std::panic::RefUnwindSafe), output: &mut BTreeMap<String, Vec<OutputData>>) -> Option<usize> {
7968    if !experiment_todo.is_empty() {
7969        if let Ok(ex) = experiment_todo.parse::<usize>() {
7970            if ex != experiment {
7971                return None;
7972            }
7973        } 
7974    }
7975    if done.contains(task) {   // already done???
7976        return Some(usize::MAX);
7977    }
7978
7979    let ans = panic::catch_unwind(|| experiment_example(examples, task, experiment, trans, func));
7980
7981    let ans = match ans {
7982        Ok(ans) => ans,
7983        Err(e) => {
7984            eprintln!("{task} / {experiment} Exception: {e:?}");
7985            vec![Grid::trivial()]
7986        },
7987    };
7988
7989    *tries += 1;
7990
7991    save(task, experiment, trans, is_test, &ans, targets, done, output)
7992}
7993
7994#[allow(clippy::too_many_arguments)]
7995fn run_experiment_tries(task: &str, experiment: usize, experiment_todo: &str, trans: Transformation, is_test: bool, examples: &Examples, targets: &[Grid], done: &mut BTreeSet<String>, tries: &mut usize, func: &(dyn Fn(&Grid, &Grid, &mut usize) -> Grid + RefUnwindSafe), output: &mut BTreeMap<String, Vec<OutputData>>) -> Option<usize> {
7996    if !experiment_todo.is_empty() {
7997        if let Ok(ex) = experiment_todo.parse::<usize>() {
7998            if ex != experiment {
7999                return None;
8000            }
8001        } 
8002    }
8003    if done.contains(task) {   // already done???
8004        return Some(usize::MAX);
8005    }
8006
8007    let ans = panic::catch_unwind(|| experiment_grid(examples, task, experiment, trans, func));
8008
8009    let ans = match ans {
8010        Ok(ans) => ans,
8011        Err(e) => {
8012            eprintln!("{task} / {experiment} Exception: {e:?}");
8013            vec![Grid::trivial()]
8014        },
8015    };
8016
8017    *tries += 1;
8018
8019    save(task, experiment, trans, is_test, &ans, targets, done, output)
8020}
8021
8022fn run_experiment_colours(task: &str, experiment: usize, experiment_todo: &str, is_test: bool, examples: &Examples, targets: &[Grid], done: &mut BTreeSet<String>, func: &(dyn Fn(&Example, Colour) -> Grid + RefUnwindSafe), output: &mut BTreeMap<String, Vec<OutputData>>) -> Option<usize> {
8023    if !experiment_todo.is_empty() {
8024        if let Ok(ex) = experiment_todo.parse::<usize>() {
8025            if ex != experiment {
8026                return None;
8027            }
8028        } 
8029    }
8030    if done.contains(task) {   // already done???
8031        return Some(usize::MAX);
8032    }
8033
8034    let ans = panic::catch_unwind(|| experiment_colours(examples, func));
8035
8036    let ans = match ans {
8037        Ok(ans) => ans,
8038        Err(e) => {
8039            eprintln!("{task} / {experiment} Exception: {e:?}");
8040            vec![Grid::trivial()]
8041        },
8042    };
8043
8044    save(task, experiment, NoTrans, is_test, &ans, targets, done, output)
8045}
8046
8047#[allow(clippy::too_many_arguments)]
8048fn save(task: &str, experiment: usize, trans: Transformation, is_test: bool, ans: &[Grid], targets: &[Grid], done: &mut BTreeSet<String>, results: &mut BTreeMap<String, Vec<OutputData>>) -> Option<usize> {
8049    let target_size: usize = targets.iter().map(|target| target.size()).sum();
8050    let ans_size: usize = ans.iter().map(|ans| ans.size()).sum();
8051    let same = if target_size > 0 && ans_size > 0 {
8052        targets.iter()
8053            .zip(ans.iter())
8054            .map(|(target, ans)| {
8055                if ans.equals(target) == Same {
8056                    1
8057                } else {
8058                    0
8059                }})
8060            .sum::<usize>() > 0
8061    } else {
8062        false
8063    };
8064
8065    if !is_test {
8066        if same {
8067            add_real_output(task, ans, results);
8068
8069            done.insert(task.to_string());
8070            println!("Success: {experiment:>05} {trans:?} / {task}");
8071
8072            Some(experiment)
8073        } else if ans_size > 0 {
8074            add_dummy_output(task, ans.len(), results);
8075
8076            let dist: Vec<_> = ans.iter().zip(targets.iter())
8077                .map(|(a,t)| format!("{:.4}", a.distance(t)))
8078                .collect();
8079
8080            println!("Final Test Failed : {experiment:>05} {trans:?} / {task} by {}", dist.join(", "));
8081
8082            None
8083        } else {
8084            add_dummy_output(task, ans.len(), results);
8085
8086            None
8087        }
8088    } else if ans_size > 0 {
8089        add_real_output(task, ans, results);
8090
8091        done.insert(task.to_string());
8092        println!("Test Success: {experiment:>05} {trans:?} / {task}");
8093
8094        Some(experiment)
8095    } else {
8096        add_dummy_output(task, ans.len(), results);
8097
8098        None
8099    }
8100}
8101
8102fn format(rule_tasks: &BTreeMap<usize, Vec<String>>) {
8103    println!();
8104    println!("Rule solving tasks:");
8105    println!("-------------------");
8106    for (k, v) in rule_tasks.iter() {
8107        println!("{k:<5}: {}", v.join(", "));
8108    }
8109    println!();
8110}