From 2b9fcff25ec128d9ebd7058588df225dd3767202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Sun, 20 Dec 2020 19:15:42 +0100 Subject: [PATCH] day 20 --- data/day20/input | 1728 ++++++++++++++++++++++++++++++++++++++++++++++ src/bin/day20.rs | 466 +++++++++++++ 2 files changed, 2194 insertions(+) create mode 100644 data/day20/input create mode 100644 src/bin/day20.rs diff --git a/data/day20/input b/data/day20/input new file mode 100644 index 0000000..333150f --- /dev/null +++ b/data/day20/input @@ -0,0 +1,1728 @@ +Tile 3457: +##.###.##. +...#..##.# +#.#..###.. +##.....#.. +#.#....#.# +...##.#... +##..#....# +..###..#.. +#........# +#.##..#.#. + +Tile 3061: +##....#### +#.#....... +#.....##.. +#........# +.....#.... +##......## +.##..###.. +........#. +...#....#. +..###.#.## + +Tile 2131: +.#..#..#.# +#....#..## +#........# +#..#..#..# +.#...#..#. +##........ +##.##..### +..#..##... +......##.# +##..###### + +Tile 2087: +.##.#..... +...#...... +###....... +#.#......# +##....#.#. +.......... +........## +#.....#.#. +...##.#... +..##.##..# + +Tile 2593: +#.###.##.# +.#..#...#. +.........# +#..###.... +....##.... +##..#..#.. +###.##.... +#....####. +.#..##..#. +.#.....### + +Tile 1277: +###.#.#... +..##...... +#..#.#...# +...##.#..# +#...###.#. +..#......# +##...#.... +......#.## +##.#.##..# +..#...#... + +Tile 2917: +###.#....# +....##.### +#......#.# +#..#.#...# +#.#....##. +#..#..#.#. +..#####... +##.##.#.## +#.#....### +#####.#..# + +Tile 1579: +#.#..#..## +..#....### +##......#. +#...#..### +#..##..#.. +##.##....# +.##....#.# +#.###...#. +..#.#.#.#. +##.#.#.... + +Tile 3011: +....#.#.#. +##........ +#.#......# +#...#..#.# +........## +#..#.....# +.....#.... +#.##...... +#...#..#.. +....#..#.. + +Tile 2539: +..#.#.#.## +...#.##### +.........# +.......... +.....##..# +##....##.# +#.....#... +....##.#.. +..#.##.#.. +#.#.#....# + +Tile 1879: +##.####### +#..#....#. +........## +..#.....#. +#.#.#..#.. +...##....# +#..##..#.# +..#.....#. +#.....#... +.#####.##. + +Tile 2081: +..#....#.# +#.##.#.#.# +#....#.##. +##......## +....#.#.## +......#..# +##.......# +#........# +..#..#...# +..###..#.. + +Tile 1721: +.#.####.## +....#.#..# +#...#.#... +#...#.##.. +#.#.#.#### +#...#.#..# +.........# +..#..##.#. +#.#.#.##.# +#..#....#. + +Tile 1237: +.....###.. +.......#.. +#...#....# +......#.## +###....#.. +#.#..#.#.. +..#......# +..#..#..#. +.#........ +#.#.#.##.. + +Tile 3037: +..#..####. +........#. +...#.#...# +.##.##..#. +#.##.#.#.. +#...#.#.## +#..###.... +#......### +#.#..###.# +.##...#.## + +Tile 2719: +######.##. +#...#...#. +#..##.#..# +##........ +..#.##.... +##........ +#.###.###. +#..#....#. +##..##.... +.#....#.#. + +Tile 1013: +.#...#.##. +#..#.##... +##..#....# +#......#.. +.#..##.... +..#....... +........## +#........# +.....##... +#.#.###... + +Tile 3571: +.......#.# +.#...#...# +....##.... +#......#.# +.###.#..#. +#...##...# +##...#.#.. +......#... +#.#....#.. +##....#..# + +Tile 2269: +##.#.#...# +..#.#..... +.##.###..# +.#....##.# +#.#..#.### +#.....#..# +#.#.#....# +#..##..#.# +...#....## +...##.#... + +Tile 3709: +##...#..## +...#...#.# +#..#.#.... +..##.####. +..#...##.# +...#...#.# +#...#.#... +.#........ +.......... +#..#.#.#.# + +Tile 2143: +#.##.#.... +####...##. +#.###...#. +....##.#.# +##.##..... +.......#.# +####..##.. +.......#.. +#......#.# +####....## + +Tile 3677: +##.###.##. +.#.###..#. +..##...#.. +..#......# +##.##..... +#.#.##.#.. +..#..#.##. +##..###... +#.#......# +...###.### + +Tile 2297: +.........# +.......... +........## +#.#..#.... +##.#..###. +#........# +.....#..#. +...#...#.# +##..#..... +.#.######. + +Tile 1871: +#.#.#..... +#.#....#.# +..#...#..# +..#..##..# +#.#.##.... +......#.## +##.##.#.## +#.###.#### +#..#....#. +###.#....# + +Tile 3449: +##..#.###. +.####..... +#..###..#. +#....#.#.. +#.....#..# +#....#.#.. +#.....#..# +.#..#..... +#..#.#...# +.####.#### + +Tile 3391: +........## +##.#.#.#.# +...##....# +..###..### +.#....#..# +.#....#.#. +.......... +#...#.#.#. +.....#.#.# +#.#....... + +Tile 2243: +..#...##.# +##...##... +..#......# +..#.##.#.# +.#......#. +#.#...##.. +#.....###. +##..##.#.# +#.#....#.# +#.#..#..## + +Tile 2153: +##.###.#.# +.#.#.#.#.# +#..#..###. +.##..#.#.# +.#.....#.. +..#......# +........## +.#.....##. +.#.......# +#......### + +Tile 3659: +.#.#....## +..#..#..#. +..###...## +.......... +#.....#..# +##.#.#..## +#.###..#.. +#..#....## +#........# +#.###..##. + +Tile 2503: +##..##.#.# +#..#..#... +.....#...# +...#.....# +#.....#... +.....###.# +#..#..#... +..#...#... +#..#...##. +.###...### + +Tile 2741: +#..#.##### +..#....... +...#..##.. +#...#..... +.#.#.#.... +..###..#.. +.#.#..#..# +.##..#.##. +##.#...... +.##....#.# + +Tile 3371: +..###.#..# +#..#...... +###...#..# +.......... +.#..##...# +...#.....# +...##.#... +#.#.#..#.. +#.......#. +###.#.###. + +Tile 2731: +#...#.#... +#.#..#.... +#...#.#... +#.###.#### +.#.##....# +##..#....# +#.#....... +##..#....# +......##.. +###...###. + +Tile 3217: +.#..#..#.# +##...#...# +....##..#. +#...#.#... +#......### +##.#....## +#..#...##. +#...#...## +#.#.#..... +.#.#...... + +Tile 3911: +..###..##. +.....#.#.. +##.#...#.# +#.....#..# +.......#.# +#........# +..#....#.# +#.##....## +.....#...# +##.##.#.#. + +Tile 1637: +.#.#..#.## +##..#.#... +.#.#####.# +..#..#..#. +#......### +#......... +#.##...##. +#........# +#..#.....# +..#...#.#. + +Tile 3989: +.#..##.##. +.......... +..#.##..## +#.#..#.... +#...#....# +#..#.#.#.# +##....#..# +#.#...#... +######.##. +.#..#..### + +Tile 2213: +...#..#### +.....###.. +##....###. +#...###.## +##...####. +#......... +......#... +#.......## +###.....## +.##...###. + +Tile 1061: +.#.....##. +#...#..#.# +#.......#. +.#.......# +.....#.... +.#....#.## +##.#....## +#...#...#. +#...#.##.. +.###.....# + +Tile 2281: +..#..##.#. +..##.....# +..##.....# +..#.#....# +#.#..##.#. +#..#..#.## +#......#.. +...#...#.# +..##...... +#.###.###. + +Tile 3803: +####.##..# +#..#..#.## +.#...##... +#..#.#.##. +#...#....# +....#....# +..#.##.#.. +#..#...#.. +##........ +#...#.#... + +Tile 3347: +.##.##...# +#..#.#.... +...##.##.. +#...#..... +#.....##.. +#.#..#...# +.....#.#.# +#......... +#......... +##..#####. + +Tile 2687: +.#####.#.. +#.#.#..... +#....#.... +.##.#..... +#.##....## +#....#...# +###.##...# +##..#....# +....#....# +#.##.#.##. + +Tile 1097: +##....#..# +....##...# +#...#.#... +#....#.... +.....#..## +#..##.#..# +#....#.... +###....### +#.....#.## +#....#...# + +Tile 1483: +#..#.##... +....##.#.# +...##....# +#..##..#.# +.#...##... +.......... +#..#..##.. +....##.#.# +######.... +####....#. + +Tile 2207: +.#.###.##. +.##..#.... +....#....# +#....#.... +#....##..# +#.#.....## +...#....#. +#.#..#...# +.#.......# +.#####.##. + +Tile 1559: +.####..##. +##..##.#.# +......##.. +##.#..#..# +.#.#.#.... +#....#..#. +#..#..#.#. +#.#..#.#.# +#...##.#.. +.#...#.... + +Tile 3019: +...#.###.# +.##..#..## +...##..#.. +..#...##.# +#......#.. +#....#.### +##..#....# +#.#....#.. +#..##..#.# +#.#####..# + +Tile 2441: +...####.#. +#..#.#...# +...##.#..# +#.#......# +#..#.#.#.. +#..##....# +.####.#... +.#.#...#.. +..##..#..# +.#..#.#... + +Tile 1997: +.##.###... +......#..# +....#.#..# +..#.##...# +.....##..# +###.#.#... +##........ +#.....#... +##....#.## +######..## + +Tile 1481: +####.##### +##.#.....# +#.#....#.# +.......#.. +#........# +#....##... +...#..#..# +.#......## +....##...# +.######### + +Tile 1811: +..#..#.##. +.....#.#.. +..#...#... +##.....#.. +.#.#.....# +...#####.# +#...#.##.# +....#.#..# +....#.#... +#..#.##... + +Tile 3701: +####.###.# +###.....## +#...##.### +....###.#. +#.#.#..#.# +..###....# +.#...#...# +#.##..#... +####....## +.#####..## + +Tile 1451: +###.##.#.. +#...##.#.# +.#.......# +#.....#... +.#........ +#.......## +...##.#.#. +.#..##..## +#.#.#..... +....#....# + +Tile 3319: +....####.# +.#..#...## +..##.###.. +#...#..#.# +.#........ +......#... +........## +#.....#... +#......... +..##.##..# + +Tile 2659: +.##..#.#.. +#.#...##.. +.####..##. +.....##### +##........ +.#........ +#.#.#..... +.....##... +........## +..#....... + +Tile 1433: +#.##.##.## +.#.....#.. +....#.#... +.#..#.#### +....#.#..# +####...#.# +.#.#..#.#. +..#......# +.#.#.#.#.. +#.###.#.#. + +Tile 1409: +#..###.... +###....... +#...#..##. +#.##....## +..#...#..# +.#..##..## +..#..#...# +##..#.#### +#....##### +##..####.. + +Tile 1747: +...##.###. +##...##.#. +......#..# +#.#.....## +#..#....## +###.##.#.# +.......#.# +#...#....# +......#..# +##...####. + +Tile 2011: +.#.#..##.. +.......### +#.#.#...## +#...#.###. +......###. +....#.#... +....#.##.. +.##......# +##....###. +###.####.. + +Tile 1009: +.#.#...### +#.#.##..#. +.......... +.....#...# +.#...#..## +.#..#.#.## +#..####.## +#.##.#.#.# +..###....# +.##..#.... + +Tile 1759: +#.#######. +#..#....## +.......... +..###..#.# +#..###.... +#.######.. +...##.##.# +#......... +##.......# +#...#..### + +Tile 1223: +###..#.##. +##..##.... +...##..... +#..#.#..#. +#..##.#... +.#.......# +...#..#.#. +##.......# +##........ +.###.#...# + +Tile 2467: +.#.##.#.#. +#......... +##.....#.. +.##...#### +#..#..#..# +#.#...#... +........#. +##.......# +..#....### +##....#... + +Tile 1571: +...##.#.## +..#....... +.#.#..#..# +.......... +#.......#. +..#....#.# +#.###..... +...#..##.# +..##.#..## +####.....# + +Tile 1931: +###..#.##. +##.#..##.. +...##.##.# +........#. +.####...## +.......... +#.....#..# +#.....#..# +.#..###..# +.......##. + +Tile 2711: +#..#.#...# +#....####. +.#.#..##.# +#.#.#..### +......##.. +###...##.# +##..##.... +.....#..#. +##....##.# +.#...#.... + +Tile 3331: +...#.#.##. +.#......#. +##.#.....# +#..##....# +.........# +##....#.#. +#.#......# +#.......#. +##......## +..##..#### + +Tile 1979: +..##.#.##. +...#..###. +......#.#. +..#..#...# +#......... +#......... +..#.#...#. +#..#..#### +#...#....# +##.######. + +Tile 1229: +##.###.### +#....#.#.. +#....##... +#.....#... +#.#......# +##...#.... +.#...###.# +#..#.#..## +...#.#.... +.##...#.## + +Tile 1217: +#..#.#.... +.#....#..# +.#.....### +..#.#....# +##....#... +.#...##.## +.#..#.#.#. +.##..##... +.#....#..# +.#.#.#.#.# + +Tile 2521: +.....####. +#.#....#.. +..#..#...# +..#...#... +......#... +#.##..#..# +..#..##..# +.#..#....# +#..##..### +#.###.##.# + +Tile 2251: +#...#..### +...##.#.#. +#..#..##.. +##........ +#......... +......#.## +##.....#.. +..#.#...#. +###.#..... +.###..#.#. + +Tile 1093: +#####.#... +###.....#. +#.#.###..# +....##.... +###.....## +.#......#. +#......... +..#....... +....#..... +#.#.#.#... + +Tile 2293: +##..#.##.# +#...#....# +#..##..... +..#......# +#....#.... +.......#.. +##.....### +#....#.... +#...#..##. +########.. + +Tile 1279: +#.###.##.. +.......... +#...#....# +.....#...# +#....##### +#...#.#.#. +#..#..#..# +.......#.. +#.#...##.# +#####..#.. + +Tile 1213: +#...##.... +##.#.....# +#.....#... +#.......#. +#......... +#.#....... +#........# +#....#.... +.#..#....# +.##...##.. + +Tile 3851: +#.#...##.# +.........# +#.......#. +.#.#.#..#. +.##.....## +...##...#. +#.#...#..# +#.....#..# +.#.#...... +.#.#.##..# + +Tile 1531: +..##..#... +#....#.... +#...#.#..# +....##..#. +#..#..##.. +.##.###.## +#..#####.# +##.#.##... +#.#.##..#. +#..##.#### + +Tile 1321: +#.##.....# +###.#..... +#......... +.......#.# +#...##...# +.....###.# +..##...#.. +..#.#.##.# +####....## +.##...##.# + +Tile 1619: +.###..#### +#..##....# +#.....#... +......#... +#.......## +#....#.... +##..#..#.. +....#...#. +.#.....#.. +.#.#.##.## + +Tile 2803: +#.#.#..#.. +#...#..#.. +#####.#.#. +.##....#.# +......#..# +##..#.#..# +..#..#..#. +##......## +..#.##...# +.#.#....## + +Tile 2383: +.####.#..# +#..#..##.. +#..##.#..# +..##...#.# +##..#.##.. +.#........ +#.##..#... +#......#.. +#...#....# +##.##..#.# + +Tile 1291: +...#.#..## +##.#...... +....#.#.## +#.#.#...## +.#.##.#..# +##.#...#.. +#..#...... +#.#..#.... +#..####..# +##.....### + +Tile 1129: +#.#....##. +...#.#.#.. +.#.#.#...# +.#..#....# +.#.##....# +........#. +.##......# +...#.#.#.. +#.....##.. +.###..#... + +Tile 2857: +#.#.#.#### +...#.....# +..#.....#. +###.....#. +###...##.# +#..#.#...# +#.##.###.. +.####..### +#.##...... +..#..#.### + +Tile 2411: +......##.# +##..#....# +#.....#..# +#..#...... +.#...##..# +#.....##.. +###.#..### +#.#.#####. +#...#.#..# +.#.##.#.## + +Tile 3923: +..#####..# +#...#.#... +#...##.#.# +....#..... +.......... +#.##....#. +.........# +##.......# +#...#...## +###..##.## + +Tile 3343: +#..#.###.# +..#...##.# +..#...#... +#...#..... +..#....... +##.#..#... +...###..#. +#.#.#.#..# +...#..##.# +#..#...##. + +Tile 2017: +.#...###.. +.........# +.##....##. +....#...## +..###..... +##..##..#. +#..#.##..# +#.#..####. +##........ +..#.##.... + +Tile 3889: +#.##.##..# +.#....#.#. +.##...##.# +#..#.###.. +#..##.#... +#...##.#.. +.#....#.## +###.#.#..# +#..#...#.# +.#.#..##.. + +Tile 1823: +....##.##. +#...#...#. +..#......# +.......... +....###..# +####....#. +.##......# +...###.### +##....#... +#.#.##.... + +Tile 3769: +.#..#..... +...#.....# +#...#....# +..#..##... +.....#...# +....#..... +#...####.# +#..#.##..# +#..#....## +#######.#. + +Tile 1523: +.#.##....# +...#...#.# +#......... +.....##.#. +##.##..#.. +..#.##...# +#...#..##. +#....#.... +.#.#...#.. +#.#.###... + +Tile 2843: +...#....#. +......###. +..##....## +#.###.#..# +#..##.#... +#.##....#. +.....##... +.#.......# +##.#..#..# +#.##....#. + +Tile 2423: +#.##.##### +..#.#...#. +#.....#.#. +#..#.....# +..##..#..# +##....#..# +#......#.# +#.#..#.##. +#.....#... +.##.##.#.. + +Tile 1999: +.#..#.#### +.#.#..#... +.......... +...#.#.#.. +..#....#.# +##.#...#.. +.#..####.. +.....#.#.# +..#..#..## +##..#..#.. + +Tile 2341: +#....#.#.# +##.##....# +#..##.#... +#..#.#.... +...#..#.#. +##..##.### +#.#.....## +.......#.# +##.##..... +....#.#### + +Tile 3359: +#..###.##. +#......... +.####.###. +#.##....#. +.#..#.##.. +#......... +.#.#.#.... +..#...#..# +###......# +...#...... + +Tile 3863: +..##.##.#. +#.##..#.## +.###...... +.#.......# +..##...... +#..##..### +.##..##... +....#.#... +#.#.#.##.# +...##..##. + +Tile 3187: +#.#.#.#... +......###. +#.....#### +..#.#...#. +#....#..#. +#......#.. +#...##..#. +#........# +#.##.....# +.##.#...#. + +Tile 3119: +##.....##. +....#....# +#..#..#..# +#....##..# +........#. +...#.#.... +...##..#.. +.....#.... +#.####.... +...#..#.## + +Tile 1063: +.#.#.#.... +##........ +#..#.##... +#..#.....# +....##...# +.#......#. +..##...##. +#........# +.......... +.#..#..#.. + +Tile 1657: +.##.#.#... +##.....#.# +....#.#.#. +#....##### +###......# +.#....#..# +#.#..#.#.. +#.#.##.... +##.#...... +#..##.#... + +Tile 3257: +##.####..# +#.#.#####. +##.#..##.. +.##.#..### +..#....... +#...#.#..# +#..#.#.#.# +...#....## +##.....##. +...###..## + +Tile 1987: +.#.#..###. +.#.......# +...#....## +#...##.... +.......#.# +.#.##.#### +...#...#.. +.##...#... +.........# +.#.##..#.. + +Tile 1459: +#.....#### +......#..# +........#. +##..#..#.. +###.##.#.# +##..#...#. +##..#.###. +.##..###.# +#..####... +.#.#####.. + +Tile 3533: +#.##...#.. +.#.....#.. +#.##...... +..#.....## +....#..#.. +##..#....# +#....##..# +..#....#.. +........## +.####.##.# + +Tile 2789: +..####...# +#....###.. +#..#..##.# +#.#..#.... +#....##... +....#..... +#......... +#..#...... +.......#.# +...####.#. + +Tile 2137: +#..####.## +....##...# +.#.....#.. +#.#..##### +...#..#... +.#.....#.# +.....#..#. +##..#...## +..#.#..... +#..######. + +Tile 1181: +.#####.#.. +..#.##...# +#....#.... +#...#.#... +##.......# +.....#...# +##..#...#. +.##.##.... +#...##.... +..#.##.... + +Tile 1117: +#####.#### +.......#.. +##.#..#..# +#....#.#.. +.......... +..#...#.#. +......#... +##...#...# +....#...#. +#.....##.. + +Tile 3739: +..####.#.# +#.#.#.#... +#.......## +.##...#.#. +#....#.#.. +#...#....# +#.....##.# +.......##. +##...###.# +....##..## + +Tile 2909: +.##..###.. +#...#..... +.....#...# +..##...... +#.##.###.. +##.....#.# +#..#...### +....##.... +#......#.. +#.#...#### + +Tile 1609: +##.###.#.. +....#.#... +#.#....##. +#..##.#... +.####..#.# +.......... +##..#....# +...#..#... +#......... +....#.###. + +Tile 1753: +....#.###. +##.##..... +....##.... +#.....##.. +#.##..#... +.......... +#..#.#..#. +#.....#... +.#........ +.#.#...#.# + +Tile 2003: +#.#.####.# +#.##.#...# +####..#... +###..##... +###....... +#.....#... +..##...... +#....#..#. +#.###...#. +.#..#.###. + +Tile 1399: +#.#..##..# +....#.##.# +#..#.....# +#..#....## +#...#..#.. +#.#.#....# +......##.. +.##....... +.####.#### +...#...#.. + +Tile 1249: +..#..####. +#.##.....# +.......... +..#.....## +#.#..#...# +#..#...### +.....#.#.# +..###..#.# +.#...#..#. +.#...##.#. + +Tile 1289: +#########. +...#...... +.....##.#. +...#.#...# +#..#..#... +#....###.# +....#..#.. +.....##..# +.....#...# +.#.#####.# + +Tile 3373: +#...##..## +#..#....## +#..#...### +#......#.. +..#......# +.....#.... +#.#....... +.....#.##. +...#.#..## +..##.##... + +Tile 1613: +####...#.. +#.#....... +.......... +#....##### +#..#....## +...#..#... +.....#...# +.#......## +##....#..# +....#..### + +Tile 2029: +#..###.#.# +#.#..#...# +##...#.... +.#..#..#.. +...#...##. +##.....##. +..##...#.# +...##.#..# +#......... +.#.####.## + +Tile 2203: +..####.### +..##....## +...##..... +....#..#.# +..#...#.## +#.#....... +...###.... +#.....#..# +.........# +.###....#. + +Tile 1877: +##.....### +.....#..#. +....#...#. +##.#.....# +.#..##...# +##.#..##.. +..#...#... +#...##.... +#.#.#..... +.##..#.... + +Tile 3847: +...##.#... +.##.....## +#.#.#..##. +#.##..###. +.........# +..#...##.# +#...##..## +##..#.##.# +#..#.....# +#.##.#..#. + +Tile 1499: +..#.###### +#....##..# +##...#...# +...#.##.#. +##...#...# +....#....# +##.....#.# +#.....#... +.#....#..# +#.#.#..#.. + +Tile 3251: +.###.#.#.# +##....#### +##..#..... +#.#....#.. +...#..#.## +...#...... +#.#.##.... +......##.. +......#... +..#.##...# + +Tile 3323: +...#.#.... +........## +...#...... +#.......## +###.##..## +##.##....# +...#..#... +...###.### +##.....#.. +.###.##..# + +Tile 3109: +.#.#.#.### +######.#.. +......#... +##.#.#...# +.#...#..## +###...#.#. +....#..... +#....#..## +#...#.#... +.#....#### + +Tile 1889: +#..#.####. +#..##.##.. +...#....## +........## +#.#..##### +#......... +#.#.#..... +...###.#.. +#....#..#. +..###.#... + +Tile 2027: +#....##... +.##....#.. +#...#...## +#........# +#.....##.# +.#...#..## +#..#...### +....#..... +#..#...##. +##.#.##### + +Tile 2677: +#..###.#.# +##.#....#. +.##.###.## +#......... +#........# +.#.##.##.# +##...##..# +##......## +...#...... +#..####... + +Tile 1663: +.####.#.#. +#...#....# +###....##. +#..##.#.## +#.....#..# +.#..##.... +#....#.#.. +##........ +#..#...... +.##.##..## + +Tile 3559: +..###...#. +##........ +..#..#..#. +#......... +.#.#..##.# +##.#.....# +..#....... +#..##.#..# +###.#....# +.#..#..#.. + +Tile 3049: +.#.##...#. +#.......#. +#.##....#. +...#...#.# +.......... +####..#.#. +.##.##...# +...#..#.#. +....#....# +###.#.#.#. + +Tile 2777: +..#.#..##. +##..#...#. +.....##... +#.###...## +##...#..#. +.##......# +....#....# +##....#... +##.....#.. +###.##...# + +Tile 2551: +#.####.##. +#......... +#..##...## +..#......# +.......... +##...#..## +.........# +#.#......# +..#.....#. +...#.###.# + +Tile 3491: +#.##...### +#.#.#.#... +#.....#..# +#.....#... +##..#..##. +###......# +#......#.. +....#.##.# +#.##....## +####.#.#.# + +Tile 3947: +#.##.#.#.. +....#.#.## +...##....# +###......# +##.#..##.# +..#.#..#.. +#....#..#. +#...#....# +...#..#.## +###.##.#.. + +Tile 1361: +..#.#.#### +#..#..#.## +.#...#...# +.......... +..#......# +##........ +#.##.....# +.#.......# +#.#..#...# +#..##...#. + +Tile 2851: +.###.##... +#.....##.. +....##...# +........#. +#.#.###..# +#...#.#..# +##...#..## +...#..#... +##.......# +#####.#.## + +Tile 2381: +.#.####### +.#..#..##. +...#...... +#......### +#.#..#...# +..###..#.. +...#.#.#.. +#......#.. +..##.....# +..#.#.##.. + +Tile 1069: +.#.#...### +##..#.##.# +#.#..###.. +###...##.. +.#.#....#. +.........# +#..#...#.. +..#....##. +.#.#....## +#.....##.# + diff --git a/src/bin/day20.rs b/src/bin/day20.rs new file mode 100644 index 0000000..88af7ce --- /dev/null +++ b/src/bin/day20.rs @@ -0,0 +1,466 @@ +use std::collections::HashMap; + +const INPUT: &str = include_str!("../../data/day20/input"); + +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] +enum Side { + Top, + Right, + Bottom, + Left, +} + +impl Side { + fn opposite(self) -> Self { + match self { + Side::Top => Side::Bottom, + Side::Right => Side::Left, + Side::Bottom => Side::Top, + Side::Left => Side::Right, + } + } + + fn transform(self, width: usize, flip: bool, row: usize, col: usize) -> (usize, usize) { + let (row, col) = if flip { + (row, width - col - 1) + } else { + (row, col) + }; + let (row, col) = match self { + Side::Top => (row, col), + Side::Right => (col, width - row - 1), + Side::Bottom => (width - row - 1, width - col - 1), + Side::Left => (width - col - 1, row), + }; + (row, col) + } +} + +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] +struct Edge { + len: u32, + mask: u32, +} + +impl Edge { + fn new(bits: I) -> Self + where + I: IntoIterator, + { + let (len, mask) = bits.into_iter().fold((0u32, 0u32), |(len, mask), bit| { + (len+1, (mask << 1) + if bit { 1 } else { 0 }) + }); + Edge { len, mask } + } + + fn norm_dir(self) -> Self { + let rev_mask = self.mask.reverse_bits() >> (32 - self.len); + if self.mask < rev_mask { + Edge { len: self.len, mask: self.mask } + } else { + Edge { len: self.len, mask: rev_mask } + } + } +} + +impl std::fmt::Debug for Edge { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use std::fmt::Write; + f.write_char('"')?; + for ndx in 0..self.len { + let v = 0 != self.mask & (1 << ndx); + f.write_char(if v { '#' } else { '.' })?; + } + f.write_char('"') + } +} + +#[derive(Clone, Copy)] +struct Mask { + lines: [[bool; 20]; 3], +} + +impl Mask { + const EMPTY: Mask = Mask { lines: [[false; 20]; 3] }; + const DEFAULT: Mask = { + let mut lines = Self::EMPTY.lines; + lines[0][18] = true; + lines[1][0] = true; + lines[1][5] = true; + lines[1][6] = true; + lines[1][11] = true; + lines[1][12] = true; + lines[1][17] = true; + lines[1][18] = true; + lines[1][19] = true; + lines[2][1] = true; + lines[2][4] = true; + lines[2][7] = true; + lines[2][10] = true; + lines[2][13] = true; + lines[2][16] = true; + Self { lines } + }; + + fn _flip_y(self) -> Self { + let [a,b,c] = self.lines; + Self { lines: [c, b, a] } + } + + fn _flip_x(self) -> Self { + let [mut a, mut b, mut c] = self.lines; + a.reverse(); + b.reverse(); + c.reverse(); + Self { lines: [a, b, c] } + } + + fn all_masks() -> Vec { + let def = Self::DEFAULT; + let flip_x = def._flip_x(); + vec![ + def, + def._flip_y(), + flip_x, + flip_x._flip_y(), + ] + } + + fn matches_horizontal(&self, tile: &Tile, row: usize, col: usize) -> bool { + if row + 3 > tile.width || col + 20 > tile.width { + return false; + } + for y in 0..3 { + for x in 0..20 { + if self.lines[y][x] && !tile[(row+y, col+x)] { + return false; + } + } + } + true + } + + fn mark_horizontal(&self, tile: &mut Tile, row: usize, col: usize) { + for y in 0..3 { + for x in 0..20 { + if self.lines[y][x] { + tile[(row+y, col+x)] = true; + } + } + } + } + + fn matches_vertical(&self, tile: &Tile, row: usize, col: usize) -> bool { + if row + 20 > tile.width || col + 3 > tile.width { + return false; + } + for y in 0..3 { + for x in 0..20 { + if self.lines[y][x] && !tile[(row+x, col+y)] { + return false; + } + } + } + true + } + + fn mark_vertical(&self, tile: &mut Tile, row: usize, col: usize) { + for y in 0..3 { + for x in 0..20 { + if self.lines[y][x] { + tile[(row+x, col+y)] = true; + } + } + } + } +} + +impl std::fmt::Debug for Mask { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use std::fmt::Write; + f.write_char('\n')?; + for y in 0..3 { + for x in 0..20 { + f.write_char(if self.lines[y][x] { '#' } else { '.' })?; + } + f.write_char('\n')?; + } + Ok(()) + } +} + +#[derive(Clone, PartialEq, Eq, Hash)] +struct Tile { + width: usize, + data: Vec, +} + +impl Tile { + fn parse(block: &str) -> (u32, Self) { + let head_split = block.find(":\n").unwrap(); + let id = block[..head_split].strip_prefix("Tile ").unwrap().parse::().unwrap(); + let block = &block[head_split+2..]; + let first_line = block.lines().next().unwrap(); + let width = first_line.len(); + let data = block.lines() + .map(|l| { + assert_eq!(l.len(), width); + l.chars().map(|c| c == '#') + }) + .flatten().collect::>(); + assert_eq!(data.len(), width * width); + + (id, Self { width, data }) + } + + fn edge(&self, side: Side) -> Edge { + match side { + Side::Top => Edge::new(self.data[..self.width].iter().copied()), + Side::Bottom => Edge::new(self.data[self.width*(self.width-1)..].iter().copied()), + Side::Left => Edge::new((0..self.width).map(|n| self.data[n*self.width])), + Side::Right => Edge::new((0..self.width).map(|n| self.data[(n+1)*self.width-1])), + } + } + + // rotate/flip given previous sides to top and left + fn rotate(&self, top: Side, left: Side) -> Self { + let flip = match (top, left) { + (Side::Top, Side::Left) => false, + (Side::Top, Side::Right) => true, + (Side::Right, Side::Top) => false, + (Side::Right, Side::Bottom) => true, + (Side::Bottom, Side::Right) => false, + (Side::Bottom, Side::Left) => true, + (Side::Left, Side::Bottom) => false, + (Side::Left, Side::Top) => true, + _ => panic!("invalid rotation: {:?} -> Top and {:?} -> Left", top, left), + }; + let data = (0..self.width).map(|row| { + (0..self.width).map(move |col| { + let (row, col) = top.transform(self.width, flip, row, col); + self[(row, col)] + }) + }).flatten().collect(); + Self { width: self.width, data } + } + + fn find_monster(&self) -> Tile { + let mut marked = Self { width: self.width, data: self.data.iter().map(|_| false).collect() }; + let patterns = Mask::all_masks(); + for row in 0..self.width { + for col in 0..self.width { + for pattern in &patterns { + if pattern.matches_horizontal(self, row, col) { + pattern.mark_horizontal(&mut marked, row, col); + } + if pattern.matches_vertical(self, row, col) { + pattern.mark_vertical(&mut marked, row, col); + } + } + } + } + marked + } +} + +impl std::ops::Index<(usize, usize)> for Tile { + type Output = bool; + + fn index(&self, (row, col): (usize, usize)) -> &Self::Output { + assert!(col <= self.width); + &self.data[row * self.width + col] + } +} + +impl std::ops::IndexMut<(usize, usize)> for Tile { + fn index_mut(&mut self, (row, col): (usize, usize)) -> &mut Self::Output { + assert!(col <= self.width); + &mut self.data[row * self.width + col] + } +} + +impl std::fmt::Debug for Tile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use std::fmt::Write; + f.write_char('\n')?; + for y in 0..self.width { + for x in 0..self.width { + f.write_char(if self[(y, x)] { '#' } else { '.' })?; + } + f.write_char('\n')?; + } + Ok(()) + } +} + +#[derive(Clone, PartialEq, Eq, Debug)] +struct TileDetailed { + tile: Tile, + edge_to_side: HashMap, + side_to_edge: HashMap, +} + +impl TileDetailed { + fn edge(&self, side: Side) -> Edge { + *self.side_to_edge.get(&side).unwrap() + } + + fn parse(block: &str) -> (u32, Self) { + let (id, tile) = Tile::parse(block); + + let edges = vec![ + (Side::Top, tile.edge(Side::Top).norm_dir()), + (Side::Right, tile.edge(Side::Right).norm_dir()), + (Side::Bottom, tile.edge(Side::Bottom).norm_dir()), + (Side::Left, tile.edge(Side::Left).norm_dir()), + ]; + let edge_to_side = edges.iter().map(|&(side, edge)| (edge, side)).collect(); + let side_to_edge = edges.into_iter().collect(); + + (id, Self { tile, edge_to_side, side_to_edge }) + } +} + +#[derive(Clone, Copy, Debug)] +struct TilePlacement { + tile: u32, + top_side: Side, + bottom_edge: Edge, + left_side: Side, + right_edge: Edge, +} + +fn main() { + let tiles: HashMap = INPUT.trim().split("\n\n").map(TileDetailed::parse).collect(); + let mut edges: HashMap> = HashMap::new(); + for (&id, tile) in &tiles { + for (&side, &edge) in &tile.side_to_edge { + edges.entry(edge).or_default().push((id, side)); + } + } + let single_edges = edges.iter().filter_map(|(_edge, id_sides)| { + if id_sides.len() == 1 { + Some(id_sides[0]) + } else { + assert!(id_sides.len() == 2); + None + } + }).collect::>(); + let mut single_edges_per_tile = HashMap::>::new(); + for &(tile_id, side) in &single_edges { + single_edges_per_tile.entry(tile_id).or_default().push(side); + } + let corners = single_edges_per_tile.iter().filter_map(|(&tile_id, sides)| { + if sides.len() == 2 { + Some(tile_id) + } else { + None + } + }).collect::>(); + let corners_prod = corners.iter().map(|&tile_id| tile_id as u64).product::(); + println!("Product of corner tile ids: {}", corners_prod); + + let mut grid_tiles: [[Option; 12]; 12] = [[None; 12]; 12]; + for row in 0..12 { + if row == 0 { + // orient top left tile + let tile: u32 = corners.iter().copied().min().unwrap(); + let top_side: Side = *single_edges_per_tile.get(&tile).unwrap().iter().min().unwrap(); + let bottom_edge = tiles.get(&tile).unwrap().edge(top_side.opposite()); + let left_side: Side = *single_edges_per_tile.get(&tile).unwrap().iter().max().unwrap(); + let right_edge = tiles.get(&tile).unwrap().edge(left_side.opposite()); + grid_tiles[0][0] = Some(TilePlacement { tile, top_side, bottom_edge, left_side, right_edge }); + } else { + // left column; look at tile above + let tile_top = grid_tiles[row-1][0].unwrap().tile; + let top_edge = grid_tiles[row-1][0].unwrap().bottom_edge; + let (tile, top_side) = edges.get(&top_edge).unwrap().iter().filter_map(|&(tile_id, side)| { + if tile_id != tile_top { + Some((tile_id, side)) + } else { + None + } + }).next().unwrap(); + let bottom_side = top_side.opposite(); + let left_side = *single_edges_per_tile.get(&tile).unwrap().iter().filter(|&&side| side != bottom_side).next().unwrap(); + assert_ne!(top_side, left_side); + assert_ne!(top_side, left_side.opposite()); + let bottom_edge = tiles.get(&tile).unwrap().edge(top_side.opposite()); + let right_edge = tiles.get(&tile).unwrap().edge(left_side.opposite()); + grid_tiles[row][0] = Some(TilePlacement { tile, top_side, bottom_edge, left_side, right_edge }); + } + // complete row + for col in 1..12 { + // look at tile to the left + let tile_left = grid_tiles[row][col-1].unwrap().tile; + let left_edge = grid_tiles[row][col-1].unwrap().right_edge; + let (tile, left_side) = edges.get(&left_edge).unwrap().iter().filter_map(|&(tile_id, side)| { + if tile_id != tile_left { + Some((tile_id, side)) + } else { + None + } + }).next().unwrap(); + let right_edge = tiles.get(&tile).unwrap().edge(left_side.opposite()); + let top_side; + if row == 0 { + if col == 11 { + // top right corner + let right_side = left_side.opposite(); + top_side = *single_edges_per_tile.get(&tile).unwrap().iter().filter(|&&side| side != right_side).next().unwrap(); + } else { + top_side = *single_edges_per_tile.get(&tile).unwrap().iter().next().unwrap(); + } + } else { + let tile_top = grid_tiles[row-1][col].unwrap().tile; + let top_edge = grid_tiles[row-1][col].unwrap().bottom_edge; + top_side = edges.get(&top_edge).unwrap().iter().filter_map(|&(tile_id, side)| { + if tile_id != tile_top { + assert_eq!(tile, tile_id); + Some(side) + } else { + None + } + }).next().unwrap(); + } + assert_ne!(left_side, top_side); + assert_ne!(left_side, top_side.opposite()); + let bottom_edge = tiles.get(&tile).unwrap().edge(top_side.opposite()); + grid_tiles[row][col] = Some(TilePlacement { tile, top_side, bottom_edge, left_side, right_edge }); + } + } + + let mut rotated_tiles = Vec::new(); + let mut picture = Tile { width: 12 * 8, data: Vec::new() }; + picture.data.resize(picture.width * picture.width, false); + for row in 0..12 { + rotated_tiles.push(Vec::new()); + for col in 0..12 { + let tp = grid_tiles[row][col].unwrap(); + let tile = tiles.get(&tp.tile).unwrap().tile.rotate(tp.top_side, tp.left_side); + rotated_tiles[row].push(tile.clone()); + assert_eq!(rotated_tiles[row][col], tile); + + // check edges + if row > 0 { + assert_eq!(rotated_tiles[row-1][col].edge(Side::Bottom), tile.edge(Side::Top)); + } + if col > 0 { + assert_eq!(rotated_tiles[row][col-1].edge(Side::Right), tile.edge(Side::Left)); + } + + // assemble full picture + for y in 0..tile.width-2 { + for x in 0..tile.width-2 { + picture[(row*8+y, col*8+x)] = tile[(y+1, x+1)]; + } + } + } + } + println!("{:?}", picture); + let monsters = picture.find_monster(); + println!("{:?}", monsters); + let sea_count = picture.data.iter().filter(|&&v| v).count(); + let monster_count = monsters.data.iter().filter(|&&v| v).count(); + println!("Roughness: {}", sea_count - monster_count); +}