Compare commits
10 Commits
e413a13b3c
...
f261ffced5
| Author | SHA1 | Date | |
|---|---|---|---|
| f261ffced5 | |||
| 776538165b | |||
| 50477e7c7e | |||
| 00d1661672 | |||
| 13d65c6a86 | |||
| 2143563b80 | |||
| 2e495f674c | |||
| 87cfe7a587 | |||
| c59575aa99 | |||
| 4db9c115f6 |
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -8,6 +8,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"priority-queue",
|
||||
"sorted-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -47,3 +48,9 @@ dependencies = [
|
||||
"autocfg",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sorted-vec"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da8edb37c24177a4d09d502f3755ef679986654742af1a50a6e4f9b68108d366"
|
||||
|
||||
@ -9,4 +9,4 @@ edition = "2018"
|
||||
[dependencies]
|
||||
arrayvec = "0.7.2"
|
||||
priority-queue = "1.2.1"
|
||||
|
||||
sorted-vec = "0.8.0"
|
||||
|
||||
102
input/20.txt
Normal file
102
input/20.txt
Normal file
@ -0,0 +1,102 @@
|
||||
#..###.##....#.#.#...#.#.#...##...####......##.##..###...#.####..#..#..#####..#.##.....#..#.###.##...#.#.....#...##.##.##...#####.#.#.#.##.###.#.##..#.##.##.#..#...####.#.#.....#..#.....###.#..#.#.#.#...#.###..#.###..##.#..#...##...####.#.........###..#.##.#..#.#...##.#.#.##.####.###....#####..###...##..#####..###..##..#.#.#..###.##.###..#.#######.####..#....###.##...#.####..#.#######...###...##.##.###...##..#.....#.###....#..#.#..###.#...#######.#...##..#.#..##.#...##.#..##.##..#...#.#.##.####........#..#.
|
||||
|
||||
#.###...#..#...###..#..#.#....#####.#...#..#####...#.##...#....#.#.#..#.#.........#..##..#..#.#..#..
|
||||
###.#..##.#.##.#......#.###.##..###.#..#.###..####.#...#.....#...#.#.#..#######..#.#.##.#.#####..###
|
||||
.....##...#..#.#..#....###.##..######.#..#.###.###.###.#.#.##.####.#..#.#....##..#.##.#.........#.#.
|
||||
.#####...##...###..####.##.##.#..###.#.#..##..###...##.#..#...###.###.#.##.#.#....##.#.##.#.#..##.#.
|
||||
..#.....#####.#.###.###..#..##.##...#######.#...#...#.##.#.###....#.....####..#.....##.#####.###..##
|
||||
.###.#####.#..#...#.#....####.#..###.##...##..#..##..#........###..#..###....###.#.#..##..#...#.#..#
|
||||
##.##.#.##.#...###.###.###....#...##.#.#..#.##...#..#.#.#..####.#.###....#.##.#.##.#..#.#.....###.#.
|
||||
..#..#.###..##..#####.##.#.#..#..##...##..#..##..##....###..#.###..##..#.#..#..#..#.##.#..##.##.....
|
||||
###.#.#.#...#.#...#.###..#.###....##..#.##.###.....###.#..#..#####.##.#.##..#..##..###.###..###....#
|
||||
###......##.##..#.......####...##.#......#.#.....#..#.#.###........##.#.####.#.#.##...#..###.#.#....
|
||||
.##.##...#.#..#...#####.#####..#.......##..##.#.....####.###.#..#...##.#.###.#..##.##..####..#..##.#
|
||||
.#...#.#.#.#....###......##.....#...##...###...##....#..##.#..##.#.##.#...##.#.#.......##.#....#.#.#
|
||||
#..#....####...#.#.#.####...###.###.######..#.#...##.#...#.##......#.#...#.#.###.#.#.#..####..#.#...
|
||||
..#..##....##.##...###..###.#...#.#...#.##..#..#.#.####..#...#..#.#.##....#....#.##..#.#..#.#....#.#
|
||||
.#.#.########.##.#....##.#..###....#.#.###.#...##....###......##########.#..#.#.####...#..##...#..##
|
||||
#..##..#..#.#.#####..#####...#.###..####..##.#.#.####.#..#.#..####......#..#..##....##...#..###.#.##
|
||||
..###.#.#.##.##.#.#...###.#..#....####..###.##..##.#..##....###.#####.#..#...###.#.#..##...#...#####
|
||||
#.##.##.#..##.###.#.#.##..#...#...###..#..##.#..##....#####...#.#.#.##...####.##....#.#.##.#.##.#...
|
||||
##...##.#.###.####.##......##...#..#..#.....##..##..#.###.#..##.#.##.##..#..####.#########...##..#..
|
||||
.###..#.#..##..##..#..#...#.#..###.....#.#####..##.####...#.#...######.........####...........#..#.#
|
||||
#..#...##.#.##...##..##..........#..#...#..#..#.#..#.........######..####.#.##...##.##.##.....##..##
|
||||
#..##.#.###..##..####.#..######....#....####...##.#.#.#.#..#.##..#..#..###..#.#.#.#.#....#..##.#.#..
|
||||
.....##.......#.#.##.......##.##.#..###...###....##.###....##.#.####.###.##..##.#..##...###........#
|
||||
##..##....#.###..###.##.....##.#...##....##..#....#....###...#..#...###..#.####....#.......##.....##
|
||||
#..#..#.#..#...##.#.##.##...#.#.##..##..#.##..#.#...#...#.###.####..#....#####...#.###.##.####..#.##
|
||||
..##..##....####..#...###.############.##.#.##.####.#..#.##.#..##....#####..#.#####...###.#..#.##...
|
||||
...#.##.#.###.....###.#.#...##.#.#.##.##.#..##.#.##.#.##.#..#.###...#####.#..#.#..##...#.####..##..#
|
||||
#.#.###.####..#.#.###...##...###..#......#..##.....###.....#.##...##.#..#.#.####.#..#.#.#.##.####.##
|
||||
.###...####..##..#..###.#.#.#.##..##.##.#..#..##.##.#..#....#.#.###...#...#....##..##.#.##.######.##
|
||||
###.##....##.#.####..#########.....#.###...######.#.#....#...##...####.##.#.#.#####.....##....#.#.##
|
||||
######.#..#......#......###.##.#.###.#####..#.###.......####.#.###.#.#.##.##.....####...#..#.#.#####
|
||||
....##.#.#.#.##..##.###..#.###.##.##..###..#..#####.#####........#..##.#..##........#.##..#..#..#...
|
||||
.###..###.##.###.#.##.####.##.#.#...####.#..#.######.#.#####.#......#####.##..##.#.#.#.##.#..###.#.#
|
||||
#.##....###...#.....#..##.##.##.#..#.#..#.#.#...##..####.#..#.......####.###.#.####..#.#..##..##.#..
|
||||
##.#########..#....#....##...##.###..##.......####...####.#..#...###..##..##.#.#####..##.#....#..###
|
||||
..#..#####..####.####...#..#.#...####...#..###..#...#...########..#.#.#..###....####.....###.##...#.
|
||||
##.###.##..###.#.#..#..#.####...#.#...###..##...#.###.....##.#.#.#.##.#.#...###..###.###..#.#..#.#.#
|
||||
#.##..#.##..##.##...#.##.....##.#..#..###.##..##.#.##..#####..#####.###.##..###...#.#.#.##.##...###.
|
||||
..#.##.###.##.###.##.##.##......###..#.##.#..#...##.##.###..#..###.#......#.#..##..#.#..#####.......
|
||||
..##.#.###.###.###.##..####.#..####.#.##.#..#.######.#..##.#.#.#...#######.##..###..####.##..#..###.
|
||||
.####.##...#.#..#...##..#.#....#.#.##.##.#.#.#..##.#.#......####....###.####..#######.##.#....#.#.#.
|
||||
###.#.##.......#...###...##.#.##.##...#..#.#..###.####.#.###.#.#.##.#.#.###....#....#.#....#..#.#..#
|
||||
.#......#...#.#...#.##.#.###...#...##...#.###.#..#..#...#.#.#.###.##...###..##..###..#.#.##.#...####
|
||||
##.##...##..##...##..#...###...###..##.##.#......#..###.....##..#.#.#####...#######.#.####.#........
|
||||
#..#.....##..##.#.##..#.####......###..#...#.###.######..#.###..#.##..#.#....###..#..########..#.#..
|
||||
##.#..#......###.#.##....#.#...##...##.#..##......###..####.###.###.#.....#...##....#####.###..##..#
|
||||
###.......#.#.##....##..#.#..####.#.#..#.#..#...###.#.#.###.#####...####.#..#.##..#.....#.#.....#...
|
||||
.##.#..###....#.#####..###...##.#...####.###...#.######.#..###...#...#######.#.##.#....##.#.##...###
|
||||
#....#..#.#.#####..###.##..#.####..##.#.#....#.#.##.....##...#..#.###.#...#....#..#....###.#..#.###.
|
||||
#..#.#######.##..#.#..#.##..#######..####....#.#.###..###......###.####.#.....##..#.##.#.....###..##
|
||||
.###.#..##.......###..#.##....#......#.##..#.##..##.####.....###.#...#.#..##....#.#.###.###.#.#.##.#
|
||||
...#####.#.###....#..#.....###.#.....#..#..#..###...###.###..#....#####.#.###..#.....#..######....#.
|
||||
#..####...#...##..##.####..###.....##.###..#.###.#.#.##..#..#####...##.#...##.#..##.##.##.#....#....
|
||||
#...#.####......#.##..##.#.##.#.#####..#######.##.##.#.#.......#.#.#...##.####.###..#..#....#####.##
|
||||
..##...###...##.#..##..#...##.#.......#..#...#.#....#.###..##.#.###..##.#..####.######..#..#.##.#..#
|
||||
.##.....#.##..#..##......###.###.#......####..####.#.#.#...#..#..#..###..#..#...#.####.#.##..###.###
|
||||
........###.####...#...##..##..#.###..##..##.#...#..##.##....###.##.#.#..###.#.####....##..#.####.##
|
||||
.#..#...###.##.#....#.#.##...#..##..#.##...#...#.######.##.##.#####....##.###..####.....#.#..#...#.#
|
||||
#.#....##....#.######.##..#...##.##.#..#..#.#...#.##..##....###.#.#.#.#.#.######...##..###.#.##...#.
|
||||
..#....####.#.#############.####...#####......####.##.##.##..#..##.#....####..####.#..####.#.#..#.##
|
||||
#.##.#..#..####...#######....#...####.#..####....#####..##..#######..#.#....##.......#.#..#..####.#.
|
||||
#.#..#.#.#...####..#.....####.#...###...###.#.##.##.#.##.#........#.##..##.###.##.......#.###.....##
|
||||
..#.#.###.#.###.#.....###.#...##...#..#.....###.#..#..#..#...##..#..#.##..#..#.#.##..##.....#...##..
|
||||
..##.###.##.##..##.##.####..##..#.#.##.##.#...##...##....###..##...#..###.##.##.....###.#.##.##.#.##
|
||||
#.####...##.###..####...#.##.#####.#....#.#..#.....#......##..##.######...#....####...#..#.#..#..#.#
|
||||
.###..#.#.##.#.....###.#..#..#..#...####.#.####.#...###.##....###..##.##..#.##.#...#.#.#...####..##.
|
||||
##..##..####.####.#.##.#.#..####..##.######.###...##.##..#.#####.###..##...#.....##.##..#..###..####
|
||||
#..##.####.#.#.#####.....##.####..##..###...##...##...##....#.#.#...######...#...........##..###.##.
|
||||
...###.##...#.#.##...####...#..#.######.####.##.##.#....#.#.###..#.##...###.#...##.....##...###..##.
|
||||
.....#.###.##.....##.###.#.#..###..##..#..#.#.###..####......#.#####..##.####..###..##.#######.##.##
|
||||
#...#..#...##..#...####.##...#.#..##.......#.#...#.##.####.....#########...##....####.......#.###.##
|
||||
.#.....#.....####...#####..###.#.........##..##.##.#...#.#..#.#.#.#.#.###.#####..####..#......##.#.#
|
||||
#..#..###.#..#######.#..###.##..#..##.#..#..#.##.###.#..###.###..........#.###.#####.#.##.#.#...##..
|
||||
.##..###.#.#####.##.####.#.#..#..###....##.#.#..###.#.##..#.#..###..##.#.##.....#.#.#.#.#.####.#.##.
|
||||
..##.###...#....##.##.#####.##....#..##.######....###..#.#.##.###.#.......######.#..#..#..###.##....
|
||||
#.#..#.##.###...#..#####.##.#.###.#.###.......#######....#.####...####.##..#.#.###.##..#..#..###..#.
|
||||
#......#.##.##....##.#..#.#....##..#.###.....#.##...#.#..#...##.####......##..#.#.#...#...#.....#.##
|
||||
#....##.#.##.#.......#.##.#.###..#...###.#.###.##......#..#####..##.#..#....######.##.#..#...##..##.
|
||||
######.#.....#.#..##.##.....##.#..####.###..#.#.###....#..###..#..##.#..#.###..#.##...####....#.#...
|
||||
#.#..###..#####..#....#.#...##....###..##....#.##.#......#.#.###.....#.#.#..#.#..###.#....####......
|
||||
#..#.###.###.#.#.#..#.##..#.#.###.#...........#.#...#.##..#....##..#.#.##..##.#...##..#.##.##.#..#.#
|
||||
#.....#..#.#..##.##.######.#######....###.###...#####..#.....#..##.#.##.#.###...#..##.....###...#...
|
||||
#####.#.#..#.#.##..#.####.#...###.##.#....##.##.####.#...####.##.#...####..#..#.####.###....###.....
|
||||
#...#.......##.#...#..####...#.#..#.##.###..#.#.#.##...#.###......##....########..##.####.##.####.##
|
||||
#..#...##.###....##.##.#.##.##..#.#.#...###..#.#........###########.##..###.###.#..#....#.###....##.
|
||||
.#.#..##..##.##.#....##....###.##..###..#.###.#.###.#.###..######..###...####.....#.#...#.#.#..##.#.
|
||||
##...#..######.#.#...#.##....#...#..#..#.##.######.#..#..#.#...##..#..#...###..###.#.#......#....#.#
|
||||
.#.......#...#..#####.#####.#########..#......#..#.#.##.#.#.##.#.#.........####.##.#.###...#.##..#..
|
||||
..###.#.....###..#..#.#..#.#..####..###.....#.####.##...#.#..#.#.#.#.#.#..###..#......#..#####.#.#..
|
||||
#...#....###..####...#.##.#......###.#.##.###.#..###..##....##....#..#.....#...###.##.#......#..####
|
||||
#.####....######.####.#.####..#.#..#..#...####..#.#####..#..##.##..#.##...###...###.#.#..###.#.##.#.
|
||||
.####.###.#.##...###........#...##.#.#.######..#...##.###.##..#.#.######.#####..###....##...##.##...
|
||||
#.###.#.###..#.#.##..####.##..#...###...####..#..####.#.######.#####..#.##.##.##.##..#.#.##..#.##...
|
||||
.#.......#....##..#.#.##.#.#.##..###..#..##.....####.#...###....##.##......#....#.......#...##.##...
|
||||
.####.###..####.#.##..#.#.#..#...#..#.##.###..######.##.##.#.####.##.##.#..#..##..######.####..#..##
|
||||
#.###.##..#.#......##.#...#..#..#.##.#....##.....#......#..#...#..##....#.#####..####.#.#..#..##.##.
|
||||
#.#....#.#.#....#.#####.......#..#..#..#.##...#.#########..##..##...####.##..##.##.##..#.##...#.#.##
|
||||
.####....#..#.####.###.#.##########.###.#...#..##.##.#.####.##.###.##.#..#..#.##.##....###.#...##.#.
|
||||
...####.#.......#......#.######.#.##...###....####.##...##...##.#..#.##..##......#...####.#..##...##
|
||||
.#####...#....#....##.#.####....###..#.##...#.##..##..###.#.##.##.##...#.###..###.###...###...##.#..
|
||||
2
input/21.txt
Normal file
2
input/21.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Player 1 starting position: 7
|
||||
Player 2 starting position: 8
|
||||
420
input/22.txt
Normal file
420
input/22.txt
Normal file
@ -0,0 +1,420 @@
|
||||
on x=-8..36,y=-13..38,z=-30..18
|
||||
on x=-21..27,y=-43..1,z=-28..20
|
||||
on x=-43..8,y=-35..16,z=-21..29
|
||||
on x=-14..33,y=1..46,z=-33..20
|
||||
on x=-20..24,y=-32..18,z=-44..3
|
||||
on x=-31..13,y=-24..24,z=-13..41
|
||||
on x=-34..17,y=-24..25,z=-32..21
|
||||
on x=-21..29,y=-40..14,z=-34..19
|
||||
on x=-11..41,y=-46..3,z=-22..25
|
||||
on x=-13..41,y=-20..32,z=-26..21
|
||||
off x=34..48,y=-8..6,z=-47..-32
|
||||
on x=-36..16,y=-25..29,z=-42..10
|
||||
off x=-27..-10,y=20..38,z=-32..-15
|
||||
on x=-43..7,y=-3..46,z=-13..41
|
||||
off x=-21..-10,y=-5..7,z=-34..-24
|
||||
on x=-47..2,y=-26..19,z=-30..19
|
||||
off x=2..18,y=39..48,z=34..49
|
||||
on x=-29..21,y=-28..19,z=-14..39
|
||||
off x=-12..1,y=-15..-6,z=-12..5
|
||||
on x=-33..11,y=-5..40,z=-19..34
|
||||
on x=4839..37119,y=-77870..-65928,z=-31721..6883
|
||||
on x=-65074..-45532,y=-76161..-55995,z=18422..28809
|
||||
on x=-19046..7513,y=65962..85040,z=-50719..-38025
|
||||
on x=31203..42162,y=42926..64021,z=25628..44570
|
||||
on x=-23080..-9369,y=20501..49221,z=70364..78911
|
||||
on x=11385..44807,y=56888..76379,z=2197..23866
|
||||
on x=17447..25479,y=-59366..-48603,z=-63221..-43855
|
||||
on x=34953..56079,y=-72829..-39611,z=24187..47582
|
||||
on x=3553..21317,y=-69977..-55642,z=38791..44119
|
||||
on x=-57043..-43446,y=-62985..-45094,z=-46766..-23033
|
||||
on x=-66953..-46125,y=7548..20111,z=36275..67691
|
||||
on x=48156..52160,y=-57159..-48177,z=-27750..-17451
|
||||
on x=-8199..9720,y=-71971..-52302,z=33698..55920
|
||||
on x=-26740..-21116,y=-47606..-32902,z=-83414..-51593
|
||||
on x=35163..49358,y=-57959..-36064,z=29918..57157
|
||||
on x=-7610..15882,y=31069..43205,z=50534..76280
|
||||
on x=-38397..-8880,y=50925..60954,z=38695..68136
|
||||
on x=-22971..3262,y=63662..94550,z=-23890..-3669
|
||||
on x=56919..85184,y=-24246..-10978,z=-45500..-14062
|
||||
on x=70576..93606,y=-3591..16458,z=12386..39202
|
||||
on x=-40810..-32824,y=46441..70619,z=-50354..-41110
|
||||
on x=-44090..-21796,y=-49222..-29203,z=-78625..-53659
|
||||
on x=4179..22689,y=62208..95078,z=-32906..-2773
|
||||
on x=41435..58226,y=-69091..-52534,z=11220..22466
|
||||
on x=44027..56489,y=-61228..-40839,z=24716..49802
|
||||
on x=58856..89381,y=-24787..-6210,z=-38387..-21495
|
||||
on x=31249..66391,y=-338..29577,z=-73616..-43844
|
||||
on x=-69236..-35435,y=-56932..-41334,z=10510..37433
|
||||
on x=-30489..7293,y=23785..50236,z=-75453..-69050
|
||||
on x=-44614..-24138,y=-14044..4035,z=-80479..-57806
|
||||
on x=75190..96327,y=-32..21796,z=-19982..654
|
||||
on x=-57769..-43737,y=-43364..-27692,z=26689..48069
|
||||
on x=-33705..-1437,y=-50304..-33797,z=-65845..-40680
|
||||
on x=-78406..-40654,y=42549..59337,z=-28001..-11767
|
||||
on x=63318..88223,y=-16500..-422,z=7937..12185
|
||||
on x=-86159..-71499,y=10841..35268,z=-23323..5521
|
||||
on x=-69927..-48219,y=-54626..-22479,z=-44943..-15579
|
||||
on x=-43768..-13251,y=-64205..-52022,z=-49650..-31322
|
||||
on x=-66574..-54884,y=17683..44711,z=31164..56138
|
||||
on x=72035..82108,y=-3813..10230,z=-2284..15893
|
||||
on x=37334..58441,y=51079..61499,z=18464..27016
|
||||
on x=-32585..-16545,y=55965..89671,z=8302..34498
|
||||
on x=-26529..3377,y=-29123..-20453,z=56842..83561
|
||||
on x=32146..54092,y=-35416..-9066,z=51048..69716
|
||||
on x=-25194..7525,y=-78242..-62921,z=-50241..-35907
|
||||
on x=51949..62077,y=39590..56347,z=-31891..-19806
|
||||
on x=2190..18191,y=-26549..-4898,z=68835..81165
|
||||
on x=37501..59670,y=-54043..-24397,z=18589..44711
|
||||
on x=53124..84011,y=-37865..-20884,z=12749..28642
|
||||
on x=11469..29443,y=-87115..-71637,z=16152..46608
|
||||
on x=-11034..2944,y=3487..21169,z=74689..82882
|
||||
on x=19100..25746,y=-61128..-36379,z=43441..71029
|
||||
on x=5600..38744,y=-7945..6683,z=66027..94407
|
||||
on x=68461..75284,y=8717..26700,z=15336..51188
|
||||
on x=-61283..-47763,y=2607..39967,z=37842..70865
|
||||
on x=-45729..-24681,y=-21605..549,z=63515..88818
|
||||
on x=25798..44610,y=47822..73500,z=-60521..-23985
|
||||
on x=-95305..-75665,y=-26118..-5350,z=-12906..15434
|
||||
on x=33757..57435,y=42302..67655,z=-54184..-23134
|
||||
on x=2994..22115,y=-88253..-58648,z=28386..48449
|
||||
on x=-62548..-49059,y=-15737..4824,z=41511..53585
|
||||
on x=67083..78970,y=4211..28190,z=-48739..-19705
|
||||
on x=-78667..-54791,y=-46045..-26836,z=24727..53046
|
||||
on x=54721..85885,y=-8372..21818,z=29648..43363
|
||||
on x=69627..90635,y=-20694..-18387,z=7933..32742
|
||||
on x=-65893..-37568,y=-11991..15161,z=-65829..-60748
|
||||
on x=-57395..-46236,y=-2048..13172,z=-70802..-56233
|
||||
on x=-22043..3715,y=57559..88108,z=-45280..-34414
|
||||
on x=-74828..-53038,y=46478..58430,z=-19255..10363
|
||||
on x=13806..37110,y=33798..59217,z=-64375..-61548
|
||||
on x=61..4442,y=-14980..13830,z=-81808..-73388
|
||||
on x=-44428..-22458,y=-30625..-10622,z=-66261..-46437
|
||||
on x=61389..79075,y=-55043..-35044,z=-31620..-5849
|
||||
on x=1257..22335,y=-92002..-65926,z=23483..35032
|
||||
on x=-66071..-40860,y=-871..30120,z=47036..74284
|
||||
on x=18446..32639,y=-16466..3221,z=-89695..-56843
|
||||
on x=-4829..18965,y=-25609..-3292,z=-83328..-71836
|
||||
on x=-51528..-12497,y=-36433..-10612,z=67126..82588
|
||||
on x=-56346..-40152,y=3846..23474,z=44670..66145
|
||||
on x=-31862..-23691,y=-90559..-67842,z=-35278..-9721
|
||||
on x=-82636..-55468,y=7393..29473,z=20855..53140
|
||||
on x=-23503..-10904,y=-71671..-43413,z=39526..74530
|
||||
on x=-24286..-10051,y=42535..69016,z=47293..59326
|
||||
on x=27107..36075,y=-68197..-63740,z=-38325..-23137
|
||||
on x=49700..61611,y=-63668..-46517,z=-32392..-27815
|
||||
on x=8270..28696,y=50213..72279,z=-43392..-25307
|
||||
on x=39641..61962,y=-20666..-417,z=-81881..-48826
|
||||
on x=12571..33176,y=-14528..8290,z=-89384..-70716
|
||||
on x=-43871..-13117,y=-39900..-7197,z=59502..90659
|
||||
on x=-36035..-2433,y=65658..84996,z=-33491..-14374
|
||||
on x=63543..80825,y=-6748..-2651,z=-58258..-19329
|
||||
on x=28713..46264,y=3886..14439,z=-90710..-60973
|
||||
on x=-22187..2425,y=54328..74307,z=28523..62729
|
||||
on x=-44284..-19454,y=-77265..-62483,z=-24166..4845
|
||||
on x=-3490..10486,y=-85697..-76511,z=5917..20496
|
||||
on x=-24962..2419,y=11207..27000,z=61253..96386
|
||||
on x=52442..59482,y=-41524..-22315,z=-68202..-48780
|
||||
on x=-34407..5096,y=-92571..-67584,z=-35286..-2042
|
||||
on x=11100..17929,y=-19300..4676,z=58434..88671
|
||||
on x=60823..86913,y=-1593..13586,z=-3558..26423
|
||||
on x=-54273..-37709,y=28937..38483,z=-62444..-46473
|
||||
on x=-3663..6115,y=-67350..-58585,z=-59265..-39858
|
||||
on x=-33708..-26120,y=62411..80951,z=-50679..-28890
|
||||
on x=54088..78257,y=-30377..5547,z=-54962..-42452
|
||||
on x=-51040..-15145,y=-75083..-71823,z=-7664..22918
|
||||
on x=-48121..-39943,y=59649..86399,z=-19305..14422
|
||||
on x=19442..39564,y=65372..89430,z=-9881..23180
|
||||
on x=-5638..-504,y=51726..81303,z=34865..52668
|
||||
on x=51177..68510,y=-55462..-49393,z=-1676..34025
|
||||
on x=-39225..-13934,y=-44638..-21274,z=-69663..-61721
|
||||
on x=-34256..-22300,y=-79410..-50706,z=18119..42580
|
||||
on x=28326..43362,y=-65829..-50909,z=-58284..-26939
|
||||
on x=-60717..-46351,y=16976..39679,z=-47682..-36099
|
||||
on x=-8972..-1099,y=-52473..-25319,z=-86121..-52942
|
||||
on x=-61000..-39159,y=49997..78225,z=-23148..1003
|
||||
on x=58182..82981,y=44518..56895,z=3777..5095
|
||||
on x=6734..28162,y=-86696..-58568,z=-24484..-2036
|
||||
on x=58887..76977,y=-39238..-25941,z=39846..46017
|
||||
on x=24847..30203,y=-67085..-34859,z=41924..66616
|
||||
on x=20441..43585,y=-92938..-64316,z=-31009..-1794
|
||||
on x=-80785..-61417,y=-38919..-35032,z=-36530..-28271
|
||||
on x=59377..75712,y=43560..68823,z=-22599..-1614
|
||||
on x=-1700..13850,y=-4069..2130,z=63749..86953
|
||||
on x=-4952..16715,y=41882..73610,z=-54756..-52305
|
||||
on x=51595..59284,y=-24107..-4393,z=-72363..-43891
|
||||
on x=-27807..-3926,y=26851..45198,z=49346..82929
|
||||
on x=12390..34498,y=63224..91240,z=-5214..800
|
||||
on x=10873..42647,y=-46607..-10385,z=65246..87490
|
||||
on x=-62055..-38470,y=-21876..173,z=-62808..-40393
|
||||
on x=20224..48752,y=-38586..-16511,z=-85733..-52651
|
||||
on x=55784..81552,y=-5619..16327,z=34077..51185
|
||||
on x=-3455..10014,y=-85026..-65575,z=-26623..-11858
|
||||
on x=-35708..-27267,y=-45850..-19818,z=-67455..-45823
|
||||
on x=41827..53199,y=41230..65698,z=27015..50197
|
||||
on x=-6012..4252,y=-72302..-66695,z=36125..47997
|
||||
on x=49528..64452,y=-58166..-30694,z=-13199..4956
|
||||
on x=9888..29239,y=-68554..-54138,z=18724..56782
|
||||
on x=-68870..-53794,y=-58759..-22882,z=7742..40403
|
||||
on x=6972..17377,y=-20708..-6722,z=-82963..-69421
|
||||
on x=20367..25651,y=58345..91004,z=-20550..10387
|
||||
on x=25694..35176,y=22099..43134,z=-70032..-63879
|
||||
on x=-45952..-11194,y=-81779..-67800,z=8182..23824
|
||||
on x=62509..80195,y=-21937..-2975,z=5609..20751
|
||||
on x=-24032..-6383,y=24506..45121,z=59690..78556
|
||||
on x=-51599..-38434,y=30719..51414,z=36050..73737
|
||||
on x=58822..68897,y=7741..15890,z=-51938..-32193
|
||||
on x=-15039..6906,y=-65212..-41797,z=30699..55624
|
||||
on x=60817..85926,y=27886..55706,z=-8663..11830
|
||||
on x=15206..34437,y=30959..54489,z=57564..71609
|
||||
on x=35392..53432,y=22100..27886,z=-71711..-46618
|
||||
on x=-63155..-33316,y=2506..33937,z=53928..70435
|
||||
on x=39063..66505,y=25641..56117,z=-52530..-39376
|
||||
on x=-25070..-14807,y=-94850..-59369,z=-15595..12932
|
||||
on x=-83108..-73279,y=-39576..-1760,z=-6745..24559
|
||||
on x=-18659..1714,y=65445..79434,z=39458..61966
|
||||
on x=-73934..-43865,y=-53154..-30276,z=-31417..-14432
|
||||
on x=8399..36820,y=-5066..-746,z=62811..89658
|
||||
on x=51461..58467,y=21289..47244,z=-48496..-34141
|
||||
on x=-31677..-15125,y=65258..94618,z=-11983..21397
|
||||
on x=-59850..-45075,y=46471..73073,z=33142..52196
|
||||
on x=-38957..-29818,y=40316..50247,z=45129..64145
|
||||
on x=-17719..3143,y=-99029..-70583,z=-15275..-3260
|
||||
on x=-20122..-5655,y=-68173..-47607,z=27797..47630
|
||||
on x=-77283..-55700,y=852..31360,z=32087..48207
|
||||
on x=28846..48388,y=63096..85300,z=-30595..-3844
|
||||
on x=-82363..-49209,y=-51315..-42669,z=-5472..13974
|
||||
on x=-33522..-24893,y=54281..60638,z=-48809..-29636
|
||||
on x=-72223..-48831,y=-46560..-25806,z=36517..53330
|
||||
on x=-49478..-43471,y=-11706..10889,z=-80068..-54930
|
||||
on x=-55073..-36710,y=66679..68786,z=-21283..-7896
|
||||
on x=23706..37729,y=15047..43923,z=-72897..-65979
|
||||
on x=17181..28459,y=62283..83521,z=-31363..-8226
|
||||
on x=-16143..9900,y=27489..59106,z=59096..76947
|
||||
on x=3206..10671,y=-14400..10991,z=-95245..-69938
|
||||
on x=56347..81552,y=-25300..-8107,z=19105..50434
|
||||
on x=-78103..-66259,y=-37451..-32307,z=-33713..-2616
|
||||
on x=30350..59481,y=29541..51913,z=39794..66802
|
||||
on x=-6369..27626,y=29467..54642,z=-87761..-63038
|
||||
on x=-75910..-44075,y=8881..33348,z=39378..53195
|
||||
on x=-93870..-77120,y=-4549..11366,z=10630..21270
|
||||
on x=63828..86196,y=7557..26186,z=-31651..-14082
|
||||
on x=-45560..-23421,y=-57108..-50195,z=-46356..-35654
|
||||
on x=27703..38747,y=-64773..-61912,z=-50641..-19460
|
||||
on x=-30255..-26778,y=-36213..-16183,z=-72571..-68332
|
||||
on x=74470..78456,y=-25411..13731,z=9282..44191
|
||||
on x=60166..74998,y=-59027..-34355,z=23594..36628
|
||||
on x=-34949..-18916,y=48964..60747,z=-65291..-40385
|
||||
on x=41085..68564,y=-51507..-22592,z=-48642..-22967
|
||||
on x=-61218..-38261,y=-64826..-57227,z=-40284..-2183
|
||||
on x=-63449..-37989,y=-39697..-27482,z=-74092..-51129
|
||||
on x=9363..31975,y=55098..78687,z=-52413..-40226
|
||||
on x=-84308..-56837,y=-40246..-7996,z=-36362..-18607
|
||||
on x=-72651..-66165,y=9333..15666,z=25597..51574
|
||||
on x=17401..47978,y=9920..42401,z=-70754..-58041
|
||||
on x=-63217..-51951,y=-12225..11075,z=44022..66562
|
||||
on x=29053..49545,y=-84344..-63035,z=-6015..22142
|
||||
on x=-71933..-39944,y=23397..41453,z=-51539..-33412
|
||||
on x=37569..61597,y=43450..53548,z=22047..45919
|
||||
on x=8968..35041,y=59910..84105,z=-52586..-33885
|
||||
on x=-57379..-27352,y=-41555..-18843,z=54181..60564
|
||||
off x=-14944..13704,y=-58332..-46987,z=52838..63073
|
||||
on x=-73816..-53118,y=-14780..2920,z=-64505..-39848
|
||||
off x=-39460..-353,y=-51496..-30749,z=46316..63357
|
||||
on x=-85117..-60538,y=-36842..-15322,z=-52531..-16603
|
||||
off x=7991..31176,y=-73583..-52023,z=32437..48771
|
||||
off x=8515..30142,y=-77709..-62651,z=17831..46909
|
||||
on x=-18303..17378,y=-21032..-6623,z=64638..88783
|
||||
on x=7339..25764,y=-90496..-66449,z=-38251..-26490
|
||||
off x=-70223..-46889,y=4443..35356,z=-42714..-28833
|
||||
on x=-77805..-50387,y=43932..53069,z=-12411..-5379
|
||||
off x=-72499..-45397,y=-53542..-41435,z=-3491..21042
|
||||
on x=10885..19988,y=-41497..-7678,z=55702..84296
|
||||
off x=50943..59682,y=9775..27593,z=41418..52240
|
||||
on x=-5512..31721,y=74926..78902,z=-24035..-8858
|
||||
on x=54750..82645,y=29855..45661,z=8586..29144
|
||||
off x=-78864..-55077,y=6925..16113,z=-59924..-27087
|
||||
off x=9337..38246,y=60440..66216,z=-47033..-39339
|
||||
on x=-31403..-21142,y=-21908..-8535,z=-77524..-68441
|
||||
off x=-48840..-15847,y=-67498..-39602,z=-67358..-37763
|
||||
off x=-19834..7437,y=-20737..16009,z=-93797..-74007
|
||||
off x=-61152..-39838,y=52890..67543,z=-394..22101
|
||||
on x=-80448..-55372,y=1276..22349,z=-50814..-32755
|
||||
off x=44370..73647,y=-55877..-35324,z=26221..47034
|
||||
on x=46532..57702,y=-13840..3895,z=-69576..-50251
|
||||
off x=-73517..-57384,y=31351..41680,z=15220..23322
|
||||
on x=31166..41044,y=-51591..-33043,z=-75269..-52116
|
||||
on x=-56761..-45567,y=-54768..-32061,z=-60838..-46237
|
||||
on x=-75017..-54994,y=-28885..-27479,z=-19257..8285
|
||||
off x=17363..19964,y=-1700..23699,z=65227..80609
|
||||
on x=-72438..-53153,y=33395..60653,z=-27435..1947
|
||||
on x=67153..86947,y=-39064..-13890,z=-24067..-7025
|
||||
off x=-23935..-7756,y=54756..73703,z=-57803..-30333
|
||||
on x=-94142..-68468,y=-38295..-14233,z=-2486..8555
|
||||
off x=-16941..5265,y=64250..78153,z=7680..25578
|
||||
off x=-96513..-66230,y=-4640..29008,z=-10817..10499
|
||||
on x=-47541..-35822,y=-56040..-37593,z=25295..56913
|
||||
off x=32696..49773,y=-77640..-67246,z=-32741..-2933
|
||||
on x=60031..96079,y=-10285..24947,z=-23593..3651
|
||||
off x=60668..82205,y=4890..26483,z=-30306..7631
|
||||
off x=52550..78640,y=-65700..-48087,z=-12117..8780
|
||||
off x=-30793..-2678,y=-45649..-34548,z=66170..81785
|
||||
on x=3954..24104,y=-77505..-64791,z=-47133..-20347
|
||||
off x=-60663..-48533,y=30758..43913,z=38074..52867
|
||||
off x=29598..55875,y=62594..74543,z=-175..18742
|
||||
on x=7268..15664,y=64342..81253,z=-39177..-11209
|
||||
off x=50616..71417,y=-7637..-11,z=-65773..-35786
|
||||
off x=-85212..-54719,y=-45697..-20353,z=-40912..-7219
|
||||
off x=51683..61140,y=-16896..8191,z=56876..63036
|
||||
on x=63796..81879,y=-6590..10629,z=-17826..-13338
|
||||
off x=-12462..19923,y=24812..46240,z=58581..91722
|
||||
off x=60238..81783,y=9597..26586,z=9422..30485
|
||||
on x=-50156..-28362,y=28748..53048,z=51469..66900
|
||||
off x=69194..89229,y=-1108..23127,z=25684..56099
|
||||
off x=-84146..-57909,y=-17501..11445,z=30089..62555
|
||||
on x=31618..49715,y=37591..62455,z=43947..51429
|
||||
off x=-3586..19186,y=69304..92938,z=-20587..-9138
|
||||
on x=-61199..-46598,y=35967..60395,z=-14556..4590
|
||||
off x=-10913..14231,y=-30261..1009,z=-84245..-76301
|
||||
off x=60186..89222,y=-3692..33740,z=-25990..-8108
|
||||
on x=36727..54779,y=43724..59581,z=27937..65959
|
||||
on x=31209..44945,y=42559..57599,z=39510..49135
|
||||
on x=-3245..14976,y=-72819..-52510,z=36034..64484
|
||||
on x=440..28782,y=-11547..4495,z=-98435..-74377
|
||||
on x=-18198..10563,y=-81024..-73403,z=-17198..5796
|
||||
on x=12612..21502,y=-51647..-31132,z=-59647..-51386
|
||||
on x=29495..52571,y=11017..19714,z=46828..68700
|
||||
on x=9809..37561,y=-30853..-19860,z=-83128..-60062
|
||||
off x=67691..79085,y=-31154..3105,z=-37577..-17350
|
||||
on x=72836..97051,y=-31514..-15790,z=-29704..1797
|
||||
on x=-87609..-69341,y=-18788..-2505,z=-12297..-10409
|
||||
on x=20443..43548,y=-62320..-37522,z=38977..60544
|
||||
off x=-38964..-26257,y=58268..79198,z=22960..47406
|
||||
on x=-73221..-48099,y=-41579..-12744,z=41233..55998
|
||||
on x=39815..61968,y=-25816..2853,z=-84604..-48176
|
||||
off x=43328..47847,y=50145..81706,z=-20854..-17930
|
||||
on x=42026..55667,y=2815..18320,z=-71420..-56114
|
||||
on x=-15046..7093,y=-2067..6846,z=-87205..-62415
|
||||
off x=-47170..-12892,y=-70768..-49876,z=15359..40080
|
||||
off x=-2457..10461,y=30411..42007,z=-81116..-70962
|
||||
off x=52522..85711,y=-59582..-35527,z=-16966..8482
|
||||
on x=-46197..-25909,y=47222..78261,z=-50850..-32047
|
||||
off x=19590..34572,y=72339..87567,z=-5750..28633
|
||||
off x=47115..83953,y=-18319..-1527,z=36796..53774
|
||||
off x=-83826..-54856,y=-42413..-32997,z=3733..27276
|
||||
on x=-56233..-44250,y=49602..74071,z=22314..30759
|
||||
off x=63420..86367,y=-10839..17688,z=-58166..-41413
|
||||
off x=-52818..-25004,y=30897..65041,z=34334..65736
|
||||
off x=-37943..-1255,y=-31595..-17688,z=-79911..-66116
|
||||
off x=-53072..-34686,y=-74173..-48306,z=29767..56394
|
||||
on x=-52788..-31825,y=-32369..-19858,z=48905..63632
|
||||
on x=-1350..29555,y=-19635..-7074,z=-87305..-65879
|
||||
off x=-20803..-15829,y=21850..48686,z=-81910..-49506
|
||||
off x=6419..36337,y=-72720..-64997,z=9779..35669
|
||||
on x=-27678..-5611,y=-63057..-58292,z=-49298..-38857
|
||||
on x=-25232..-8560,y=-36175..-7964,z=-79251..-62089
|
||||
on x=3484..8094,y=60295..74830,z=19467..40876
|
||||
on x=25344..49707,y=55996..61107,z=27573..40860
|
||||
off x=47919..70340,y=-21803..-8394,z=-48605..-36363
|
||||
off x=-46037..-33978,y=47245..79330,z=-37903..-25173
|
||||
off x=-71914..-46814,y=2394..17414,z=-64968..-46103
|
||||
on x=19065..32293,y=-81832..-70280,z=-14026..1070
|
||||
off x=-38512..-31573,y=47413..61535,z=37582..62106
|
||||
on x=48305..70579,y=-62027..-50478,z=-15171..1424
|
||||
off x=-75249..-57569,y=-35309..-10651,z=33081..55723
|
||||
on x=25348..44691,y=-63608..-38147,z=40069..50336
|
||||
off x=29076..42828,y=43230..71477,z=-50728..-30676
|
||||
off x=-79502..-64190,y=-38572..-26384,z=-15092..12199
|
||||
on x=-23179..-7624,y=48807..73012,z=33610..40354
|
||||
on x=-3592..8389,y=60961..82397,z=-49081..-28054
|
||||
off x=51476..83453,y=28705..56528,z=-12926..1967
|
||||
on x=-27187..-19195,y=-82395..-52994,z=21622..43848
|
||||
off x=-90506..-68537,y=-9823..6672,z=26454..41372
|
||||
off x=44140..77814,y=-53839..-33067,z=19437..52037
|
||||
off x=70486..89103,y=-32008..-18702,z=-30582..-3135
|
||||
off x=9812..37159,y=-13683..5581,z=67454..90785
|
||||
on x=55516..76011,y=29943..54363,z=-35505..-8311
|
||||
on x=18107..53089,y=40166..76403,z=-46033..-31026
|
||||
on x=-44076..-28970,y=-69649..-38867,z=31937..54687
|
||||
off x=-6903..6265,y=-92551..-76965,z=10824..29131
|
||||
off x=-73096..-47990,y=-40737..-12561,z=-56032..-37870
|
||||
off x=-69834..-46771,y=-11406..9831,z=-70442..-38701
|
||||
off x=-63167..-28547,y=-2453..13753,z=-73159..-51770
|
||||
off x=-12546..-4517,y=-90466..-67177,z=-45521..-19870
|
||||
on x=-29818..-1746,y=50057..67629,z=41692..53982
|
||||
on x=-84294..-59113,y=33649..49960,z=-514..23937
|
||||
off x=-57940..-53375,y=17137..29536,z=-66645..-34791
|
||||
on x=-45417..-13403,y=-22323..12972,z=56661..78987
|
||||
on x=37008..53186,y=-52723..-32702,z=-81286..-61118
|
||||
off x=62401..92686,y=-32370..-8632,z=3648..32213
|
||||
on x=46130..54088,y=12139..21408,z=60375..72557
|
||||
on x=-78284..-60622,y=-60558..-34232,z=3228..21753
|
||||
off x=-26367..-17693,y=-44140..-38359,z=-76315..-54921
|
||||
on x=-50778..-25901,y=-62396..-47707,z=-46585..-24121
|
||||
on x=-31891..-7439,y=-38110..-6297,z=-83562..-54313
|
||||
on x=53088..73992,y=-40054..-10359,z=37676..54496
|
||||
off x=16508..40245,y=-62074..-36376,z=-71638..-56256
|
||||
off x=41517..56789,y=31056..37033,z=41339..66625
|
||||
off x=-70827..-68212,y=7248..41853,z=-32734..-16519
|
||||
off x=32333..52847,y=-89957..-62307,z=-5050..6149
|
||||
off x=-17149..-10468,y=-32928..-9851,z=56537..82605
|
||||
on x=-84541..-54098,y=-58633..-36289,z=-12748..2668
|
||||
on x=38782..73823,y=-47393..-38721,z=16744..50416
|
||||
off x=39068..59022,y=21209..55515,z=34421..52108
|
||||
on x=-71216..-46104,y=-73471..-55003,z=-37496..-2060
|
||||
off x=-42432..-23889,y=-86804..-68846,z=-3653..23244
|
||||
off x=-16056..17364,y=-72921..-54772,z=-40563..-21696
|
||||
off x=-25993..-10482,y=18139..45085,z=-86836..-55465
|
||||
off x=-6145..6154,y=15388..23210,z=-89142..-68482
|
||||
on x=46085..67991,y=-73185..-44337,z=-45070..-27405
|
||||
on x=65191..77310,y=644..12100,z=6335..26349
|
||||
on x=61530..80630,y=33572..40611,z=3139..25295
|
||||
off x=-22306..-1057,y=-64514..-54752,z=50646..59125
|
||||
off x=-31245..428,y=-69703..-42002,z=33460..67700
|
||||
off x=18783..26105,y=57879..76612,z=-46736..-17226
|
||||
on x=65144..85202,y=-34414..-9442,z=-15694..-3293
|
||||
on x=-30025..-19969,y=2384..18772,z=-85674..-56255
|
||||
on x=-21671..-1706,y=-88695..-66277,z=-32871..-31219
|
||||
off x=41938..56563,y=36056..55655,z=29417..39627
|
||||
off x=-35141..-13943,y=51556..73844,z=12868..28552
|
||||
off x=-62811..-35918,y=-44104..-21236,z=35127..62940
|
||||
on x=62916..82143,y=7866..27555,z=17805..50739
|
||||
on x=29498..66404,y=-38144..-7002,z=52432..62757
|
||||
off x=-40743..-17461,y=-3977..27203,z=-82649..-69934
|
||||
on x=61462..87066,y=-29424..1075,z=-53444..-28127
|
||||
off x=-20296..755,y=-68543..-34376,z=45810..71640
|
||||
off x=-69466..-36179,y=-62860..-52547,z=-31500..-5258
|
||||
off x=44866..53371,y=-24236..-6665,z=-73108..-53122
|
||||
off x=-79007..-53057,y=-17042..5274,z=22078..36248
|
||||
off x=-57167..-28268,y=-51111..-32915,z=-77704..-38825
|
||||
off x=-4958..9484,y=5801..13607,z=74030..98668
|
||||
on x=-35563..-13589,y=42209..54631,z=44769..75384
|
||||
off x=-60812..-37640,y=-63777..-55796,z=24372..34208
|
||||
off x=-46941..-16156,y=-36595..-17426,z=-79732..-64679
|
||||
on x=-59888..-28115,y=12521..32347,z=-78750..-58674
|
||||
on x=72376..82684,y=4253..30848,z=-40351..-9522
|
||||
off x=-32933..-1254,y=-75313..-57763,z=-49186..-39785
|
||||
on x=23434..55093,y=46836..66125,z=36750..49491
|
||||
on x=-46482..-28852,y=-3093..26488,z=52024..72731
|
||||
on x=43735..78088,y=-44597..-11422,z=-45272..-31611
|
||||
off x=9842..13060,y=-32334..-18544,z=-81402..-71916
|
||||
on x=4162..7921,y=-99019..-65156,z=-19030..4628
|
||||
on x=54190..69481,y=-597..28621,z=-39799..-25080
|
||||
off x=41810..71069,y=-60566..-49113,z=-28756..-6676
|
||||
off x=-79628..-67314,y=-10495..9141,z=-1753..22526
|
||||
on x=-80854..-54338,y=-47067..-35714,z=-41157..-4068
|
||||
off x=7961..36511,y=-68928..-39346,z=42154..66633
|
||||
on x=55071..86104,y=-26491..-12993,z=35080..46483
|
||||
on x=16937..38277,y=45614..76853,z=-68179..-32041
|
||||
on x=-59142..-45042,y=-44541..-15747,z=38408..54791
|
||||
on x=-8928..11676,y=-46464..-33539,z=-75322..-62649
|
||||
on x=-25001..-1799,y=60438..82665,z=-6409..20165
|
||||
on x=-73110..-45573,y=-56868..-33358,z=8495..25515
|
||||
on x=-1691..18521,y=60075..85944,z=-2617..10836
|
||||
off x=17339..45519,y=46033..72006,z=37649..43076
|
||||
off x=-79475..-70079,y=3154..12209,z=-24437..-12055
|
||||
off x=46696..52595,y=-51367..-22325,z=-49480..-29533
|
||||
off x=45715..64763,y=-22780..-16581,z=-78193..-55110
|
||||
off x=-16579..2489,y=-64160..-54806,z=41992..63536
|
||||
off x=-55417..-30493,y=-88205..-51837,z=-3486..19240
|
||||
off x=-77740..-75400,y=-16116..7915,z=-31057..-18206
|
||||
5
input/23.txt
Normal file
5
input/23.txt
Normal file
@ -0,0 +1,5 @@
|
||||
#############
|
||||
#...........#
|
||||
###C#B#D#A###
|
||||
#B#D#A#C#
|
||||
#########
|
||||
252
input/24.txt
Normal file
252
input/24.txt
Normal file
@ -0,0 +1,252 @@
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 1
|
||||
add x 12
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 7
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 1
|
||||
add x 13
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 8
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 1
|
||||
add x 13
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 10
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 26
|
||||
add x -2
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 4
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 26
|
||||
add x -10
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 4
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 1
|
||||
add x 13
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 6
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 26
|
||||
add x -14
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 11
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 26
|
||||
add x -5
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 13
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 1
|
||||
add x 15
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 1
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 1
|
||||
add x 15
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 8
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 26
|
||||
add x -14
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 4
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 1
|
||||
add x 10
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 13
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 26
|
||||
add x -14
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 4
|
||||
mul y x
|
||||
add z y
|
||||
inp w
|
||||
mul x 0
|
||||
add x z
|
||||
mod x 26
|
||||
div z 26
|
||||
add x -5
|
||||
eql x w
|
||||
eql x 0
|
||||
mul y 0
|
||||
add y 25
|
||||
mul y x
|
||||
add y 1
|
||||
mul z y
|
||||
mul y 0
|
||||
add y w
|
||||
add y 14
|
||||
mul y x
|
||||
add z y
|
||||
137
input/25.txt
Normal file
137
input/25.txt
Normal file
@ -0,0 +1,137 @@
|
||||
vv>v......vvvv.v...v>..v..>...>>.>.vv>vv>.v>v...>....v...>>...>..>..v..v.>.>.>v>v.>v>.v>.v.>.>>>>>>.>>v..v...>v..vv>>v.>.vv.v.>>.>.>...v>v.
|
||||
v>...>>..>v.>>v>...vv..>>..>>v..v........>>.v.>>.>.vv.>.>.>....v.>>.v..>.>>.v.....>.v>>vv>...>>.>..>>..>...v.>...>v.>.....>v>.v>v>>>..>..v.
|
||||
.>vv..v.>...v>vv.vv..vv>.>...>.....>v....v>>>.v>v.>vvv..v>...v>.v....v>vv>...vvv.v>.>>>>...v>.vvvv>v>vv>.>.vvv.........>>>v..>..vv>...v..>.
|
||||
..v>>.>>....v..>>v.>.>...>>>v.v.vv.......v>..v>vv>v>v.v..>.>>..>v...>vvv.>.v>>v>v>..v.vv....vvv>>v>vv.>>>v....v.>..v.>.vv>>>>>.....>v>...>v
|
||||
...>>.>.>vv>>......>vvvv>..v.>.>.>.>..>...>v.v>>v.v.vvv.>vv....vv......>.>>..>..>v.v..>.>>>..>v..>...>v>....vv...v..>>.>v.>...>v.vv>.>.v..v
|
||||
v....>.>vv.>>>v.>v....v.....vv..>....v..v>>v>.>..>..>.>.>>..vv>.>>.>>>.>.>>v>..>v.v>...>.>...v.>.vv..v.v...>>...vv>...>>v>.>>.>>.>.>..>..>>
|
||||
...v>.v>>....v>.v.v>vv>..........>.>.>>v..v>..v>.v.v..>v>v>.>vv>..vv..v.v>..>....>...v>..>.vv>.>vv.v>>>.v>>...vv>..v>>..>..v.v>v.v..>...vvv
|
||||
>.>.v.>...>v.>.>....>..>vvv...v....vv>>>.>>>.v..>>>v>vv>.v.>vvv>.>v..v..v.v>.vv..v...>vv....>v.v.>.v>.v..v..v....>v.>v..v>>.v>>....v>.vv..>
|
||||
.>.>.v.>vvv...>v.v..v.>.>..v..>.>>v.v.>>.vv>>>>..v..vv>>.v..>.....>.v>.>>>.>vv..>>>..v.vv....vvv>v>..v..>v.....v.v.v...>>>vv..>v.v..v.>..>.
|
||||
v>v...>...>.v......vv.....>.>>v>.>>.>v.v.v...v.>vv..v>>.v>>.>.>..vvvvv>.>v.v...v...v>..>...v...vv>....v.>>vv....v.v....vv..v..v..vvvv>v....
|
||||
.vv.>.>v>.v.v.>>.v........>>..>v.v.v.v..v>..>v....vv>..vv....>>...>v>.>...>.vvv>>v...>..vv.>.>>>.vvvv...v>vv..vvv..vv>...vvv.>v.>>.v...>>v.
|
||||
.....v...>v.v.>.>>>>>.vv>..v.vv>...vv>...v.v..vv.v...v>>..v....v>v..v.v.>v.>>vv>.....>.>>vv..v.v.vv.v>......>>>...>>...v.>.v.vvvv......>>>v
|
||||
.>.vvvvv>.>..>>.>...v>>>.>>......vv>>.v......v..vv..v.vv>v...vv>.vv.vv....>>.>v..>>.>.......>.>.v.....>>.>.......v.v...v>..>>>..>>>vvvv>.>v
|
||||
.......v...v>v..v>>>.>.v..vv>.>.v.>.v.v...v>.....>....v.....>......v....>...v.vv.>vvv.>.>v..>>>v....>..v....v.>..v...>>>.vv>>v.>..vv>v>..>.
|
||||
v.v>..........v>>>.v.v..>v>vvv>.>.>>>v>.v>.v>v....>v>.v...v>.....>..v.v>.v>>>v.v>...v.v>>>v.v>>.>..>.vv>v>...>>..>.>v...>.v....vv..vvv>..vv
|
||||
v.v..>...v...>...v...v.>..v..v>....v.>>...>>vv..v..v>v...v..>v..v>v>.>.>.>.>.........v.v..>.>.v>v>>..>...>.>.v.v>v..>>v>..>.vvvv..>.v>>.>v.
|
||||
.v..v>v..v>v.vv>....>v>vv.v....v..>..vv.v>.....v..>.v>v..v.>v>>>....>>.v>v.v>>...>...>.>>>..>..>v>vv.vv>>v.>>>v.>......vv>v.vvv...>>>..v>>.
|
||||
..vv.......v..>vv>v..>.>>..vvv.>vv>>....v.v>vv>>.>>vv...v..v.vvv.vv...v..vv>>...>.>v..v..>.v>.v>v.v..>>.>..vv>...>..>..>..>>..>.v.>v>>>>..v
|
||||
v>v.v....>.>.v...>.>v..>>>.>v..v..vvv>.>>.vvv..>v>>>>......>..>...v.v>>>.v>vv.>...>.>.vv>....v.v>vv.>v>v>.....>..v.v....>.vv>v..>v>.>...v..
|
||||
.>v.>v.>...v.>>>..v.>vv>>v>.v...>..v.....vvvv>.v..>..>.>>..vv..>.>.>>........v>.>.v......>.v..>>v.>v....v>.v.>v.>.>v.>.>>>.>...>vv.>.>.v..v
|
||||
v..v>.>.>.>.>>v......>v..>.vv.>.>>..vvvv..v..>..>....>>>v.v>.>..v.v>v>..>v.v>>>>v.>....>.v.>v.v.>>>..>.>>.vv..v>v.v..>.>..vvv>v.vv..>v.vv..
|
||||
.v.>...vvv.v.>.v.>..v...>.......vvv.....v.>.vv>vvvv..v.>..>..>>>...vv...v>vv>.>.v>.v..v...vv.v.vvv...vvv.>v.>>...>v...>.vv>>.>.>v>>v.>>..v.
|
||||
v.v>>v>v.>...>.v>..v>vv...v>.v........>..>v.vvv>..>>..vv>>..vv.>....v>>..>vvv.>....v>..>>v.>.>v.>.v>v>>v...>...>>v.>>>>>.v>...v>>....v..>..
|
||||
>v>>.....>>.v>vv>.v.v...>.v...>>>.v....>v.>.>.v>>v.v.......v.v>>>>v.v.v>v.>..>v.v>.vvvv...>.>.vv.>>.vv.v.>v.>>>>v......vv..>v..>....v>>v.>>
|
||||
vv>vv.v.>.vv....v..>.v......v>.vv...v..>.>v.vvv..>.>vv....v>.>.>..vv...>v>>v..>vv.v.>v..>v.>>...v.v..>..>.v..vv>v>v>...>v>v..>>>.>...vvv>>.
|
||||
.>.>.vv.v...v>..>...>...v..v>v...>..v.vv..>..v.v....v.>v.v>>>>>..v.v.>...vv>vv>v.>....v..vvvv>>......v.v>..vv.....>>v...>.v>vv...v>>..>.>.>
|
||||
vvv.v..>.vv>....>vvv....vv.>vv.v.>v.>v>...>.vv>>..vv.....>>>>...>.vv.v.>v.v..>v>>vv>v..v>>....v>.>>.....>>vv..v..v>v....>..>..v.....>vv....
|
||||
...>...>vvv.>.....>.>vv...>v..v>>.>>..>>.v>>>.>>.>...v...>vvv.........v>....v>>v>....v.>...>.....v..v...v..>.....v..>v>v...>v.v..>>.v..vv>.
|
||||
..>.>.vv...v.......vvv>.>..vv>v....>v....>.>...>v>v...>.>>.vv.>...v>....>.v........v....>.>.>.v.v...>v.>v.>.v>>>vv..v>.>..>....>.>.v...>v..
|
||||
v.......>.vv>.v.......>...v.>..v>.....>..>v>v.....v....>vv>>..>v..vv>...v>..v.>v.vv>v...v.>vv.>v...>>.vv>>.>v.>.>.v...>.>>.v.v..vv.v>vvvv.v
|
||||
.v>..>..>v..>.v>.......v>...v>>>..>.v>v>v.>..v>..vv.>v...v.>v.>v>>.vv...>v..>........>.>..v.>....>v..>..>>....>>.>.v.>vv.>.>.v.>>..>.v...>v
|
||||
>v....v...v.v..>>.v....v>.v..v..v.v.........>.>>v>..>.>..>>v..>v>vv..v..>.v..v.vvv>>>vv.v.v.v.v..v.>v>.v.v>.>...v..>v...>v..v>>>..v>>..>.v.
|
||||
v..v..>..>v>...vv>>vv>.>>>.......>.v.vv..>..vv.vv......>......v...v.vvvv>.v.>.v>..>...>>>>vv.>.v.>>.>.v.v>v..>>vv>>>.....vvvvv...v..>...>..
|
||||
..v.>v>..>.vv....>v.....>>...>v...v..>..v>.vv>..v..vv....>.v....v.....>..v.....vv.v>v>..v......v...v>v.......v..>.>..>>v.....v>.>.v.>.vv...
|
||||
.v>>vvv>..>v>.>....vv>v..>...v.v..>.vv.....v>>v>>.>v.>.....v..v.>..>.v>.>.>v..v>....>>>...>...>.>..v.>>.>>v...v..>v>.>...v...v>v>v.>>......
|
||||
.vv.>v>.>v..vv..v..vv>v.>>>....vvvv>v....v...>.>..>.>..>..v>.v.v>.v..v...>.vv>.v..v.>v>>.>..v.v>.>.v...>>v..>v..v.>.v>v>.vv..>...v..>.>vv..
|
||||
...>.>.>>v.v.v..>.v>.v>.v.vv..v.v...vv...>.vv.v>>...v.>vv.>.v>..>>v>.vv....>.>..>v.v..>>>..>v.v.>vv>.>.....v..>v>>.>.vvv..>....v>.v>vv>...>
|
||||
v...v...v..>.v>.v..v.v>v..vvv.>.>....v>>...>>.v>...>v...>...>..v>v...vv>...v...>.>>.>.>.....>v...>..vv>v..v.>..>v.v.>v..>>>.v>>.>v.v.vv>.>.
|
||||
>..v.....v.v>v.....>>vv..>.>.>.....v>....v>v>>.vvvv.>.v...>vv..vv..v...v.>..v..v.v>.v.>v>..>>vvv..>vv..vv>.v.v>>vv>vvv...v..v....vv..>.>...
|
||||
>v>..v.>>>...>...v>.>.v>v...>v>>.v.>>v>.v.vv..v.v>.v>.>>..vv>..>v>>.>......>.v>..v.v.v.vvv.>v>v.>.>vv....vvv..>.v....v...v...>..>>vv...>...
|
||||
vvv...>......v>>>..vv>.>>....>.>>v...>.>>.>.v..>>>>.>>...>.vv.v.>.v>.>..>>.v>..>.>v.>..>v.v>vv..>..>>.vvvvv.>.>v.>..v...>>>....vv>>.vv.>vv.
|
||||
v.>>.>.v...v..>.v.>v.....v.....>v...>.>..v..>.....>vv....>..>>v>vv..v.>..>........>.>..vvvv>....v.>v>v>...>..v.v.>.>vv>>>v.v.>>..>.v>>.vv..
|
||||
.>v.v>.>v.>>..v.v>....>v..v>.>..>..vv>>v..>vv>.>.v..>vvv>.>>v..v..>...>v.v.v..>...>...>.>>..>..vv..>vvv>>.>v...v>.v>..>vv..v.>v>.....v>v>.>
|
||||
.v.v...>..>v..>...v>v>.v>>..>.vv..v>>v.>>..>.....>>>>>>>..v....v>.>>>v>.v...........v.v..>v.>>>v>v>>v...>..>v...>.v...>..>v>.>.>>.>>...vvv.
|
||||
.v...v..v>..>...v.vvv..>..>vv....>...>v>v....>..>v.>>.>>v>.....>>...>v..>..>...>vvv.v...v>...vvvv.v....>.>vv.>>>>....>>>..>..>.v...v>..>v..
|
||||
..v.>..>....>.>>.>>v.v......v>.>>.>.>.v.v>..>>....>...v>>>.v>.>.>vv.>>.v>..v.>.>.v>>v..>...>v>v>.>..v>.v.>>.>.>>.....>.v>vv..>>vv...v.....>
|
||||
.vv.>.>v.>>v...>....v...v..v>.v>.>.v.>>>vv...v.v.v>.>>..v>.>...>.v..v>.>.vv.>v>.>...>.>.v...vv.v.v.v..>>..>.>.........>..v>.>.>v>v>.vv>.v..
|
||||
.>..v>>.>>v.v.>....v....v>v......vvvv.vv.vv.v....>.>.>.v.>v.v...>v.v.v>.>.>v..v..>>v>.>>vv.v>>......>....vvv.v..v..v.>..>>.>>...vv.>>v..v.v
|
||||
>....v.v>.>.>..>....>>>..v>.>.v..>....>.v>.v>.vv....v..vvv.>>..>>>>.>>vv.>..>.vv.....v..>>..v.>>v.>>..>.v....>>..>>...v>....v>.v>.v..>v>.>.
|
||||
v.v..v>v...>>v>..vv.>..v.>>v...v..>v.....v.v.>v.vv.....>>v>>vv>.v..>..>v..>v.>v.v..v>v>.v.>....>.>..v>.>.v..>..>v....v...>vv..>v>..>...>v..
|
||||
v.>vv>.v...v>v..v.v>...>>v.>.>v...v.>...>......v..>.vv.....>v>v.vvv..v.v.>>v>v>v>..>..v>...>..>..>>v>>..>....>v..>>.v.>>>>.>..>........>>..
|
||||
vvv.>>.....v.>v.v.>.>.vv.>.v....v.v>>..v.v.>v.v.v.v>.v>..v.....v>>v.v.>..>v...v>v.>.v.>.v.v>v.>....>>vv..v..v......>v.....>.vvv.v>>.v>.v.>.
|
||||
.v.>>v>.v>.>>..v.v...>v....v.v.v.v....v.....>vv>>.....v.>v.v..>>..v..v.>>v.>........v.vv.>v..>.>..v>..v.v>.>>..v..v...>..>v.>>v>v.>v.>..>.>
|
||||
.vv...>v>v>.>.>...>>.........>.v>..>.v.>>.v.>>>...v.vvv>......v.vv>v...>v>>vvvv>..>..>v.v>vv>.>v..>....>.>.vv.v.v>..v.v.....vv.>>.....>v>..
|
||||
>...>..>....>...vvv>.>....v>...vvv...v...>.v>>vvvv..>.v>..>...>.v>>v.v.v>>>..v>>>v>>>.>>>...>..>>.........>>.>vvv.>.....>..>...vv...>....v.
|
||||
>v>>..>..>v..>.vv..>...vv.>.v>v...v>.>...v.v>...v.v...>.v>.>...v.v>>..v.v>..v.>>.>>..>vv>v....v>v..vv>v..v>v>>.....>.>>>v>v..v>>....>v.>.v.
|
||||
>.>.v.v>v..>>...>..v..v>...>>vv>.v.>.v>>.vv..v.>..v>v.>v>v.>.......>.v>>v..v.>v.vvvv>>v.>v..v.>>vv>.>.>.>.vv>>v..>.>v.vv.v>..v>vv.>.>>..>.v
|
||||
>.v.v.v.>.>>..v.>.>>.v..v.>.v>.v>.vv...v..v..vvv.v.v.v..>vvv>.v>.>..vv.v.vv..>>v>..v>.>.>.>.>.>v...vvv.>..>..v...v.v.v>.v.>v.>......v..>...
|
||||
..>.vv>.v.>.>.v.vv.>>v.>v..v.>.v...>.vv>v..>>.v.vvvvv>..>v>>.v.v..>>...v.vv..>..vv...>......>>>....>v..>..vv..>..>v..v>..>..>..>>.v>v...v.>
|
||||
.>.>>v.>....vvv....v.>.>vv>.vv>>>>....v.v.v>>>.>..>>..>>>..>>..v.>v>>..v>.vv>v.v>.......v>v.>..vv.>v.v..>v>.>..v.v>...>>>...v>..vv..v>vv..>
|
||||
..v.>>...vvv.vv...v>v.>>.v...>>>>.vv>v.>>v..>vv.>......v...vv.v>>v.v..v.v>.v.....>v>.>.v...>>..v.vv.>>>>>>>v>....>v..>vv.>..>..>v>>.v....v.
|
||||
vv>>>.v......v..>.vvv.>.>.>v..v.>v>>>v>>....vv>..>..>v...>..vvv........v>>>..v.>v>v.v>..>...>v>>>v.>...>...vv>v......>.>vv..v>.>>.v...>....
|
||||
>.>..vv.v..>>>v...vv>>>v.>>.vvvvv>>.......>>..v..vv>>v...v....v>v.vv.vvv........v>.v....v..v.>v.>..>>....>>..>vv...vvv.....>>>.>v>>v.v>v.>>
|
||||
>>.....v.v..>vv.>.....vv.>>>..v..>>..vv>vv..>>v>v.>.>v.>..v.v...>.v.v>.>>.....>..>>.>.v.v>...vvv..v>v>>.....>..vvv.>>>.....v>>....v...>>>>>
|
||||
...>vv.....>>>vv.>..>>>v.v.v>v>...>>>v..>.>...>.>>...vv.vv.>>.>>>...v...>>.>..v..vv....>..v.v.>v...v..v>.v>..v.v>>..>.>>>>.v.>v.>v.>v.>.v.v
|
||||
..v>>.vv.v.vv.>v.v>>v.>>>..>.>v..vv.v.....v..v>v>.v..>....vv.vv.>vv.v...>.vv...>..>v...>..v>v.v.v..>>.v..v>.v..>.>vv.>.v>vv>..v.v>.v...v>..
|
||||
v>.vv....v..>....v>.>v..>...>>.>>v>>..v..v..>v>..>>v...v..>..v....>v..v>..v.>v>v>...>..>....>.>>..>vvv......>...>.>.>...v....v>>v.v>>>.>v.v
|
||||
v..v..>v.v...v>>.>..>>..v.v.v.....v>...>>.....>.>>..>..>.>..>.vv>.>>>v>>v.>.>>..>...>..vv....v...>>..>>v>.....v>...v>..>v....v.v>vv>>..v>.v
|
||||
.v.vvv.v>>.....>...v.vv.v.v.....>>v.v.....v....v..v..>...v..>>.>.....>>>>>.v>..>v>vv.vv>.....>.>.>v...vv...>.v.....v....v.v.>......vv..v.v>
|
||||
>v..v.....>...vvvv>>..>>>.>>v.>>.v.v.>>v..>.v...>.>.v..vvv...v.>.....v..vv>v>>.v.>v.....>...>>.v>...v>.>..vv.v...>.>..>v...v.v.>>..>v>.>...
|
||||
>....>v>.>v>vv>v..>..>v....v.>>.>.>...v..>>v>v>>v....>vv.vv>>v..>>>.....>>>vv.vv...>v..>>>>.vvv.....>...>>vv.v....>.>>>.v.vv>.....>...>>v.v
|
||||
.>vv.>..v.vv.>>..v>v>.>.v>>.>........>.v.v..v..>>vv>>>..v.....v.v>..>..>.v.vvv....>.>v>.v.vv.......>v....v..>..>...v>..vvv..v...vv.>.vv>..v
|
||||
...>v......>..v.>>.>.v>.>.......>>v..vv.>>>>v.v>>v.>...>v..>.v>..>>v>>vvvv.>..>>v.>>...v>>...v......>vv..>..v.>....>>.>v>.>.>v.>>>v.v......
|
||||
..v.>v..vv.....>...v...v>v.>.v>...........>>>..vvvv>......v.vv..v..v...v....>>v.v.>.v.....v..v>.vv.>>v.vv.>...>v..vvv..>..v.>>.>..v>...vv>>
|
||||
v>......v..>..>vv.>>v.vv..v....v..>.....v....>..v.v>...v>.>....v>...>.>.v.....>.v>.>....>>v>v.>.>vv.>>v..>.vv..>>vv>..v.>.>v..v..........>.
|
||||
....v.v>....>..>>..>...v..>..>>vv.vv.vv>..>..vvvvv.>.>v.>>>.vvv.>v..v.>>>..vv...>v>..>.>v...v...v...v.v>vvv>>....>..v>.v.v.v.....>>.>v>..v.
|
||||
..>..vvv..v>>>.>v...>......v....>..>.>...v>...>>.v>.v..>....>..v>vv>..>>.vvv.>>v>..>.v..v>.vv.....v.>.v.>....>>...>v.>v>vv>.......v....>..>
|
||||
>>.v>.>v..vv....>v>>>v.>.......>.>...>vv>v....vv.>>v..vv..>v..v>>v>.....v>v>.>...>>..vv.>.>v..>.......v..vvv.v..v...>.vvv.v.>vvv...>..>...>
|
||||
>.vvv.vv.vvv.>>.>vv...>.>.vvv.>>..>>>>...>v....vv>.>>>..vv.>>>>.......>.vv...>>>v..v>vv...v.>...v.>..>v>..v....>.v.>...>vvvv...>vv..vv..v.v
|
||||
....v..>...>v>>v..>....v>v.v.>v.v>.v.v....>...v..v>>>.>..v...>vv>..>...v.v...>vv.....>v.>.v...>>.>..>v.>.>..v....>>.>>v...v.>.v>.>..v>.>.vv
|
||||
...>.v>v>>..>.v.vv>.>....v>.>.>>.vv.......>>vv>vv>.>v>.>v...>.v.>.>.>>v..>>..vvv>.vvv.v.vvv>>..>v>.v.>..v...v.>.v.vv>.>>>>.>v......vv>.....
|
||||
....>.>.v>>v>>v.>.>.v...v..>.....>.vv...>v>.>v>>v>......>.>v>.>..v.v>vv..>....>>...v.vv..v..v>v>v......v.v.>...>v.>...v>>v.v....vv...>>.v.v
|
||||
>.v..v..>>v........>.v...v..>.>>>v..vv.v>vv.v>>v.v.>v...>...>...>.>.>.>.v>......>v.>vv>>>...v...v>vvv>..>vvv.>>v>>.v..v>.v.vv..>v..v>>v.>.v
|
||||
v..v..>.>>.>>.>v.v.>v>>..>.>.>v.vvv.>.v>.>>..>v..vv>v.>>v.>>v.>>.>...v.v...>.v..v....>.v>v>.>.vvv.vv.>v...>v>v>vv...>>..v>....v>>...v>>...v
|
||||
v..vv>>...v>...vv>>>>v>..v>.>...>.vvv..vv.vv.>>>>>>...>>..>v>v..v.v..v.>v>.>>>>...v...>.v.>.v.>v..>vv>........v.v.>..>..>v>...v.v.>v>..>...
|
||||
.>....v>..v.v..v>v.v...v>..>......>>.v....>.v.....v.>....v.>.>.v.>v.>.>v>>>>v....v..>..v...v.>.vv.>>.vv.>>..v..vvvv..>v.v..>..>.>>>>..vvv>v
|
||||
>.....v.....vv...v.v..v....v>v>..v>v>>>vv..v.>..>.....>>>......>>v..>..>>.vv>vv......>v...v...>v.v>>.>.>..v.v.v>>>.......>>.v.>>>v.vv.>vv.>
|
||||
>v...>..>.v.>vv.v...>...>v..>vv....>>v...vv>.v>vvv.v.>.>vv....>..>.vvv>.vvv...v>>.>v>v>.v.vv>>.>...>..>..v..v>v.vvv.>v.>>.....v...v>v>>v.v.
|
||||
v>>.....vv..>..>......>v...v>>v.>...>>>v.v....v.>>>.vv.v..>>v...v.>vv.v.>.>>vv..>>.v.v>..>>.>..v>..vv...>.....>...v>>>.>>vv.....>.v>>vv>...
|
||||
v.....>>.>.v...>v..v.v.v>..v.v>>...>v.v..vv..vv...v>.>>.>...>v>>>.>...v.>>>...v..v>>>..>v.>v....>...vv.>>v>.v.vv.>vv>>v.>.vv.v.vv...v..v.v.
|
||||
>v>v.>.>>>>..>.v>..>...>......vv.v......v>v...>>.v>v.v>.....v>>>v>..v>>.>v..v.v>vv>v...>...v>v...v...>..vvv>..v.>v....v..>>..v>...v>v.>.>..
|
||||
...>>..>v>.......vv...v......vv>v...>v.>.>....>.vv.vv.vv>>vv>.v..v.>>....>v.>...>v>>v>....>v>...>>..v.vv>vvv.v...>.>v>>vv....v.>vv.>.>.....
|
||||
>...v>v>.>>.....v>>...v>.>v.>.>>v>..vvv>.v.>vv>v.>v.>v>.>>vv.....v.v....v..v...v..v.>.>v.....>...>>>>..>.vv.v.....v>.v>..v>.>v>v>...v..>..v
|
||||
v>.......v>>......>vv.vv>..v.>.>>..>>...v.>.>.>.vv>v>vvv.v..>>>.vv.>..v.>vv.>>.....>..v>vvv>.>.v>..>v......v>>.>>vv.v.v.vv..>vvv>.>>.>...v.
|
||||
...>.v..vv.vv.v>vvv.>.v..>vv.vv..>v>..>.>vv>...vv...v....v>...>v.>vv>...v>v..v.>..v.v>.>.v.v>.v.vv>>..v.v.v>v>..>.v.>>....v..v..v..v>..>.>v
|
||||
vv.v.>.>v....v..vv>>>.>>vv>v.>..v..vvvv.>.....>>.v>vv..vvv.>.>.>.>v...v>vvv.>..v..v...>.v>.>...v...vv.v.>>v>v>.>>.vv>.v.>>v..>.v.v>.v.v.vv.
|
||||
.v>vv...>.v....v>..v...>v.v.>.>.>>.vv>.v.....>...vv..>>>.v....>v...vv>v.v.>.v.v.vv..>v.>.....v...vv...>>>>v>v....>..v...>....v..>v.v>..>>.>
|
||||
..v>.v>>.>..>>..v>..>.>..>.>.v..vv.v>.vv>>.>.v.v..v.>v.>.>>v>>>.v..>>....>....vvv>...>..>.vv...v.>...>.>.....>>vv>>.>..v.>v.>....>.v.>....>
|
||||
...>.vvv>>.>>.v..v.vvv..>.>.....v......>>vv>v.v.>...vvvv>>v>v.v...v.v..>.>v.>.v.v..>.v>..v.v.>>.>.v.....>..v.....>...v.>v...>.v..vv>...vvvv
|
||||
>.>>.v>v>>v.>..>v>........vv....>...>.>>.>.v..>.v.v.>vv>...>v.>>>>.vv...>...>.v....>>vvvvvvv>vv.vv..>vv..>.>v.>..>..v.....v..vvvv>.v..v>.v>
|
||||
v.v.v..vv>..v.v..v>v..v>....>>..v.vv....>.v....v....>>.>vv.>.v>.>.v>>...>.>.>.v>v.vv.v.v.>...v>..>>>v>.>>>>v.v....>.....vv.>v.>vv..>.v.v...
|
||||
...v..v...>v...v.v.............>>vv....vv>vvv>>>.v>v>vv>v>..vv>.v>..>>.vvvv..>v.v.>>>v....>.v>..v.>v>>.v>...>>.vv...v>v...v.vv.....>>>>....
|
||||
>>.>..v..>>v>.>vv....vv>v.>.>.v.....v...>>.>.>......v.v.vv.v...v.v.>>..v........v..vv.>>.vv..v.v.>>>>vvv>....>v..>vv..v>.>.>v....vvvvvv>v..
|
||||
...vv>>v....v.>v.>..>.>......v>.>.v.>.>.>.v.v.>.>.>.v.vvvv>>.>.vv..>v.>.vv.>>..v>v.v.>.v>v.>.v>vv..>.v..vv>vv>.>v.v.v>......v..v.>v.>v.>..>
|
||||
v.v>.....>v>.v.v.>.v...>.vv>v>>.....>....>..>.>.v.v..>v.vv..vvv>>.vv>..>>v.v..v.v.>.v.>>..v.>vvv...v>>..vv>vv>.>>.>....v>..>v>.....>v>>v>..
|
||||
.v..vv.>>vv>.v>..>>>v.>v....v.>v>...v>.v.v....v.>.>>..vv>>.........vvv>.>...>v.>.>.>>>>.vv>>.>...>>..>v..v..>>>..>v>v>...v...>.>v...>......
|
||||
..>>>.>v>....vv.>....>.>.v..v>...v..>.>.v>.v.>...v>>v>v.v..v>.v...>vv.v>.>>.>>....>..>>vv..vvv>>v.vv...v.v..v.>>.>v.v.v.>.vv.>....>vvv..v..
|
||||
....vvv>.v>.v.v>v.v..>....v.v>.v...>>v...>.vvvv.vv.v..>vv..>>...>.v.v..v...>..v.vv>>v.>..>v.v.>>..>.>....>>vvvv>vv....v.vv>v.>..>vv>v>..v>.
|
||||
...v.>>v...vv>v.>vvv.vv.....>v>>....vv...v>.>>>.vv>.v>v...>.v.>...v>..>>>.>vv.v....v...>>...>vvv>.v.>vv>.v...>>>......>v.v.>>vv.>.>..v.....
|
||||
.....>v>v.v..>v.v>.v.>..v..>>>vv>...vvv>...v..v.>vv..v>>.v......>....v.vvv...>...v.v>...>...v.v.>v..vvv.v>v>.v.v>...v.>vvv>>>....>>..v...>v
|
||||
.>.>v>.>...>..v>>>v..v.v.v..>..v.vv..>....>.vv>.>...v.>>>>>....vv.>v.>>..>.vvvv.v..>.v..v..>>..v.v.>..>.v....>v.....>v...>.....>v.>v.v.>...
|
||||
.>>v.v.>v.>vvv>......>v>>>v..v.vv..>>v>.>...>>.>.....vv..>>.>.....>.v...>v.v>..v........vv..>>vv..vv..v>.v....>>>v.vvv>.>v.....v...v>...v..
|
||||
v..vv..>>...v.>..v..>.>...v.>>v.>.....>>.>.v...>v>v...>>>>.....>.>>.v>...vv...>v.v.....>>.>..>.>...>....>...vv......v.>>v.vvv>>.>...>>..>>>
|
||||
.v...>>.>..v..vv>.>>..>.>vvv.v.....>v>.>..vv..>>vvv>..>v.>>..>....v>>>....>>.v..v.v..>>.>vvv.>vv.v.>>.v>.......vvv..vv....>.v>>v.>>>>>.>vv>
|
||||
.>.>..v...>..vv.>..v...v.>.v>>v.>.v.v>>v..>>>v>>vv.>v>v..>..>...vv.....>>..v..>>>.vvvv..vv..v.>..>>>...>....>v..>..>>..>..>.>.>>..v....>...
|
||||
>v>.vv..v..v.v>...>>.....>.v.>....v>..>>vvv.>>>.>v.v.>...vvvv.>v...v>.>.>v...>>>>v>..vv>>v..>v....vv....vv>......v....v...v.vv..>vv>>.v>v>v
|
||||
.>vvv...v>v...v..v>.......v>v>>>..v..v..v.>....>...>>>.v>.v>..v.vv.>v>v..>.v...v...>v.>v..vvv.v.....>.>.>>.>>>>vv.....>v>v....v.....v..v.v.
|
||||
>>.>.v..v.v>>....vv.>.v.....>...v>v...>v....v>>.v.v>......>..v>.>vv.v..>>>v..v...>...>vv.>..>>.>..>v.>v>.>v>...>>...v.v..v.>v.>..>..vv>.>v.
|
||||
>>.v>v.vvv.>>....>v..>..v>>>..>v.>....v>...vvv....>.vv....v>....>.vvvv.v.v.>..>v..v.>..vv>..v.>...v>.>>>v>v>v.>..v..v>..vv..>v.v.>.>>..v>v>
|
||||
...>..vv.>......v>.v..>v...>>.v>.v>v..>>..vv.vv...>>.....v>....v.>.v>>v..>v..>....>.>>.v>.>vv..vv>...v>.>>>..>>>..v.>v.>.....>>..v.>.v..>..
|
||||
v>..v.v>v..v>>v.....v.>>....v..v..>>..v>..>>.v.v.....>..>>>...v....>vv>..vvv.>>......v..>>>>>........v..>>.>>>.>>>v...v.vv..v.vv.v..>vv..v.
|
||||
>v..v...v>v.v>vvv...vv.v.v.>......>.>.v.....v>>....>>.v...>vv.>...>..vv>..>...>v.>>...v.v>>v...v..>>v>...>vvv....>v..v..>..>....>.>.v.>>vv.
|
||||
...>v>>>.v>.>vvvvv..>..>.v....>..vv.>>.>...v.....>.v.>.v..v.>>...>.v.v...>>.v>>..v.>.vv...vv.v.>....>.v>.v.>v.v>.>>...vv>vvv>>>>v.vv...v>v.
|
||||
.v.>v...>.v.v..v.v.v......>>v..>....>....>>..>.v>v>>.>.>..v.>....>..>>.>...v.v.>>......>v.>>v.vvvvv>v.>.v>v..>.v.v...>..>..v....v.>v.>>.>v.
|
||||
>.>v>v>v.>v..>v.....>..v...>>>v>.vv...v>.>>...vv.>v.v>>>..v...>.>>>..v>v>v.vv>>v.v.>>..>.>.>....>.v>...>>..vv>.vvv>v..>>>.v.>.vv>>>>.vv>vv.
|
||||
v>>.vv..>..v...>v>.....>.v..v>..v...vvvv.v...>v>>....>...v.>>.>>....>>...>v...v..>>>v.vv.vv>....v>..vv..vv.>.>>...>..v>....>>..v.v>>...>>>v
|
||||
...v>v....v..>..v.v.>.v.>.v..>vv>v.v.v.v.v.>...v>.v..v....v>v..>>.>>>>..>.v...>....>v..vv.v.vvvv...v>>....>..>.>v>v>..>......vv>.....vvv>>.
|
||||
.>.>v.>>..>..>.v.v....vv>>>v..>..v>v>v>v>...>>v>>>.vvv...>v>>v..v.vv.>..v>......v>......>>..>.v>>.>>>v>v..v>.vv>v......>>.....>v.v>....vv..
|
||||
vv>..vvv.v.v.v......>>v...>>.vv....vvvv.>.v>v>.....v.>>v...v..v>..>v..>..>>...>>.v.vv..v>v>.>>.>v..>>v>vv>v>>.>v..v.>.....>...>v.vv.vv.v>..
|
||||
..>v...v.v.v.>>...>.>>v>.>.v..>.v.>...>...>>v>....v....>>..v>>..>>v>>.>..vv..v>v...v.>.>>.>.v>.>.vv>vvvvv>>.v>.>v>v..v.>v.>...>v>....vvv.vv
|
||||
v>v..>>v>...v...>v>....>>v..>v..>>.>>.vv.>..v...>>......v..vv.vv..vv.>>>..>.>>v..vv..v....v...v>..v..>.>..>v>>v.>..v..v>.>v.v>..vvv...v>>..
|
||||
>>v.v>vvv.v...>>.>v..v>....>....v..>>.v>>v>v.v>.........v>v>.v..>.v.>>.>..>....>vvv.>...vv.>>...>.vvv....>.>.v.vv.v>..>..>>>..v..v>>.v.>.v.
|
||||
.v.v.v.>vv.v..>>vv>v>v>..........>v>.>.>.v..vv..>v>>>v.vv....vv>vv....>>v>.vv>vv..vv..v...>v..v.>>vv.>.v.....vv>v.>.>v>>.>>v...>.>.v.v.v>.v
|
||||
v.>>vv.>..>..v.vv....>>..>v>v.v..vv.>>>v.vv..>.>>v..v......>>.>>>..>>...>>>>>v>.>>.>>v>.v>>vv.>v...v..v..v.v>...>>>.v>>.v.v..>.>...>>....v.
|
||||
.>vvv>v>...v>v>..v>>v.>...vvv.v..>>v....v>>vvv..vv>....vv>....vv>v.v.v.>>.v>.....>.>......>.vv.>v...>..>v.v.v>v.vv....v.v....v.>.>>...vvv.>
|
||||
..>v>>...>.v...>..v>>.vvvv.>v>..>...v.v>.v.vv>>v>vv>.>v.>>v>..v.vv.>v>>.v..>v>>...>v>.vvv..>.v.v.>..>...>>v.v..vv>...vvv.vvv.>>.v.>vv>v>v.v
|
||||
>..v>.v.>>v>>..v.>>....vvv.v..v.>....>>..v.>>>.vvv.v..v>vv>>....v.....v..>v.v>.>.vvv..>>.>..>.v.v...vvv..>v>...>vvv>.>vvv>.v>v.>>..>.>..vvv
|
||||
4
rustfmt.toml
Normal file
4
rustfmt.toml
Normal file
@ -0,0 +1,4 @@
|
||||
tab_spaces = 2
|
||||
hard_tabs = true
|
||||
reorder_imports = true
|
||||
newline_style = "Unix"
|
||||
59
src/day1.rs
59
src/day1.rs
@ -1,47 +1,44 @@
|
||||
use std::num::ParseIntError;
|
||||
|
||||
pub fn parse_input(input: &str) -> Result<Vec<u32>, ParseIntError> {
|
||||
input.split_whitespace()
|
||||
.map(|s| s.parse())
|
||||
.collect()
|
||||
input.split_whitespace().map(|s| s.parse()).collect()
|
||||
}
|
||||
|
||||
pub fn part1(depths: &[u32]) -> u32 {
|
||||
let mut count = 0;
|
||||
for i in 1..depths.len() {
|
||||
if depths[i] > depths[i-1] {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
let mut count = 0;
|
||||
for i in 1..depths.len() {
|
||||
if depths[i] > depths[i - 1] {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
pub fn part2(depths: &[u32]) -> u32 {
|
||||
let mut count = 0;
|
||||
for i in 2..depths.len()-1 {
|
||||
if depths[i+1] > depths[i-2] {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
let mut count = 0;
|
||||
for i in 2..depths.len() - 1 {
|
||||
if depths[i + 1] > depths[i - 2] {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 7);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 5);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
208
src/day10.rs
208
src/day10.rs
@ -1,137 +1,135 @@
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum ChunkVariant {
|
||||
Parenthesis,
|
||||
Bracket,
|
||||
Curly,
|
||||
Pointy
|
||||
Parenthesis,
|
||||
Bracket,
|
||||
Curly,
|
||||
Pointy,
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<String> {
|
||||
input.lines().map(|s| s.into()).collect()
|
||||
input.lines().map(|s| s.into()).collect()
|
||||
}
|
||||
|
||||
fn is_opening(c: char) -> bool {
|
||||
c == '(' || c == '[' || c == '{' || c == '<'
|
||||
c == '(' || c == '[' || c == '{' || c == '<'
|
||||
}
|
||||
|
||||
// I know that it is not ideal to throw a panic here. But I'm too lazy to do
|
||||
// error handling. And the input is guaranteed to be correct to this is fine.
|
||||
fn get_chunk_variant(c: char) -> ChunkVariant {
|
||||
match c {
|
||||
'('|')' => ChunkVariant::Parenthesis,
|
||||
'['|']' => ChunkVariant::Bracket,
|
||||
'{'|'}' => ChunkVariant::Curly,
|
||||
'<'|'>' => ChunkVariant::Pointy,
|
||||
_ => panic!("Invalid chunk character")
|
||||
}
|
||||
match c {
|
||||
'(' | ')' => ChunkVariant::Parenthesis,
|
||||
'[' | ']' => ChunkVariant::Bracket,
|
||||
'{' | '}' => ChunkVariant::Curly,
|
||||
'<' | '>' => ChunkVariant::Pointy,
|
||||
_ => panic!("Invalid chunk character"),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_corrupted_chunk_symbol(line: &str) -> Option<ChunkVariant> {
|
||||
let mut active_chunks: Vec<ChunkVariant> = Vec::new();
|
||||
for c in line.chars() {
|
||||
let variant = get_chunk_variant(c);
|
||||
if is_opening(c) {
|
||||
active_chunks.push(variant);
|
||||
} else {
|
||||
if *active_chunks.last().unwrap() != variant {
|
||||
return Some(variant);
|
||||
}
|
||||
active_chunks.pop();
|
||||
}
|
||||
}
|
||||
None
|
||||
let mut active_chunks: Vec<ChunkVariant> = Vec::new();
|
||||
for c in line.chars() {
|
||||
let variant = get_chunk_variant(c);
|
||||
if is_opening(c) {
|
||||
active_chunks.push(variant);
|
||||
} else {
|
||||
if *active_chunks.last().unwrap() != variant {
|
||||
return Some(variant);
|
||||
}
|
||||
active_chunks.pop();
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn part1(lines: &Vec<String>) -> u32 {
|
||||
let mut score = 0;
|
||||
for line in lines {
|
||||
let result = find_corrupted_chunk_symbol(line);
|
||||
score += match result {
|
||||
Some(ChunkVariant::Parenthesis) => 3,
|
||||
Some(ChunkVariant::Bracket) => 57,
|
||||
Some(ChunkVariant::Curly) => 1197,
|
||||
Some(ChunkVariant::Pointy) => 25137,
|
||||
None => 0
|
||||
}
|
||||
}
|
||||
return score;
|
||||
let mut score = 0;
|
||||
for line in lines {
|
||||
let result = find_corrupted_chunk_symbol(line);
|
||||
score += match result {
|
||||
Some(ChunkVariant::Parenthesis) => 3,
|
||||
Some(ChunkVariant::Bracket) => 57,
|
||||
Some(ChunkVariant::Curly) => 1197,
|
||||
Some(ChunkVariant::Pointy) => 25137,
|
||||
None => 0,
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
fn find_unclosed_chunks(line: &str) -> Vec<ChunkVariant> {
|
||||
let mut active_chunks: Vec<ChunkVariant> = Vec::new();
|
||||
for c in line.chars() {
|
||||
if is_opening(c) {
|
||||
active_chunks.push(get_chunk_variant(c));
|
||||
} else {
|
||||
active_chunks.pop();
|
||||
}
|
||||
}
|
||||
active_chunks
|
||||
let mut active_chunks: Vec<ChunkVariant> = Vec::new();
|
||||
for c in line.chars() {
|
||||
if is_opening(c) {
|
||||
active_chunks.push(get_chunk_variant(c));
|
||||
} else {
|
||||
active_chunks.pop();
|
||||
}
|
||||
}
|
||||
active_chunks
|
||||
}
|
||||
|
||||
pub fn part2(lines: &Vec<String>) -> u64 {
|
||||
let mut scores = Vec::new();
|
||||
for line in lines {
|
||||
let corrupted = find_corrupted_chunk_symbol(line);
|
||||
if corrupted == None {
|
||||
let mut score = 0;
|
||||
let mut unclosed_chunks = find_unclosed_chunks(line);
|
||||
unclosed_chunks.reverse();
|
||||
for chunk in unclosed_chunks {
|
||||
score *= 5;
|
||||
score += match chunk {
|
||||
ChunkVariant::Parenthesis => 1,
|
||||
ChunkVariant::Bracket => 2,
|
||||
ChunkVariant::Curly => 3,
|
||||
ChunkVariant::Pointy => 4
|
||||
}
|
||||
}
|
||||
scores.push(score);
|
||||
}
|
||||
}
|
||||
scores.sort();
|
||||
return scores[scores.len()/2];
|
||||
let mut scores = Vec::new();
|
||||
for line in lines {
|
||||
let corrupted = find_corrupted_chunk_symbol(line);
|
||||
if corrupted == None {
|
||||
let mut score = 0;
|
||||
let mut unclosed_chunks = find_unclosed_chunks(line);
|
||||
unclosed_chunks.reverse();
|
||||
for chunk in unclosed_chunks {
|
||||
score *= 5;
|
||||
score += match chunk {
|
||||
ChunkVariant::Parenthesis => 1,
|
||||
ChunkVariant::Bracket => 2,
|
||||
ChunkVariant::Curly => 3,
|
||||
ChunkVariant::Pointy => 4,
|
||||
}
|
||||
}
|
||||
scores.push(score);
|
||||
}
|
||||
}
|
||||
scores.sort();
|
||||
return scores[scores.len() / 2];
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = vec![
|
||||
"[({(<(())[]>[[{[]{<()<>>".into(),
|
||||
"[(()[<>])]({[<{<<[]>>(".into(),
|
||||
"{([(<{}[<>[]}>{[]{[(<()>".into(),
|
||||
"(((({<>}<{<{<>}{[]{[]{}".into(),
|
||||
"[[<[([]))<([[{}[[()]]]".into(),
|
||||
"[{[{({}]{}}([{[{{{}}([]".into(),
|
||||
"{<[[]]>}<{[{[{[]{()[[[]".into(),
|
||||
"[<(<(<(<{}))><([]([]()".into(),
|
||||
"<{([([[(<>()){}]>(<<{{".into(),
|
||||
"<{([{{}}[<[[[<>{}]]]>[]]".into(),
|
||||
];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 26397);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = vec![
|
||||
"[({(<(())[]>[[{[]{<()<>>".into(),
|
||||
"[(()[<>])]({[<{<<[]>>(".into(),
|
||||
"{([(<{}[<>[]}>{[]{[(<()>".into(),
|
||||
"(((({<>}<{<{<>}{[]{[]{}".into(),
|
||||
"[[<[([]))<([[{}[[()]]]".into(),
|
||||
"[{[{({}]{}}([{[{{{}}([]".into(),
|
||||
"{<[[]]>}<{[{[{[]{()[[[]".into(),
|
||||
"[<(<(<(<{}))><([]([]()".into(),
|
||||
"<{([([[(<>()){}]>(<<{{".into(),
|
||||
"<{([{{}}[<[[[<>{}]]]>[]]".into(),
|
||||
];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 26397);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = vec![
|
||||
"[({(<(())[]>[[{[]{<()<>>".into(),
|
||||
"[(()[<>])]({[<{<<[]>>(".into(),
|
||||
"{([(<{}[<>[]}>{[]{[(<()>".into(),
|
||||
"(((({<>}<{<{<>}{[]{[]{}".into(),
|
||||
"[[<[([]))<([[{}[[()]]]".into(),
|
||||
"[{[{({}]{}}([{[{{{}}([]".into(),
|
||||
"{<[[]]>}<{[{[{[]{()[[[]".into(),
|
||||
"[<(<(<(<{}))><([]([]()".into(),
|
||||
"<{([([[(<>()){}]>(<<{{".into(),
|
||||
"<{([{{}}[<[[[<>{}]]]>[]]".into(),
|
||||
];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 288957);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = vec![
|
||||
"[({(<(())[]>[[{[]{<()<>>".into(),
|
||||
"[(()[<>])]({[<{<<[]>>(".into(),
|
||||
"{([(<{}[<>[]}>{[]{[(<()>".into(),
|
||||
"(((({<>}<{<{<>}{[]{[]{}".into(),
|
||||
"[[<[([]))<([[{}[[()]]]".into(),
|
||||
"[{[{({}]{}}([{[{{{}}([]".into(),
|
||||
"{<[[]]>}<{[{[{[]{()[[[]".into(),
|
||||
"[<(<(<(<{}))><([]([]()".into(),
|
||||
"<{([([[(<>()){}]>(<<{{".into(),
|
||||
"<{([{{}}[<[[[<>{}]]]>[]]".into(),
|
||||
];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 288957);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
262
src/day11.rs
262
src/day11.rs
@ -1,171 +1,173 @@
|
||||
use arrayvec::ArrayVec;
|
||||
|
||||
pub fn parse_input(input: &str) -> [[u32; 10]; 10] {
|
||||
input.lines()
|
||||
.map(|s| s.chars()
|
||||
.map(|s| s.to_digit(10).unwrap())
|
||||
.collect::<ArrayVec<u32, 10>>()
|
||||
.into_inner()
|
||||
.unwrap())
|
||||
.collect::<ArrayVec<[u32; 10], 10>>()
|
||||
.into_inner()
|
||||
.unwrap()
|
||||
input
|
||||
.lines()
|
||||
.map(|s| {
|
||||
s.chars()
|
||||
.map(|s| s.to_digit(10).unwrap())
|
||||
.collect::<ArrayVec<u32, 10>>()
|
||||
.into_inner()
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<ArrayVec<[u32; 10], 10>>()
|
||||
.into_inner()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn _display_grid(grid: &[[u32; 10]; 10]) {
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
print!("{:X}", grid[i][j]);
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
print!("\n");
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
print!("{:X}", grid[i][j]);
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
|
||||
fn bump_energy(grid: &mut [[u32; 10]; 10]) {
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
grid[i][j] += 1;
|
||||
}
|
||||
}
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
grid[i][j] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bump_energy_around(grid: &mut [[u32; 10]; 10], i: usize, j: usize) {
|
||||
if j > 0 {
|
||||
grid[i+0][j-1] += 1;
|
||||
}
|
||||
if j < 9 {
|
||||
grid[i+0][j+1] += 1;
|
||||
}
|
||||
if i > 0 {
|
||||
grid[i-1][j+0] += 1;
|
||||
}
|
||||
if i < 9 {
|
||||
grid[i+1][j+0] += 1;
|
||||
}
|
||||
if j > 0 {
|
||||
grid[i + 0][j - 1] += 1;
|
||||
}
|
||||
if j < 9 {
|
||||
grid[i + 0][j + 1] += 1;
|
||||
}
|
||||
if i > 0 {
|
||||
grid[i - 1][j + 0] += 1;
|
||||
}
|
||||
if i < 9 {
|
||||
grid[i + 1][j + 0] += 1;
|
||||
}
|
||||
|
||||
if i > 0 && j > 0 {
|
||||
grid[i-1][j-1] += 1;
|
||||
}
|
||||
if i < 9 && j > 0 {
|
||||
grid[i+1][j-1] += 1;
|
||||
}
|
||||
if i > 0 && j < 9 {
|
||||
grid[i-1][j+1] += 1;
|
||||
}
|
||||
if i < 9 && j < 9 {
|
||||
grid[i+1][j+1] += 1;
|
||||
}
|
||||
if i > 0 && j > 0 {
|
||||
grid[i - 1][j - 1] += 1;
|
||||
}
|
||||
if i < 9 && j > 0 {
|
||||
grid[i + 1][j - 1] += 1;
|
||||
}
|
||||
if i > 0 && j < 9 {
|
||||
grid[i - 1][j + 1] += 1;
|
||||
}
|
||||
if i < 9 && j < 9 {
|
||||
grid[i + 1][j + 1] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn perform_flashes(grid: &mut [[u32; 10]; 10]) -> u32 {
|
||||
let mut flashes = 0;
|
||||
let mut has_flashed: [[bool; 10]; 10] = [[false; 10]; 10];
|
||||
let mut anyone_flashed = true;
|
||||
let mut flashes = 0;
|
||||
let mut has_flashed: [[bool; 10]; 10] = [[false; 10]; 10];
|
||||
let mut anyone_flashed = true;
|
||||
|
||||
while anyone_flashed {
|
||||
anyone_flashed = false;
|
||||
while anyone_flashed {
|
||||
anyone_flashed = false;
|
||||
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
if grid[i][j] > 9 && !has_flashed[i][j] {
|
||||
flashes += 1;
|
||||
has_flashed[i][j] = true;
|
||||
anyone_flashed = true;
|
||||
bump_energy_around(grid, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
if grid[i][j] > 9 && !has_flashed[i][j] {
|
||||
flashes += 1;
|
||||
has_flashed[i][j] = true;
|
||||
anyone_flashed = true;
|
||||
bump_energy_around(grid, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return flashes;
|
||||
return flashes;
|
||||
}
|
||||
|
||||
fn reset_energy(grid: &mut [[u32; 10]; 10]) {
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
if grid[i][j] > 9 {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
if grid[i][j] > 9 {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_step(grid: &mut [[u32; 10]; 10]) -> u32 {
|
||||
bump_energy(grid);
|
||||
let flashes = perform_flashes(grid);
|
||||
reset_energy(grid);
|
||||
return flashes;
|
||||
bump_energy(grid);
|
||||
let flashes = perform_flashes(grid);
|
||||
reset_energy(grid);
|
||||
return flashes;
|
||||
}
|
||||
|
||||
fn has_all_zeros(grid: &[[u32; 10]; 10]) -> bool {
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
if grid[i][j] != 0 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
if grid[i][j] != 0 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn part1(grid: &[[u32; 10]; 10]) -> u32 {
|
||||
let mut flashes = 0;
|
||||
let mut active_grid = grid.clone();
|
||||
for _ in 0..100 {
|
||||
flashes += do_step(&mut active_grid);
|
||||
}
|
||||
return flashes;
|
||||
let mut flashes = 0;
|
||||
let mut active_grid = grid.clone();
|
||||
for _ in 0..100 {
|
||||
flashes += do_step(&mut active_grid);
|
||||
}
|
||||
return flashes;
|
||||
}
|
||||
|
||||
pub fn part2(grid: &[[u32; 10]; 10]) -> u32 {
|
||||
let mut active_grid = grid.clone();
|
||||
let mut step = 0;
|
||||
while !has_all_zeros(&active_grid) {
|
||||
do_step(&mut active_grid);
|
||||
step += 1;
|
||||
}
|
||||
return step;
|
||||
let mut active_grid = grid.clone();
|
||||
let mut step = 0;
|
||||
while !has_all_zeros(&active_grid) {
|
||||
do_step(&mut active_grid);
|
||||
step += 1;
|
||||
}
|
||||
return step;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [
|
||||
[5, 4, 8, 3, 1, 4, 3, 2, 2, 3],
|
||||
[2, 7, 4, 5, 8, 5, 4, 7, 1, 1],
|
||||
[5, 2, 6, 4, 5, 5, 6, 1, 7, 3],
|
||||
[6, 1, 4, 1, 3, 3, 6, 1, 4, 6],
|
||||
[6, 3, 5, 7, 3, 8, 5, 4, 7, 8],
|
||||
[4, 1, 6, 7, 5, 2, 4, 6, 4, 5],
|
||||
[2, 1, 7, 6, 8, 4, 1, 7, 2, 1],
|
||||
[6, 8, 8, 2, 8, 8, 1, 1, 3, 4],
|
||||
[4, 8, 4, 6, 8, 4, 8, 5, 5, 4],
|
||||
[5, 2, 8, 3, 7, 5, 1, 5, 2, 6]
|
||||
];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 1656);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [
|
||||
[5, 4, 8, 3, 1, 4, 3, 2, 2, 3],
|
||||
[2, 7, 4, 5, 8, 5, 4, 7, 1, 1],
|
||||
[5, 2, 6, 4, 5, 5, 6, 1, 7, 3],
|
||||
[6, 1, 4, 1, 3, 3, 6, 1, 4, 6],
|
||||
[6, 3, 5, 7, 3, 8, 5, 4, 7, 8],
|
||||
[4, 1, 6, 7, 5, 2, 4, 6, 4, 5],
|
||||
[2, 1, 7, 6, 8, 4, 1, 7, 2, 1],
|
||||
[6, 8, 8, 2, 8, 8, 1, 1, 3, 4],
|
||||
[4, 8, 4, 6, 8, 4, 8, 5, 5, 4],
|
||||
[5, 2, 8, 3, 7, 5, 1, 5, 2, 6],
|
||||
];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 1656);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [
|
||||
[5, 4, 8, 3, 1, 4, 3, 2, 2, 3],
|
||||
[2, 7, 4, 5, 8, 5, 4, 7, 1, 1],
|
||||
[5, 2, 6, 4, 5, 5, 6, 1, 7, 3],
|
||||
[6, 1, 4, 1, 3, 3, 6, 1, 4, 6],
|
||||
[6, 3, 5, 7, 3, 8, 5, 4, 7, 8],
|
||||
[4, 1, 6, 7, 5, 2, 4, 6, 4, 5],
|
||||
[2, 1, 7, 6, 8, 4, 1, 7, 2, 1],
|
||||
[6, 8, 8, 2, 8, 8, 1, 1, 3, 4],
|
||||
[4, 8, 4, 6, 8, 4, 8, 5, 5, 4],
|
||||
[5, 2, 8, 3, 7, 5, 1, 5, 2, 6]
|
||||
];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 195);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [
|
||||
[5, 4, 8, 3, 1, 4, 3, 2, 2, 3],
|
||||
[2, 7, 4, 5, 8, 5, 4, 7, 1, 1],
|
||||
[5, 2, 6, 4, 5, 5, 6, 1, 7, 3],
|
||||
[6, 1, 4, 1, 3, 3, 6, 1, 4, 6],
|
||||
[6, 3, 5, 7, 3, 8, 5, 4, 7, 8],
|
||||
[4, 1, 6, 7, 5, 2, 4, 6, 4, 5],
|
||||
[2, 1, 7, 6, 8, 4, 1, 7, 2, 1],
|
||||
[6, 8, 8, 2, 8, 8, 1, 1, 3, 4],
|
||||
[4, 8, 4, 6, 8, 4, 8, 5, 5, 4],
|
||||
[5, 2, 8, 3, 7, 5, 1, 5, 2, 6],
|
||||
];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 195);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
233
src/day12.rs
233
src/day12.rs
@ -1,160 +1,175 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<(String, String)> {
|
||||
let mut edges: Vec<(String, String)> = Vec::new();
|
||||
let mut edges: Vec<(String, String)> = Vec::new();
|
||||
|
||||
for line in input.lines() {
|
||||
let (from, to) = line.split_once('-').unwrap();
|
||||
edges.push((from.into(), to.into()));
|
||||
}
|
||||
for line in input.lines() {
|
||||
let (from, to) = line.split_once('-').unwrap();
|
||||
edges.push((from.into(), to.into()));
|
||||
}
|
||||
|
||||
return edges;
|
||||
return edges;
|
||||
}
|
||||
|
||||
fn edges_to_map(edges: &Vec<(String, String)>) -> HashMap<String, Vec<String>> {
|
||||
let mut map = HashMap::new();
|
||||
let mut map = HashMap::new();
|
||||
|
||||
for line in edges {
|
||||
map.entry(line.1.clone())
|
||||
.or_insert(Vec::new())
|
||||
.push(line.0.clone());
|
||||
for line in edges {
|
||||
map
|
||||
.entry(line.1.clone())
|
||||
.or_insert(Vec::new())
|
||||
.push(line.0.clone());
|
||||
|
||||
map.entry(line.0.clone())
|
||||
.or_insert(Vec::new())
|
||||
.push(line.1.clone());
|
||||
}
|
||||
map
|
||||
.entry(line.0.clone())
|
||||
.or_insert(Vec::new())
|
||||
.push(line.1.clone());
|
||||
}
|
||||
|
||||
return map;
|
||||
return map;
|
||||
}
|
||||
|
||||
fn is_path_finished(path: &Vec<&str>) -> bool {
|
||||
return path.contains(&"end")
|
||||
return path.contains(&"end");
|
||||
}
|
||||
|
||||
fn can_be_appended_part1(path: &Vec<&str>, node: &str) -> bool {
|
||||
node.to_uppercase() == node || !path.contains(&node)
|
||||
node.to_uppercase() == node || !path.contains(&node)
|
||||
}
|
||||
|
||||
pub fn part1(edges: &Vec<(String, String)>) -> usize {
|
||||
let map = edges_to_map(edges);
|
||||
let map = edges_to_map(edges);
|
||||
|
||||
let mut finished_paths: Vec<Vec<&str>> = Vec::new();
|
||||
let mut finished_paths: Vec<Vec<&str>> = Vec::new();
|
||||
|
||||
let mut unfinished_paths: Vec<Vec<&str>> = Vec::new();
|
||||
unfinished_paths.push(vec!["start"]);
|
||||
while unfinished_paths.len() > 0 {
|
||||
let mut new_paths = Vec::new();
|
||||
let mut unfinished_paths: Vec<Vec<&str>> = Vec::new();
|
||||
unfinished_paths.push(vec!["start"]);
|
||||
while unfinished_paths.len() > 0 {
|
||||
let mut new_paths = Vec::new();
|
||||
|
||||
for path in &mut unfinished_paths {
|
||||
for node in map.get(*path.last().unwrap()).unwrap() {
|
||||
if can_be_appended_part1(path, node) {
|
||||
let mut new_path = path.clone();
|
||||
new_path.push(node);
|
||||
for path in &mut unfinished_paths {
|
||||
for node in map.get(*path.last().unwrap()).unwrap() {
|
||||
if can_be_appended_part1(path, node) {
|
||||
let mut new_path = path.clone();
|
||||
new_path.push(node);
|
||||
|
||||
if is_path_finished(&new_path) {
|
||||
finished_paths.push(new_path);
|
||||
} else {
|
||||
new_paths.push(new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if is_path_finished(&new_path) {
|
||||
finished_paths.push(new_path);
|
||||
} else {
|
||||
new_paths.push(new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unfinished_paths = new_paths;
|
||||
}
|
||||
unfinished_paths = new_paths;
|
||||
}
|
||||
|
||||
return finished_paths.len();
|
||||
return finished_paths.len();
|
||||
}
|
||||
|
||||
fn can_be_appended_part2(path: &Vec<&str>, node: &str) -> bool {
|
||||
if node == "start" { return false; }
|
||||
if node == "end" { return true; }
|
||||
if node.to_uppercase() == node { return true; }
|
||||
if node == "start" {
|
||||
return false;
|
||||
}
|
||||
if node == "end" {
|
||||
return true;
|
||||
}
|
||||
if node.to_uppercase() == node {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If all lowercase nodes only apear once we can be assure that any lowercase
|
||||
// node that will be added will be correct.
|
||||
let mut uniq = HashSet::new();
|
||||
if path.into_iter().all(move |x| x.to_lowercase() != *x || uniq.insert(x)) {
|
||||
return true;
|
||||
}
|
||||
// If all lowercase nodes only apear once we can be assure that any lowercase
|
||||
// node that will be added will be correct.
|
||||
let mut uniq = HashSet::new();
|
||||
if path
|
||||
.into_iter()
|
||||
.all(move |x| x.to_lowercase() != *x || uniq.insert(x))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return !path.contains(&node);
|
||||
return !path.contains(&node);
|
||||
}
|
||||
|
||||
pub fn part2(edges: &Vec<(String, String)>) -> usize {
|
||||
let map = edges_to_map(edges);
|
||||
let map = edges_to_map(edges);
|
||||
|
||||
let mut finished_paths: Vec<Vec<&str>> = Vec::new();
|
||||
let mut finished_paths: Vec<Vec<&str>> = Vec::new();
|
||||
|
||||
let mut unfinished_paths: Vec<Vec<&str>> = Vec::new();
|
||||
unfinished_paths.push(vec!["start"]);
|
||||
while unfinished_paths.len() > 0 {
|
||||
let mut new_paths = Vec::new();
|
||||
let mut unfinished_paths: Vec<Vec<&str>> = Vec::new();
|
||||
unfinished_paths.push(vec!["start"]);
|
||||
while unfinished_paths.len() > 0 {
|
||||
let mut new_paths = Vec::new();
|
||||
|
||||
for path in &mut unfinished_paths {
|
||||
for node in map.get(*path.last().unwrap()).unwrap() {
|
||||
if can_be_appended_part2(path, node) {
|
||||
let mut new_path = path.clone();
|
||||
new_path.push(node);
|
||||
for path in &mut unfinished_paths {
|
||||
for node in map.get(*path.last().unwrap()).unwrap() {
|
||||
if can_be_appended_part2(path, node) {
|
||||
let mut new_path = path.clone();
|
||||
new_path.push(node);
|
||||
|
||||
if is_path_finished(&new_path) {
|
||||
finished_paths.push(new_path);
|
||||
} else {
|
||||
new_paths.push(new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if is_path_finished(&new_path) {
|
||||
finished_paths.push(new_path);
|
||||
} else {
|
||||
new_paths.push(new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unfinished_paths = new_paths;
|
||||
}
|
||||
unfinished_paths = new_paths;
|
||||
}
|
||||
|
||||
return finished_paths.len();
|
||||
return finished_paths.len();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let cave_system = parse_input("start-A\nstart-b\nA-c\nA-b\nb-d\nA-end\nb-end");
|
||||
let result = part1(&cave_system);
|
||||
assert_eq!(result, 10);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let cave_system = parse_input("start-A\nstart-b\nA-c\nA-b\nb-d\nA-end\nb-end");
|
||||
let result = part1(&cave_system);
|
||||
assert_eq!(result, 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_larger_example() {
|
||||
let cave_system = parse_input("dc-end\nHN-start\nstart-kj\ndc-start\ndc-HN\nLN-dc\nHN-end\nkj-sa\nkj-HN\nkj-dc");
|
||||
let result = part1(&cave_system);
|
||||
assert_eq!(result, 19);
|
||||
}
|
||||
#[test]
|
||||
fn part1_larger_example() {
|
||||
let cave_system = parse_input(
|
||||
"dc-end\nHN-start\nstart-kj\ndc-start\ndc-HN\nLN-dc\nHN-end\nkj-sa\nkj-HN\nkj-dc",
|
||||
);
|
||||
let result = part1(&cave_system);
|
||||
assert_eq!(result, 19);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_largest_example() {
|
||||
let cave_system = parse_input("fs-end\nhe-DX\nfs-he\nstart-DX\npj-DX\nend-zg\nzg-sl\nzg-pj\npj-he\nRW-he\nfs-DX\npj-RW\nzg-RW\nstart-pj\nhe-WI\nzg-he\npj-fs\nstart-RW");
|
||||
let result = part1(&cave_system);
|
||||
assert_eq!(result, 226);
|
||||
}
|
||||
#[test]
|
||||
fn part1_largest_example() {
|
||||
let cave_system = parse_input("fs-end\nhe-DX\nfs-he\nstart-DX\npj-DX\nend-zg\nzg-sl\nzg-pj\npj-he\nRW-he\nfs-DX\npj-RW\nzg-RW\nstart-pj\nhe-WI\nzg-he\npj-fs\nstart-RW");
|
||||
let result = part1(&cave_system);
|
||||
assert_eq!(result, 226);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let cave_system = parse_input("start-A\nstart-b\nA-c\nA-b\nb-d\nA-end\nb-end");
|
||||
let result = part2(&cave_system);
|
||||
assert_eq!(result, 36);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let cave_system = parse_input("start-A\nstart-b\nA-c\nA-b\nb-d\nA-end\nb-end");
|
||||
let result = part2(&cave_system);
|
||||
assert_eq!(result, 36);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_larger_example() {
|
||||
let cave_system = parse_input("dc-end\nHN-start\nstart-kj\ndc-start\ndc-HN\nLN-dc\nHN-end\nkj-sa\nkj-HN\nkj-dc");
|
||||
let result = part2(&cave_system);
|
||||
assert_eq!(result, 103);
|
||||
}
|
||||
#[test]
|
||||
fn part2_larger_example() {
|
||||
let cave_system = parse_input(
|
||||
"dc-end\nHN-start\nstart-kj\ndc-start\ndc-HN\nLN-dc\nHN-end\nkj-sa\nkj-HN\nkj-dc",
|
||||
);
|
||||
let result = part2(&cave_system);
|
||||
assert_eq!(result, 103);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_largest_example() {
|
||||
let cave_system = parse_input("fs-end\nhe-DX\nfs-he\nstart-DX\npj-DX\nend-zg\nzg-sl\nzg-pj\npj-he\nRW-he\nfs-DX\npj-RW\nzg-RW\nstart-pj\nhe-WI\nzg-he\npj-fs\nstart-RW");
|
||||
let result = part2(&cave_system);
|
||||
assert_eq!(result, 3509);
|
||||
}
|
||||
#[test]
|
||||
fn part2_largest_example() {
|
||||
let cave_system = parse_input("fs-end\nhe-DX\nfs-he\nstart-DX\npj-DX\nend-zg\nzg-sl\nzg-pj\npj-he\nRW-he\nfs-DX\npj-RW\nzg-RW\nstart-pj\nhe-WI\nzg-he\npj-fs\nstart-RW");
|
||||
let result = part2(&cave_system);
|
||||
assert_eq!(result, 3509);
|
||||
}
|
||||
}
|
||||
|
||||
215
src/day13.rs
215
src/day13.rs
@ -5,156 +5,143 @@ pub struct Dot(u32, u32);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Fold {
|
||||
X(u32),
|
||||
Y(u32),
|
||||
X(u32),
|
||||
Y(u32),
|
||||
}
|
||||
|
||||
pub struct InputData {
|
||||
dots: Vec<Dot>,
|
||||
folds: Vec<Fold>
|
||||
dots: Vec<Dot>,
|
||||
folds: Vec<Fold>,
|
||||
}
|
||||
|
||||
fn parse_dot(line: &str) -> Dot {
|
||||
let (x, y) = line.split_once(',').unwrap();
|
||||
return Dot(
|
||||
x.parse().unwrap(),
|
||||
y.parse().unwrap()
|
||||
);
|
||||
let (x, y) = line.split_once(',').unwrap();
|
||||
return Dot(x.parse().unwrap(), y.parse().unwrap());
|
||||
}
|
||||
|
||||
fn parse_fold(line: &str) -> Fold {
|
||||
let (axis, coordinate_str) = line.split_once('=').unwrap();
|
||||
let coordinate = coordinate_str.parse().unwrap();
|
||||
match axis {
|
||||
"fold along x" => Fold::X(coordinate),
|
||||
"fold along y" => Fold::Y(coordinate),
|
||||
_ => unreachable!("Unable to parse fold direction")
|
||||
}
|
||||
let (axis, coordinate_str) = line.split_once('=').unwrap();
|
||||
let coordinate = coordinate_str.parse().unwrap();
|
||||
match axis {
|
||||
"fold along x" => Fold::X(coordinate),
|
||||
"fold along y" => Fold::Y(coordinate),
|
||||
_ => unreachable!("Unable to parse fold direction"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> InputData {
|
||||
let (dots_section, folds_section) = input.split_once("\n\n").unwrap();
|
||||
let (dots_section, folds_section) = input.split_once("\n\n").unwrap();
|
||||
|
||||
let dots = dots_section.lines()
|
||||
.map(parse_dot)
|
||||
.collect();
|
||||
let folds = folds_section.lines()
|
||||
.map(parse_fold)
|
||||
.collect();
|
||||
let dots = dots_section.lines().map(parse_dot).collect();
|
||||
let folds = folds_section.lines().map(parse_fold).collect();
|
||||
|
||||
return InputData {
|
||||
dots,
|
||||
folds
|
||||
};
|
||||
return InputData { dots, folds };
|
||||
}
|
||||
|
||||
fn perform_fold(dots: &HashSet<Dot>, fold: &Fold) -> HashSet<Dot> {
|
||||
let mut folded_dots = HashSet::new();
|
||||
let mut folded_dots = HashSet::new();
|
||||
|
||||
for dot in dots.iter() {
|
||||
let folded_dot = match fold {
|
||||
Fold::X(x) => {
|
||||
if dot.0 > *x {
|
||||
Dot(2*x - dot.0, dot.1)
|
||||
} else {
|
||||
dot.clone()
|
||||
}
|
||||
},
|
||||
Fold::Y(y) => {
|
||||
if dot.1 > *y {
|
||||
Dot(dot.0, 2*y - dot.1)
|
||||
} else {
|
||||
dot.clone()
|
||||
}
|
||||
},
|
||||
};
|
||||
folded_dots.insert(folded_dot);
|
||||
}
|
||||
for dot in dots.iter() {
|
||||
let folded_dot = match fold {
|
||||
Fold::X(x) => {
|
||||
if dot.0 > *x {
|
||||
Dot(2 * x - dot.0, dot.1)
|
||||
} else {
|
||||
dot.clone()
|
||||
}
|
||||
}
|
||||
Fold::Y(y) => {
|
||||
if dot.1 > *y {
|
||||
Dot(dot.0, 2 * y - dot.1)
|
||||
} else {
|
||||
dot.clone()
|
||||
}
|
||||
}
|
||||
};
|
||||
folded_dots.insert(folded_dot);
|
||||
}
|
||||
|
||||
return folded_dots;
|
||||
return folded_dots;
|
||||
}
|
||||
|
||||
pub fn part1(input: &InputData) -> usize {
|
||||
let mut folded_dots = HashSet::new();
|
||||
for dot in &input.dots {
|
||||
folded_dots.insert(dot.clone());
|
||||
}
|
||||
folded_dots = perform_fold(&folded_dots, &input.folds[0]);
|
||||
folded_dots.len() as usize
|
||||
let mut folded_dots = HashSet::new();
|
||||
for dot in &input.dots {
|
||||
folded_dots.insert(dot.clone());
|
||||
}
|
||||
folded_dots = perform_fold(&folded_dots, &input.folds[0]);
|
||||
folded_dots.len() as usize
|
||||
}
|
||||
|
||||
fn determine_dot_bounds(dots: &HashSet<Dot>) -> (u32, u32, u32, u32) {
|
||||
let mut min_x = u32::MAX;
|
||||
let mut min_y = u32::MAX;
|
||||
let mut max_x = u32::MIN;
|
||||
let mut max_y = u32::MIN;
|
||||
let mut min_x = u32::MAX;
|
||||
let mut min_y = u32::MAX;
|
||||
let mut max_x = u32::MIN;
|
||||
let mut max_y = u32::MIN;
|
||||
|
||||
for dot in dots {
|
||||
min_x = min_x.min(dot.0);
|
||||
min_y = min_y.min(dot.1);
|
||||
max_x = max_x.max(dot.0);
|
||||
max_y = max_y.max(dot.1);
|
||||
}
|
||||
for dot in dots {
|
||||
min_x = min_x.min(dot.0);
|
||||
min_y = min_y.min(dot.1);
|
||||
max_x = max_x.max(dot.0);
|
||||
max_y = max_y.max(dot.1);
|
||||
}
|
||||
|
||||
return (min_x, min_y, max_x, max_y);
|
||||
return (min_x, min_y, max_x, max_y);
|
||||
}
|
||||
|
||||
fn render_dots(dots: &HashSet<Dot>) {
|
||||
let (min_x, min_y, max_x, max_y) = determine_dot_bounds(dots);
|
||||
for y in min_y..=max_y {
|
||||
for x in min_x..=max_x {
|
||||
if dots.contains(&Dot(x, y)) {
|
||||
print!("#");
|
||||
} else {
|
||||
print!(".");
|
||||
}
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
let (min_x, min_y, max_x, max_y) = determine_dot_bounds(dots);
|
||||
for y in min_y..=max_y {
|
||||
for x in min_x..=max_x {
|
||||
if dots.contains(&Dot(x, y)) {
|
||||
print!("#");
|
||||
} else {
|
||||
print!(".");
|
||||
}
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part2(input: &InputData) {
|
||||
let mut folded_dots = HashSet::new();
|
||||
for dot in &input.dots {
|
||||
folded_dots.insert(dot.clone());
|
||||
}
|
||||
for fold in &input.folds {
|
||||
folded_dots = perform_fold(&folded_dots, fold);
|
||||
}
|
||||
render_dots(&folded_dots);
|
||||
let mut folded_dots = HashSet::new();
|
||||
for dot in &input.dots {
|
||||
folded_dots.insert(dot.clone());
|
||||
}
|
||||
for fold in &input.folds {
|
||||
folded_dots = perform_fold(&folded_dots, fold);
|
||||
}
|
||||
render_dots(&folded_dots);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let dots = vec![
|
||||
Dot(6, 10),
|
||||
Dot(0, 14),
|
||||
Dot(9, 10),
|
||||
Dot(0, 3),
|
||||
Dot(10, 4),
|
||||
Dot(4, 11),
|
||||
Dot(6, 0),
|
||||
Dot(6, 12),
|
||||
Dot(4, 1),
|
||||
Dot(0, 13),
|
||||
Dot(10, 12),
|
||||
Dot(3, 4),
|
||||
Dot(3, 0),
|
||||
Dot(8, 4),
|
||||
Dot(1, 10),
|
||||
Dot(2 ,14),
|
||||
Dot(8 ,10),
|
||||
Dot(9, 0)
|
||||
];
|
||||
let folds = vec![
|
||||
Fold::Y(7),
|
||||
Fold::X(5),
|
||||
];
|
||||
let result = part1(&InputData{ dots, folds });
|
||||
assert_eq!(result, 17);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let dots = vec![
|
||||
Dot(6, 10),
|
||||
Dot(0, 14),
|
||||
Dot(9, 10),
|
||||
Dot(0, 3),
|
||||
Dot(10, 4),
|
||||
Dot(4, 11),
|
||||
Dot(6, 0),
|
||||
Dot(6, 12),
|
||||
Dot(4, 1),
|
||||
Dot(0, 13),
|
||||
Dot(10, 12),
|
||||
Dot(3, 4),
|
||||
Dot(3, 0),
|
||||
Dot(8, 4),
|
||||
Dot(1, 10),
|
||||
Dot(2, 14),
|
||||
Dot(8, 10),
|
||||
Dot(9, 0),
|
||||
];
|
||||
let folds = vec![Fold::Y(7), Fold::X(5)];
|
||||
let result = part1(&InputData { dots, folds });
|
||||
assert_eq!(result, 17);
|
||||
}
|
||||
}
|
||||
|
||||
285
src/day14.rs
285
src/day14.rs
@ -1,160 +1,187 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct InputData {
|
||||
polymer_template: String,
|
||||
rules: HashMap<[char; 2], char>
|
||||
polymer_template: String,
|
||||
rules: HashMap<[char; 2], char>,
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> InputData {
|
||||
let (polymer_template, rules_section) = input.split_once("\n\n").unwrap();
|
||||
let mut rules = HashMap::new();
|
||||
for line in rules_section.lines() {
|
||||
let (pattern, expansion) = line.split_once(" -> ").unwrap();
|
||||
rules.insert(
|
||||
[pattern.chars().nth(0).unwrap(), pattern.chars().nth(1).unwrap()],
|
||||
expansion.chars().nth(0).unwrap()
|
||||
);
|
||||
}
|
||||
return InputData {
|
||||
polymer_template: polymer_template.into(),
|
||||
rules
|
||||
};
|
||||
let (polymer_template, rules_section) = input.split_once("\n\n").unwrap();
|
||||
let mut rules = HashMap::new();
|
||||
for line in rules_section.lines() {
|
||||
let (pattern, expansion) = line.split_once(" -> ").unwrap();
|
||||
rules.insert(
|
||||
[
|
||||
pattern.chars().nth(0).unwrap(),
|
||||
pattern.chars().nth(1).unwrap(),
|
||||
],
|
||||
expansion.chars().nth(0).unwrap(),
|
||||
);
|
||||
}
|
||||
return InputData {
|
||||
polymer_template: polymer_template.into(),
|
||||
rules,
|
||||
};
|
||||
}
|
||||
|
||||
fn naive_expand_polymer(polymer: Vec<char>, rules: &HashMap<[char; 2], char>) -> Vec<char> {
|
||||
let mut new_polymer = Vec::new();
|
||||
for i in 0..polymer.len()-1 {
|
||||
new_polymer.push(polymer[i]);
|
||||
let pair = [polymer[i], polymer[i+1]];
|
||||
let rule = rules.get(&pair);
|
||||
if rule != None {
|
||||
new_polymer.push(*rule.unwrap());
|
||||
}
|
||||
}
|
||||
new_polymer.push(*polymer.last().unwrap());
|
||||
return new_polymer;
|
||||
let mut new_polymer = Vec::new();
|
||||
for i in 0..polymer.len() - 1 {
|
||||
new_polymer.push(polymer[i]);
|
||||
let pair = [polymer[i], polymer[i + 1]];
|
||||
let rule = rules.get(&pair);
|
||||
if rule != None {
|
||||
new_polymer.push(*rule.unwrap());
|
||||
}
|
||||
}
|
||||
new_polymer.push(*polymer.last().unwrap());
|
||||
return new_polymer;
|
||||
}
|
||||
|
||||
pub fn part1(input: &InputData) -> u32 {
|
||||
let mut polymer = input.polymer_template.chars().collect();
|
||||
for _ in 0..10 {
|
||||
polymer = naive_expand_polymer(polymer, &input.rules);
|
||||
}
|
||||
let mut polymer = input.polymer_template.chars().collect();
|
||||
for _ in 0..10 {
|
||||
polymer = naive_expand_polymer(polymer, &input.rules);
|
||||
}
|
||||
|
||||
let mut element_amounts = HashMap::new();
|
||||
for c in polymer {
|
||||
let amount = element_amounts.entry(c).or_insert(0);
|
||||
*amount += 1;
|
||||
}
|
||||
let mut element_amounts = HashMap::new();
|
||||
for c in polymer {
|
||||
let amount = element_amounts.entry(c).or_insert(0);
|
||||
*amount += 1;
|
||||
}
|
||||
|
||||
let least_common_element = element_amounts.iter().min_by(|a, b| a.1.cmp(b.1)).unwrap().1;
|
||||
let most_common_element = element_amounts.iter().max_by(|a, b| a.1.cmp(b.1)).unwrap().1;
|
||||
return most_common_element - least_common_element;
|
||||
let least_common_element = element_amounts
|
||||
.iter()
|
||||
.min_by(|a, b| a.1.cmp(b.1))
|
||||
.unwrap()
|
||||
.1;
|
||||
let most_common_element = element_amounts
|
||||
.iter()
|
||||
.max_by(|a, b| a.1.cmp(b.1))
|
||||
.unwrap()
|
||||
.1;
|
||||
return most_common_element - least_common_element;
|
||||
}
|
||||
|
||||
fn expand_polymer(polymer_pairs: &HashMap<[char; 2], u64>, rules: &HashMap<[char; 2], char>) -> HashMap<[char; 2], u64> {
|
||||
let mut new_pairs = HashMap::new();
|
||||
for entry in polymer_pairs {
|
||||
let pair = entry.0;
|
||||
if rules.contains_key(pair) {
|
||||
let rule = *rules.get(pair).unwrap();
|
||||
fn expand_polymer(
|
||||
polymer_pairs: &HashMap<[char; 2], u64>,
|
||||
rules: &HashMap<[char; 2], char>,
|
||||
) -> HashMap<[char; 2], u64> {
|
||||
let mut new_pairs = HashMap::new();
|
||||
for entry in polymer_pairs {
|
||||
let pair = entry.0;
|
||||
if rules.contains_key(pair) {
|
||||
let rule = *rules.get(pair).unwrap();
|
||||
|
||||
let left_pair = [pair[0], rule];
|
||||
let left_entry = new_pairs.entry(left_pair).or_insert(0);
|
||||
*left_entry += entry.1;
|
||||
let left_pair = [pair[0], rule];
|
||||
let left_entry = new_pairs.entry(left_pair).or_insert(0);
|
||||
*left_entry += entry.1;
|
||||
|
||||
let right_pair = [rule, pair[1]];
|
||||
let right_entry = new_pairs.entry(right_pair).or_insert(0);
|
||||
*right_entry += entry.1;
|
||||
} else {
|
||||
let new_entry = new_pairs.entry(*entry.0).or_insert(0);
|
||||
*new_entry = *entry.1;
|
||||
}
|
||||
}
|
||||
return new_pairs;
|
||||
|
||||
let right_pair = [rule, pair[1]];
|
||||
let right_entry = new_pairs.entry(right_pair).or_insert(0);
|
||||
*right_entry += entry.1;
|
||||
} else {
|
||||
let new_entry = new_pairs.entry(*entry.0).or_insert(0);
|
||||
*new_entry = *entry.1;
|
||||
}
|
||||
}
|
||||
return new_pairs;
|
||||
}
|
||||
|
||||
pub fn part2(input: &InputData) -> u64 {
|
||||
let polymer_template = &input.polymer_template;
|
||||
let mut polymer_pairs = HashMap::new();
|
||||
for i in 0..polymer_template.len()-1 {
|
||||
let pair = [
|
||||
polymer_template.chars().nth(i).unwrap(),
|
||||
polymer_template.chars().nth(i+1).unwrap()
|
||||
];
|
||||
let entry = polymer_pairs.entry(pair).or_insert(0);
|
||||
*entry += 1;
|
||||
}
|
||||
let polymer_template = &input.polymer_template;
|
||||
let mut polymer_pairs = HashMap::new();
|
||||
for i in 0..polymer_template.len() - 1 {
|
||||
let pair = [
|
||||
polymer_template.chars().nth(i).unwrap(),
|
||||
polymer_template.chars().nth(i + 1).unwrap(),
|
||||
];
|
||||
let entry = polymer_pairs.entry(pair).or_insert(0);
|
||||
*entry += 1;
|
||||
}
|
||||
|
||||
for _ in 0..40 {
|
||||
polymer_pairs = expand_polymer(&polymer_pairs, &input.rules);
|
||||
}
|
||||
for _ in 0..40 {
|
||||
polymer_pairs = expand_polymer(&polymer_pairs, &input.rules);
|
||||
}
|
||||
|
||||
let mut element_amounts = HashMap::new();
|
||||
for entry in polymer_pairs {
|
||||
for c in entry.0 {
|
||||
let amount = element_amounts.entry(c).or_insert(0);
|
||||
*amount += entry.1;
|
||||
}
|
||||
}
|
||||
let mut element_amounts = HashMap::new();
|
||||
for entry in polymer_pairs {
|
||||
for c in entry.0 {
|
||||
let amount = element_amounts.entry(c).or_insert(0);
|
||||
*amount += entry.1;
|
||||
}
|
||||
}
|
||||
|
||||
let least_common_element = element_amounts.iter().min_by(|a, b| a.1.cmp(b.1)).unwrap().1;
|
||||
let most_common_element = element_amounts.iter().max_by(|a, b| a.1.cmp(b.1)).unwrap().1;
|
||||
return (most_common_element - least_common_element)/2 + 1;
|
||||
let least_common_element = element_amounts
|
||||
.iter()
|
||||
.min_by(|a, b| a.1.cmp(b.1))
|
||||
.unwrap()
|
||||
.1;
|
||||
let most_common_element = element_amounts
|
||||
.iter()
|
||||
.max_by(|a, b| a.1.cmp(b.1))
|
||||
.unwrap()
|
||||
.1;
|
||||
return (most_common_element - least_common_element) / 2 + 1;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let polymer_template = String::from("NNCB");
|
||||
let rules = HashMap::from([
|
||||
(['C', 'H'], 'B'),
|
||||
(['H', 'H'], 'N'),
|
||||
(['C', 'B'], 'H'),
|
||||
(['N', 'H'], 'C'),
|
||||
(['H', 'B'], 'C'),
|
||||
(['H', 'C'], 'B'),
|
||||
(['H', 'N'], 'C'),
|
||||
(['N', 'N'], 'C'),
|
||||
(['B', 'H'], 'H'),
|
||||
(['N', 'C'], 'B'),
|
||||
(['N', 'B'], 'B'),
|
||||
(['B', 'N'], 'B'),
|
||||
(['B', 'B'], 'N'),
|
||||
(['B', 'C'], 'B'),
|
||||
(['C', 'C'], 'N'),
|
||||
(['C', 'N'], 'C')
|
||||
]);
|
||||
let result = part1(&InputData { polymer_template, rules });
|
||||
assert_eq!(result, 1588);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let polymer_template = String::from("NNCB");
|
||||
let rules = HashMap::from([
|
||||
(['C', 'H'], 'B'),
|
||||
(['H', 'H'], 'N'),
|
||||
(['C', 'B'], 'H'),
|
||||
(['N', 'H'], 'C'),
|
||||
(['H', 'B'], 'C'),
|
||||
(['H', 'C'], 'B'),
|
||||
(['H', 'N'], 'C'),
|
||||
(['N', 'N'], 'C'),
|
||||
(['B', 'H'], 'H'),
|
||||
(['N', 'C'], 'B'),
|
||||
(['N', 'B'], 'B'),
|
||||
(['B', 'N'], 'B'),
|
||||
(['B', 'B'], 'N'),
|
||||
(['B', 'C'], 'B'),
|
||||
(['C', 'C'], 'N'),
|
||||
(['C', 'N'], 'C'),
|
||||
]);
|
||||
let result = part1(&InputData {
|
||||
polymer_template,
|
||||
rules,
|
||||
});
|
||||
assert_eq!(result, 1588);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let polymer_template = String::from("NNCB");
|
||||
let rules = HashMap::from([
|
||||
(['C', 'H'], 'B'),
|
||||
(['H', 'H'], 'N'),
|
||||
(['C', 'B'], 'H'),
|
||||
(['N', 'H'], 'C'),
|
||||
(['H', 'B'], 'C'),
|
||||
(['H', 'C'], 'B'),
|
||||
(['H', 'N'], 'C'),
|
||||
(['N', 'N'], 'C'),
|
||||
(['B', 'H'], 'H'),
|
||||
(['N', 'C'], 'B'),
|
||||
(['N', 'B'], 'B'),
|
||||
(['B', 'N'], 'B'),
|
||||
(['B', 'B'], 'N'),
|
||||
(['B', 'C'], 'B'),
|
||||
(['C', 'C'], 'N'),
|
||||
(['C', 'N'], 'C')
|
||||
]);
|
||||
let result = part2(&InputData { polymer_template, rules });
|
||||
assert_eq!(result, 2188189693529);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let polymer_template = String::from("NNCB");
|
||||
let rules = HashMap::from([
|
||||
(['C', 'H'], 'B'),
|
||||
(['H', 'H'], 'N'),
|
||||
(['C', 'B'], 'H'),
|
||||
(['N', 'H'], 'C'),
|
||||
(['H', 'B'], 'C'),
|
||||
(['H', 'C'], 'B'),
|
||||
(['H', 'N'], 'C'),
|
||||
(['N', 'N'], 'C'),
|
||||
(['B', 'H'], 'H'),
|
||||
(['N', 'C'], 'B'),
|
||||
(['N', 'B'], 'B'),
|
||||
(['B', 'N'], 'B'),
|
||||
(['B', 'B'], 'N'),
|
||||
(['B', 'C'], 'B'),
|
||||
(['C', 'C'], 'N'),
|
||||
(['C', 'N'], 'C'),
|
||||
]);
|
||||
let result = part2(&InputData {
|
||||
polymer_template,
|
||||
rules,
|
||||
});
|
||||
assert_eq!(result, 2188189693529);
|
||||
}
|
||||
}
|
||||
|
||||
186
src/day15.rs
186
src/day15.rs
@ -1,114 +1,120 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use priority_queue::PriorityQueue;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Grid {
|
||||
rows: u32,
|
||||
cols: u32,
|
||||
data: Vec<u32>,
|
||||
scale: u32
|
||||
rows: u32,
|
||||
cols: u32,
|
||||
data: Vec<u32>,
|
||||
scale: u32,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
fn new(rows: u32, cols: u32, data: Vec<u32>) -> Grid {
|
||||
return Grid {
|
||||
rows, cols, data,
|
||||
scale: 1
|
||||
}
|
||||
}
|
||||
fn new(rows: u32, cols: u32, data: Vec<u32>) -> Grid {
|
||||
return Grid {
|
||||
rows,
|
||||
cols,
|
||||
data,
|
||||
scale: 1,
|
||||
};
|
||||
}
|
||||
|
||||
fn get(&self, point: &(u32, u32)) -> u32 {
|
||||
let row = point.0 % self.rows;
|
||||
let col = point.1 % self.cols;
|
||||
let value = self.data[(row * self.cols + col) as usize];
|
||||
return (value + point.0 / self.rows + point.1 / self.cols - 1) % 9 + 1;
|
||||
}
|
||||
fn get(&self, point: &(u32, u32)) -> u32 {
|
||||
let row = point.0 % self.rows;
|
||||
let col = point.1 % self.cols;
|
||||
let value = self.data[(row * self.cols + col) as usize];
|
||||
return (value + point.0 / self.rows + point.1 / self.cols - 1) % 9 + 1;
|
||||
}
|
||||
|
||||
fn width(&self) -> u32 {
|
||||
self.cols * self.scale
|
||||
}
|
||||
fn width(&self) -> u32 {
|
||||
self.cols * self.scale
|
||||
}
|
||||
|
||||
fn height(&self) -> u32 {
|
||||
self.rows * self.scale
|
||||
}
|
||||
fn height(&self) -> u32 {
|
||||
self.rows * self.scale
|
||||
}
|
||||
|
||||
fn within_bounds(&self, point: &(i32, i32)) -> bool {
|
||||
point.0 >= 0 && point.1 >= 0 && point.0 < self.height() as i32 && point.1 < self.width() as i32
|
||||
}
|
||||
fn within_bounds(&self, point: &(i32, i32)) -> bool {
|
||||
point.0 >= 0 && point.1 >= 0 && point.0 < self.height() as i32 && point.1 < self.width() as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Grid {
|
||||
let mut data = Vec::new();
|
||||
let mut rows = 0;
|
||||
let mut cols = 0;
|
||||
for line in input.lines() {
|
||||
rows += 1;
|
||||
for c in line.chars() {
|
||||
if rows == 1 { cols += 1 }
|
||||
data.push(c.to_digit(10).unwrap());
|
||||
}
|
||||
}
|
||||
return Grid::new(rows, cols, data);
|
||||
let mut data = Vec::new();
|
||||
let mut rows = 0;
|
||||
let mut cols = 0;
|
||||
for line in input.lines() {
|
||||
rows += 1;
|
||||
for c in line.chars() {
|
||||
if rows == 1 {
|
||||
cols += 1
|
||||
}
|
||||
data.push(c.to_digit(10).unwrap());
|
||||
}
|
||||
}
|
||||
return Grid::new(rows, cols, data);
|
||||
}
|
||||
|
||||
fn find_neighbours(pos: &(u32, u32), grid: &Grid, offsets: &[(i32, i32)]) -> Vec<(u32, u32)> {
|
||||
let mut neighbours = Vec::new();
|
||||
for offset in offsets {
|
||||
let row = pos.0 as i32 + offset.0;
|
||||
let col = pos.1 as i32 + offset.1;
|
||||
if grid.within_bounds(&(row, col)) {
|
||||
neighbours.push((row as u32, col as u32));
|
||||
}
|
||||
}
|
||||
return neighbours;
|
||||
let mut neighbours = Vec::new();
|
||||
for offset in offsets {
|
||||
let row = pos.0 as i32 + offset.0;
|
||||
let col = pos.1 as i32 + offset.1;
|
||||
if grid.within_bounds(&(row, col)) {
|
||||
neighbours.push((row as u32, col as u32));
|
||||
}
|
||||
}
|
||||
return neighbours;
|
||||
}
|
||||
|
||||
fn find_shortest_path_cost(grid: &Grid) -> u32 {
|
||||
let mut total_costs: HashMap<(u32, u32), u32> = HashMap::new();
|
||||
let mut min_pq: PriorityQueue<(u32, u32), i32> = PriorityQueue::new();
|
||||
let mut visited: HashSet<(u32, u32)> = HashSet::new();
|
||||
let neighbour_offsets = [ (0, 1), (0, -1), (1, 0), (-1, 0) ];
|
||||
min_pq.push((0, 0), 0);
|
||||
total_costs.insert((0, 0), 0);
|
||||
let mut total_costs: HashMap<(u32, u32), u32> = HashMap::new();
|
||||
let mut min_pq: PriorityQueue<(u32, u32), i32> = PriorityQueue::new();
|
||||
let mut visited: HashSet<(u32, u32)> = HashSet::new();
|
||||
let neighbour_offsets = [(0, 1), (0, -1), (1, 0), (-1, 0)];
|
||||
min_pq.push((0, 0), 0);
|
||||
total_costs.insert((0, 0), 0);
|
||||
|
||||
while !min_pq.is_empty() {
|
||||
let new_smallest = min_pq.pop().unwrap().0;
|
||||
visited.insert(new_smallest);
|
||||
while !min_pq.is_empty() {
|
||||
let new_smallest = min_pq.pop().unwrap().0;
|
||||
visited.insert(new_smallest);
|
||||
|
||||
for neighbour in find_neighbours(&new_smallest, grid, &neighbour_offsets) {
|
||||
if visited.contains(&neighbour) {
|
||||
continue;
|
||||
}
|
||||
for neighbour in find_neighbours(&new_smallest, grid, &neighbour_offsets) {
|
||||
if visited.contains(&neighbour) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let alt_distance = grid.get(&neighbour);
|
||||
let alt_path = total_costs.get(&new_smallest).unwrap_or(&u32::MAX) + alt_distance;
|
||||
if alt_path < *total_costs.get(&neighbour).unwrap_or(&u32::MAX) {
|
||||
total_costs.insert(neighbour, alt_path);
|
||||
min_pq.push_decrease(neighbour, -(alt_path as i32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *total_costs.get(&(grid.height()-1, grid.width()-1)).unwrap();
|
||||
let alt_distance = grid.get(&neighbour);
|
||||
let alt_path = total_costs.get(&new_smallest).unwrap_or(&u32::MAX) + alt_distance;
|
||||
if alt_path < *total_costs.get(&neighbour).unwrap_or(&u32::MAX) {
|
||||
total_costs.insert(neighbour, alt_path);
|
||||
min_pq.push_decrease(neighbour, -(alt_path as i32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return *total_costs
|
||||
.get(&(grid.height() - 1, grid.width() - 1))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn part1(grid: &Grid) -> u32 {
|
||||
find_shortest_path_cost(grid)
|
||||
find_shortest_path_cost(grid)
|
||||
}
|
||||
|
||||
pub fn part2(grid: &mut Grid) -> u32 {
|
||||
grid.scale = 5;
|
||||
find_shortest_path_cost(grid)
|
||||
grid.scale = 5;
|
||||
find_shortest_path_cost(grid)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let grid = parse_input("1163751742
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let grid = parse_input(
|
||||
"1163751742
|
||||
1381373672
|
||||
2136511328
|
||||
3694931569
|
||||
@ -117,14 +123,16 @@ mod tests {
|
||||
1359912421
|
||||
3125421639
|
||||
1293138521
|
||||
2311944581");
|
||||
let result = part1(&grid);
|
||||
assert_eq!(result, 40);
|
||||
}
|
||||
2311944581",
|
||||
);
|
||||
let result = part1(&grid);
|
||||
assert_eq!(result, 40);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let mut grid = parse_input("1163751742
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let mut grid = parse_input(
|
||||
"1163751742
|
||||
1381373672
|
||||
2136511328
|
||||
3694931569
|
||||
@ -133,9 +141,9 @@ mod tests {
|
||||
1359912421
|
||||
3125421639
|
||||
1293138521
|
||||
2311944581");
|
||||
let result = part2(&mut grid);
|
||||
assert_eq!(result, 315);
|
||||
}
|
||||
2311944581",
|
||||
);
|
||||
let result = part2(&mut grid);
|
||||
assert_eq!(result, 315);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
393
src/day16.rs
393
src/day16.rs
@ -1,256 +1,267 @@
|
||||
|
||||
pub enum PacketBody {
|
||||
Literal(u64),
|
||||
Operator(Vec<Packet>)
|
||||
Literal(u64),
|
||||
Operator(Vec<Packet>),
|
||||
}
|
||||
|
||||
pub struct Packet {
|
||||
version: u8,
|
||||
r#type: u8,
|
||||
body: PacketBody
|
||||
version: u8,
|
||||
r#type: u8,
|
||||
body: PacketBody,
|
||||
}
|
||||
|
||||
fn to_bits(hex: &str) -> String {
|
||||
let mut bits = String::new();
|
||||
for c in hex.bytes() {
|
||||
match c {
|
||||
b'0'..=b'9' => bits.push_str(format!("{:0>4b}", c - b'0').as_str()),
|
||||
b'A'..=b'F' => bits.push_str(format!("{:0>4b}", c - b'A' + 10).as_str()),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
let mut bits = String::new();
|
||||
for c in hex.bytes() {
|
||||
match c {
|
||||
b'0'..=b'9' => bits.push_str(format!("{:0>4b}", c - b'0').as_str()),
|
||||
b'A'..=b'F' => bits.push_str(format!("{:0>4b}", c - b'A' + 10).as_str()),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
fn parse_literal_body(bits_str: &str) -> (PacketBody, u32) {
|
||||
let mut value_bits = String::new();
|
||||
let mut cursor = 0;
|
||||
let bytes = bits_str.as_bytes();
|
||||
loop {
|
||||
value_bits.push_str(&bits_str[cursor+1..cursor+5]);
|
||||
if bytes[cursor] == b'0' { break; }
|
||||
cursor += 5;
|
||||
}
|
||||
let value = u64::from_str_radix(&value_bits, 2).unwrap();
|
||||
let mut value_bits = String::new();
|
||||
let mut cursor = 0;
|
||||
let bytes = bits_str.as_bytes();
|
||||
loop {
|
||||
value_bits.push_str(&bits_str[cursor + 1..cursor + 5]);
|
||||
if bytes[cursor] == b'0' {
|
||||
break;
|
||||
}
|
||||
cursor += 5;
|
||||
}
|
||||
let value = u64::from_str_radix(&value_bits, 2).unwrap();
|
||||
|
||||
return (PacketBody::Literal(value), (cursor+5) as u32);
|
||||
return (PacketBody::Literal(value), (cursor + 5) as u32);
|
||||
}
|
||||
|
||||
fn parse_operator_body(bits_str: &str) -> (PacketBody, u32) {
|
||||
let mut size: usize = 0;
|
||||
let mut packets = Vec::new();
|
||||
let bytes = bits_str.as_bytes();
|
||||
size += 1;
|
||||
if bytes[0] == b'1' {
|
||||
size += 11;
|
||||
let count = u32::from_str_radix(&bits_str[1..12], 2).unwrap();
|
||||
for _ in 0..count {
|
||||
let (packet, s) = parse_packet(&bits_str[size..]);
|
||||
packets.push(packet);
|
||||
size += s as usize;
|
||||
}
|
||||
} else {
|
||||
let total_size = u32::from_str_radix(&bits_str[1..16], 2).unwrap();
|
||||
size += 15;
|
||||
while ((size-16) as u32) < total_size {
|
||||
let (packet, s) = parse_packet(&bits_str[size..]);
|
||||
packets.push(packet);
|
||||
size += s as usize;
|
||||
}
|
||||
}
|
||||
return (PacketBody::Operator(packets), size as u32);
|
||||
let mut size: usize = 0;
|
||||
let mut packets = Vec::new();
|
||||
let bytes = bits_str.as_bytes();
|
||||
size += 1;
|
||||
if bytes[0] == b'1' {
|
||||
size += 11;
|
||||
let count = u32::from_str_radix(&bits_str[1..12], 2).unwrap();
|
||||
for _ in 0..count {
|
||||
let (packet, s) = parse_packet(&bits_str[size..]);
|
||||
packets.push(packet);
|
||||
size += s as usize;
|
||||
}
|
||||
} else {
|
||||
let total_size = u32::from_str_radix(&bits_str[1..16], 2).unwrap();
|
||||
size += 15;
|
||||
while ((size - 16) as u32) < total_size {
|
||||
let (packet, s) = parse_packet(&bits_str[size..]);
|
||||
packets.push(packet);
|
||||
size += s as usize;
|
||||
}
|
||||
}
|
||||
return (PacketBody::Operator(packets), size as u32);
|
||||
}
|
||||
|
||||
fn parse_packet(bits: &str) -> (Packet, u32) {
|
||||
let r#type = u8::from_str_radix(&bits[3..6], 2).unwrap();
|
||||
let (body, body_size) = match r#type {
|
||||
4 => parse_literal_body(&bits[6..]),
|
||||
_ => parse_operator_body(&bits[6..])
|
||||
};
|
||||
let r#type = u8::from_str_radix(&bits[3..6], 2).unwrap();
|
||||
let (body, body_size) = match r#type {
|
||||
4 => parse_literal_body(&bits[6..]),
|
||||
_ => parse_operator_body(&bits[6..]),
|
||||
};
|
||||
|
||||
return (Packet {
|
||||
version: u8::from_str_radix(&bits[0..3], 2).unwrap(),
|
||||
r#type,
|
||||
body
|
||||
},
|
||||
body_size + 6
|
||||
);
|
||||
return (
|
||||
Packet {
|
||||
version: u8::from_str_radix(&bits[0..3], 2).unwrap(),
|
||||
r#type,
|
||||
body,
|
||||
},
|
||||
body_size + 6,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Packet {
|
||||
let (packet, _) = parse_packet(&to_bits(input));
|
||||
return packet;
|
||||
let (packet, _) = parse_packet(&to_bits(input));
|
||||
return packet;
|
||||
}
|
||||
|
||||
fn sum_packet_versions(packet: &Packet) -> u32 {
|
||||
let mut sum: u32 = packet.version.into();
|
||||
match &packet.body {
|
||||
PacketBody::Operator(packets) => {
|
||||
for sub_packet in packets {
|
||||
sum += sum_packet_versions(sub_packet);
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
};
|
||||
return sum;
|
||||
let mut sum: u32 = packet.version.into();
|
||||
match &packet.body {
|
||||
PacketBody::Operator(packets) => {
|
||||
for sub_packet in packets {
|
||||
sum += sum_packet_versions(sub_packet);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
return sum;
|
||||
}
|
||||
|
||||
pub fn part1(packet: &Packet) -> u32 {
|
||||
sum_packet_versions(packet)
|
||||
sum_packet_versions(packet)
|
||||
}
|
||||
|
||||
fn eval_sum_packets(packets: &[Packet]) -> u64 {
|
||||
let mut sum = 0;
|
||||
for packet in packets {
|
||||
sum += eval_packet(packet);
|
||||
}
|
||||
return sum;
|
||||
let mut sum = 0;
|
||||
for packet in packets {
|
||||
sum += eval_packet(packet);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
fn eval_product_packets(packets: &[Packet]) -> u64 {
|
||||
let mut product = 1;
|
||||
for packet in packets {
|
||||
product *= eval_packet(packet);
|
||||
}
|
||||
return product;
|
||||
let mut product = 1;
|
||||
for packet in packets {
|
||||
product *= eval_packet(packet);
|
||||
}
|
||||
return product;
|
||||
}
|
||||
fn eval_minimum_packets(packets: &[Packet]) -> u64 {
|
||||
let mut min = u64::MAX;
|
||||
for packet in packets {
|
||||
min = min.min(eval_packet(packet));
|
||||
}
|
||||
return min;
|
||||
let mut min = u64::MAX;
|
||||
for packet in packets {
|
||||
min = min.min(eval_packet(packet));
|
||||
}
|
||||
return min;
|
||||
}
|
||||
fn eval_maximum_packets(packets: &[Packet]) -> u64 {
|
||||
let mut max = 0;
|
||||
for packet in packets {
|
||||
max = max.max(eval_packet(packet));
|
||||
}
|
||||
return max;
|
||||
let mut max = 0;
|
||||
for packet in packets {
|
||||
max = max.max(eval_packet(packet));
|
||||
}
|
||||
return max;
|
||||
}
|
||||
fn eval_greater_packets(packets: &[Packet]) -> u64 {
|
||||
let first_packet = packets.get(0).unwrap();
|
||||
let second_packet = packets.get(1).unwrap();
|
||||
if eval_packet(first_packet) > eval_packet(second_packet) { 1 } else { 0 }
|
||||
let first_packet = packets.get(0).unwrap();
|
||||
let second_packet = packets.get(1).unwrap();
|
||||
if eval_packet(first_packet) > eval_packet(second_packet) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
fn eval_less_packets(packets: &[Packet]) -> u64 {
|
||||
let first_packet = packets.get(0).unwrap();
|
||||
let second_packet = packets.get(1).unwrap();
|
||||
if eval_packet(first_packet) < eval_packet(second_packet) { 1 } else { 0 }
|
||||
let first_packet = packets.get(0).unwrap();
|
||||
let second_packet = packets.get(1).unwrap();
|
||||
if eval_packet(first_packet) < eval_packet(second_packet) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
fn eval_equal_packets(packets: &[Packet]) -> u64 {
|
||||
let first_packet = packets.get(0).unwrap();
|
||||
let second_packet = packets.get(1).unwrap();
|
||||
if eval_packet(first_packet) == eval_packet(second_packet) { 1 } else { 0 }
|
||||
let first_packet = packets.get(0).unwrap();
|
||||
let second_packet = packets.get(1).unwrap();
|
||||
if eval_packet(first_packet) == eval_packet(second_packet) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_packet(packet: &Packet) -> u64 {
|
||||
match &packet.body {
|
||||
PacketBody::Literal(value) => *value,
|
||||
PacketBody::Operator(packets) => {
|
||||
match packet.r#type {
|
||||
0 => eval_sum_packets(packets),
|
||||
1 => eval_product_packets(packets),
|
||||
2 => eval_minimum_packets(packets),
|
||||
3 => eval_maximum_packets(packets),
|
||||
5 => eval_greater_packets(packets),
|
||||
6 => eval_less_packets(packets),
|
||||
7 => eval_equal_packets(packets),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
match &packet.body {
|
||||
PacketBody::Literal(value) => *value,
|
||||
PacketBody::Operator(packets) => match packet.r#type {
|
||||
0 => eval_sum_packets(packets),
|
||||
1 => eval_product_packets(packets),
|
||||
2 => eval_minimum_packets(packets),
|
||||
3 => eval_maximum_packets(packets),
|
||||
5 => eval_greater_packets(packets),
|
||||
6 => eval_less_packets(packets),
|
||||
7 => eval_equal_packets(packets),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part2(packet: &Packet) -> u64 {
|
||||
eval_packet(packet)
|
||||
eval_packet(packet)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example_1() {
|
||||
let packet = parse_input("8A004A801A8002F478");
|
||||
let result = part1(&packet);
|
||||
assert_eq!(result, 16);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example_1() {
|
||||
let packet = parse_input("8A004A801A8002F478");
|
||||
let result = part1(&packet);
|
||||
assert_eq!(result, 16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_example_2() {
|
||||
let packet = parse_input("620080001611562C8802118E34");
|
||||
let result = part1(&packet);
|
||||
assert_eq!(result, 12);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example_2() {
|
||||
let packet = parse_input("620080001611562C8802118E34");
|
||||
let result = part1(&packet);
|
||||
assert_eq!(result, 12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_example_3() {
|
||||
let packet = parse_input("C0015000016115A2E0802F182340");
|
||||
let result = part1(&packet);
|
||||
assert_eq!(result, 23);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example_3() {
|
||||
let packet = parse_input("C0015000016115A2E0802F182340");
|
||||
let result = part1(&packet);
|
||||
assert_eq!(result, 23);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_example_4() {
|
||||
let packet = parse_input("A0016C880162017C3686B18A3D4780");
|
||||
let result = part1(&packet);
|
||||
assert_eq!(result, 31);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example_4() {
|
||||
let packet = parse_input("A0016C880162017C3686B18A3D4780");
|
||||
let result = part1(&packet);
|
||||
assert_eq!(result, 31);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example_1() {
|
||||
let packet = parse_input("C200B40A82");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 3);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example_1() {
|
||||
let packet = parse_input("C200B40A82");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example_2() {
|
||||
let packet = parse_input("04005AC33890");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 54);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example_2() {
|
||||
let packet = parse_input("04005AC33890");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 54);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example_3() {
|
||||
let packet = parse_input("880086C3E88112");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 7);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example_3() {
|
||||
let packet = parse_input("880086C3E88112");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example_4() {
|
||||
let packet = parse_input("CE00C43D881120");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 9);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example_4() {
|
||||
let packet = parse_input("CE00C43D881120");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example_5() {
|
||||
let packet = parse_input("D8005AC2A8F0");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 1);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example_5() {
|
||||
let packet = parse_input("D8005AC2A8F0");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example_6() {
|
||||
let packet = parse_input("F600BC2D8F");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 0);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example_6() {
|
||||
let packet = parse_input("F600BC2D8F");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example_7() {
|
||||
let packet = parse_input("9C005AC2F8F0");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 0);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example_7() {
|
||||
let packet = parse_input("9C005AC2F8F0");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example_8() {
|
||||
let packet = parse_input("9C0141080250320F1802104A08");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 1);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example_8() {
|
||||
let packet = parse_input("9C0141080250320F1802104A08");
|
||||
let result = part2(&packet);
|
||||
assert_eq!(result, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
144
src/day17.rs
144
src/day17.rs
@ -1,102 +1,108 @@
|
||||
|
||||
pub struct Rect {
|
||||
x0: i32, x1: i32,
|
||||
y0: i32, y1: i32,
|
||||
x0: i32,
|
||||
x1: i32,
|
||||
y0: i32,
|
||||
y1: i32,
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Rect {
|
||||
let (x_part, y_part) = input.strip_suffix("\n")
|
||||
.or(Some(input))
|
||||
.unwrap()
|
||||
.strip_prefix("target area: ")
|
||||
.unwrap()
|
||||
.split_once(", ")
|
||||
.unwrap();
|
||||
let (x0, x1) = x_part[2..].split_once("..").unwrap();
|
||||
let (y0, y1) = y_part[2..].split_once("..").unwrap();
|
||||
return Rect {
|
||||
x0: x0.parse().unwrap(),
|
||||
x1: x1.parse().unwrap(),
|
||||
y0: y0.parse().unwrap(),
|
||||
y1: y1.parse().unwrap()
|
||||
}
|
||||
let (x_part, y_part) = input
|
||||
.strip_suffix("\n")
|
||||
.or(Some(input))
|
||||
.unwrap()
|
||||
.strip_prefix("target area: ")
|
||||
.unwrap()
|
||||
.split_once(", ")
|
||||
.unwrap();
|
||||
let (x0, x1) = x_part[2..].split_once("..").unwrap();
|
||||
let (y0, y1) = y_part[2..].split_once("..").unwrap();
|
||||
return Rect {
|
||||
x0: x0.parse().unwrap(),
|
||||
x1: x1.parse().unwrap(),
|
||||
y0: y0.parse().unwrap(),
|
||||
y1: y1.parse().unwrap(),
|
||||
};
|
||||
}
|
||||
|
||||
fn sign(x: i32) -> i32 {
|
||||
if x > 0 { 1 } else if x < 0 { -1 } else { 0 }
|
||||
if x > 0 {
|
||||
1
|
||||
} else if x < 0 {
|
||||
-1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn is_overshot(px: i32, py: i32, target: &Rect) -> bool {
|
||||
px > target.x1 || py < target.y0
|
||||
px > target.x1 || py < target.y0
|
||||
}
|
||||
|
||||
fn is_in_rect(px: i32, py: i32, target: &Rect) -> bool {
|
||||
target.x0 <= px && px <= target.x1 &&
|
||||
target.y0 <= py && py <= target.y1
|
||||
target.x0 <= px && px <= target.x1 && target.y0 <= py && py <= target.y1
|
||||
}
|
||||
|
||||
fn simulate(target: &Rect, initial_vx: i32, initial_vy: i32) -> i32 {
|
||||
let mut px = 0;
|
||||
let mut py = 0;
|
||||
let mut vx = initial_vx;
|
||||
let mut vy = initial_vy;
|
||||
let mut maxy = 0;
|
||||
let mut px = 0;
|
||||
let mut py = 0;
|
||||
let mut vx = initial_vx;
|
||||
let mut vy = initial_vy;
|
||||
let mut maxy = 0;
|
||||
|
||||
while !is_overshot(px, py, target) {
|
||||
px += vx;
|
||||
py += vy;
|
||||
while !is_overshot(px, py, target) {
|
||||
px += vx;
|
||||
py += vy;
|
||||
|
||||
if is_in_rect(px, py, target) {
|
||||
return maxy;
|
||||
}
|
||||
|
||||
maxy = maxy.max(py);
|
||||
if is_in_rect(px, py, target) {
|
||||
return maxy;
|
||||
}
|
||||
|
||||
vx -= sign(vx);
|
||||
vy -= 1;
|
||||
}
|
||||
maxy = maxy.max(py);
|
||||
|
||||
return -1;
|
||||
vx -= sign(vx);
|
||||
vy -= 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pub fn part1(target: &Rect) -> i32 {
|
||||
let mut maxy = 0;
|
||||
for vx in 0..target.x1 {
|
||||
for vy in target.y0..-target.y0 {
|
||||
maxy = maxy.max(simulate(target, vx, vy));
|
||||
}
|
||||
}
|
||||
return maxy;
|
||||
let mut maxy = 0;
|
||||
for vx in 0..target.x1 {
|
||||
for vy in target.y0..-target.y0 {
|
||||
maxy = maxy.max(simulate(target, vx, vy));
|
||||
}
|
||||
}
|
||||
return maxy;
|
||||
}
|
||||
|
||||
pub fn part2(target: &Rect) -> i32 {
|
||||
let mut count = 0;
|
||||
for vx in 0..=target.x1 {
|
||||
for vy in target.y0..-target.y0 {
|
||||
if simulate(target, vx, vy) >= 0 {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
let mut count = 0;
|
||||
for vx in 0..=target.x1 {
|
||||
for vy in target.y0..-target.y0 {
|
||||
if simulate(target, vx, vy) >= 0 {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let target = parse_input("target area: x=20..30, y=-10..-5");
|
||||
let result = part1(&target);
|
||||
assert_eq!(result, 45);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let target = parse_input("target area: x=20..30, y=-10..-5");
|
||||
let result = part1(&target);
|
||||
assert_eq!(result, 45);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let target = parse_input("target area: x=20..30, y=-10..-5");
|
||||
let result = part2(&target);
|
||||
assert_eq!(result, 112);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let target = parse_input("target area: x=20..30, y=-10..-5");
|
||||
let result = part2(&target);
|
||||
assert_eq!(result, 112);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
429
src/day18.rs
429
src/day18.rs
@ -1,136 +1,143 @@
|
||||
// Solution gotten from: https://github.com/AxlLind/AdventOfCode2021/blob/main/src/bin/18.rs
|
||||
|
||||
fn parse_snailfish(line: &str) -> Vec<(i32, u8)> {
|
||||
let mut depth = 0;
|
||||
let mut nums = Vec::new();
|
||||
for c in line.chars() {
|
||||
match c {
|
||||
'[' => depth += 1,
|
||||
']' => depth -= 1,
|
||||
',' => {},
|
||||
_ => nums.push(((c as u8 - b'0') as i32, depth))
|
||||
}
|
||||
}
|
||||
return nums;
|
||||
let mut depth = 0;
|
||||
let mut nums = Vec::new();
|
||||
for c in line.chars() {
|
||||
match c {
|
||||
'[' => depth += 1,
|
||||
']' => depth -= 1,
|
||||
',' => {}
|
||||
_ => nums.push(((c as u8 - b'0') as i32, depth)),
|
||||
}
|
||||
}
|
||||
return nums;
|
||||
}
|
||||
|
||||
fn find_deepest_index(num: &Vec<(i32, u8)>) -> usize {
|
||||
let mut deepest_index = 0;
|
||||
let mut deepest_depth = 0;
|
||||
for i in 0..num.len() {
|
||||
let depth = num[i].1;
|
||||
if deepest_depth < depth {
|
||||
deepest_depth = depth;
|
||||
deepest_index = i;
|
||||
}
|
||||
}
|
||||
return deepest_index;
|
||||
let mut deepest_index = 0;
|
||||
let mut deepest_depth = 0;
|
||||
for i in 0..num.len() {
|
||||
let depth = num[i].1;
|
||||
if deepest_depth < depth {
|
||||
deepest_depth = depth;
|
||||
deepest_index = i;
|
||||
}
|
||||
}
|
||||
return deepest_index;
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<Vec<(i32, u8)>> {
|
||||
let mut nums = Vec::new();
|
||||
for line in input.lines() {
|
||||
nums.push(parse_snailfish(line));
|
||||
}
|
||||
return nums;
|
||||
let mut nums = Vec::new();
|
||||
for line in input.lines() {
|
||||
nums.push(parse_snailfish(line));
|
||||
}
|
||||
return nums;
|
||||
}
|
||||
|
||||
fn add_snailfish(a: &Vec<(i32, u8)>, b: &Vec<(i32, u8)>) -> Vec<(i32, u8)> {
|
||||
let mut added = Vec::new();
|
||||
for (num, depth) in a {
|
||||
added.push((*num, depth+1));
|
||||
}
|
||||
for (num, depth) in b {
|
||||
added.push((*num, depth+1));
|
||||
}
|
||||
return added;
|
||||
let mut added = Vec::new();
|
||||
for (num, depth) in a {
|
||||
added.push((*num, depth + 1));
|
||||
}
|
||||
for (num, depth) in b {
|
||||
added.push((*num, depth + 1));
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
fn try_exploding(num: &mut Vec<(i32, u8)>) -> bool {
|
||||
let i = find_deepest_index(num);
|
||||
if num[i].1 < 5 { return false; }
|
||||
let (left_num, depth) = num[i];
|
||||
let right_num = num.remove(i+1).0;
|
||||
if i > 0 {
|
||||
num[i-1].0 += left_num;
|
||||
}
|
||||
if i+1 < num.len() {
|
||||
num[i+1].0 += right_num;
|
||||
}
|
||||
num[i] = (0, depth-1);
|
||||
return true;
|
||||
let i = find_deepest_index(num);
|
||||
if num[i].1 < 5 {
|
||||
return false;
|
||||
}
|
||||
let (left_num, depth) = num[i];
|
||||
let right_num = num.remove(i + 1).0;
|
||||
if i > 0 {
|
||||
num[i - 1].0 += left_num;
|
||||
}
|
||||
if i + 1 < num.len() {
|
||||
num[i + 1].0 += right_num;
|
||||
}
|
||||
num[i] = (0, depth - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
fn try_splitting(num: &mut Vec<(i32, u8)>) -> bool {
|
||||
let target = match num.iter().position(|&(n,_)| n > 9) {
|
||||
Some(i) => i,
|
||||
None => return false,
|
||||
};
|
||||
let (x, depth) = num[target];
|
||||
num[target] = (x/2, depth+1);
|
||||
num.insert(target+1, ((x+1)/2, depth+1));
|
||||
return true;
|
||||
let target = match num.iter().position(|&(n, _)| n > 9) {
|
||||
Some(i) => i,
|
||||
None => return false,
|
||||
};
|
||||
let (x, depth) = num[target];
|
||||
num[target] = (x / 2, depth + 1);
|
||||
num.insert(target + 1, ((x + 1) / 2, depth + 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
fn reduce_snailfish(num: &mut Vec<(i32, u8)>) {
|
||||
loop {
|
||||
if try_exploding(num) { continue; }
|
||||
if try_splitting(num) { continue; }
|
||||
break;
|
||||
}
|
||||
loop {
|
||||
if try_exploding(num) {
|
||||
continue;
|
||||
}
|
||||
if try_splitting(num) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_magnitude(mut num: Vec<(i32, u8)>) -> i32 {
|
||||
while num.len() > 1 {
|
||||
let i = find_deepest_index(&num);
|
||||
let (left_num, depth) = num[i];
|
||||
let right_num = num[i+1].0;
|
||||
num[i] = (3*left_num + 2*right_num, depth-1);
|
||||
num.remove(i+1);
|
||||
}
|
||||
num[0].0
|
||||
while num.len() > 1 {
|
||||
let i = find_deepest_index(&num);
|
||||
let (left_num, depth) = num[i];
|
||||
let right_num = num[i + 1].0;
|
||||
num[i] = (3 * left_num + 2 * right_num, depth - 1);
|
||||
num.remove(i + 1);
|
||||
}
|
||||
num[0].0
|
||||
}
|
||||
|
||||
fn add_and_reduce(a: &Vec<(i32, u8)>, b: &Vec<(i32, u8)>) -> Vec<(i32, u8)> {
|
||||
let mut result = add_snailfish(a, b);
|
||||
reduce_snailfish(&mut result);
|
||||
return result;
|
||||
let mut result = add_snailfish(a, b);
|
||||
reduce_snailfish(&mut result);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn sum(nums: &Vec<Vec<(i32, u8)>>) -> Vec<(i32, u8)> {
|
||||
let mut result = nums[0].clone();
|
||||
for i in 1..nums.len() {
|
||||
result = add_snailfish(&result, &nums[i]);
|
||||
reduce_snailfish(&mut result);
|
||||
}
|
||||
return result;
|
||||
let mut result = nums[0].clone();
|
||||
for i in 1..nums.len() {
|
||||
result = add_snailfish(&result, &nums[i]);
|
||||
reduce_snailfish(&mut result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn part1(nums: &Vec<Vec<(i32, u8)>>) -> i32 {
|
||||
return get_magnitude(sum(nums));
|
||||
return get_magnitude(sum(nums));
|
||||
}
|
||||
|
||||
pub fn part2(nums: &Vec<Vec<(i32, u8)>>) -> i32 {
|
||||
let mut max_magnitude = 0;
|
||||
let n = nums.len();
|
||||
for i in 0..n {
|
||||
for j in 0..n-1 {
|
||||
let a = &nums[i];
|
||||
let b = &nums[j];
|
||||
max_magnitude = max_magnitude.max(get_magnitude(add_and_reduce(a, b)));
|
||||
max_magnitude = max_magnitude.max(get_magnitude(add_and_reduce(b, a)));
|
||||
}
|
||||
}
|
||||
return max_magnitude;
|
||||
let mut max_magnitude = 0;
|
||||
let n = nums.len();
|
||||
for i in 0..n {
|
||||
for j in 0..n - 1 {
|
||||
let a = &nums[i];
|
||||
let b = &nums[j];
|
||||
max_magnitude = max_magnitude.max(get_magnitude(add_and_reduce(a, b)));
|
||||
max_magnitude = max_magnitude.max(get_magnitude(add_and_reduce(b, a)));
|
||||
}
|
||||
}
|
||||
return max_magnitude;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let nums = parse_input("[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let nums = parse_input(
|
||||
"[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
|
||||
[[[5,[2,8]],4],[5,[[9,9],0]]]
|
||||
[6,[[[6,2],[5,6]],[[7,6],[4,7]]]]
|
||||
[[[6,[0,7]],[0,9]],[4,[9,[9,0]]]]
|
||||
@ -139,14 +146,16 @@ mod tests {
|
||||
[[[[5,4],[7,7]],8],[[8,3],8]]
|
||||
[[9,3],[[9,9],[6,[4,9]]]]
|
||||
[[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]]
|
||||
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]");
|
||||
let result = part1(&nums);
|
||||
assert_eq!(result, 4140);
|
||||
}
|
||||
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]",
|
||||
);
|
||||
let result = part1(&nums);
|
||||
assert_eq!(result, 4140);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let nums = parse_input("[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let nums = parse_input(
|
||||
"[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
|
||||
[[[5,[2,8]],4],[5,[[9,9],0]]]
|
||||
[6,[[[6,2],[5,6]],[[7,6],[4,7]]]]
|
||||
[[[6,[0,7]],[0,9]],[4,[9,[9,0]]]]
|
||||
@ -155,124 +164,118 @@ mod tests {
|
||||
[[[[5,4],[7,7]],8],[[8,3],8]]
|
||||
[[9,3],[[9,9],[6,[4,9]]]]
|
||||
[[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]]
|
||||
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]");
|
||||
let result = part2(&nums);
|
||||
assert_eq!(result, 3993);
|
||||
}
|
||||
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]",
|
||||
);
|
||||
let result = part2(&nums);
|
||||
assert_eq!(result, 3993);
|
||||
}
|
||||
|
||||
fn test_explosion(initial: &str, expected: &str) {
|
||||
let mut num = parse_snailfish(initial);
|
||||
try_exploding(&mut num);
|
||||
assert_eq!(num, parse_snailfish(expected));
|
||||
}
|
||||
fn test_explosion(initial: &str, expected: &str) {
|
||||
let mut num = parse_snailfish(initial);
|
||||
try_exploding(&mut num);
|
||||
assert_eq!(num, parse_snailfish(expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exploding_1() {
|
||||
test_explosion("[[[[[9,8],1],2],3],4]", "[[[[0,9],2],3],4]");
|
||||
}
|
||||
#[test]
|
||||
fn exploding_2() {
|
||||
test_explosion("[7,[6,[5,[4,[3,2]]]]]", "[7,[6,[5,[7,0]]]]");
|
||||
}
|
||||
#[test]
|
||||
fn exploding_3() {
|
||||
test_explosion("[[6,[5,[4,[3,2]]]],1]", "[[6,[5,[7,0]]],3]");
|
||||
}
|
||||
#[test]
|
||||
fn exploding_4() {
|
||||
test_explosion("[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]", "[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]");
|
||||
}
|
||||
#[test]
|
||||
fn exploding_5() {
|
||||
test_explosion("[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]", "[[3,[2,[8,0]]],[9,[5,[7,0]]]]");
|
||||
}
|
||||
#[test]
|
||||
fn exploding_1() {
|
||||
test_explosion("[[[[[9,8],1],2],3],4]", "[[[[0,9],2],3],4]");
|
||||
}
|
||||
#[test]
|
||||
fn exploding_2() {
|
||||
test_explosion("[7,[6,[5,[4,[3,2]]]]]", "[7,[6,[5,[7,0]]]]");
|
||||
}
|
||||
#[test]
|
||||
fn exploding_3() {
|
||||
test_explosion("[[6,[5,[4,[3,2]]]],1]", "[[6,[5,[7,0]]],3]");
|
||||
}
|
||||
#[test]
|
||||
fn exploding_4() {
|
||||
test_explosion(
|
||||
"[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]",
|
||||
"[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]",
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn exploding_5() {
|
||||
test_explosion(
|
||||
"[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]",
|
||||
"[[3,[2,[8,0]]],[9,[5,[7,0]]]]",
|
||||
);
|
||||
}
|
||||
|
||||
fn test_sum(nums: Vec<&str>, expected: &str) {
|
||||
let mut parsed_nums = Vec::new();
|
||||
for num in nums {
|
||||
parsed_nums.push(parse_snailfish(num));
|
||||
}
|
||||
assert_eq!(sum(&parsed_nums), parse_snailfish(expected));
|
||||
}
|
||||
fn test_sum(nums: Vec<&str>, expected: &str) {
|
||||
let mut parsed_nums = Vec::new();
|
||||
for num in nums {
|
||||
parsed_nums.push(parse_snailfish(num));
|
||||
}
|
||||
assert_eq!(sum(&parsed_nums), parse_snailfish(expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sum_1() {
|
||||
let nums = vec![
|
||||
"[1,1]",
|
||||
"[2,2]",
|
||||
"[3,3]",
|
||||
"[4,4]"
|
||||
];
|
||||
test_sum(nums, "[[[[1,1],[2,2]],[3,3]],[4,4]]");
|
||||
}
|
||||
#[test]
|
||||
fn sum_2() {
|
||||
let nums = vec![
|
||||
"[1,1]",
|
||||
"[2,2]",
|
||||
"[3,3]",
|
||||
"[4,4]",
|
||||
"[5,5]"
|
||||
];
|
||||
test_sum(nums, "[[[[3,0],[5,3]],[4,4]],[5,5]]");
|
||||
}
|
||||
#[test]
|
||||
fn sum_3() {
|
||||
let nums = vec![
|
||||
"[1,1]",
|
||||
"[2,2]",
|
||||
"[3,3]",
|
||||
"[4,4]",
|
||||
"[5,5]",
|
||||
"[6,6]",
|
||||
];
|
||||
test_sum(nums, "[[[[5,0],[7,4]],[5,5]],[6,6]]");
|
||||
}
|
||||
#[test]
|
||||
fn sum_4() {
|
||||
let nums = vec![
|
||||
"[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]",
|
||||
"[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]",
|
||||
"[[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]]",
|
||||
"[[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]]",
|
||||
"[7,[5,[[3,8],[1,4]]]]",
|
||||
"[[2,[2,2]],[8,[8,1]]]",
|
||||
"[2,9]",
|
||||
"[1,[[[9,3],9],[[9,0],[0,7]]]]",
|
||||
"[[[5,[7,4]],7],1]",
|
||||
"[[[[4,2],2],6],[8,7]]"
|
||||
];
|
||||
test_sum(nums, "[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]");
|
||||
}
|
||||
#[test]
|
||||
fn sum_1() {
|
||||
let nums = vec!["[1,1]", "[2,2]", "[3,3]", "[4,4]"];
|
||||
test_sum(nums, "[[[[1,1],[2,2]],[3,3]],[4,4]]");
|
||||
}
|
||||
#[test]
|
||||
fn sum_2() {
|
||||
let nums = vec!["[1,1]", "[2,2]", "[3,3]", "[4,4]", "[5,5]"];
|
||||
test_sum(nums, "[[[[3,0],[5,3]],[4,4]],[5,5]]");
|
||||
}
|
||||
#[test]
|
||||
fn sum_3() {
|
||||
let nums = vec!["[1,1]", "[2,2]", "[3,3]", "[4,4]", "[5,5]", "[6,6]"];
|
||||
test_sum(nums, "[[[[5,0],[7,4]],[5,5]],[6,6]]");
|
||||
}
|
||||
#[test]
|
||||
fn sum_4() {
|
||||
let nums = vec![
|
||||
"[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]",
|
||||
"[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]",
|
||||
"[[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]]",
|
||||
"[[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]]",
|
||||
"[7,[5,[[3,8],[1,4]]]]",
|
||||
"[[2,[2,2]],[8,[8,1]]]",
|
||||
"[2,9]",
|
||||
"[1,[[[9,3],9],[[9,0],[0,7]]]]",
|
||||
"[[[5,[7,4]],7],1]",
|
||||
"[[[[4,2],2],6],[8,7]]",
|
||||
];
|
||||
test_sum(
|
||||
nums,
|
||||
"[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]",
|
||||
);
|
||||
}
|
||||
|
||||
fn test_magnitude(initial: &str, expected: i32) {
|
||||
let num = parse_snailfish(initial);
|
||||
assert_eq!(get_magnitude(num), expected);
|
||||
}
|
||||
fn test_magnitude(initial: &str, expected: i32) {
|
||||
let num = parse_snailfish(initial);
|
||||
assert_eq!(get_magnitude(num), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn magnitude_1() {
|
||||
test_magnitude("[[1,2],[[3,4],5]]", 143);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_2() {
|
||||
test_magnitude("[[[[0,7],4],[[7,8],[6,0]]],[8,1]]", 1384);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_3() {
|
||||
test_magnitude("[[[[1,1],[2,2]],[3,3]],[4,4]]", 445);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_4() {
|
||||
test_magnitude("[[[[3,0],[5,3]],[4,4]],[5,5]]", 791);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_5() {
|
||||
test_magnitude("[[[[5,0],[7,4]],[5,5]],[6,6]]", 1137);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_6() {
|
||||
test_magnitude("[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]", 3488);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_1() {
|
||||
test_magnitude("[[1,2],[[3,4],5]]", 143);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_2() {
|
||||
test_magnitude("[[[[0,7],4],[[7,8],[6,0]]],[8,1]]", 1384);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_3() {
|
||||
test_magnitude("[[[[1,1],[2,2]],[3,3]],[4,4]]", 445);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_4() {
|
||||
test_magnitude("[[[[3,0],[5,3]],[4,4]],[5,5]]", 791);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_5() {
|
||||
test_magnitude("[[[[5,0],[7,4]],[5,5]],[6,6]]", 1137);
|
||||
}
|
||||
#[test]
|
||||
fn magnitude_6() {
|
||||
test_magnitude(
|
||||
"[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]",
|
||||
3488,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
550
src/day19.rs
550
src/day19.rs
@ -1,263 +1,375 @@
|
||||
// Solution for this problem by somone else: https://github.com/Jellycious/aoc-2021/blob/main/src/days/day19.rs
|
||||
use std::{ops::{Sub, Mul, Add, Neg}, collections::{HashMap, HashSet}, vec, fmt};
|
||||
|
||||
use std::{collections::{HashSet, HashMap}, ops::{Add, Sub}};
|
||||
// https://i.imgur.com/Ff1vGT9.png
|
||||
const ROTATIONS: [Rotation; 24] = [
|
||||
Rotation( 1, 0, 0, 0, 1, 0, 0, 0, 1), // (x ,y ,z)
|
||||
Rotation( 1, 0, 0, 0, 0, 1, 0,-1, 0), // (x ,z ,-y)
|
||||
Rotation( 1, 0, 0, 0,-1, 0, 0, 0,-1), // (x ,-y,-z)
|
||||
Rotation( 1, 0, 0, 0, 0,-1, 0, 1, 0), // (x ,-z,y )
|
||||
Rotation(-1, 0, 0, 0,-1, 0, 0, 0, 1), // (-x,-y,z)
|
||||
Rotation(-1, 0, 0, 0, 0, 1, 0, 1, 0), // (-x,z ,y )
|
||||
Rotation(-1, 0, 0, 0, 1, 0, 0, 0,-1), // (-x,y ,-z)
|
||||
Rotation(-1, 0, 0, 0, 0,-1, 0,-1, 0), // (-x,-z,-y )
|
||||
Rotation( 0, 1, 0, 0, 0, 1, 1, 0, 0), // (y ,z ,x)
|
||||
Rotation( 0, 1, 0, 1, 0, 0, 0, 0,-1), // (y ,x ,-z)
|
||||
Rotation( 0, 1, 0, 0, 0,-1,-1, 0, 0), // (y ,-z,-x)
|
||||
Rotation( 0, 1, 0,-1, 0, 0, 0, 0, 1), // (y ,-x,z )
|
||||
Rotation( 0,-1, 0, 0, 0,-1, 1, 0, 0), // (-y,-z,x)
|
||||
Rotation( 0,-1, 0, 1, 0, 0, 0, 0, 1), // (-y,x ,z )
|
||||
Rotation( 0,-1, 0, 0, 0, 1,-1, 0, 0), // (-y,z ,-x)
|
||||
Rotation( 0,-1, 0,-1, 0, 0, 0, 0,-1), // (-y,-x,-z )
|
||||
Rotation( 0, 0, 1, 1, 0, 0, 0, 1, 0), // (z ,x ,y)
|
||||
Rotation( 0, 0, 1, 0, 1, 0,-1, 0, 0), // (z ,y ,-x)
|
||||
Rotation( 0, 0, 1,-1, 0, 0, 0,-1, 0), // (z ,-x,-y)
|
||||
Rotation( 0, 0, 1, 0,-1, 0, 1, 0, 0), // (z ,-y,x )
|
||||
Rotation( 0, 0,-1,-1, 0, 0, 0, 1, 0), // (-z,-x,y)
|
||||
Rotation( 0, 0,-1, 0, 1, 0, 1, 0, 0), // (-z,y ,x )
|
||||
Rotation( 0, 0,-1, 1, 0, 0, 0,-1, 0), // (-z,x ,-y)
|
||||
Rotation( 0, 0,-1, 0,-1, 0,-1, 0, 0), // (-z,-y,-x)
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
struct Rotation(i32, i32, i32, i32, i32, i32, i32, i32, i32);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
impl Rotation {
|
||||
fn identity() -> Rotation {
|
||||
Rotation(1, 0, 0, 0, 1, 0, 0, 0, 1)
|
||||
}
|
||||
|
||||
fn transpose(self) -> Rotation {
|
||||
Rotation(
|
||||
self.0,
|
||||
self.3,
|
||||
self.6,
|
||||
|
||||
self.1,
|
||||
self.4,
|
||||
self.7,
|
||||
|
||||
self.2,
|
||||
self.5,
|
||||
self.8,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Rotation {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fn write_param(f: &mut fmt::Formatter<'_>, x: i32, y: i32, z: i32) -> fmt::Result {
|
||||
if x != 0 {
|
||||
write!(f, "{}", if x < 0 {"-x"} else {"x"})?;
|
||||
} else if y != 0 {
|
||||
write!(f, "{}", if y < 0 {"-y"} else {"y"})?;
|
||||
} else if z != 0 {
|
||||
write!(f, "{}", if z < 0 {"-z"} else {"z"})?;
|
||||
} else {
|
||||
write!(f, "0")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
write!(f, "Rotation(")?;
|
||||
write_param(f, self.0, self.1, self.2)?;
|
||||
write!(f, ",")?;
|
||||
write_param(f, self.3, self.4, self.5)?;
|
||||
write!(f, ",")?;
|
||||
write_param(f, self.6, self.7, self.8)?;
|
||||
write!(f, ")")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Point> for Rotation {
|
||||
type Output = Point;
|
||||
|
||||
fn mul(self, rhs: Point) -> Self::Output {
|
||||
Point(
|
||||
self.0*rhs.0 + self.1*rhs.1 + self.2*rhs.2,
|
||||
self.3*rhs.0 + self.4*rhs.1 + self.5*rhs.2,
|
||||
self.6*rhs.0 + self.7*rhs.1 + self.8*rhs.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Rotation {
|
||||
type Output = Rotation;
|
||||
|
||||
// https://www.fhybea.com/en/multiplication-matrix-3x3.html
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
Rotation(
|
||||
(self.0 * rhs.0) + (self.1 * rhs.3) + (self.2 * rhs.6),
|
||||
(self.0 * rhs.1) + (self.1 * rhs.4) + (self.2 * rhs.7),
|
||||
(self.0 * rhs.2) + (self.1 * rhs.5) + (self.2 * rhs.8),
|
||||
(self.3 * rhs.0) + (self.4 * rhs.3) + (self.5 * rhs.6),
|
||||
(self.3 * rhs.1) + (self.4 * rhs.4) + (self.5 * rhs.7),
|
||||
(self.3 * rhs.2) + (self.4 * rhs.5) + (self.5 * rhs.8),
|
||||
(self.6 * rhs.0) + (self.7 * rhs.3) + (self.8 * rhs.6),
|
||||
(self.6 * rhs.1) + (self.7 * rhs.4) + (self.8 * rhs.7),
|
||||
(self.6 * rhs.2) + (self.7 * rhs.5) + (self.8 * rhs.8)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Point(i32, i32, i32);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct RotationMatrix(i32, i32, i32, i32, i32, i32, i32, i32, i32);
|
||||
impl Neg for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
Point(-self.0, -self.1, -self.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Point {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Point({},{},{})", self.0, self.1, self.2)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn apply_rotation(&self, t: &RotationMatrix) -> Point {
|
||||
return Point(
|
||||
self.0 * t.0 + self.1 * t.1 + self.2 * t.2,
|
||||
self.0 * t.3 + self.1 * t.4 + self.2 * t.5,
|
||||
self.0 * t.6 + self.1 * t.7 + self.2 * t.8
|
||||
);
|
||||
}
|
||||
fn mag_sqrd(&self) -> i32 {
|
||||
self.0*self.0 + self.1*self.1 + self.2*self.2
|
||||
}
|
||||
|
||||
fn sqr_dist(&self, other: &Point) -> i32 {
|
||||
let dx = self.0 - other.0;
|
||||
let dy = self.1 - other.1;
|
||||
let dz = self.2 - other.2;
|
||||
return dx*dx + dy*dy + dz*dz;
|
||||
fn manhattan(&self, other: &Point) -> i32 {
|
||||
(self.0-other.0).abs() + (self.1-other.1).abs() + (self.2-other.2).abs()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Point (
|
||||
self.0 - rhs.0,
|
||||
self.1 - rhs.1,
|
||||
self.2 - rhs.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Point {
|
||||
type Output = Self;
|
||||
type Output = Point;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Point(
|
||||
self.0 + rhs.0,
|
||||
self.1 + rhs.1,
|
||||
self.2 + rhs.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Point(
|
||||
self.0 - rhs.0,
|
||||
self.1 - rhs.1,
|
||||
self.2 - rhs.2
|
||||
)
|
||||
Point (
|
||||
self.0 + rhs.0,
|
||||
self.1 + rhs.1,
|
||||
self.2 + rhs.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_point(line: &str) -> Point {
|
||||
let nums: Vec<&str> = line.splitn(3, ',').collect();
|
||||
let x = nums[0].parse().unwrap();
|
||||
let y = nums[1].parse().unwrap();
|
||||
let z = nums[2].parse().unwrap();
|
||||
return Point(x, y, z);
|
||||
let nums: Vec<&str> = line.splitn(3, ',').collect();
|
||||
let x = nums[0].parse().unwrap();
|
||||
let y = nums[1].parse().unwrap();
|
||||
let z = nums[2].parse().unwrap();
|
||||
Point(x, y, z)
|
||||
}
|
||||
|
||||
fn parse_scanner(input: &str) -> Vec<Point> {
|
||||
let mut beacons = Vec::new();
|
||||
for line in input.lines().skip(1) {
|
||||
beacons.push(parse_point(line));
|
||||
}
|
||||
return beacons;
|
||||
let mut beacons = Vec::new();
|
||||
for line in input.lines().skip(1) {
|
||||
beacons.push(parse_point(line));
|
||||
}
|
||||
beacons
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<Vec<Point>> {
|
||||
let mut scanners = Vec::new();
|
||||
for scanner_section in input.split("\n\n") {
|
||||
scanners.push(parse_scanner(scanner_section));
|
||||
}
|
||||
return scanners;
|
||||
let mut scanners = Vec::new(); for scanner_section in input.split("\n\n") {
|
||||
scanners.push(parse_scanner(scanner_section));
|
||||
}
|
||||
scanners
|
||||
}
|
||||
|
||||
fn generate_rotations() -> Vec<RotationMatrix> {
|
||||
let mut transforms = Vec::new();
|
||||
|
||||
// +z axis
|
||||
transforms.push(RotationMatrix( 1, 0, 0, 0, 1, 0, 0, 0, 1));
|
||||
transforms.push(RotationMatrix( 0, 1, 0, -1, 0, 0, 0, 0, 1));
|
||||
transforms.push(RotationMatrix(-1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
transforms.push(RotationMatrix(0, -1, 0, 1, 0, 0, 0, 0, 1));
|
||||
|
||||
// -z axis
|
||||
transforms.push(RotationMatrix( 1, 0, 0, 0, -1, 0, 0, 0, -1));
|
||||
transforms.push(RotationMatrix( 0, 1, 0, 1, 0, 0, 0, 0, -1));
|
||||
transforms.push(RotationMatrix(-1, 0, 0, 0, 1, 0, 0, 0, -1));
|
||||
transforms.push(RotationMatrix(0, -1, 0, -1, 0, 0, 0, 0, -1));
|
||||
|
||||
// +y axis
|
||||
transforms.push(RotationMatrix( 1, 0, 0, 0, 0, -1, 0, 1, 0));
|
||||
transforms.push(RotationMatrix( 0, 0, 1, 1, 0, 0, 0, 1, 0));
|
||||
transforms.push(RotationMatrix(-1, 0, 0, 0, 0, 1, 0, 1, 0));
|
||||
transforms.push(RotationMatrix( 0, 0,-1, -1, 0, 0, 0, 1, 0));
|
||||
|
||||
// -y axis
|
||||
transforms.push(RotationMatrix( 1, 0, 0, 0, 0, 1, 0,-1, 0));
|
||||
transforms.push(RotationMatrix( 0, 0, 1, -1, 0, 0, 0,-1, 0));
|
||||
transforms.push(RotationMatrix(-1, 0, 0, 0, 0, -1, 0,-1, 0));
|
||||
transforms.push(RotationMatrix( 0, 0,-1, 1, 0, 0, 0,-1, 0));
|
||||
|
||||
// +x axis
|
||||
transforms.push(RotationMatrix( 0,-1, 0, 0, 0, -1, 1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 0,-1, 0, 1, 0, 1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 1, 0, 0, 0, 1, 1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 0, 1, 0,-1, 0, 1, 0, 0));
|
||||
|
||||
// -x axis
|
||||
transforms.push(RotationMatrix( 0, 1, 0, 0, 0, -1, -1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 0, 1, 0, 1, 0, -1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0,-1, 0, 0, 0, 1, -1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 0,-1, 0,-1, 0, -1, 0, 0));
|
||||
|
||||
return transforms;
|
||||
fn calc_beacon_pairs(beacons: &[Point]) -> HashMap<(usize, usize), i32> {
|
||||
let mut diffs = HashMap::new();
|
||||
for (i, p1) in beacons.iter().enumerate() {
|
||||
for (j, p2) in beacons.iter().enumerate().skip(i+1) {
|
||||
let diff = (*p1 - *p2).mag_sqrd();
|
||||
diffs.insert((i, j), diff);
|
||||
}
|
||||
}
|
||||
diffs
|
||||
}
|
||||
|
||||
fn find_distances_pairs<'a>(points: &'a Vec<Point>) -> Vec<(i32, &'a Point, &'a Point)> {
|
||||
let mut distances = Vec::new();
|
||||
let n = points.len();
|
||||
for i in 0..n-1 {
|
||||
for j in i+1..n {
|
||||
let p1 = &points[i];
|
||||
let p2 = &points[j];
|
||||
let dist = p1.sqr_dist(&p2);
|
||||
distances.push((dist, p1, p2));
|
||||
}
|
||||
}
|
||||
return distances;
|
||||
fn find_correct_transform(
|
||||
points1: &[Point], diffs1: &HashMap<(usize, usize), i32>,
|
||||
points2: &[Point], diffs2: &HashMap<(usize, usize), i32>
|
||||
) -> Option<(Rotation, Point)> {
|
||||
|
||||
for rot in ROTATIONS {
|
||||
for (pair1, diff1) in diffs1 {
|
||||
for (pair2, diff2) in diffs2 {
|
||||
if diff1 == diff2 {
|
||||
let base1 = points1[pair1.0];
|
||||
let base2 = points2[pair2.0];
|
||||
let normalized1 = points1.iter().map(|p| *p - base1).collect::<HashSet<_>>();
|
||||
let normalized2 = points2.iter().map(|p| rot.mul(*p - base2)).collect::<HashSet<_>>();
|
||||
|
||||
if normalized1.intersection(&normalized2).count() >= 12 {
|
||||
let offset = base1 - rot.mul(base2);
|
||||
// dbg!(normalized1.intersection(&normalized2).count());
|
||||
// let a = points1.iter().copied().collect::<HashSet<_>>();
|
||||
// let b = points2.iter().map(|p| rot.mul(*p) + offset).collect::<HashSet<_>>();
|
||||
// dbg!(a.intersection(&b).count());
|
||||
return Some((rot, offset))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn find_common_points<'a, 'b>(scanner1: &'a Vec<Point>, scanner2: &'b Vec<Point>) -> (Vec<Point>, Vec<Point>) {
|
||||
let mut common_points1: Vec<Point> = Vec::new();
|
||||
let mut common_points2: Vec<Point> = Vec::new();
|
||||
fn calc_transforms(scanners: &[Vec<Point>]) -> Vec<(Rotation, Point)> {
|
||||
let mut diffs = vec![];
|
||||
for scanner in scanners {
|
||||
diffs.push(calc_beacon_pairs(scanner))
|
||||
}
|
||||
|
||||
for pair1 in find_distances_pairs(scanner1) {
|
||||
for pair2 in find_distances_pairs(scanner2) {
|
||||
if pair1.0 == pair2.0 {
|
||||
if !common_points1.contains(pair1.1) {
|
||||
common_points1.push(*pair1.1);
|
||||
}
|
||||
if !common_points1.contains(pair1.2) {
|
||||
common_points1.push(*pair1.2);
|
||||
}
|
||||
if !common_points2.contains(pair2.1) {
|
||||
common_points2.push(*pair2.1);
|
||||
}
|
||||
if !common_points2.contains(pair2.2) {
|
||||
common_points2.push(*pair2.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut relative_transforms = HashMap::new();
|
||||
{
|
||||
let dist_diffs = diffs.iter()
|
||||
.map(|m| m.values().collect::<HashSet<_>>())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
return (common_points1, common_points2);
|
||||
for (i, pairs1) in dist_diffs.iter().enumerate() {
|
||||
for (j, pairs2) in dist_diffs.iter().enumerate().skip(i+1) {
|
||||
if pairs1.intersection(pairs2).count() >= 66 {
|
||||
let trans = find_correct_transform(
|
||||
&scanners[i], &diffs[i],
|
||||
&scanners[j], &diffs[j]
|
||||
);
|
||||
if let Some((rot, offset)) = trans {
|
||||
relative_transforms.entry(i)
|
||||
.or_insert(vec![])
|
||||
.push((j, rot, offset));
|
||||
|
||||
let inv_rot = rot.transpose();
|
||||
|
||||
relative_transforms.entry(j)
|
||||
.or_insert(vec![])
|
||||
.push((i, inv_rot, inv_rot.mul(-offset)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut transforms = vec![];
|
||||
for _ in 0..scanners.len() {
|
||||
transforms.push((Rotation::identity(), Point(0, 0, 0)));
|
||||
}
|
||||
|
||||
let mut stack = vec![(0, Rotation::identity(), Point(0, 0, 0))];
|
||||
let mut visited = HashSet::new();
|
||||
while !stack.is_empty() {
|
||||
let (id, rot, offset) = stack.pop().unwrap();
|
||||
|
||||
if visited.contains(&id) { continue; }
|
||||
visited.insert(id);
|
||||
|
||||
for nbr in relative_transforms.get(&id).unwrap() {
|
||||
if visited.contains(&nbr.0) { continue; }
|
||||
|
||||
let new_offset = rot.mul(nbr.2) + offset;
|
||||
let new_rot = rot.mul(nbr.1);
|
||||
stack.push((nbr.0, new_rot, new_offset));
|
||||
transforms[nbr.0] = (new_rot, new_offset);
|
||||
}
|
||||
}
|
||||
|
||||
transforms
|
||||
}
|
||||
|
||||
fn apply_offset_rotation(points: &Vec<Point>, offset: &Point, rotation: &RotationMatrix) -> Vec<Point> {
|
||||
points.iter()
|
||||
.map(|p| p.apply_rotation(&rotation) + *offset)
|
||||
.collect()
|
||||
pub fn part1(scanners: &[Vec<Point>]) -> u32 {
|
||||
let transforms = calc_transforms(scanners);
|
||||
|
||||
let mut all_beacons = HashSet::new();
|
||||
for (i, (rot, offset)) in transforms.iter().enumerate() {
|
||||
for scanner in &scanners[i] {
|
||||
all_beacons.insert(rot.mul(*scanner) + *offset);
|
||||
}
|
||||
}
|
||||
|
||||
all_beacons.len() as u32
|
||||
}
|
||||
|
||||
fn find_offset_rotation(mut points1: Vec<Point>, points2: Vec<Point>) -> Option<(Point, RotationMatrix)> {
|
||||
points1.sort();
|
||||
pub fn part2(scanners: &[Vec<Point>]) -> i32 {
|
||||
let transforms = calc_transforms(scanners);
|
||||
|
||||
'outer: for rotation in generate_rotations() {
|
||||
let mut transformed_points: Vec<_> = points2.iter()
|
||||
.map(|p| p.apply_rotation(&rotation))
|
||||
.collect();
|
||||
transformed_points.sort();
|
||||
let mut result = 0;
|
||||
for (i, (_, offset1)) in transforms.iter().enumerate() {
|
||||
for (_, offset2) in transforms.iter().skip(i+1) {
|
||||
result = result.max(offset1.manhattan(offset2))
|
||||
}
|
||||
}
|
||||
|
||||
let offset = points1[0] - transformed_points[0];
|
||||
if rotation == RotationMatrix(-1, 0, 0, 0, -1, 0, 0, 0, 1) {
|
||||
println!("\n\nTransform: {:?}", rotation);
|
||||
println!("Offset: {:?}\n", offset);
|
||||
println!("{:?}\n", points1);
|
||||
// println!("{:?}", transformed_points);
|
||||
}
|
||||
|
||||
for i in 1..points1.len() {
|
||||
let diff = points1[i] - transformed_points[i];
|
||||
if offset != diff {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
|
||||
return Some((offset, rotation));
|
||||
}
|
||||
|
||||
return None;
|
||||
result
|
||||
}
|
||||
|
||||
fn align_scanners(scanners: &mut Vec<Vec<Point>>) {
|
||||
let mut unaligned = HashSet::new();
|
||||
let mut unchecked = vec![0];
|
||||
|
||||
for i in 1..scanners.len() {
|
||||
unaligned.insert(i);
|
||||
}
|
||||
|
||||
while !unchecked.is_empty() {
|
||||
|
||||
let aligned_id = unchecked.pop().unwrap();
|
||||
for i in unaligned.clone() {
|
||||
let unaligned_scanner = &scanners[i];
|
||||
let (common_points1, common_points2) = find_common_points(&scanners[aligned_id], unaligned_scanner);
|
||||
if common_points1.len() >= 12 {
|
||||
let transform = find_offset_rotation(common_points1, common_points2);
|
||||
if let Some((offset, rotation)) = transform {
|
||||
scanners[i] = apply_offset_rotation(&scanners[i], &offset, &rotation);
|
||||
unchecked.push(i);
|
||||
unaligned.remove(&i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn find_unique_points(scanners: &Vec<Vec<Point>>) -> Vec<Point> {
|
||||
let mut cloned = scanners.clone();
|
||||
|
||||
align_scanners(&mut cloned);
|
||||
|
||||
let mut point_set = HashSet::new();
|
||||
for scanner in cloned {
|
||||
for point in scanner {
|
||||
point_set.insert(point);
|
||||
}
|
||||
}
|
||||
|
||||
return point_set.into_iter().collect();
|
||||
}
|
||||
|
||||
pub fn part1(scanners: &Vec<Vec<Point>>) -> u32 {
|
||||
find_unique_points(scanners).len() as u32
|
||||
}
|
||||
|
||||
pub fn part2(scanners: &Vec<Vec<Point>>) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let scanners = vec![
|
||||
vec![Point(404,-588,-901), Point(528,-643,409), Point(-838,591,734), Point(390,-675,-793), Point(-537,-823,-458), Point(-485,-357,347), Point(-345,-311,381), Point(-661,-816,-575), Point(-876,649,763), Point(-618,-824,-621), Point(553,345,-567), Point(474,580,667), Point(-447,-329,318), Point(-584,868,-557), Point(544,-627,-890), Point(564,392,-477), Point(455,729,728), Point(-892,524,684), Point(-689,845,-530), Point(423,-701,434), Point(7,-33,-71), Point(630,319,-379), Point(443,580,662), Point(-789,900,-551), Point(459,-707,401)],
|
||||
vec![Point(686,422,578), Point(605,423,415), Point(515,917,-361), Point(-336,658,858), Point(95,138,22), Point(-476,619,847), Point(-340,-569,-846), Point(567,-361,727), Point(-460,603,-452), Point(669,-402,600), Point(729,430,532), Point(-500,-761,534), Point(-322,571,750), Point(-466,-666,-811), Point(-429,-592,574), Point(-355,545,-477), Point(703,-491,-529), Point(-328,-685,520), Point(413,935,-424), Point(-391,539,-444), Point(586,-435,557), Point(-364,-763,-893), Point(807,-499,-711), Point(755,-354,-619), Point(553,889,-390)],
|
||||
vec![Point(649,640,665), Point(682,-795,504), Point(-784,533,-524), Point(-644,584,-595), Point(-588,-843,648), Point(-30,6,44), Point(-674,560,763), Point(500,723,-460), Point(609,671,-379), Point(-555,-800,653), Point(-675,-892,-343), Point(697,-426,-610), Point(578,704,681), Point(493,664,-388), Point(-671,-858,530), Point(-667,343,800), Point(571,-461,-707), Point(-138,-166,112), Point(-889,563,-600), Point(646,-828,498), Point(640,759,510), Point(-630,509,768), Point(-681,-892,-333), Point(673,-379,-804), Point(-742,-814,-386), Point(577,-820,562)],
|
||||
vec![Point(-589,542,597), Point(605,-692,669), Point(-500,565,-823), Point(-660,373,557), Point(-458,-679,-417), Point(-488,449,543), Point(-626,468,-788), Point(338,-750,-386), Point(528,-832,-391), Point(562,-778,733), Point(-938,-730,414), Point(543,643,-506), Point(-524,371,-870), Point(407,773,750), Point(-104,29,83), Point(378,-903,-323), Point(-778,-728,485), Point(426,699,580), Point(-438,-605,-362), Point(-469,-447,-387), Point(509,732,623), Point(647,635,-688), Point(-868,-804,481), Point(614,-800,639), Point(595,780,-596)],
|
||||
vec![Point(727,592,562), Point(-293,-554,779), Point(441,611,-461), Point(-714,465,-776), Point(-743,427,-804), Point(-660,-479,-426), Point(832,-632,460), Point(927,-485,-438), Point(408,393,-506), Point(466,436,-512), Point(110,16,151), Point(-258,-428,682), Point(-393,719,612), Point(-211,-452,876), Point(808,-476,-593), Point(-575,615,604), Point(-485,667,467), Point(-680,325,-822), Point(-627,-443,-432), Point(872,-547,-609), Point(833,512,582), Point(807,604,487), Point(839,-516,451), Point(891,-625,532), Point(-652,-548,-490), Point(30,-46,-14)]
|
||||
];
|
||||
let result = part1(&scanners);
|
||||
assert_eq!(result, 79);
|
||||
}
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn part1_example() {
|
||||
let scanners = vec![
|
||||
vec![Point(404, -588, -901), Point(528, -643, 409), Point(-838, 591, 734), Point(390, -675, -793), Point(-537, -823, -458), Point(-485, -357, 347), Point(-345, -311, 381), Point(-661, -816, -575), Point(-876, 649, 763), Point(-618, -824, -621), Point(553, 345, -567), Point(474, 580, 667), Point(-447, -329, 318), Point(-584, 868, -557), Point(544, -627, -890), Point(564, 392, -477), Point(455, 729, 728), Point(-892, 524, 684), Point(-689, 845, -530), Point(423, -701, 434), Point(7, -33, -71), Point(630, 319, -379), Point(443, 580, 662), Point(-789, 900, -551), Point(459, -707, 401)],
|
||||
vec![Point(686, 422, 578), Point(605, 423, 415), Point(515, 917, -361), Point(-336, 658, 858), Point(95, 138, 22), Point(-476, 619, 847), Point(-340, -569, -846), Point(567, -361, 727), Point(-460, 603, -452), Point(669, -402, 600), Point(729, 430, 532), Point(-500, -761, 534), Point(-322, 571, 750), Point(-466, -666, -811), Point(-429, -592, 574), Point(-355, 545, -477), Point(703, -491, -529), Point(-328, -685, 520), Point(413, 935, -424), Point(-391, 539, -444), Point(586, -435, 557), Point(-364, -763, -893), Point(807, -499, -711), Point(755, -354, -619), Point(553, 889, -390)],
|
||||
vec![Point(649, 640, 665), Point(682, -795, 504), Point(-784, 533, -524), Point(-644, 584, -595), Point(-588, -843, 648), Point(-30, 6, 44), Point(-674, 560, 763), Point(500, 723, -460), Point(609, 671, -379), Point(-555, -800, 653), Point(-675, -892, -343), Point(697, -426, -610), Point(578, 704, 681), Point(493, 664, -388), Point(-671, -858, 530), Point(-667, 343, 800), Point(571, -461, -707), Point(-138, -166, 112), Point(-889, 563, -600), Point(646, -828, 498), Point(640, 759, 510), Point(-630, 509, 768), Point(-681, -892, -333), Point(673, -379, -804), Point(-742, -814, -386), Point(577, -820, 562)],
|
||||
vec![Point(-589, 542, 597), Point(605, -692, 669), Point(-500, 565, -823), Point(-660, 373, 557), Point(-458, -679, -417), Point(-488, 449, 543), Point(-626, 468, -788), Point(338, -750, -386), Point(528, -832, -391), Point(562, -778, 733), Point(-938, -730, 414), Point(543, 643, -506), Point(-524, 371, -870), Point(407, 773, 750), Point(-104, 29, 83), Point(378, -903, -323), Point(-778, -728, 485), Point(426, 699, 580), Point(-438, -605, -362), Point(-469, -447, -387), Point(509, 732, 623), Point(647, 635, -688), Point(-868, -804, 481), Point(614, -800, 639), Point(595, 780, -596)],
|
||||
vec![Point(727, 592, 562), Point(-293, -554, 779), Point(441, 611, -461), Point(-714, 465, -776), Point(-743, 427, -804), Point(-660, -479, -426), Point(832, -632, 460), Point(927, -485, -438), Point(408, 393, -506), Point(466, 436, -512), Point(110, 16, 151), Point(-258, -428, 682), Point(-393, 719, 612), Point(-211, -452, 876), Point(808, -476, -593), Point(-575, 615, 604), Point(-485, 667, 467), Point(-680, 325, -822), Point(-627, -443, -432), Point(872, -547, -609), Point(833, 512, 582), Point(807, 604, 487), Point(839, -516, 451), Point(891, -625, 532), Point(-652, -548, -490), Point(30, -46, -14)],
|
||||
];
|
||||
let result = part1(&scanners);
|
||||
assert_eq!(result, 79);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn part2_example() {
|
||||
let scanners = vec![
|
||||
vec![Point(404, -588, -901), Point(528, -643, 409), Point(-838, 591, 734), Point(390, -675, -793), Point(-537, -823, -458), Point(-485, -357, 347), Point(-345, -311, 381), Point(-661, -816, -575), Point(-876, 649, 763), Point(-618, -824, -621), Point(553, 345, -567), Point(474, 580, 667), Point(-447, -329, 318), Point(-584, 868, -557), Point(544, -627, -890), Point(564, 392, -477), Point(455, 729, 728), Point(-892, 524, 684), Point(-689, 845, -530), Point(423, -701, 434), Point(7, -33, -71), Point(630, 319, -379), Point(443, 580, 662), Point(-789, 900, -551), Point(459, -707, 401)],
|
||||
vec![Point(686, 422, 578), Point(605, 423, 415), Point(515, 917, -361), Point(-336, 658, 858), Point(95, 138, 22), Point(-476, 619, 847), Point(-340, -569, -846), Point(567, -361, 727), Point(-460, 603, -452), Point(669, -402, 600), Point(729, 430, 532), Point(-500, -761, 534), Point(-322, 571, 750), Point(-466, -666, -811), Point(-429, -592, 574), Point(-355, 545, -477), Point(703, -491, -529), Point(-328, -685, 520), Point(413, 935, -424), Point(-391, 539, -444), Point(586, -435, 557), Point(-364, -763, -893), Point(807, -499, -711), Point(755, -354, -619), Point(553, 889, -390)],
|
||||
vec![Point(649, 640, 665), Point(682, -795, 504), Point(-784, 533, -524), Point(-644, 584, -595), Point(-588, -843, 648), Point(-30, 6, 44), Point(-674, 560, 763), Point(500, 723, -460), Point(609, 671, -379), Point(-555, -800, 653), Point(-675, -892, -343), Point(697, -426, -610), Point(578, 704, 681), Point(493, 664, -388), Point(-671, -858, 530), Point(-667, 343, 800), Point(571, -461, -707), Point(-138, -166, 112), Point(-889, 563, -600), Point(646, -828, 498), Point(640, 759, 510), Point(-630, 509, 768), Point(-681, -892, -333), Point(673, -379, -804), Point(-742, -814, -386), Point(577, -820, 562)],
|
||||
vec![Point(-589, 542, 597), Point(605, -692, 669), Point(-500, 565, -823), Point(-660, 373, 557), Point(-458, -679, -417), Point(-488, 449, 543), Point(-626, 468, -788), Point(338, -750, -386), Point(528, -832, -391), Point(562, -778, 733), Point(-938, -730, 414), Point(543, 643, -506), Point(-524, 371, -870), Point(407, 773, 750), Point(-104, 29, 83), Point(378, -903, -323), Point(-778, -728, 485), Point(426, 699, 580), Point(-438, -605, -362), Point(-469, -447, -387), Point(509, 732, 623), Point(647, 635, -688), Point(-868, -804, 481), Point(614, -800, 639), Point(595, 780, -596)],
|
||||
vec![Point(727, 592, 562), Point(-293, -554, 779), Point(441, 611, -461), Point(-714, 465, -776), Point(-743, 427, -804), Point(-660, -479, -426), Point(832, -632, 460), Point(927, -485, -438), Point(408, 393, -506), Point(466, 436, -512), Point(110, 16, 151), Point(-258, -428, 682), Point(-393, 719, 612), Point(-211, -452, 876), Point(808, -476, -593), Point(-575, 615, 604), Point(-485, 667, 467), Point(-680, 325, -822), Point(-627, -443, -432), Point(872, -547, -609), Point(833, 512, 582), Point(807, 604, 487), Point(839, -516, 451), Point(891, -625, 532), Point(-652, -548, -490), Point(30, -46, -14)],
|
||||
];
|
||||
let result = part2(&scanners);
|
||||
assert_eq!(result, 3621);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn rotation_matrices() {
|
||||
let p = Point(1, 2, 3);
|
||||
let Point(x, y, z) = p;
|
||||
let ref_rotations = vec![
|
||||
Point(x ,y ,z), Point(x ,z,-y), Point(x ,-y,-z), Point(x ,-z,y ),
|
||||
Point(-x,-y,z), Point(-x,z,y ), Point(-x,y ,-z), Point(-x,-z,-y ),
|
||||
Point(y ,z ,x), Point(y ,x,-z), Point(y ,-z,-x), Point(y ,-x,z ),
|
||||
Point(-y,-z,x), Point(-y,x,z ), Point(-y,z ,-x), Point(-y,-x,-z ),
|
||||
Point(z ,x ,y), Point(z ,y,-x), Point(z ,-x,-y), Point(z ,-y,x ),
|
||||
Point(-z,-x,y), Point(-z,y,x ), Point(-z,x ,-y), Point(-z,-y,-x)
|
||||
];
|
||||
let calculated: Vec<_> = ROTATIONS.iter().map(|rot| rot.mul(p)).collect();
|
||||
for (i, rot) in calculated.iter().enumerate() {
|
||||
assert_eq!(*rot, ref_rotations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn multiply_matrices() {
|
||||
let a = Rotation(2, 3, 1, 7, 4, 1, 9, -2, 1);
|
||||
let b = Rotation(9, -2, -1, 5, 7, 3, 8, 1, 0);
|
||||
let c = a.mul(b);
|
||||
assert_eq!(c, Rotation(41, 18, 7, 91, 15, 5, 79, -31, -15));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
135
src/day2.rs
135
src/day2.rs
@ -2,96 +2,93 @@ use std::num::ParseIntError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseCommandError {
|
||||
ParseEnumError,
|
||||
ParseIntError(ParseIntError),
|
||||
ParseEnumError,
|
||||
ParseIntError(ParseIntError),
|
||||
}
|
||||
|
||||
pub enum CommandType {
|
||||
Forward,
|
||||
Down,
|
||||
Up
|
||||
Forward,
|
||||
Down,
|
||||
Up,
|
||||
}
|
||||
|
||||
pub struct Command(CommandType, u32);
|
||||
|
||||
fn parse_line(line: &str) -> Result<Command, ParseCommandError> {
|
||||
let parts: Vec<&str> = line.split(' ').collect();
|
||||
let command = match parts[0] {
|
||||
"up" => Ok(CommandType::Up),
|
||||
"down" => Ok(CommandType::Down),
|
||||
"forward" => Ok(CommandType::Forward),
|
||||
_ => Err(ParseCommandError::ParseEnumError)
|
||||
}?;
|
||||
let amount = parts[1].parse().map_err(ParseCommandError::ParseIntError)?;
|
||||
Ok(Command(command, amount))
|
||||
let parts: Vec<&str> = line.split(' ').collect();
|
||||
let command = match parts[0] {
|
||||
"up" => Ok(CommandType::Up),
|
||||
"down" => Ok(CommandType::Down),
|
||||
"forward" => Ok(CommandType::Forward),
|
||||
_ => Err(ParseCommandError::ParseEnumError),
|
||||
}?;
|
||||
let amount = parts[1].parse().map_err(ParseCommandError::ParseIntError)?;
|
||||
Ok(Command(command, amount))
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Result<Vec<Command>, ParseCommandError> {
|
||||
input.split_terminator('\n')
|
||||
.map(parse_line)
|
||||
.collect()
|
||||
input.split_terminator('\n').map(parse_line).collect()
|
||||
}
|
||||
|
||||
pub fn part1(commands: &[Command]) -> u32 {
|
||||
let mut depth = 0;
|
||||
let mut horizontal = 0;
|
||||
for command in commands {
|
||||
match command.0 {
|
||||
CommandType::Up => depth -= command.1,
|
||||
CommandType::Down => depth += command.1,
|
||||
CommandType::Forward => horizontal += command.1,
|
||||
}
|
||||
}
|
||||
return depth * horizontal;
|
||||
let mut depth = 0;
|
||||
let mut horizontal = 0;
|
||||
for command in commands {
|
||||
match command.0 {
|
||||
CommandType::Up => depth -= command.1,
|
||||
CommandType::Down => depth += command.1,
|
||||
CommandType::Forward => horizontal += command.1,
|
||||
}
|
||||
}
|
||||
return depth * horizontal;
|
||||
}
|
||||
|
||||
pub fn part2(commands: &[Command]) -> u32 {
|
||||
let mut depth = 0;
|
||||
let mut horizontal = 0;
|
||||
let mut aim = 0;
|
||||
for command in commands {
|
||||
match command.0 {
|
||||
CommandType::Up => aim -= command.1,
|
||||
CommandType::Down => aim += command.1,
|
||||
CommandType::Forward => {
|
||||
horizontal += command.1;
|
||||
depth += aim * command.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return depth * horizontal;
|
||||
let mut depth = 0;
|
||||
let mut horizontal = 0;
|
||||
let mut aim = 0;
|
||||
for command in commands {
|
||||
match command.0 {
|
||||
CommandType::Up => aim -= command.1,
|
||||
CommandType::Down => aim += command.1,
|
||||
CommandType::Forward => {
|
||||
horizontal += command.1;
|
||||
depth += aim * command.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return depth * horizontal;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let commands = [
|
||||
Command(CommandType::Forward, 5),
|
||||
Command(CommandType::Down, 5),
|
||||
Command(CommandType::Forward, 8),
|
||||
Command(CommandType::Up, 3),
|
||||
Command(CommandType::Down, 8),
|
||||
Command(CommandType::Forward, 2)
|
||||
];
|
||||
let result = part1(&commands);
|
||||
assert_eq!(result, 150);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let commands = [
|
||||
Command(CommandType::Forward, 5),
|
||||
Command(CommandType::Down, 5),
|
||||
Command(CommandType::Forward, 8),
|
||||
Command(CommandType::Up, 3),
|
||||
Command(CommandType::Down, 8),
|
||||
Command(CommandType::Forward, 2),
|
||||
];
|
||||
let result = part1(&commands);
|
||||
assert_eq!(result, 150);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let commands = [
|
||||
Command(CommandType::Forward, 5),
|
||||
Command(CommandType::Down, 5),
|
||||
Command(CommandType::Forward, 8),
|
||||
Command(CommandType::Up, 3),
|
||||
Command(CommandType::Down, 8),
|
||||
Command(CommandType::Forward, 2)
|
||||
];
|
||||
let result = part2(&commands);
|
||||
assert_eq!(result, 900)
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let commands = [
|
||||
Command(CommandType::Forward, 5),
|
||||
Command(CommandType::Down, 5),
|
||||
Command(CommandType::Forward, 8),
|
||||
Command(CommandType::Up, 3),
|
||||
Command(CommandType::Down, 8),
|
||||
Command(CommandType::Forward, 2),
|
||||
];
|
||||
let result = part2(&commands);
|
||||
assert_eq!(result, 900)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
236
src/day20.rs
Normal file
236
src/day20.rs
Normal file
@ -0,0 +1,236 @@
|
||||
use std::{fmt::Display, ops::Range};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Image {
|
||||
width: usize,
|
||||
height: usize,
|
||||
data: Vec<bool>,
|
||||
default_value: bool,
|
||||
offset_x: i32,
|
||||
offset_y: i32,
|
||||
}
|
||||
|
||||
impl Image {
|
||||
fn new(width: usize, height: usize) -> Image {
|
||||
let data = vec![false; width * height];
|
||||
Image {
|
||||
width,
|
||||
height,
|
||||
data,
|
||||
default_value: false,
|
||||
offset_x: 0,
|
||||
offset_y: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, x: i32, y: i32) -> bool {
|
||||
if self.in_bounds(x, y) {
|
||||
let index = (y + self.offset_y) * self.width as i32 + (x + self.offset_x);
|
||||
*self.data.get(index as usize).unwrap_or(&self.default_value)
|
||||
} else {
|
||||
self.default_value
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, x: i32, y: i32, value: bool) {
|
||||
// Make image larger if it is too small
|
||||
let (left, top, right, bottom) = self.bounds();
|
||||
if !(left <= x && x < right && top <= y && y < bottom) {
|
||||
if x < left {
|
||||
self.offset_x = -x;
|
||||
self.width = self.width + (-x + left) as usize;
|
||||
} else if x >= right {
|
||||
self.width = self.width + 1 + (x - right) as usize;
|
||||
}
|
||||
|
||||
if y < top {
|
||||
self.offset_y = -y;
|
||||
self.height = self.height + (-y + top) as usize;
|
||||
} else if y >= bottom {
|
||||
self.height = self.height + 1 + (y - bottom) as usize;
|
||||
}
|
||||
|
||||
let mut new_data = Vec::new();
|
||||
for y in self.y_range(0) {
|
||||
for x in self.x_range(0) {
|
||||
new_data.push(self.get(x, y));
|
||||
}
|
||||
}
|
||||
self.data = new_data;
|
||||
}
|
||||
|
||||
let index = ((y + self.offset_y) * self.width as i32 + (x + self.offset_x)) as usize;
|
||||
self.data[index] = value;
|
||||
}
|
||||
|
||||
fn in_bounds(&self, x: i32, y: i32) -> bool {
|
||||
let (left, top, right, bottom) = self.bounds();
|
||||
left <= x && x < right && top <= y && y < bottom
|
||||
}
|
||||
|
||||
fn count(&self, value: bool) -> usize {
|
||||
if self.default_value == value {
|
||||
usize::MAX
|
||||
} else {
|
||||
self.data.iter().filter(|x| **x == value).count()
|
||||
}
|
||||
}
|
||||
|
||||
fn x_range(&self, padding: u32) -> Range<i32> {
|
||||
let padding = padding as i32;
|
||||
Range {
|
||||
start: -self.offset_x - padding,
|
||||
end: self.width as i32 - self.offset_x + padding,
|
||||
}
|
||||
}
|
||||
|
||||
fn y_range(&self, padding: u32) -> Range<i32> {
|
||||
let padding = padding as i32;
|
||||
Range {
|
||||
start: -self.offset_y - padding,
|
||||
end: self.height as i32 - self.offset_y + padding,
|
||||
}
|
||||
}
|
||||
|
||||
// (i32, i32, i32, i32) => (left, top, right, bottom)
|
||||
fn bounds(&self) -> (i32, i32, i32, i32) {
|
||||
return (
|
||||
-self.offset_x,
|
||||
-self.offset_y,
|
||||
self.width as i32 - self.offset_x,
|
||||
self.height as i32 - self.offset_y,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Image {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let mut grid = String::new();
|
||||
for y in self.y_range(1) {
|
||||
for x in self.x_range(1) {
|
||||
let symbol = if self.get(x, y) { '#' } else { '.' };
|
||||
grid.push(symbol);
|
||||
}
|
||||
grid.push('\n');
|
||||
}
|
||||
write!(f, "{}", grid)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_image(input: &str) -> Image {
|
||||
let mut image = Image::new(3, 3);
|
||||
let mut y = 0;
|
||||
for line in input.lines() {
|
||||
let mut x = 0;
|
||||
for c in line.chars() {
|
||||
image.set(x, y, c == '#');
|
||||
x += 1;
|
||||
}
|
||||
y += 1
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
fn parse_enchancer(input: &str) -> [bool; 512] {
|
||||
let mut enhancer = [false; 512];
|
||||
let mut i = 0;
|
||||
for c in input.chars() {
|
||||
enhancer[i] = c == '#';
|
||||
i += 1;
|
||||
}
|
||||
return enhancer;
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> ([bool; 512], Image) {
|
||||
let (section1, section2) = input.split_once("\n\n").unwrap();
|
||||
return (parse_enchancer(section1), parse_image(section2));
|
||||
}
|
||||
|
||||
fn lookup_enhancer(x: i32, y: i32, image: &Image, enhancer: &[bool; 512]) -> bool {
|
||||
let pixel_offsets = [
|
||||
(-1, -1),
|
||||
(0, -1),
|
||||
(1, -1),
|
||||
(-1, 0),
|
||||
(0, 0),
|
||||
(1, 0),
|
||||
(-1, 1),
|
||||
(0, 1),
|
||||
(1, 1),
|
||||
];
|
||||
|
||||
let mut lookup_index = 0;
|
||||
for i in 0..9 {
|
||||
let (ox, oy) = pixel_offsets[i];
|
||||
let pixel = image.get(x + ox, y + oy);
|
||||
if pixel {
|
||||
lookup_index += 2usize.pow((8 - i) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
enhancer[lookup_index]
|
||||
}
|
||||
|
||||
fn enhance(image: &Image, enhancer: &[bool; 512]) -> Image {
|
||||
let mut enhanced = image.clone();
|
||||
for y in image.y_range(1) {
|
||||
for x in image.x_range(1) {
|
||||
enhanced.set(x, y, lookup_enhancer(x, y, image, enhancer));
|
||||
}
|
||||
}
|
||||
|
||||
if image.default_value {
|
||||
enhanced.default_value = enhancer[511];
|
||||
} else {
|
||||
enhanced.default_value = enhancer[0];
|
||||
}
|
||||
|
||||
enhanced
|
||||
}
|
||||
|
||||
pub fn part1(data: &([bool; 512], Image)) -> usize {
|
||||
let (enhancer, image) = data;
|
||||
let mut enhanced_image = enhance(&image, enhancer);
|
||||
enhanced_image = enhance(&enhanced_image, enhancer);
|
||||
enhanced_image.count(true)
|
||||
}
|
||||
|
||||
pub fn part2(data: &([bool; 512], Image)) -> usize {
|
||||
let (enhancer, image) = data;
|
||||
let mut enhanced_image = enhance(&image, enhancer);
|
||||
for _ in 0..49 {
|
||||
enhanced_image = enhance(&enhanced_image, enhancer);
|
||||
}
|
||||
enhanced_image.count(true)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = parse_input("..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
|
||||
|
||||
#..#.
|
||||
#....
|
||||
##..#
|
||||
..#..
|
||||
..###");
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 35);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = parse_input("..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#....#..#..##..###..######.###...####..#..#####..##..#.#####...##.#.#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..#####.....#.#....###..#.##......#.....#..#..#..##..#...##.######.####.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.##..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#.....####.#..#..#.##.#....##..#.####....##...##..#...#......#.#.......#.......##..####..#...#.#.#...##..#.#..###..#####........#..####......#..#
|
||||
|
||||
#..#.
|
||||
#....
|
||||
##..#
|
||||
..#..
|
||||
..###");
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 3351);
|
||||
}
|
||||
}
|
||||
108
src/day21.rs
Normal file
108
src/day21.rs
Normal file
@ -0,0 +1,108 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn parse_input(input: &str) -> (u8, u8) {
|
||||
let players: Vec<u8> = input
|
||||
.lines()
|
||||
.map(|l| l.split_once(": ").unwrap().1.parse().unwrap())
|
||||
.collect();
|
||||
return (players[0], players[1]);
|
||||
}
|
||||
|
||||
pub fn part1(starting_positions: &(u8, u8)) -> u32 {
|
||||
let mut player1_position = starting_positions.0 as u32;
|
||||
let mut player2_position = starting_positions.1 as u32;
|
||||
let mut player1_score: u32 = 0;
|
||||
let mut player2_score: u32 = 0;
|
||||
let mut rolled_count = 0;
|
||||
|
||||
let mut is_player1_turn = true;
|
||||
|
||||
while player1_score < 1000 && player2_score < 1000 {
|
||||
let position;
|
||||
let score;
|
||||
if is_player1_turn {
|
||||
position = &mut player1_position;
|
||||
score = &mut player1_score;
|
||||
} else {
|
||||
position = &mut player2_position;
|
||||
score = &mut player2_score;
|
||||
}
|
||||
|
||||
*position += (rolled_count + 1 - 1) % 100 + 1;
|
||||
*position += (rolled_count + 2 - 1) % 100 + 1;
|
||||
*position += (rolled_count + 3 - 1) % 100 + 1;
|
||||
|
||||
*position = (*position - 1) % 10 + 1;
|
||||
*score += *position as u32;
|
||||
|
||||
rolled_count += 3;
|
||||
is_player1_turn = !is_player1_turn;
|
||||
}
|
||||
|
||||
player1_score.min(player2_score) * rolled_count as u32
|
||||
}
|
||||
|
||||
fn get_wins_amount(
|
||||
starting_pos1: u32,
|
||||
starting_pos2: u32,
|
||||
starting_score1: u32,
|
||||
starting_score2: u32,
|
||||
memo: &mut HashMap<(u32, u32, u32, u32), (u64, u64)>,
|
||||
) -> (u64, u64) {
|
||||
let memo_key = (
|
||||
starting_pos1,
|
||||
starting_pos2,
|
||||
starting_score1,
|
||||
starting_score2,
|
||||
);
|
||||
if memo.contains_key(&memo_key) {
|
||||
return *memo.get(&memo_key).unwrap();
|
||||
}
|
||||
let mut total_wins1 = 0;
|
||||
let mut total_wins2 = 0;
|
||||
|
||||
for dice1 in 1..=3 {
|
||||
for dice2 in 1..=3 {
|
||||
for dice3 in 1..=3 {
|
||||
let pos1 = (starting_pos1 + dice1 + dice2 + dice3 - 1) % 10 + 1;
|
||||
let score1 = starting_score1 + pos1;
|
||||
if score1 >= 21 {
|
||||
total_wins1 += 1
|
||||
} else {
|
||||
let (wins2, wins1) = get_wins_amount(starting_pos2, pos1, starting_score2, score1, memo);
|
||||
total_wins1 += wins1;
|
||||
total_wins2 += wins2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memo.insert(memo_key, (total_wins1, total_wins2));
|
||||
|
||||
(total_wins1, total_wins2)
|
||||
}
|
||||
|
||||
pub fn part2(positions: &(u8, u8)) -> u64 {
|
||||
let mut memo = HashMap::new();
|
||||
let (wins1, wins2) = get_wins_amount(positions.0 as u32, positions.1 as u32, 0, 0, &mut memo);
|
||||
wins1.max(wins2)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = (4, 8);
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 739785);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = (4, 8);
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 444356092776315);
|
||||
}
|
||||
}
|
||||
381
src/day22.rs
Normal file
381
src/day22.rs
Normal file
@ -0,0 +1,381 @@
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
convert::{TryFrom, TryInto},
|
||||
num::ParseIntError,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Cuboid {
|
||||
x: (i32, i32),
|
||||
y: (i32, i32),
|
||||
z: (i32, i32),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StepAction {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RebootStep(StepAction, Cuboid);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseRangeError {
|
||||
Empty,
|
||||
BadLen,
|
||||
ParseInt(ParseIntError),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseCuboidError {
|
||||
Empty,
|
||||
BadLen,
|
||||
ParseRange(ParseRangeError),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseRebootStepError {
|
||||
Empty,
|
||||
BadLen,
|
||||
BadAction,
|
||||
ParseCuboid(ParseCuboidError),
|
||||
}
|
||||
|
||||
impl Cuboid {
|
||||
fn contains(&self, point: &(i32, i32, i32)) -> bool {
|
||||
self.x.0 <= point.0
|
||||
&& point.0 <= self.x.1
|
||||
&& self.y.0 <= point.1
|
||||
&& point.1 <= self.y.1
|
||||
&& self.z.0 <= point.2
|
||||
&& point.2 <= self.z.1
|
||||
}
|
||||
|
||||
fn clamp(&self, other: &Cuboid) -> Cuboid {
|
||||
Cuboid {
|
||||
x: (self.x.0.max(other.x.0), self.x.1.min(other.x.1)),
|
||||
y: (self.y.0.max(other.y.0), self.y.1.min(other.y.1)),
|
||||
z: (self.z.0.max(other.z.0), self.z.1.min(other.z.1)),
|
||||
}
|
||||
}
|
||||
|
||||
fn intersection(&self, other: &Cuboid) -> Option<Cuboid> {
|
||||
if self.z.0 > other.z.1 || other.z.0 > self.z.1 {
|
||||
return None;
|
||||
}
|
||||
if self.y.0 > other.y.1 || other.y.0 > self.y.1 {
|
||||
return None;
|
||||
}
|
||||
if self.x.0 > other.x.1 || other.x.0 > self.x.1 {
|
||||
return None;
|
||||
}
|
||||
Some(self.clamp(other))
|
||||
}
|
||||
|
||||
fn volume(&self) -> u64 {
|
||||
(self.x.1 - self.x.0 + 1) as u64
|
||||
* (self.y.1 - self.y.0 + 1) as u64
|
||||
* (self.z.1 - self.z.0 + 1) as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for ParseRangeError {
|
||||
fn from(e: ParseIntError) -> Self {
|
||||
ParseRangeError::ParseInt(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseRangeError> for ParseCuboidError {
|
||||
fn from(e: ParseRangeError) -> Self {
|
||||
ParseCuboidError::ParseRange(e)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_range(value: &str) -> Result<(i32, i32), ParseRangeError> {
|
||||
if value.is_empty() {
|
||||
return Err(ParseRangeError::Empty);
|
||||
}
|
||||
let (start, end) = value[2..].split_once("..").ok_or(ParseRangeError::BadLen)?;
|
||||
Ok((start.parse()?, end.parse()?))
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Cuboid {
|
||||
type Error = ParseCuboidError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
if value.is_empty() {
|
||||
return Err(Self::Error::Empty);
|
||||
}
|
||||
let ranges: Vec<_> = value
|
||||
.split(',')
|
||||
.map(parse_range)
|
||||
.collect::<Result<_, _>>()?;
|
||||
if ranges.len() != 3 {
|
||||
return Err(Self::Error::BadLen);
|
||||
}
|
||||
Ok(Cuboid {
|
||||
x: ranges[0],
|
||||
y: ranges[1],
|
||||
z: ranges[2],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseCuboidError> for ParseRebootStepError {
|
||||
fn from(e: ParseCuboidError) -> Self {
|
||||
ParseRebootStepError::ParseCuboid(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for RebootStep {
|
||||
type Error = ParseRebootStepError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
if value.is_empty() {
|
||||
return Err(Self::Error::Empty);
|
||||
}
|
||||
let (action_str, cuboid) = value.split_once(" ").ok_or(Self::Error::BadLen)?;
|
||||
|
||||
let action = match action_str {
|
||||
"on" => StepAction::On,
|
||||
"off" => StepAction::Off,
|
||||
_ => return Err(Self::Error::BadAction),
|
||||
};
|
||||
|
||||
Ok(RebootStep(action, cuboid.try_into()?))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<RebootStep> {
|
||||
input.lines().map(|l| l.try_into().unwrap()).collect()
|
||||
}
|
||||
|
||||
fn count_cubes_in_cuboid(steps: &[RebootStep], region: &Cuboid) -> u32 {
|
||||
let mut cubes = HashSet::new();
|
||||
|
||||
for step in steps {
|
||||
let clamped = step.1.clamp(region);
|
||||
for x in clamped.x.0..=clamped.x.1 {
|
||||
for y in clamped.y.0..=clamped.y.1 {
|
||||
for z in clamped.z.0..=clamped.z.1 {
|
||||
let cube = (x, y, z);
|
||||
match step.0 {
|
||||
StepAction::On => cubes.insert(cube),
|
||||
StepAction::Off => cubes.remove(&cube),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cubes.len() as u32
|
||||
}
|
||||
|
||||
// From: http://twocentstudios.com/2016/08/16/calculating-the-area-of-multiple-intersecting-rectangles-with-swift
|
||||
/*
|
||||
fn total_volume(cuboids: &Vec<Cuboid>) -> u64 {
|
||||
let mut unique_x = HashSet::new();
|
||||
let mut unique_y = HashSet::new();
|
||||
let mut unique_z = HashSet::new();
|
||||
for cuboid in cuboids {
|
||||
unique_x.insert(cuboid.x.0);
|
||||
unique_x.insert(cuboid.x.1);
|
||||
unique_y.insert(cuboid.y.0);
|
||||
unique_y.insert(cuboid.y.1);
|
||||
unique_z.insert(cuboid.z.0);
|
||||
unique_z.insert(cuboid.z.1);
|
||||
}
|
||||
|
||||
let mut unique_x: Vec<_> = unique_x.iter().collect();
|
||||
let mut unique_y: Vec<_> = unique_y.iter().collect();
|
||||
let mut unique_z: Vec<_> = unique_z.iter().collect();
|
||||
|
||||
unique_x.sort();
|
||||
unique_y.sort();
|
||||
unique_z.sort();
|
||||
|
||||
let mut volume = 0;
|
||||
for (i, x) in unique_x.iter().enumerate().skip(1) {
|
||||
for (j, y) in unique_y.iter().enumerate().skip(1) {
|
||||
for (k, z) in unique_z.iter().enumerate().skip(1) {
|
||||
let cuboid = Cuboid {
|
||||
x: (*unique_x[i-1], **x),
|
||||
y: (*unique_y[j-1], **y),
|
||||
z: (*unique_z[k-1], **z)
|
||||
};
|
||||
for c in cuboids {
|
||||
if c.has_overlap(&cuboid) {
|
||||
volume += cuboid.volume();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// let point = (
|
||||
// (*unique_x[i-1] + **x)/2,
|
||||
// (*unique_y[j-1] + **y)/2,
|
||||
// (*unique_z[k-1] + **z)/2
|
||||
// );
|
||||
// for c in cuboids {
|
||||
// if c.contains(&point) {
|
||||
// let cuboid = Cuboid {
|
||||
// x: (*unique_x[i-1], **x),
|
||||
// y: (*unique_y[j-1], **y),
|
||||
// z: (*unique_z[k-1], **z)
|
||||
// };
|
||||
// volume += cuboid.volume();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
volume
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* From: https://github.com/Jellycious/aoc-2021/blob/main/src/days/day22.rs
|
||||
* Based on inclusion-exclusion principle. https://en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_principle
|
||||
*/
|
||||
fn count_cubes(steps: Vec<RebootStep>) -> u64 {
|
||||
let mut cuboids: Vec<(Cuboid, bool)> = Vec::new();
|
||||
|
||||
for step in steps {
|
||||
let mut extra_cuboids = Vec::new();
|
||||
for c in cuboids.iter() {
|
||||
if let Some(intersect) = step.1.intersection(&c.0) {
|
||||
extra_cuboids.push((intersect, !c.1));
|
||||
}
|
||||
}
|
||||
|
||||
if let StepAction::On = step.0 {
|
||||
cuboids.push((step.1, true));
|
||||
}
|
||||
cuboids.append(&mut extra_cuboids);
|
||||
}
|
||||
|
||||
let mut total_volume = 0;
|
||||
for (cuboid, additive) in cuboids {
|
||||
let sign: i64 = if additive { 1 } else { -1 };
|
||||
total_volume += sign * cuboid.volume() as i64;
|
||||
}
|
||||
total_volume as u64
|
||||
}
|
||||
|
||||
pub fn part1(steps: &[RebootStep]) -> u32 {
|
||||
let region = Cuboid {
|
||||
x: (-50, 50),
|
||||
y: (-50, 50),
|
||||
z: (-50, 50),
|
||||
};
|
||||
count_cubes_in_cuboid(steps, ®ion)
|
||||
}
|
||||
|
||||
pub fn part2(steps: Vec<RebootStep>) -> u64 {
|
||||
count_cubes(steps)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let steps = parse_input(
|
||||
"on x=-20..26,y=-36..17,z=-47..7
|
||||
on x=-20..33,y=-21..23,z=-26..28
|
||||
on x=-22..28,y=-29..23,z=-38..16
|
||||
on x=-46..7,y=-6..46,z=-50..-1
|
||||
on x=-49..1,y=-3..46,z=-24..28
|
||||
on x=2..47,y=-22..22,z=-23..27
|
||||
on x=-27..23,y=-28..26,z=-21..29
|
||||
on x=-39..5,y=-6..47,z=-3..44
|
||||
on x=-30..21,y=-8..43,z=-13..34
|
||||
on x=-22..26,y=-27..20,z=-29..19
|
||||
off x=-48..-32,y=26..41,z=-47..-37
|
||||
on x=-12..35,y=6..50,z=-50..-2
|
||||
off x=-48..-32,y=-32..-16,z=-15..-5
|
||||
on x=-18..26,y=-33..15,z=-7..46
|
||||
off x=-40..-22,y=-38..-28,z=23..41
|
||||
on x=-16..35,y=-41..10,z=-47..6
|
||||
off x=-32..-23,y=11..30,z=-14..3
|
||||
on x=-49..-5,y=-3..45,z=-29..18
|
||||
off x=18..30,y=-20..-8,z=-3..13
|
||||
on x=-41..9,y=-7..43,z=-33..15
|
||||
on x=-54112..-39298,y=-85059..-49293,z=-27449..7877
|
||||
on x=967..23432,y=45373..81175,z=27513..53682",
|
||||
);
|
||||
let result = part1(&steps);
|
||||
assert_eq!(result, 590784);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let steps = parse_input(
|
||||
"on x=-5..47,y=-31..22,z=-19..33
|
||||
on x=-44..5,y=-27..21,z=-14..35
|
||||
on x=-49..-1,y=-11..42,z=-10..38
|
||||
on x=-20..34,y=-40..6,z=-44..1
|
||||
off x=26..39,y=40..50,z=-2..11
|
||||
on x=-41..5,y=-41..6,z=-36..8
|
||||
off x=-43..-33,y=-45..-28,z=7..25
|
||||
on x=-33..15,y=-32..19,z=-34..11
|
||||
off x=35..47,y=-46..-34,z=-11..5
|
||||
on x=-14..36,y=-6..44,z=-16..29
|
||||
on x=-57795..-6158,y=29564..72030,z=20435..90618
|
||||
on x=36731..105352,y=-21140..28532,z=16094..90401
|
||||
on x=30999..107136,y=-53464..15513,z=8553..71215
|
||||
on x=13528..83982,y=-99403..-27377,z=-24141..23996
|
||||
on x=-72682..-12347,y=18159..111354,z=7391..80950
|
||||
on x=-1060..80757,y=-65301..-20884,z=-103788..-16709
|
||||
on x=-83015..-9461,y=-72160..-8347,z=-81239..-26856
|
||||
on x=-52752..22273,y=-49450..9096,z=54442..119054
|
||||
on x=-29982..40483,y=-108474..-28371,z=-24328..38471
|
||||
on x=-4958..62750,y=40422..118853,z=-7672..65583
|
||||
on x=55694..108686,y=-43367..46958,z=-26781..48729
|
||||
on x=-98497..-18186,y=-63569..3412,z=1232..88485
|
||||
on x=-726..56291,y=-62629..13224,z=18033..85226
|
||||
on x=-110886..-34664,y=-81338..-8658,z=8914..63723
|
||||
on x=-55829..24974,y=-16897..54165,z=-121762..-28058
|
||||
on x=-65152..-11147,y=22489..91432,z=-58782..1780
|
||||
on x=-120100..-32970,y=-46592..27473,z=-11695..61039
|
||||
on x=-18631..37533,y=-124565..-50804,z=-35667..28308
|
||||
on x=-57817..18248,y=49321..117703,z=5745..55881
|
||||
on x=14781..98692,y=-1341..70827,z=15753..70151
|
||||
on x=-34419..55919,y=-19626..40991,z=39015..114138
|
||||
on x=-60785..11593,y=-56135..2999,z=-95368..-26915
|
||||
on x=-32178..58085,y=17647..101866,z=-91405..-8878
|
||||
on x=-53655..12091,y=50097..105568,z=-75335..-4862
|
||||
on x=-111166..-40997,y=-71714..2688,z=5609..50954
|
||||
on x=-16602..70118,y=-98693..-44401,z=5197..76897
|
||||
on x=16383..101554,y=4615..83635,z=-44907..18747
|
||||
off x=-95822..-15171,y=-19987..48940,z=10804..104439
|
||||
on x=-89813..-14614,y=16069..88491,z=-3297..45228
|
||||
on x=41075..99376,y=-20427..49978,z=-52012..13762
|
||||
on x=-21330..50085,y=-17944..62733,z=-112280..-30197
|
||||
on x=-16478..35915,y=36008..118594,z=-7885..47086
|
||||
off x=-98156..-27851,y=-49952..43171,z=-99005..-8456
|
||||
off x=2032..69770,y=-71013..4824,z=7471..94418
|
||||
on x=43670..120875,y=-42068..12382,z=-24787..38892
|
||||
off x=37514..111226,y=-45862..25743,z=-16714..54663
|
||||
off x=25699..97951,y=-30668..59918,z=-15349..69697
|
||||
off x=-44271..17935,y=-9516..60759,z=49131..112598
|
||||
on x=-61695..-5813,y=40978..94975,z=8655..80240
|
||||
off x=-101086..-9439,y=-7088..67543,z=33935..83858
|
||||
off x=18020..114017,y=-48931..32606,z=21474..89843
|
||||
off x=-77139..10506,y=-89994..-18797,z=-80..59318
|
||||
off x=8476..79288,y=-75520..11602,z=-96624..-24783
|
||||
on x=-47488..-1262,y=24338..100707,z=16292..72967
|
||||
off x=-84341..13987,y=2429..92914,z=-90671..-1318
|
||||
off x=-37810..49457,y=-71013..-7894,z=-105357..-13188
|
||||
off x=-27365..46395,y=31009..98017,z=15428..76570
|
||||
off x=-70369..-16548,y=22648..78696,z=-1892..86821
|
||||
on x=-53470..21291,y=-120233..-33476,z=-44150..38147
|
||||
off x=-93533..-4276,y=-16170..68771,z=-104985..-24507",
|
||||
);
|
||||
let result = part2(steps);
|
||||
assert_eq!(result, 2758514936282235);
|
||||
}
|
||||
}
|
||||
325
src/day23.rs
Normal file
325
src/day23.rs
Normal file
@ -0,0 +1,325 @@
|
||||
use core::fmt;
|
||||
use std::cmp::Reverse;
|
||||
|
||||
use priority_queue::PriorityQueue;
|
||||
|
||||
const HALLWAY_POINTS: &[Point] = &[Point(1, 1), Point(2, 1), Point(4, 1), Point(6, 1), Point(8, 1), Point(10, 1), Point(11, 1)];
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Amphipod {
|
||||
A, B, C, D
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Point(u32, u32);
|
||||
|
||||
impl fmt::Debug for Point {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Point({},{})", self.0, self.1)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Map {
|
||||
room_size: u32,
|
||||
amphipod_positions: Vec<Point>,
|
||||
amphipod_types: Vec<Amphipod>
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Map {
|
||||
let mut positions = vec![];
|
||||
let mut types = vec![];
|
||||
for (y, line) in input.lines().enumerate() {
|
||||
for (x, c) in line.chars().enumerate() {
|
||||
let amphipod = match c {
|
||||
'A' => Amphipod::A,
|
||||
'B' => Amphipod::B,
|
||||
'C' => Amphipod::C,
|
||||
'D' => Amphipod::D,
|
||||
_ => continue
|
||||
};
|
||||
|
||||
positions.push(Point(x as u32, y as u32));
|
||||
types.push(amphipod);
|
||||
}
|
||||
}
|
||||
|
||||
let room_size = (input.lines().count()-3) as u32;
|
||||
|
||||
Map {
|
||||
room_size,
|
||||
amphipod_types: types,
|
||||
amphipod_positions: positions
|
||||
}
|
||||
}
|
||||
|
||||
fn is_in_hallway(point: &Point) -> bool {
|
||||
point.1 == 1
|
||||
}
|
||||
|
||||
fn get_home_column(amphipod: &Amphipod) -> u32 {
|
||||
match amphipod {
|
||||
Amphipod::A => 3,
|
||||
Amphipod::B => 5,
|
||||
Amphipod::C => 7,
|
||||
Amphipod::D => 9,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_amphipod_cost(amphipod: &Amphipod) -> u32 {
|
||||
match amphipod {
|
||||
Amphipod::A => 1,
|
||||
Amphipod::B => 10,
|
||||
Amphipod::C => 100,
|
||||
Amphipod::D => 1000
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn dbg_map(map: &Map, positions: &[Point]) {
|
||||
fn print_amphipod(map: &Map, positions: &[Point], x: u32, y: u32) {
|
||||
for (i, Point(ix, iy)) in positions.iter().enumerate() {
|
||||
if *ix == x && *iy == y {
|
||||
match map.amphipod_types[i] {
|
||||
Amphipod::A => print!("A"),
|
||||
Amphipod::B => print!("B"),
|
||||
Amphipod::C => print!("C"),
|
||||
Amphipod::D => print!("D"),
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
print!(".");
|
||||
}
|
||||
|
||||
println!("#############");
|
||||
print!("#");
|
||||
for x in 1..=11 {
|
||||
print_amphipod(map, positions, x, 1);
|
||||
}
|
||||
println!("#");
|
||||
|
||||
print!("###");
|
||||
print_amphipod(map, positions, 3, 2);
|
||||
print!("#");
|
||||
print_amphipod(map, positions, 5, 2);
|
||||
print!("#");
|
||||
print_amphipod(map, positions, 7, 2);
|
||||
print!("#");
|
||||
print_amphipod(map, positions, 9, 2);
|
||||
println!("###");
|
||||
|
||||
for y in 3..2+map.room_size {
|
||||
print!(" #");
|
||||
print_amphipod(map, positions, 3, y);
|
||||
print!("#");
|
||||
print_amphipod(map, positions, 5, y);
|
||||
print!("#");
|
||||
print_amphipod(map, positions, 7, y);
|
||||
print!("#");
|
||||
print_amphipod(map, positions, 9, y);
|
||||
println!("# ");
|
||||
}
|
||||
|
||||
println!(" ######### ");
|
||||
}
|
||||
|
||||
fn is_solved(map: &Map, positions: &[Point]) -> bool {
|
||||
for (i, position) in positions.iter().enumerate() {
|
||||
let home_column = get_home_column(&map.amphipod_types[i]);
|
||||
if home_column != position.0 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn solve(map: &Map) -> u32 {
|
||||
if is_solved(map, &map.amphipod_positions) { return 0; }
|
||||
|
||||
fn push_next_state(states: &mut PriorityQueue<Vec<Point>, Reverse<u32>>, next_state: Vec<Point>, cost: u32) {
|
||||
if let Some((_, Reverse(v))) = states.get(&next_state) {
|
||||
if cost < *v {
|
||||
states.push(next_state, Reverse(cost));
|
||||
}
|
||||
} else {
|
||||
states.push(next_state, Reverse(cost));
|
||||
}
|
||||
}
|
||||
|
||||
fn has_point(points: &[Point], x: u32, y: u32) -> bool {
|
||||
for p in points {
|
||||
if p.0 == x && p.1 == y {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn get_top_free_point(map: &Map, state: &[Point], column: u32) -> Point {
|
||||
for y in (2..(2+map.room_size)).rev() {
|
||||
if !has_point(state, column, y) {
|
||||
return Point(column, y);
|
||||
}
|
||||
}
|
||||
panic!("this should never happen")
|
||||
}
|
||||
|
||||
let mut states = PriorityQueue::new();
|
||||
states.push(map.amphipod_positions.clone(), Reverse(0));
|
||||
while !states.is_empty() {
|
||||
let (state, Reverse(state_cost)) = states.pop().unwrap();
|
||||
|
||||
if is_solved(map, &state) {
|
||||
return state_cost;
|
||||
}
|
||||
|
||||
'outer: for (i, point) in state.iter().enumerate() {
|
||||
let home_column = get_home_column(&map.amphipod_types[i]);
|
||||
let step_cost = get_amphipod_cost(&map.amphipod_types[i]);
|
||||
|
||||
if is_in_hallway(point) {
|
||||
for y in (2..(2+map.room_size)).rev() {
|
||||
let index = state.iter().position(|p| p.0 == home_column && p.1 == y);
|
||||
if let Some(index) = index {
|
||||
if map.amphipod_types[index] != map.amphipod_types[i] { continue 'outer }
|
||||
}
|
||||
}
|
||||
|
||||
let x_range = {
|
||||
if point.0 > home_column {
|
||||
home_column..=(point.0-1)
|
||||
} else {
|
||||
(point.0+1)..=home_column
|
||||
}
|
||||
};
|
||||
for x in x_range {
|
||||
if has_point(&state, x, 1) { continue 'outer }
|
||||
}
|
||||
|
||||
let top_free_point = get_top_free_point(map, &state, home_column);
|
||||
let mut next_state = state.clone();
|
||||
next_state[i] = top_free_point;
|
||||
let cost = state_cost + ((top_free_point.1 - 1) + (home_column as i32 - point.0 as i32).abs() as u32) * step_cost;
|
||||
push_next_state(&mut states, next_state, cost);
|
||||
} else {
|
||||
// Check if there are not amphipod above
|
||||
for y in 2..point.1 {
|
||||
if has_point(&state, point.0, y) { continue 'outer }
|
||||
}
|
||||
|
||||
// Check if amphipod is block anything below it
|
||||
if home_column == point.0 {
|
||||
let mut needs_moving = false;
|
||||
for y in (point.1+1)..=(2+map.room_size) {
|
||||
let index = state.iter().position(|p| p.0 == point.0 && p.1 == y);
|
||||
if let Some(index) = index {
|
||||
if map.amphipod_types[index] != map.amphipod_types[i] {
|
||||
needs_moving = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !needs_moving {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
|
||||
'inner: for hallway_point in HALLWAY_POINTS {
|
||||
if !state.contains(hallway_point) {
|
||||
let from_x = point.0.min(hallway_point.0);
|
||||
let to_x = point.0.max(hallway_point.0);
|
||||
for x in from_x..to_x {
|
||||
if has_point(&state, x, 1) { continue 'inner }
|
||||
}
|
||||
|
||||
let mut next_state = state.clone();
|
||||
next_state[i] = *hallway_point;
|
||||
let cost = state_cost + ((point.1 - 1) + (to_x - from_x)) * step_cost;
|
||||
push_next_state(&mut states, next_state, cost);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
panic!("how did we get here?");
|
||||
}
|
||||
|
||||
pub fn part1(map: Map) -> u32 {
|
||||
solve(&map)
|
||||
}
|
||||
|
||||
pub fn part2(mut map: Map) -> u32 {
|
||||
map.room_size = 4;
|
||||
for position in [Point(3, 3), Point(5,3), Point(7,3), Point(9,3)] {
|
||||
let index = map.amphipod_positions.iter().position(|p| *p == position);
|
||||
if let Some(index) = index {
|
||||
map.amphipod_positions[index] = Point(position.0, 5);
|
||||
}
|
||||
}
|
||||
|
||||
let new_amphipods = [
|
||||
(Point(3, 3), Amphipod::D),
|
||||
(Point(3, 4), Amphipod::D),
|
||||
(Point(5, 3), Amphipod::C),
|
||||
(Point(5, 4), Amphipod::B),
|
||||
(Point(7, 3), Amphipod::B),
|
||||
(Point(7, 4), Amphipod::A),
|
||||
(Point(9, 3), Amphipod::A),
|
||||
(Point(9, 4), Amphipod::C),
|
||||
];
|
||||
for (position, r#type) in new_amphipods {
|
||||
map.amphipod_positions.push(position);
|
||||
map.amphipod_types.push(r#type);
|
||||
}
|
||||
|
||||
solve(&map)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let map = parse_input(&[
|
||||
"#############",
|
||||
"#...........#",
|
||||
"###B#C#B#D###",
|
||||
" #A#D#C#A# ",
|
||||
" ######### "
|
||||
].join("\n"));
|
||||
let result = part1(map);
|
||||
assert_eq!(result, 12521);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn my_input() {
|
||||
let map = parse_input(&[
|
||||
"#############",
|
||||
"#...........#",
|
||||
"###C#B#D#A###",
|
||||
" #B#D#A#C# ",
|
||||
" ######### "
|
||||
].join("\n"));
|
||||
let result = part1(map);
|
||||
assert_eq!(result, 13520);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let map = parse_input(&[
|
||||
"#############",
|
||||
"#...........#",
|
||||
"###B#C#B#D###",
|
||||
" #A#D#C#A# ",
|
||||
" ######### "
|
||||
].join("\n"));
|
||||
let result = part2(map);
|
||||
assert_eq!(result, 44169);
|
||||
}
|
||||
}
|
||||
269
src/day24.rs
Normal file
269
src/day24.rs
Normal file
@ -0,0 +1,269 @@
|
||||
// Beautiful explanation: https://github.com/dphilipson/advent-of-code-2021/blob/master/src/days/day24.rs
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Register {
|
||||
X, Y, Z, W
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Operand {
|
||||
Register(Register),
|
||||
Number(i32)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Instruction {
|
||||
Input(Register),
|
||||
Add(Register, Operand),
|
||||
Multiply(Register, Operand),
|
||||
Divide(Register, Operand),
|
||||
Modulo(Register, Operand),
|
||||
Equal(Register, Operand)
|
||||
}
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub struct CPU {
|
||||
rx: i32,
|
||||
ry: i32,
|
||||
rz: i32,
|
||||
rw: i32,
|
||||
input: Vec<i32>
|
||||
}
|
||||
|
||||
impl CPU {
|
||||
fn new() -> CPU {
|
||||
CPU { rx: 0, ry: 0, rz: 0, rw: 0, input: vec![] }
|
||||
}
|
||||
|
||||
fn reg(&mut self, reg: Register) -> &mut i32 {
|
||||
match reg {
|
||||
Register::X => &mut self.rx,
|
||||
Register::Y => &mut self.ry,
|
||||
Register::Z => &mut self.rz,
|
||||
Register::W => &mut self.rw,
|
||||
}
|
||||
}
|
||||
|
||||
fn op(&mut self, op: Operand) -> i32 {
|
||||
match op {
|
||||
Operand::Register(reg) => *self.reg(reg),
|
||||
Operand::Number(num) => num,
|
||||
}
|
||||
}
|
||||
|
||||
fn input(&mut self, reg: Register, num: i32) {
|
||||
*self.reg(reg) = num;
|
||||
}
|
||||
|
||||
fn add(&mut self, reg: Register, op: Operand) {
|
||||
*self.reg(reg) += self.op(op);
|
||||
}
|
||||
|
||||
fn multiply(&mut self, reg: Register, op: Operand) {
|
||||
*self.reg(reg) *= self.op(op);
|
||||
}
|
||||
|
||||
fn divide(&mut self, reg: Register, op: Operand) {
|
||||
*self.reg(reg) /= self.op(op);
|
||||
}
|
||||
|
||||
fn modulo(&mut self, reg: Register, op: Operand) {
|
||||
*self.reg(reg) %= self.op(op);
|
||||
}
|
||||
|
||||
fn equal(&mut self, reg: Register, op: Operand) {
|
||||
let b = self.op(op);
|
||||
let a = self.reg(reg);
|
||||
*a = if *a == b { 1 } else { 0 };
|
||||
}
|
||||
|
||||
fn run(&mut self, inst: &Instruction) {
|
||||
use Instruction::*;
|
||||
match *inst {
|
||||
Input(a) => {
|
||||
let b = self.input.pop().expect("Missing input");
|
||||
self.input(a, b)
|
||||
},
|
||||
Add(a, b) => self.add(a, b),
|
||||
Multiply(a, b) => self.multiply(a, b),
|
||||
Divide(a, b) => self.divide(a, b),
|
||||
Modulo(a, b) => self.modulo(a, b),
|
||||
Equal(a, b) => self.equal(a, b),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_register(input: &str) -> Register {
|
||||
match input {
|
||||
"x" => Register::X,
|
||||
"y" => Register::Y,
|
||||
"z" => Register::Z,
|
||||
"w" => Register::W,
|
||||
_ => panic!("Unknown variable '{}'", input)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_operand(input: &str) -> Operand {
|
||||
if let Ok(number) = input.parse::<i32>() {
|
||||
Operand::Number(number)
|
||||
} else {
|
||||
Operand::Register(parse_register(input))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<Instruction> {
|
||||
let mut instructions = vec![];
|
||||
for line in input.lines() {
|
||||
if line.is_empty() { continue; }
|
||||
let parts = line.split(' ').collect::<Vec<_>>();
|
||||
let opcode = *parts.get(0).expect("Missing opcode");
|
||||
let instruction = match opcode {
|
||||
"inp" => {
|
||||
let op1 = parts.get(1).expect("Missing variable");
|
||||
Instruction::Input(parse_register(op1))
|
||||
},
|
||||
"add" => {
|
||||
let op1 = parts.get(1).expect("Missing variable");
|
||||
let op2 = parts.get(2).expect("Missing operand");
|
||||
Instruction::Add(parse_register(op1), parse_operand(op2))
|
||||
},
|
||||
"mul" => {
|
||||
let op1 = parts.get(1).expect("Missing variable");
|
||||
let op2 = parts.get(2).expect("Missing operand");
|
||||
Instruction::Multiply(parse_register(op1), parse_operand(op2))
|
||||
}
|
||||
"div" => {
|
||||
let op1 = parts.get(1).expect("Missing variable");
|
||||
let op2 = parts.get(2).expect("Missing operand");
|
||||
Instruction::Divide(parse_register(op1), parse_operand(op2))
|
||||
},
|
||||
"mod" => {
|
||||
let op1 = parts.get(1).expect("Missing variable");
|
||||
let op2 = parts.get(2).expect("Missing operand");
|
||||
Instruction::Modulo(parse_register(op1), parse_operand(op2))
|
||||
}
|
||||
"eql" => {
|
||||
let op1 = parts.get(1).expect("Missing variable");
|
||||
let op2 = parts.get(2).expect("Missing operand");
|
||||
Instruction::Equal(parse_register(op1), parse_operand(op2))
|
||||
},
|
||||
_ => panic!("Unexpected opcode '{}'", opcode)
|
||||
};
|
||||
instructions.push(instruction);
|
||||
}
|
||||
instructions
|
||||
}
|
||||
|
||||
fn check(instructions: &[Instruction], monad: &[u8]) -> bool {
|
||||
let mut cpu = CPU::new();
|
||||
cpu.input = vec![];
|
||||
for num in monad {
|
||||
cpu.input.push(*num as i32);
|
||||
}
|
||||
cpu.input.reverse();
|
||||
for inst in instructions {
|
||||
cpu.run(inst);
|
||||
}
|
||||
cpu.rz == 0
|
||||
}
|
||||
|
||||
fn analyze(instructions: &[Instruction]) -> Vec<(i32, i32, i32)> {
|
||||
let mut result = vec![];
|
||||
for (i, _) in instructions.iter().enumerate()
|
||||
.filter(|(_, inst)| **inst == Instruction::Input(Register::W)) {
|
||||
let a = match instructions.get(i+4) {
|
||||
Some(Instruction::Divide(_, Operand::Number(num))) => *num,
|
||||
_ => panic!()
|
||||
};
|
||||
|
||||
let b = match instructions.get(i+5) {
|
||||
Some(Instruction::Add(_, Operand::Number(num))) => *num,
|
||||
_ => panic!()
|
||||
};
|
||||
|
||||
let c = match instructions.get(i+15) {
|
||||
Some(Instruction::Add(_, Operand::Number(num))) => *num,
|
||||
_ => panic!()
|
||||
};
|
||||
|
||||
result.push((a, b, c));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn analyze_requirements(instructions: &[Instruction]) -> Vec<(u8, u8, i8)> {
|
||||
let mut requirements = vec![];
|
||||
let result = analyze(instructions);
|
||||
let mut stack = vec![];
|
||||
for (i, (_, check, offset)) in result.iter().enumerate() {
|
||||
if *check > 0 {
|
||||
stack.push((i, offset))
|
||||
} else {
|
||||
let top = stack.pop().unwrap();
|
||||
requirements.push((i as u8, top.0 as u8, (*check + top.1) as i8));
|
||||
}
|
||||
}
|
||||
requirements
|
||||
}
|
||||
|
||||
fn concat_nums(nums: &[u8]) -> u64 {
|
||||
let mut answer = 0u64;
|
||||
for num in nums {
|
||||
answer *= 10;
|
||||
answer += *num as u64;
|
||||
}
|
||||
answer
|
||||
}
|
||||
|
||||
pub fn part1(instructions: Vec<Instruction>) -> u64 {
|
||||
let mut monad = [9u8; 14];
|
||||
for (i, j, offset) in analyze_requirements(&instructions) {
|
||||
if offset > 0 {
|
||||
monad[j as usize] = (9 - offset) as u8;
|
||||
} else {
|
||||
monad[i as usize] = (9 + offset) as u8;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(check(&instructions, &monad));
|
||||
|
||||
concat_nums(&monad)
|
||||
}
|
||||
|
||||
pub fn part2(instructions: Vec<Instruction>) -> u64 {
|
||||
let mut monad = [1u8; 14];
|
||||
for (i, j, offset) in analyze_requirements(&instructions) {
|
||||
if offset > 0 {
|
||||
monad[i as usize] = (1 + offset) as u8;
|
||||
} else {
|
||||
monad[j as usize] = (1 - offset) as u8;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(check(&instructions, &monad));
|
||||
|
||||
concat_nums(&monad)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn input_parsing() {
|
||||
use Instruction::*;
|
||||
use Register::*;
|
||||
let instructions = parse_input(&[
|
||||
"inp z",
|
||||
"inp x",
|
||||
"mul z 3",
|
||||
"eql z x",
|
||||
].join("\n"));
|
||||
assert_eq!(instructions, vec![
|
||||
Input(Z),
|
||||
Input(X),
|
||||
Multiply(Z, Operand::Number(3)),
|
||||
Equal(Z, Operand::Register(X))
|
||||
])
|
||||
}
|
||||
}
|
||||
122
src/day25.rs
Normal file
122
src/day25.rs
Normal file
@ -0,0 +1,122 @@
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Tile {
|
||||
East,
|
||||
South,
|
||||
Empty
|
||||
}
|
||||
|
||||
type SeaFloor = Vec<Vec<Tile>>;
|
||||
|
||||
pub fn parse_input(input: &str) -> SeaFloor {
|
||||
let mut floor = vec![];
|
||||
|
||||
for line in input.lines() {
|
||||
let mut row = vec![];
|
||||
for char in line.chars() {
|
||||
match char {
|
||||
'>' => row.push(Tile::East),
|
||||
'v' => row.push(Tile::South),
|
||||
'.' => row.push(Tile::Empty),
|
||||
_ => panic!()
|
||||
};
|
||||
}
|
||||
floor.push(row);
|
||||
}
|
||||
floor
|
||||
}
|
||||
|
||||
fn step(floor: &mut SeaFloor) -> bool {
|
||||
let mut moved = false;
|
||||
let width = floor.first().unwrap().len();
|
||||
let height = floor.len();
|
||||
|
||||
{
|
||||
for row in floor.iter_mut() {
|
||||
let mut moved_tiles = vec![];
|
||||
for (x, tile) in row.iter().enumerate() {
|
||||
if *tile == Tile::East && row[(x+1) % width] == Tile::Empty {
|
||||
moved_tiles.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
if !moved_tiles.is_empty() {
|
||||
moved = true;
|
||||
}
|
||||
|
||||
for x in moved_tiles {
|
||||
row[x] = Tile::Empty;
|
||||
row[(x+1) % width] = Tile::East;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
for x in 0..width {
|
||||
let mut moved_tiles = vec![];
|
||||
for y in 0..height {
|
||||
if floor[y][x] == Tile::South && floor[(y+1) % height][x] == Tile::Empty {
|
||||
moved_tiles.push(y);
|
||||
}
|
||||
}
|
||||
|
||||
if !moved_tiles.is_empty() {
|
||||
moved = true;
|
||||
}
|
||||
|
||||
for y in moved_tiles {
|
||||
floor[y][x] = Tile::Empty;
|
||||
floor[(y+1) % height][x] = Tile::South;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moved
|
||||
}
|
||||
|
||||
fn show_seafloor(floor: &SeaFloor) {
|
||||
for row in floor {
|
||||
for tile in row {
|
||||
match tile {
|
||||
Tile::East => print!(">"),
|
||||
Tile::South => print!("v"),
|
||||
Tile::Empty => print!("."),
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
pub fn part1(mut floor: SeaFloor) -> u32 {
|
||||
let mut count = 1;
|
||||
while step(&mut floor) {
|
||||
count += 1;
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
pub fn part2(floor: SeaFloor) -> u32 {
|
||||
todo!();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let map = parse_input(&[
|
||||
"v...>>.vv>",
|
||||
".vv>>.vv..",
|
||||
">>.>v>...v",
|
||||
">>v>>.>.v.",
|
||||
"v>v.vv.v..",
|
||||
">.>>..v...",
|
||||
".vv..>.>v.",
|
||||
"v.v..>>v.v",
|
||||
"....v..v.>",
|
||||
].join("\n"));
|
||||
let result = part1(map);
|
||||
assert_eq!(result, 58);
|
||||
}
|
||||
}
|
||||
166
src/day3.rs
166
src/day3.rs
@ -1,103 +1,123 @@
|
||||
use std::{num::ParseIntError, slice::Iter};
|
||||
|
||||
pub fn parse_input(input: &str) -> Result<Vec<i32>, ParseIntError> {
|
||||
input.split_whitespace()
|
||||
.map(|s| i32::from_str_radix(s, 2))
|
||||
.collect()
|
||||
input
|
||||
.split_whitespace()
|
||||
.map(|s| i32::from_str_radix(s, 2))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn calculate_max_bits(nums: &[i32]) -> u32 {
|
||||
let mut max_bits = 0;
|
||||
for num in nums {
|
||||
max_bits = max_bits.max((*num as f32).log2().ceil() as u32);
|
||||
}
|
||||
return max_bits;
|
||||
let mut max_bits = 0;
|
||||
for num in nums {
|
||||
max_bits = max_bits.max((*num as f32).log2().ceil() as u32);
|
||||
}
|
||||
return max_bits;
|
||||
}
|
||||
|
||||
fn count_bits(nums: Iter<i32>, power: &i32) -> u32 {
|
||||
let mut bits = 0;
|
||||
for num in nums {
|
||||
if num & power > 0 {
|
||||
bits += 1;
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
let mut bits = 0;
|
||||
for num in nums {
|
||||
if num & power > 0 {
|
||||
bits += 1;
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
pub fn part1(diagnostics: &[i32]) -> i32 {
|
||||
let n = diagnostics.len() as u32;
|
||||
let mut gamma = 0;
|
||||
let mut epsilon = 0;
|
||||
let n = diagnostics.len() as u32;
|
||||
let mut gamma = 0;
|
||||
let mut epsilon = 0;
|
||||
|
||||
let max_bits = calculate_max_bits(&diagnostics);
|
||||
let mut power = 1;
|
||||
for _ in 1..=max_bits {
|
||||
let bits = count_bits(diagnostics.iter(), &power);
|
||||
if 2*bits >= n {
|
||||
gamma += power;
|
||||
} else {
|
||||
epsilon += power;
|
||||
}
|
||||
power *= 2;
|
||||
}
|
||||
let max_bits = calculate_max_bits(&diagnostics);
|
||||
let mut power = 1;
|
||||
for _ in 1..=max_bits {
|
||||
let bits = count_bits(diagnostics.iter(), &power);
|
||||
if 2 * bits >= n {
|
||||
gamma += power;
|
||||
} else {
|
||||
epsilon += power;
|
||||
}
|
||||
power *= 2;
|
||||
}
|
||||
|
||||
return gamma * epsilon;
|
||||
return gamma * epsilon;
|
||||
}
|
||||
|
||||
pub fn part2(diagnostics: &[i32]) -> i32 {
|
||||
let mut carbon_diagnostics = Vec::new();
|
||||
let mut oxygen_diagnostics = Vec::new();
|
||||
let mut carbon_diagnostics = Vec::new();
|
||||
let mut oxygen_diagnostics = Vec::new();
|
||||
|
||||
carbon_diagnostics.extend_from_slice(diagnostics);
|
||||
oxygen_diagnostics.extend_from_slice(diagnostics);
|
||||
carbon_diagnostics.extend_from_slice(diagnostics);
|
||||
oxygen_diagnostics.extend_from_slice(diagnostics);
|
||||
|
||||
let max_bits = calculate_max_bits(&diagnostics);
|
||||
let mut power = 2i32.pow(max_bits-1);
|
||||
for _ in 1..=max_bits {
|
||||
let oxygen_len = oxygen_diagnostics.len() as u32;
|
||||
if oxygen_len > 1 {
|
||||
let bit_count = count_bits(oxygen_diagnostics.iter(), &power);
|
||||
if 2*bit_count >= oxygen_len {
|
||||
oxygen_diagnostics = oxygen_diagnostics.into_iter().filter(|n| n & power > 0).collect();
|
||||
} else {
|
||||
oxygen_diagnostics = oxygen_diagnostics.into_iter().filter(|n| n & power == 0).collect();
|
||||
}
|
||||
}
|
||||
let max_bits = calculate_max_bits(&diagnostics);
|
||||
let mut power = 2i32.pow(max_bits - 1);
|
||||
for _ in 1..=max_bits {
|
||||
let oxygen_len = oxygen_diagnostics.len() as u32;
|
||||
if oxygen_len > 1 {
|
||||
let bit_count = count_bits(oxygen_diagnostics.iter(), &power);
|
||||
if 2 * bit_count >= oxygen_len {
|
||||
oxygen_diagnostics = oxygen_diagnostics
|
||||
.into_iter()
|
||||
.filter(|n| n & power > 0)
|
||||
.collect();
|
||||
} else {
|
||||
oxygen_diagnostics = oxygen_diagnostics
|
||||
.into_iter()
|
||||
.filter(|n| n & power == 0)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
let carbon_len = carbon_diagnostics.len() as u32;
|
||||
if carbon_len > 1 {
|
||||
let bit_count = count_bits(carbon_diagnostics.iter(), &power);
|
||||
if 2*bit_count < carbon_len {
|
||||
carbon_diagnostics = carbon_diagnostics.into_iter().filter(|n| n & power > 0).collect();
|
||||
} else {
|
||||
carbon_diagnostics = carbon_diagnostics.into_iter().filter(|n| n & power == 0).collect();
|
||||
}
|
||||
}
|
||||
let carbon_len = carbon_diagnostics.len() as u32;
|
||||
if carbon_len > 1 {
|
||||
let bit_count = count_bits(carbon_diagnostics.iter(), &power);
|
||||
if 2 * bit_count < carbon_len {
|
||||
carbon_diagnostics = carbon_diagnostics
|
||||
.into_iter()
|
||||
.filter(|n| n & power > 0)
|
||||
.collect();
|
||||
} else {
|
||||
carbon_diagnostics = carbon_diagnostics
|
||||
.into_iter()
|
||||
.filter(|n| n & power == 0)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
if oxygen_len == 1 && carbon_len == 1 { break; }
|
||||
if oxygen_len == 1 && carbon_len == 1 {
|
||||
break;
|
||||
}
|
||||
|
||||
power /= 2;
|
||||
}
|
||||
power /= 2;
|
||||
}
|
||||
|
||||
return carbon_diagnostics[0] * oxygen_diagnostics[0];
|
||||
return carbon_diagnostics[0] * oxygen_diagnostics[0];
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let diagnostics = [0b00100, 0b11110, 0b10110, 0b10111, 0b10101, 0b01111, 0b00111, 0b11100, 0b10000, 0b11001, 0b00010, 0b01010];
|
||||
let result = part1(&diagnostics);
|
||||
assert_eq!(result, 198);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let diagnostics = [
|
||||
0b00100, 0b11110, 0b10110, 0b10111, 0b10101, 0b01111, 0b00111, 0b11100, 0b10000, 0b11001,
|
||||
0b00010, 0b01010,
|
||||
];
|
||||
let result = part1(&diagnostics);
|
||||
assert_eq!(result, 198);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let diagnostics = [0b00100, 0b11110, 0b10110, 0b10111, 0b10101, 0b01111, 0b00111, 0b11100, 0b10000, 0b11001, 0b00010, 0b01010];
|
||||
let result = part2(&diagnostics);
|
||||
assert_eq!(result, 230);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let diagnostics = [
|
||||
0b00100, 0b11110, 0b10110, 0b10111, 0b10101, 0b01111, 0b00111, 0b11100, 0b10000, 0b11001,
|
||||
0b00010, 0b01010,
|
||||
];
|
||||
let result = part2(&diagnostics);
|
||||
assert_eq!(result, 230);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
354
src/day4.rs
354
src/day4.rs
@ -1,229 +1,217 @@
|
||||
use std::num::ParseIntError;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BingoGame {
|
||||
numbers: Vec<i32>,
|
||||
boards: Vec<[i32; 25]>
|
||||
numbers: Vec<i32>,
|
||||
boards: Vec<[i32; 25]>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseBingoGameError {
|
||||
NoNumbersError,
|
||||
ParseNumberError(ParseIntError),
|
||||
NoNumbersError,
|
||||
ParseNumberError(ParseIntError),
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Result<BingoGame, ParseBingoGameError> {
|
||||
let mut sections = input.split_terminator("\n\n");
|
||||
let mut sections = input.split_terminator("\n\n");
|
||||
|
||||
let numbers_section = sections
|
||||
.next()
|
||||
.ok_or(ParseBingoGameError::NoNumbersError)?;
|
||||
let numbers_section = sections.next().ok_or(ParseBingoGameError::NoNumbersError)?;
|
||||
|
||||
let numbers = numbers_section
|
||||
.split_terminator(",")
|
||||
.map(|s| s.parse::<i32>())
|
||||
.collect::<Result<Vec<i32>, ParseIntError>>()
|
||||
.map_err(ParseBingoGameError::ParseNumberError)?;
|
||||
|
||||
let mut boards = Vec::new();
|
||||
for section in sections {
|
||||
let mut board: [i32; 25] = [0; 25];
|
||||
let mut y = 0;
|
||||
for row in section.split_terminator("\n") {
|
||||
let mut x = 0;
|
||||
for s in row.split_whitespace() {
|
||||
let n = s.trim().parse::<i32>().map_err(ParseBingoGameError::ParseNumberError)?;
|
||||
board[5*y + x] = n;
|
||||
x += 1;
|
||||
}
|
||||
y += 1;
|
||||
}
|
||||
boards.push(board);
|
||||
}
|
||||
|
||||
Ok(BingoGame { numbers, boards })
|
||||
let numbers = numbers_section
|
||||
.split_terminator(",")
|
||||
.map(|s| s.parse::<i32>())
|
||||
.collect::<Result<Vec<i32>, ParseIntError>>()
|
||||
.map_err(ParseBingoGameError::ParseNumberError)?;
|
||||
|
||||
let mut boards = Vec::new();
|
||||
for section in sections {
|
||||
let mut board: [i32; 25] = [0; 25];
|
||||
let mut y = 0;
|
||||
for row in section.split_terminator("\n") {
|
||||
let mut x = 0;
|
||||
for s in row.split_whitespace() {
|
||||
let n = s
|
||||
.trim()
|
||||
.parse::<i32>()
|
||||
.map_err(ParseBingoGameError::ParseNumberError)?;
|
||||
board[5 * y + x] = n;
|
||||
x += 1;
|
||||
}
|
||||
y += 1;
|
||||
}
|
||||
boards.push(board);
|
||||
}
|
||||
|
||||
Ok(BingoGame { numbers, boards })
|
||||
}
|
||||
|
||||
fn find_number(board: &[i32], value: i32) -> Option<usize> {
|
||||
for i in 0..board.len() {
|
||||
if board[i] == value {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
for i in 0..board.len() {
|
||||
if board[i] == value {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
fn mark_number(board: &[i32], markings: &mut i32, value: i32) -> bool {
|
||||
let pos: usize;
|
||||
match find_number(board, value) {
|
||||
None => return false,
|
||||
Some(n) => pos = n
|
||||
};
|
||||
*markings |= 1 << pos;
|
||||
return true;
|
||||
let pos: usize;
|
||||
match find_number(board, value) {
|
||||
None => return false,
|
||||
Some(n) => pos = n,
|
||||
};
|
||||
*markings |= 1 << pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
fn contains_win(markings: i32) -> bool {
|
||||
const WINNING_COMBINATIONS: [i32; 10] = [
|
||||
0b11111 << 0, // First row
|
||||
0b11111 << 5, // Second row
|
||||
0b11111 << 10, // Third row
|
||||
0b11111 << 15, // Fourth row
|
||||
0b11111 << 20, // Fifth row
|
||||
0b0000100001000010000100001, // First column
|
||||
0b0001000010000100001000010, // Second column
|
||||
0b0010000100001000010000100, // Third column
|
||||
0b0100001000010000100001000, // Fourth column
|
||||
0b1000010000100001000010000, // Fifth column
|
||||
];
|
||||
const WINNING_COMBINATIONS: [i32; 10] = [
|
||||
0b11111 << 0, // First row
|
||||
0b11111 << 5, // Second row
|
||||
0b11111 << 10, // Third row
|
||||
0b11111 << 15, // Fourth row
|
||||
0b11111 << 20, // Fifth row
|
||||
0b0000100001000010000100001, // First column
|
||||
0b0001000010000100001000010, // Second column
|
||||
0b0010000100001000010000100, // Third column
|
||||
0b0100001000010000100001000, // Fourth column
|
||||
0b1000010000100001000010000, // Fifth column
|
||||
];
|
||||
|
||||
for comb in WINNING_COMBINATIONS.iter() {
|
||||
if markings & comb == *comb {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
for comb in WINNING_COMBINATIONS.iter() {
|
||||
if markings & comb == *comb {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn sum_unmarked_numbers(board: &[i32], markings: i32) -> i32 {
|
||||
let mut sum = 0;
|
||||
for i in 0..25 {
|
||||
if markings & (1 << i) == 0 {
|
||||
sum += board[i];
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
let mut sum = 0;
|
||||
for i in 0..25 {
|
||||
if markings & (1 << i) == 0 {
|
||||
sum += board[i];
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
pub fn part1(game: &BingoGame) -> i32 {
|
||||
let mut markings = vec![0; game.boards.len()];
|
||||
let mut markings = vec![0; game.boards.len()];
|
||||
|
||||
for num in game.numbers.iter() {
|
||||
for i in 0..game.boards.len() {
|
||||
if mark_number(&game.boards[i], &mut markings[i], *num) && contains_win(markings[i]) {
|
||||
return num * sum_unmarked_numbers(&game.boards[i], markings[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
|
||||
for num in game.numbers.iter() {
|
||||
for i in 0..game.boards.len() {
|
||||
if mark_number(&game.boards[i], &mut markings[i], *num) && contains_win(markings[i]) {
|
||||
return num * sum_unmarked_numbers(&game.boards[i], markings[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn part2(game: &BingoGame) -> i32 {
|
||||
let mut markings = vec![0; game.boards.len()];
|
||||
let mut winning_numbers: Vec<i32> = vec![0; game.boards.len()];
|
||||
let mut last_winning_board = usize::MAX;
|
||||
let mut markings = vec![0; game.boards.len()];
|
||||
let mut winning_numbers: Vec<i32> = vec![0; game.boards.len()];
|
||||
let mut last_winning_board = usize::MAX;
|
||||
|
||||
for num in game.numbers.iter() {
|
||||
for i in 0..game.boards.len() {
|
||||
if winning_numbers[i] == 0 && mark_number(&game.boards[i], &mut markings[i], *num) && contains_win(markings[i]) {
|
||||
winning_numbers[i] = *num;
|
||||
last_winning_board = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
for num in game.numbers.iter() {
|
||||
for i in 0..game.boards.len() {
|
||||
if winning_numbers[i] == 0
|
||||
&& mark_number(&game.boards[i], &mut markings[i], *num)
|
||||
&& contains_win(markings[i])
|
||||
{
|
||||
winning_numbers[i] = *num;
|
||||
last_winning_board = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return winning_numbers[last_winning_board] * sum_unmarked_numbers(&game.boards[last_winning_board], markings[last_winning_board]);
|
||||
return winning_numbers[last_winning_board]
|
||||
* sum_unmarked_numbers(
|
||||
&game.boards[last_winning_board],
|
||||
markings[last_winning_board],
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
fn new_test_board() -> [i32; 25] {
|
||||
let mut board: [i32; 25] = [0; 25];
|
||||
for i in 0..25 {
|
||||
board[i] = i as i32;
|
||||
}
|
||||
return board;
|
||||
}
|
||||
fn new_test_board() -> [i32; 25] {
|
||||
let mut board: [i32; 25] = [0; 25];
|
||||
for i in 0..25 {
|
||||
board[i] = i as i32;
|
||||
}
|
||||
return board;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = BingoGame {
|
||||
numbers: vec![7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1],
|
||||
boards: vec![
|
||||
[
|
||||
22, 13, 17, 11, 0,
|
||||
8, 2, 23, 4, 24,
|
||||
21, 9, 14, 16, 7,
|
||||
6, 10, 3, 18, 5,
|
||||
1, 12, 20, 15, 19
|
||||
],
|
||||
[
|
||||
3, 15, 0, 2, 22,
|
||||
9, 18, 13, 17, 5,
|
||||
19, 8, 7, 25, 23,
|
||||
20, 11, 10, 24, 4,
|
||||
14, 21, 16, 12, 6
|
||||
],
|
||||
[
|
||||
14, 21, 17, 24, 4,
|
||||
10, 16, 15, 9, 19,
|
||||
18, 8, 23, 26, 20,
|
||||
22, 11, 13, 6, 5,
|
||||
2, 0, 12, 3, 7
|
||||
]
|
||||
]
|
||||
};
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 4512);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = BingoGame {
|
||||
numbers: vec![
|
||||
7, 4, 9, 5, 11, 17, 23, 2, 0, 14, 21, 24, 10, 16, 13, 6, 15, 25, 12, 22, 18, 20, 8, 19, 3,
|
||||
26, 1,
|
||||
],
|
||||
boards: vec![
|
||||
[
|
||||
22, 13, 17, 11, 0, 8, 2, 23, 4, 24, 21, 9, 14, 16, 7, 6, 10, 3, 18, 5, 1, 12, 20, 15, 19,
|
||||
],
|
||||
[
|
||||
3, 15, 0, 2, 22, 9, 18, 13, 17, 5, 19, 8, 7, 25, 23, 20, 11, 10, 24, 4, 14, 21, 16, 12, 6,
|
||||
],
|
||||
[
|
||||
14, 21, 17, 24, 4, 10, 16, 15, 9, 19, 18, 8, 23, 26, 20, 22, 11, 13, 6, 5, 2, 0, 12, 3, 7,
|
||||
],
|
||||
],
|
||||
};
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 4512);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = BingoGame {
|
||||
numbers: vec![7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1],
|
||||
boards: vec![
|
||||
[
|
||||
22, 13, 17, 11, 0,
|
||||
8, 2, 23, 4, 24,
|
||||
21, 9, 14, 16, 7,
|
||||
6, 10, 3, 18, 5,
|
||||
1, 12, 20, 15, 19
|
||||
],
|
||||
[
|
||||
3, 15, 0, 2, 22,
|
||||
9, 18, 13, 17, 5,
|
||||
19, 8, 7, 25, 23,
|
||||
20, 11, 10, 24, 4,
|
||||
14, 21, 16, 12, 6
|
||||
],
|
||||
[
|
||||
14, 21, 17, 24, 4,
|
||||
10, 16, 15, 9, 19,
|
||||
18, 8, 23, 26, 20,
|
||||
22, 11, 13, 6, 5,
|
||||
2, 0, 12, 3, 7
|
||||
]
|
||||
]
|
||||
};
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 1924);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = BingoGame {
|
||||
numbers: vec![
|
||||
7, 4, 9, 5, 11, 17, 23, 2, 0, 14, 21, 24, 10, 16, 13, 6, 15, 25, 12, 22, 18, 20, 8, 19, 3,
|
||||
26, 1,
|
||||
],
|
||||
boards: vec![
|
||||
[
|
||||
22, 13, 17, 11, 0, 8, 2, 23, 4, 24, 21, 9, 14, 16, 7, 6, 10, 3, 18, 5, 1, 12, 20, 15, 19,
|
||||
],
|
||||
[
|
||||
3, 15, 0, 2, 22, 9, 18, 13, 17, 5, 19, 8, 7, 25, 23, 20, 11, 10, 24, 4, 14, 21, 16, 12, 6,
|
||||
],
|
||||
[
|
||||
14, 21, 17, 24, 4, 10, 16, 15, 9, 19, 18, 8, 23, 26, 20, 22, 11, 13, 6, 5, 2, 0, 12, 3, 7,
|
||||
],
|
||||
],
|
||||
};
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 1924);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_mark_number() {
|
||||
let board = new_test_board();
|
||||
let mut markings = 0b0;
|
||||
mark_number(&board, &mut markings, 0);
|
||||
assert_eq!(markings, 1);
|
||||
#[test]
|
||||
fn check_mark_number() {
|
||||
let board = new_test_board();
|
||||
let mut markings = 0b0;
|
||||
mark_number(&board, &mut markings, 0);
|
||||
assert_eq!(markings, 1);
|
||||
|
||||
mark_number(&board, &mut markings, 1);
|
||||
assert_eq!(markings, 3);
|
||||
}
|
||||
mark_number(&board, &mut markings, 1);
|
||||
assert_eq!(markings, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_contains_win() {
|
||||
let board = new_test_board();
|
||||
let mut markings = 0b0;
|
||||
mark_number(&board, &mut markings, 0);
|
||||
mark_number(&board, &mut markings, 1);
|
||||
mark_number(&board, &mut markings, 2);
|
||||
mark_number(&board, &mut markings, 3);
|
||||
mark_number(&board, &mut markings, 4);
|
||||
mark_number(&board, &mut markings, 5);
|
||||
assert!(contains_win(markings));
|
||||
}
|
||||
#[test]
|
||||
fn check_contains_win() {
|
||||
let board = new_test_board();
|
||||
let mut markings = 0b0;
|
||||
mark_number(&board, &mut markings, 0);
|
||||
mark_number(&board, &mut markings, 1);
|
||||
mark_number(&board, &mut markings, 2);
|
||||
mark_number(&board, &mut markings, 3);
|
||||
mark_number(&board, &mut markings, 4);
|
||||
mark_number(&board, &mut markings, 5);
|
||||
assert!(contains_win(markings));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
359
src/day5.rs
359
src/day5.rs
@ -1,177 +1,282 @@
|
||||
use std::{num::ParseIntError, cmp::{min, max}};
|
||||
use std::{
|
||||
cmp::{max, min},
|
||||
num::ParseIntError,
|
||||
};
|
||||
|
||||
type Grid = Vec<Vec<i32>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Line {
|
||||
x1: i32,
|
||||
y1: i32,
|
||||
x2: i32,
|
||||
y2: i32
|
||||
x1: i32,
|
||||
y1: i32,
|
||||
x2: i32,
|
||||
y2: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseLineError {
|
||||
ParseNumberError(ParseIntError),
|
||||
ParsePointsError,
|
||||
ParsePointError
|
||||
ParseNumberError(ParseIntError),
|
||||
ParsePointsError,
|
||||
ParsePointError,
|
||||
}
|
||||
|
||||
pub fn parse_point(input: &str) -> Result<(i32, i32), ParseLineError> {
|
||||
let mut parts = input.split(',');
|
||||
let x = parts.next()
|
||||
.ok_or(ParseLineError::ParsePointError)?
|
||||
.parse()
|
||||
.map_err(ParseLineError::ParseNumberError)?;
|
||||
let y = parts.next()
|
||||
.ok_or(ParseLineError::ParsePointError)?
|
||||
.parse()
|
||||
.map_err(ParseLineError::ParseNumberError)?;
|
||||
return Ok((x, y));
|
||||
let mut parts = input.split(',');
|
||||
let x = parts
|
||||
.next()
|
||||
.ok_or(ParseLineError::ParsePointError)?
|
||||
.parse()
|
||||
.map_err(ParseLineError::ParseNumberError)?;
|
||||
let y = parts
|
||||
.next()
|
||||
.ok_or(ParseLineError::ParsePointError)?
|
||||
.parse()
|
||||
.map_err(ParseLineError::ParseNumberError)?;
|
||||
return Ok((x, y));
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Result<Vec<Line>, ParseLineError> {
|
||||
let mut lines = Vec::new();
|
||||
for input_line in input.lines() {
|
||||
let mut parts = input_line.split(" -> ");
|
||||
let mut lines = Vec::new();
|
||||
for input_line in input.lines() {
|
||||
let mut parts = input_line.split(" -> ");
|
||||
|
||||
let point1 = parts.next().ok_or(ParseLineError::ParsePointsError)?;
|
||||
let (x1, y1) = parse_point(point1)?;
|
||||
let point1 = parts.next().ok_or(ParseLineError::ParsePointsError)?;
|
||||
let (x1, y1) = parse_point(point1)?;
|
||||
|
||||
let point2 = parts.next().ok_or(ParseLineError::ParsePointsError)?;
|
||||
let (x2, y2) = parse_point(point2)?;
|
||||
let point2 = parts.next().ok_or(ParseLineError::ParsePointsError)?;
|
||||
let (x2, y2) = parse_point(point2)?;
|
||||
|
||||
lines.push(Line { x1, y1, x2, y2 })
|
||||
}
|
||||
return Ok(lines);
|
||||
lines.push(Line { x1, y1, x2, y2 })
|
||||
}
|
||||
return Ok(lines);
|
||||
}
|
||||
|
||||
fn determine_bounds(lines: &[Line]) -> (i32, i32, i32, i32) {
|
||||
let mut x1 = i32::MAX;
|
||||
let mut y1 = i32::MAX;
|
||||
let mut x2 = i32::MIN;
|
||||
let mut y2 = i32::MIN;
|
||||
for line in lines {
|
||||
x1 = min(x1, min(line.x1, line.x2));
|
||||
y1 = min(y1, min(line.y1, line.y2));
|
||||
x2 = max(x2, max(line.x1, line.x2));
|
||||
y2 = max(y2, max(line.y1, line.y2));
|
||||
}
|
||||
return (x1, y1, x2, y2);
|
||||
let mut x1 = i32::MAX;
|
||||
let mut y1 = i32::MAX;
|
||||
let mut x2 = i32::MIN;
|
||||
let mut y2 = i32::MIN;
|
||||
for line in lines {
|
||||
x1 = min(x1, min(line.x1, line.x2));
|
||||
y1 = min(y1, min(line.y1, line.y2));
|
||||
x2 = max(x2, max(line.x1, line.x2));
|
||||
y2 = max(y2, max(line.y1, line.y2));
|
||||
}
|
||||
return (x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
fn new_grid(width: usize, height: usize) -> Grid {
|
||||
let mut grid = Vec::new();
|
||||
for _ in 0..height {
|
||||
grid.push(vec![0; width]);
|
||||
}
|
||||
grid
|
||||
let mut grid = Vec::new();
|
||||
for _ in 0..height {
|
||||
grid.push(vec![0; width]);
|
||||
}
|
||||
grid
|
||||
}
|
||||
|
||||
fn sign(x: i32) -> i32 {
|
||||
if x > 0 {
|
||||
1
|
||||
} else if x < 0 {
|
||||
-1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
if x > 0 {
|
||||
1
|
||||
} else if x < 0 {
|
||||
-1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_line(grid: &mut Grid, line: &Line, ox: i32, oy: i32) {
|
||||
let dx = sign(line.x2 - line.x1);
|
||||
let dy = sign(line.y2 - line.y1);
|
||||
let mut x = line.x1;
|
||||
let mut y = line.y1;
|
||||
while x != line.x2 || y != line.y2 {
|
||||
grid[(y - oy) as usize][(x - ox) as usize] += 1;
|
||||
if x != line.x2 {
|
||||
x += dx;
|
||||
}
|
||||
if y != line.y2 {
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
grid[(y - oy) as usize][(x - ox) as usize] += 1;
|
||||
let dx = sign(line.x2 - line.x1);
|
||||
let dy = sign(line.y2 - line.y1);
|
||||
let mut x = line.x1;
|
||||
let mut y = line.y1;
|
||||
while x != line.x2 || y != line.y2 {
|
||||
grid[(y - oy) as usize][(x - ox) as usize] += 1;
|
||||
if x != line.x2 {
|
||||
x += dx;
|
||||
}
|
||||
if y != line.y2 {
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
grid[(y - oy) as usize][(x - ox) as usize] += 1;
|
||||
}
|
||||
|
||||
fn count_dangerous_areas(grid: &Grid) -> u32 {
|
||||
let mut count = 0;
|
||||
for row in grid {
|
||||
for point in row {
|
||||
if *point > 1 {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
count
|
||||
let mut count = 0;
|
||||
for row in grid {
|
||||
for point in row {
|
||||
if *point > 1 {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
pub fn part1(lines: &[Line]) -> u32 {
|
||||
let bounds = determine_bounds(lines);
|
||||
let width = (bounds.2 - bounds.0 + 1) as usize;
|
||||
let height = (bounds.3 - bounds.1 + 1) as usize;
|
||||
let mut grid = new_grid(width, height);
|
||||
let bounds = determine_bounds(lines);
|
||||
let width = (bounds.2 - bounds.0 + 1) as usize;
|
||||
let height = (bounds.3 - bounds.1 + 1) as usize;
|
||||
let mut grid = new_grid(width, height);
|
||||
|
||||
for line in lines {
|
||||
if (line.x1 == line.x2) || (line.y1 == line.y2) {
|
||||
mark_line(&mut grid, line, bounds.0, bounds.1);
|
||||
}
|
||||
}
|
||||
for line in lines {
|
||||
if (line.x1 == line.x2) || (line.y1 == line.y2) {
|
||||
mark_line(&mut grid, line, bounds.0, bounds.1);
|
||||
}
|
||||
}
|
||||
|
||||
count_dangerous_areas(&grid)
|
||||
count_dangerous_areas(&grid)
|
||||
}
|
||||
|
||||
pub fn part2(lines: &[Line]) -> u32 {
|
||||
let bounds = determine_bounds(lines);
|
||||
let width = (bounds.2 - bounds.0 + 1) as usize;
|
||||
let height = (bounds.3 - bounds.1 + 1) as usize;
|
||||
let mut grid = new_grid(width, height);
|
||||
let bounds = determine_bounds(lines);
|
||||
let width = (bounds.2 - bounds.0 + 1) as usize;
|
||||
let height = (bounds.3 - bounds.1 + 1) as usize;
|
||||
let mut grid = new_grid(width, height);
|
||||
|
||||
for line in lines {
|
||||
mark_line(&mut grid, line, bounds.0, bounds.1);
|
||||
}
|
||||
for line in lines {
|
||||
mark_line(&mut grid, line, bounds.0, bounds.1);
|
||||
}
|
||||
|
||||
count_dangerous_areas(&grid)
|
||||
count_dangerous_areas(&grid)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [
|
||||
Line { x1: 0, y1: 9, x2: 5, y2: 9 },
|
||||
Line { x1: 8, y1: 0, x2: 0, y2: 8 },
|
||||
Line { x1: 9, y1: 4, x2: 3, y2: 4 },
|
||||
Line { x1: 2, y1: 2, x2: 2, y2: 1 },
|
||||
Line { x1: 7, y1: 0, x2: 7, y2: 4 },
|
||||
Line { x1: 6, y1: 4, x2: 2, y2: 0 },
|
||||
Line { x1: 0, y1: 9, x2: 2, y2: 9 },
|
||||
Line { x1: 3, y1: 4, x2: 1, y2: 4 },
|
||||
Line { x1: 0, y1: 0, x2: 8, y2: 8 },
|
||||
Line { x1: 5, y1: 5, x2: 8, y2: 2 }
|
||||
];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 5);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [
|
||||
Line {
|
||||
x1: 0,
|
||||
y1: 9,
|
||||
x2: 5,
|
||||
y2: 9,
|
||||
},
|
||||
Line {
|
||||
x1: 8,
|
||||
y1: 0,
|
||||
x2: 0,
|
||||
y2: 8,
|
||||
},
|
||||
Line {
|
||||
x1: 9,
|
||||
y1: 4,
|
||||
x2: 3,
|
||||
y2: 4,
|
||||
},
|
||||
Line {
|
||||
x1: 2,
|
||||
y1: 2,
|
||||
x2: 2,
|
||||
y2: 1,
|
||||
},
|
||||
Line {
|
||||
x1: 7,
|
||||
y1: 0,
|
||||
x2: 7,
|
||||
y2: 4,
|
||||
},
|
||||
Line {
|
||||
x1: 6,
|
||||
y1: 4,
|
||||
x2: 2,
|
||||
y2: 0,
|
||||
},
|
||||
Line {
|
||||
x1: 0,
|
||||
y1: 9,
|
||||
x2: 2,
|
||||
y2: 9,
|
||||
},
|
||||
Line {
|
||||
x1: 3,
|
||||
y1: 4,
|
||||
x2: 1,
|
||||
y2: 4,
|
||||
},
|
||||
Line {
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 8,
|
||||
y2: 8,
|
||||
},
|
||||
Line {
|
||||
x1: 5,
|
||||
y1: 5,
|
||||
x2: 8,
|
||||
y2: 2,
|
||||
},
|
||||
];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [
|
||||
Line { x1: 0, y1: 9, x2: 5, y2: 9 },
|
||||
Line { x1: 8, y1: 0, x2: 0, y2: 8 },
|
||||
Line { x1: 9, y1: 4, x2: 3, y2: 4 },
|
||||
Line { x1: 2, y1: 2, x2: 2, y2: 1 },
|
||||
Line { x1: 7, y1: 0, x2: 7, y2: 4 },
|
||||
Line { x1: 6, y1: 4, x2: 2, y2: 0 },
|
||||
Line { x1: 0, y1: 9, x2: 2, y2: 9 },
|
||||
Line { x1: 3, y1: 4, x2: 1, y2: 4 },
|
||||
Line { x1: 0, y1: 0, x2: 8, y2: 8 },
|
||||
Line { x1: 5, y1: 5, x2: 8, y2: 2 }
|
||||
];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 12);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [
|
||||
Line {
|
||||
x1: 0,
|
||||
y1: 9,
|
||||
x2: 5,
|
||||
y2: 9,
|
||||
},
|
||||
Line {
|
||||
x1: 8,
|
||||
y1: 0,
|
||||
x2: 0,
|
||||
y2: 8,
|
||||
},
|
||||
Line {
|
||||
x1: 9,
|
||||
y1: 4,
|
||||
x2: 3,
|
||||
y2: 4,
|
||||
},
|
||||
Line {
|
||||
x1: 2,
|
||||
y1: 2,
|
||||
x2: 2,
|
||||
y2: 1,
|
||||
},
|
||||
Line {
|
||||
x1: 7,
|
||||
y1: 0,
|
||||
x2: 7,
|
||||
y2: 4,
|
||||
},
|
||||
Line {
|
||||
x1: 6,
|
||||
y1: 4,
|
||||
x2: 2,
|
||||
y2: 0,
|
||||
},
|
||||
Line {
|
||||
x1: 0,
|
||||
y1: 9,
|
||||
x2: 2,
|
||||
y2: 9,
|
||||
},
|
||||
Line {
|
||||
x1: 3,
|
||||
y1: 4,
|
||||
x2: 1,
|
||||
y2: 4,
|
||||
},
|
||||
Line {
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 8,
|
||||
y2: 8,
|
||||
},
|
||||
Line {
|
||||
x1: 5,
|
||||
y1: 5,
|
||||
x2: 8,
|
||||
y2: 2,
|
||||
},
|
||||
];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 12);
|
||||
}
|
||||
}
|
||||
|
||||
105
src/day6.rs
105
src/day6.rs
@ -1,81 +1,82 @@
|
||||
use std::num::ParseIntError;
|
||||
|
||||
pub fn parse_input(input: &str) -> Result<Vec<i32>, ParseIntError> {
|
||||
input.trim_end().split_terminator(',')
|
||||
.map(|s| s.parse())
|
||||
.collect()
|
||||
input
|
||||
.trim_end()
|
||||
.split_terminator(',')
|
||||
.map(|s| s.parse())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn simulate_step(fishes: &mut Vec<i32>) {
|
||||
for i in 0..fishes.len() {
|
||||
if fishes[i] == 0 {
|
||||
fishes[i] = 7;
|
||||
fishes.push(9);
|
||||
}
|
||||
}
|
||||
for i in 0..fishes.len() {
|
||||
if fishes[i] == 0 {
|
||||
fishes[i] = 7;
|
||||
fishes.push(9);
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..fishes.len() {
|
||||
if fishes[i] > 0 {
|
||||
fishes[i] -= 1;
|
||||
}
|
||||
}
|
||||
for i in 0..fishes.len() {
|
||||
if fishes[i] > 0 {
|
||||
fishes[i] -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part1(input: &[i32]) -> u32 {
|
||||
let mut fishes = input.to_vec();
|
||||
let mut fishes = input.to_vec();
|
||||
|
||||
for _ in 0..80 {
|
||||
simulate_step(&mut fishes)
|
||||
}
|
||||
for _ in 0..80 {
|
||||
simulate_step(&mut fishes)
|
||||
}
|
||||
|
||||
fishes.len() as u32
|
||||
fishes.len() as u32
|
||||
}
|
||||
|
||||
// Instead of storing each fishes cycle as individual values group them up
|
||||
// by there cycles. Because it dosen't matter where the fish is in the list.
|
||||
// So just make an array of size 9 for the 9 possible fish cycle timers.
|
||||
// And one extra group, for accounting for the delay that when the timer is 0,
|
||||
// And one extra group, for accounting for the delay that when the timer is 0,
|
||||
// they produce a new fish only on the next turn.
|
||||
pub fn part2(input: &[i32]) -> u64 {
|
||||
let mut groups: [u64; 10] = [0; 10];
|
||||
let mut groups: [u64; 10] = [0; 10];
|
||||
|
||||
for fish in input.iter() {
|
||||
groups[*fish as usize + 1] += 1;
|
||||
}
|
||||
for fish in input.iter() {
|
||||
groups[*fish as usize + 1] += 1;
|
||||
}
|
||||
|
||||
for _ in 0..256 {
|
||||
for i in 1..10 {
|
||||
groups[i-1] += groups[i];
|
||||
groups[i] = 0;
|
||||
}
|
||||
groups[7] += groups[0];
|
||||
groups[9] += groups[0];
|
||||
groups[0] = 0;
|
||||
}
|
||||
for _ in 0..256 {
|
||||
for i in 1..10 {
|
||||
groups[i - 1] += groups[i];
|
||||
groups[i] = 0;
|
||||
}
|
||||
groups[7] += groups[0];
|
||||
groups[9] += groups[0];
|
||||
groups[0] = 0;
|
||||
}
|
||||
|
||||
let mut count: u64 = 0;
|
||||
for amount in groups.iter() {
|
||||
count += amount;
|
||||
}
|
||||
count
|
||||
let mut count: u64 = 0;
|
||||
for amount in groups.iter() {
|
||||
count += amount;
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [3,4,3,1,2];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 5934);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [3, 4, 3, 1, 2];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 5934);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [3,4,3,1,2];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 26984457539 as u64);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [3, 4, 3, 1, 2];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 26984457539 as u64);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
111
src/day7.rs
111
src/day7.rs
@ -1,85 +1,90 @@
|
||||
use std::num::ParseIntError;
|
||||
|
||||
pub fn parse_input(input: &str) -> Result<Vec<i32>, ParseIntError> {
|
||||
input.trim_end().split_terminator(',')
|
||||
.map(|s| s.parse())
|
||||
.collect()
|
||||
input
|
||||
.trim_end()
|
||||
.split_terminator(',')
|
||||
.map(|s| s.parse())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn abs(x: i32) -> u32 {
|
||||
if x < 0 { -x as u32 } else { x as u32 }
|
||||
if x < 0 {
|
||||
-x as u32
|
||||
} else {
|
||||
x as u32
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_total_cost_to1(crabs: &[i32], target: i32) -> u32 {
|
||||
let mut sum = 0;
|
||||
for crab in crabs {
|
||||
sum += abs(crab-target);
|
||||
}
|
||||
return sum;
|
||||
let mut sum = 0;
|
||||
for crab in crabs {
|
||||
sum += abs(crab - target);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
pub fn part1(crabs: &[i32]) -> u32 {
|
||||
let mut best_cost = calculate_total_cost_to1(crabs, crabs[0]);
|
||||
let mut best_cost = calculate_total_cost_to1(crabs, crabs[0]);
|
||||
|
||||
for position in crabs.iter().skip(1) {
|
||||
let cost = calculate_total_cost_to1(crabs, *position);
|
||||
if cost < best_cost {
|
||||
best_cost = cost;
|
||||
}
|
||||
}
|
||||
for position in crabs.iter().skip(1) {
|
||||
let cost = calculate_total_cost_to1(crabs, *position);
|
||||
if cost < best_cost {
|
||||
best_cost = cost;
|
||||
}
|
||||
}
|
||||
|
||||
best_cost
|
||||
best_cost
|
||||
}
|
||||
|
||||
fn calculate_total_cost_to2(crabs: &[i32], target: i32) -> u32 {
|
||||
let mut sum = 0;
|
||||
for crab in crabs {
|
||||
let distance = abs(crab - target);
|
||||
for i in 1..=distance {
|
||||
sum += i;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
let mut sum = 0;
|
||||
for crab in crabs {
|
||||
let distance = abs(crab - target);
|
||||
for i in 1..=distance {
|
||||
sum += i;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
fn calculate_average(arr: &[i32]) -> f32 {
|
||||
let mut sum = 0.0;
|
||||
for a in arr {
|
||||
sum += *a as f32;
|
||||
}
|
||||
return sum / arr.len() as f32;
|
||||
let mut sum = 0.0;
|
||||
for a in arr {
|
||||
sum += *a as f32;
|
||||
}
|
||||
return sum / arr.len() as f32;
|
||||
}
|
||||
|
||||
pub fn part2(crabs: &[i32]) -> u32 {
|
||||
let average_position = calculate_average(crabs).round() as i32;
|
||||
let mut best_cost = calculate_total_cost_to2(crabs, average_position);
|
||||
let average_position = calculate_average(crabs).round() as i32;
|
||||
let mut best_cost = calculate_total_cost_to2(crabs, average_position);
|
||||
|
||||
for position in average_position-5..=average_position+5 {
|
||||
let cost = calculate_total_cost_to2(crabs, position);
|
||||
if cost < best_cost {
|
||||
best_cost = cost;
|
||||
}
|
||||
}
|
||||
for position in average_position - 5..=average_position + 5 {
|
||||
let cost = calculate_total_cost_to2(crabs, position);
|
||||
if cost < best_cost {
|
||||
best_cost = cost;
|
||||
}
|
||||
}
|
||||
|
||||
best_cost
|
||||
best_cost
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [16,1,2,0,4,2,7,1,2,14];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 37);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = [16, 1, 2, 0, 4, 2, 7, 1, 2, 14];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 37);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [16,1,2,0,4,2,7,1,2,14];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 168);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = [16, 1, 2, 0, 4, 2, 7, 1, 2, 14];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 168);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
602
src/day8.rs
602
src/day8.rs
@ -1,179 +1,507 @@
|
||||
use std::{convert::TryInto, collections::HashMap};
|
||||
use std::{collections::HashMap, convert::TryInto};
|
||||
|
||||
pub struct Entry([String; 10], [String; 4]);
|
||||
|
||||
fn parse_line(line: &str) -> Entry {
|
||||
let parts: Vec<&str> = line.split(" | ").collect();
|
||||
let unique_patterns = parts[0]
|
||||
.split_whitespace()
|
||||
.map(|s| String::from(s))
|
||||
.collect::<Vec<String>>()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
let output_digits = parts[1]
|
||||
.split_whitespace()
|
||||
.map(|s| String::from(s))
|
||||
.collect::<Vec<String>>()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
return Entry(unique_patterns, output_digits);
|
||||
let parts: Vec<&str> = line.split(" | ").collect();
|
||||
let unique_patterns = parts[0]
|
||||
.split_whitespace()
|
||||
.map(|s| String::from(s))
|
||||
.collect::<Vec<String>>()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
let output_digits = parts[1]
|
||||
.split_whitespace()
|
||||
.map(|s| String::from(s))
|
||||
.collect::<Vec<String>>()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
return Entry(unique_patterns, output_digits);
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<Entry> {
|
||||
input.lines()
|
||||
.map(parse_line)
|
||||
.collect()
|
||||
input.lines().map(parse_line).collect()
|
||||
}
|
||||
|
||||
pub fn part1(entries: &[Entry]) -> u32 {
|
||||
let mut count = 0;
|
||||
for entry in entries {
|
||||
for digit in entry.1.iter() {
|
||||
let len = digit.len();
|
||||
if len == 2 || len == 3 || len == 4 || len == 7 {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
count
|
||||
let mut count = 0;
|
||||
for entry in entries {
|
||||
for digit in entry.1.iter() {
|
||||
let len = digit.len();
|
||||
if len == 2 || len == 3 || len == 4 || len == 7 {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
// Helper function which converts a string into a binary representation
|
||||
// I did this is so that the order of the letters won't matter
|
||||
fn signal_to_bitmask(signal: &str) -> u32 {
|
||||
let mut bitmask = 0;
|
||||
for c in signal.chars() {
|
||||
match c {
|
||||
'a' => bitmask += 0b0000001,
|
||||
'b' => bitmask += 0b0000010,
|
||||
'c' => bitmask += 0b0000100,
|
||||
'd' => bitmask += 0b0001000,
|
||||
'e' => bitmask += 0b0010000,
|
||||
'f' => bitmask += 0b0100000,
|
||||
'g' => bitmask += 0b1000000,
|
||||
_ => bitmask += 0
|
||||
}
|
||||
}
|
||||
return bitmask;
|
||||
let mut bitmask = 0;
|
||||
for c in signal.chars() {
|
||||
match c {
|
||||
'a' => bitmask += 0b0000001,
|
||||
'b' => bitmask += 0b0000010,
|
||||
'c' => bitmask += 0b0000100,
|
||||
'd' => bitmask += 0b0001000,
|
||||
'e' => bitmask += 0b0010000,
|
||||
'f' => bitmask += 0b0100000,
|
||||
'g' => bitmask += 0b1000000,
|
||||
_ => bitmask += 0,
|
||||
}
|
||||
}
|
||||
return bitmask;
|
||||
}
|
||||
|
||||
fn decode_signal(signal: &str, wire_loopup: &HashMap<u32, u32>) -> Option<u32> {
|
||||
wire_loopup.get(&signal_to_bitmask(signal)).map(|n| *n)
|
||||
wire_loopup.get(&signal_to_bitmask(signal)).map(|n| *n)
|
||||
}
|
||||
|
||||
fn decode_signals(signals: &[String], wire_loopup: &HashMap<u32, u32>) -> u32 {
|
||||
let mut number = 0;
|
||||
let n = signals.len();
|
||||
for i in 0..n {
|
||||
let value = decode_signal(&signals[i], wire_loopup).unwrap();
|
||||
number += value * u32::pow(10, (n-i-1) as u32);
|
||||
}
|
||||
return number;
|
||||
let mut number = 0;
|
||||
let n = signals.len();
|
||||
for i in 0..n {
|
||||
let value = decode_signal(&signals[i], wire_loopup).unwrap();
|
||||
number += value * u32::pow(10, (n - i - 1) as u32);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
fn decode_wire_lookup(signals: &[String; 10]) -> HashMap<u32, u32> {
|
||||
let mut wire_lookup = HashMap::new();
|
||||
let mut bitmasks: [u32; 10] = [0; 10];
|
||||
for i in 0..10 {
|
||||
bitmasks[i] = signal_to_bitmask(&signals[i]);
|
||||
}
|
||||
let mut wire_lookup = HashMap::new();
|
||||
let mut bitmasks: [u32; 10] = [0; 10];
|
||||
for i in 0..10 {
|
||||
bitmasks[i] = signal_to_bitmask(&signals[i]);
|
||||
}
|
||||
|
||||
let mut one_bitmask = 0;
|
||||
let mut four_bitmask = 0;
|
||||
let mut one_bitmask = 0;
|
||||
let mut four_bitmask = 0;
|
||||
|
||||
// Decode all signals which have unique number of wires
|
||||
for i in 0..10 {
|
||||
let len = signals[i].len();
|
||||
if len == 2 {
|
||||
one_bitmask = bitmasks[i];
|
||||
wire_lookup.insert(one_bitmask, 1);
|
||||
} else if len == 3 {
|
||||
wire_lookup.insert(bitmasks[i], 7);
|
||||
} else if len == 4 {
|
||||
four_bitmask = bitmasks[i];
|
||||
wire_lookup.insert(four_bitmask, 4);
|
||||
} else if len == 7 {
|
||||
wire_lookup.insert(bitmasks[i], 8);
|
||||
}
|
||||
}
|
||||
// Decode all signals which have unique number of wires
|
||||
for i in 0..10 {
|
||||
let len = signals[i].len();
|
||||
if len == 2 {
|
||||
one_bitmask = bitmasks[i];
|
||||
wire_lookup.insert(one_bitmask, 1);
|
||||
} else if len == 3 {
|
||||
wire_lookup.insert(bitmasks[i], 7);
|
||||
} else if len == 4 {
|
||||
four_bitmask = bitmasks[i];
|
||||
wire_lookup.insert(four_bitmask, 4);
|
||||
} else if len == 7 {
|
||||
wire_lookup.insert(bitmasks[i], 8);
|
||||
}
|
||||
}
|
||||
|
||||
let fourdiff = four_bitmask ^ one_bitmask;
|
||||
let fourdiff = four_bitmask ^ one_bitmask;
|
||||
|
||||
for i in 0..10 {
|
||||
let len = signals[i].len();
|
||||
if len == 5 {
|
||||
if bitmasks[i] & one_bitmask == one_bitmask {
|
||||
wire_lookup.insert(bitmasks[i], 3);
|
||||
} else if bitmasks[i] & fourdiff == fourdiff {
|
||||
wire_lookup.insert(bitmasks[i], 5);
|
||||
} else {
|
||||
wire_lookup.insert(bitmasks[i], 2);
|
||||
}
|
||||
} else if len == 6 {
|
||||
if bitmasks[i] & four_bitmask == four_bitmask {
|
||||
wire_lookup.insert(bitmasks[i], 9);
|
||||
} else if bitmasks[i] & fourdiff == fourdiff {
|
||||
wire_lookup.insert(bitmasks[i], 6);
|
||||
} else {
|
||||
wire_lookup.insert(bitmasks[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
for i in 0..10 {
|
||||
let len = signals[i].len();
|
||||
if len == 5 {
|
||||
if bitmasks[i] & one_bitmask == one_bitmask {
|
||||
wire_lookup.insert(bitmasks[i], 3);
|
||||
} else if bitmasks[i] & fourdiff == fourdiff {
|
||||
wire_lookup.insert(bitmasks[i], 5);
|
||||
} else {
|
||||
wire_lookup.insert(bitmasks[i], 2);
|
||||
}
|
||||
} else if len == 6 {
|
||||
if bitmasks[i] & four_bitmask == four_bitmask {
|
||||
wire_lookup.insert(bitmasks[i], 9);
|
||||
} else if bitmasks[i] & fourdiff == fourdiff {
|
||||
wire_lookup.insert(bitmasks[i], 6);
|
||||
} else {
|
||||
wire_lookup.insert(bitmasks[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wire_lookup;
|
||||
return wire_lookup;
|
||||
}
|
||||
|
||||
fn decode_entry(entry: &Entry) -> u32 {
|
||||
let wire_lookup = decode_wire_lookup(&entry.0);
|
||||
return decode_signals(&entry.1, &wire_lookup);
|
||||
let wire_lookup = decode_wire_lookup(&entry.0);
|
||||
return decode_signals(&entry.1, &wire_lookup);
|
||||
}
|
||||
|
||||
pub fn part2(entries: &[Entry]) -> u32 {
|
||||
let mut sum = 0;
|
||||
for entry in entries {
|
||||
sum += decode_entry(entry);
|
||||
}
|
||||
sum
|
||||
let mut sum = 0;
|
||||
for entry in entries {
|
||||
sum += decode_entry(entry);
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
// I know it's ugly
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = vec![
|
||||
Entry(["be" .into(), "cfbegad" .into(), "cbdgef" .into(), "fgaecd" .into(), "cgeb" .into(), "fdcge" .into(), "agebfd" .into(), "fecdb" .into(), "fabcd" .into(), "edb".into()], ["fdgacbe" .into(), "cefdb" .into(), "cefbgd" .into(), "gcbe".into()]),
|
||||
Entry(["edbfga" .into(), "begcd" .into(), "cbg" .into(), "gc" .into(), "gcadebf" .into(), "fbgde" .into(), "acbgfd" .into(), "abcde" .into(), "gfcbed" .into(), "gfec".into()], ["fcgedb" .into(), "cgb" .into(), "dgebacf" .into(), "gc".into()]),
|
||||
Entry(["fgaebd" .into(), "cg" .into(), "bdaec" .into(), "gdafb" .into(), "agbcfd" .into(), "gdcbef" .into(), "bgcad" .into(), "gfac" .into(), "gcb" .into(), "cdgabef".into()], ["cg" .into(), "cg" .into(), "fdcagb" .into(), "cbg".into()]),
|
||||
Entry(["fbegcd" .into(), "cbd" .into(), "adcefb" .into(), "dageb" .into(), "afcb" .into(), "bc" .into(), "aefdc" .into(), "ecdab" .into(), "fgdeca" .into(), "fcdbega".into()], ["efabcd" .into(), "cedba" .into(), "gadfec" .into(), "cb".into()]),
|
||||
Entry(["aecbfdg" .into(), "fbg" .into(), "gf" .into(), "bafeg" .into(), "dbefa" .into(), "fcge" .into(), "gcbea" .into(), "fcaegb" .into(), "dgceab" .into(), "fcbdga".into()], ["gecf" .into(), "egdcabf" .into(), "bgf" .into(), "bfgea".into()]),
|
||||
Entry(["fgeab" .into(), "ca" .into(), "afcebg" .into(), "bdacfeg" .into(), "cfaedg" .into(), "gcfdb" .into(), "baec" .into(), "bfadeg" .into(), "bafgc" .into(), "acf".into()], ["gebdcfa" .into(), "ecba" .into(), "ca" .into(), "fadegcb".into()]),
|
||||
Entry(["dbcfg" .into(), "fgd" .into(), "bdegcaf" .into(), "fgec" .into(), "aegbdf" .into(), "ecdfab" .into(), "fbedc" .into(), "dacgb" .into(), "gdcebf" .into(), "gf".into()], ["cefg" .into(), "dcbef" .into(), "fcge" .into(), "gbcadfe".into()]),
|
||||
Entry(["bdfegc" .into(), "cbegaf" .into(), "gecbf" .into(), "dfcage" .into(), "bdacg" .into(), "ed" .into(), "bedf" .into(), "ced" .into(), "adcbefg" .into(), "gebcd".into()], ["ed" .into(), "bcgafe" .into(), "cdgba" .into(), "cbgef".into()]),
|
||||
Entry(["egadfb" .into(), "cdbfeg" .into(), "cegd" .into(), "fecab" .into(), "cgb" .into(), "gbdefca" .into(), "cg" .into(), "fgcdab" .into(), "egfdb" .into(), "bfceg".into()], ["gbdfcae" .into(), "bgc" .into(), "cg" .into(), "cgb".into()]),
|
||||
Entry(["gcafb" .into(), "gcf" .into(), "dcaebfg" .into(), "ecagb" .into(), "gf" .into(), "abcdeg" .into(), "gaef" .into(), "cafbge" .into(), "fdbac" .into(), "fegbdc".into()], ["fgae" .into(), "cfgab" .into(), "fg" .into(), "bagce".into()]),
|
||||
];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 26);
|
||||
}
|
||||
// I know it's ugly
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = vec![
|
||||
Entry(
|
||||
[
|
||||
"be".into(),
|
||||
"cfbegad".into(),
|
||||
"cbdgef".into(),
|
||||
"fgaecd".into(),
|
||||
"cgeb".into(),
|
||||
"fdcge".into(),
|
||||
"agebfd".into(),
|
||||
"fecdb".into(),
|
||||
"fabcd".into(),
|
||||
"edb".into(),
|
||||
],
|
||||
[
|
||||
"fdgacbe".into(),
|
||||
"cefdb".into(),
|
||||
"cefbgd".into(),
|
||||
"gcbe".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"edbfga".into(),
|
||||
"begcd".into(),
|
||||
"cbg".into(),
|
||||
"gc".into(),
|
||||
"gcadebf".into(),
|
||||
"fbgde".into(),
|
||||
"acbgfd".into(),
|
||||
"abcde".into(),
|
||||
"gfcbed".into(),
|
||||
"gfec".into(),
|
||||
],
|
||||
["fcgedb".into(), "cgb".into(), "dgebacf".into(), "gc".into()],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"fgaebd".into(),
|
||||
"cg".into(),
|
||||
"bdaec".into(),
|
||||
"gdafb".into(),
|
||||
"agbcfd".into(),
|
||||
"gdcbef".into(),
|
||||
"bgcad".into(),
|
||||
"gfac".into(),
|
||||
"gcb".into(),
|
||||
"cdgabef".into(),
|
||||
],
|
||||
["cg".into(), "cg".into(), "fdcagb".into(), "cbg".into()],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"fbegcd".into(),
|
||||
"cbd".into(),
|
||||
"adcefb".into(),
|
||||
"dageb".into(),
|
||||
"afcb".into(),
|
||||
"bc".into(),
|
||||
"aefdc".into(),
|
||||
"ecdab".into(),
|
||||
"fgdeca".into(),
|
||||
"fcdbega".into(),
|
||||
],
|
||||
[
|
||||
"efabcd".into(),
|
||||
"cedba".into(),
|
||||
"gadfec".into(),
|
||||
"cb".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"aecbfdg".into(),
|
||||
"fbg".into(),
|
||||
"gf".into(),
|
||||
"bafeg".into(),
|
||||
"dbefa".into(),
|
||||
"fcge".into(),
|
||||
"gcbea".into(),
|
||||
"fcaegb".into(),
|
||||
"dgceab".into(),
|
||||
"fcbdga".into(),
|
||||
],
|
||||
[
|
||||
"gecf".into(),
|
||||
"egdcabf".into(),
|
||||
"bgf".into(),
|
||||
"bfgea".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"fgeab".into(),
|
||||
"ca".into(),
|
||||
"afcebg".into(),
|
||||
"bdacfeg".into(),
|
||||
"cfaedg".into(),
|
||||
"gcfdb".into(),
|
||||
"baec".into(),
|
||||
"bfadeg".into(),
|
||||
"bafgc".into(),
|
||||
"acf".into(),
|
||||
],
|
||||
[
|
||||
"gebdcfa".into(),
|
||||
"ecba".into(),
|
||||
"ca".into(),
|
||||
"fadegcb".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"dbcfg".into(),
|
||||
"fgd".into(),
|
||||
"bdegcaf".into(),
|
||||
"fgec".into(),
|
||||
"aegbdf".into(),
|
||||
"ecdfab".into(),
|
||||
"fbedc".into(),
|
||||
"dacgb".into(),
|
||||
"gdcebf".into(),
|
||||
"gf".into(),
|
||||
],
|
||||
[
|
||||
"cefg".into(),
|
||||
"dcbef".into(),
|
||||
"fcge".into(),
|
||||
"gbcadfe".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"bdfegc".into(),
|
||||
"cbegaf".into(),
|
||||
"gecbf".into(),
|
||||
"dfcage".into(),
|
||||
"bdacg".into(),
|
||||
"ed".into(),
|
||||
"bedf".into(),
|
||||
"ced".into(),
|
||||
"adcbefg".into(),
|
||||
"gebcd".into(),
|
||||
],
|
||||
["ed".into(), "bcgafe".into(), "cdgba".into(), "cbgef".into()],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"egadfb".into(),
|
||||
"cdbfeg".into(),
|
||||
"cegd".into(),
|
||||
"fecab".into(),
|
||||
"cgb".into(),
|
||||
"gbdefca".into(),
|
||||
"cg".into(),
|
||||
"fgcdab".into(),
|
||||
"egfdb".into(),
|
||||
"bfceg".into(),
|
||||
],
|
||||
["gbdfcae".into(), "bgc".into(), "cg".into(), "cgb".into()],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"gcafb".into(),
|
||||
"gcf".into(),
|
||||
"dcaebfg".into(),
|
||||
"ecagb".into(),
|
||||
"gf".into(),
|
||||
"abcdeg".into(),
|
||||
"gaef".into(),
|
||||
"cafbge".into(),
|
||||
"fdbac".into(),
|
||||
"fegbdc".into(),
|
||||
],
|
||||
["fgae".into(), "cfgab".into(), "fg".into(), "bagce".into()],
|
||||
),
|
||||
];
|
||||
let result = part1(&input);
|
||||
assert_eq!(result, 26);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = vec![
|
||||
Entry(["be" .into(), "cfbegad" .into(), "cbdgef" .into(), "fgaecd" .into(), "cgeb" .into(), "fdcge" .into(), "agebfd" .into(), "fecdb" .into(), "fabcd" .into(), "edb".into()], ["fdgacbe" .into(), "cefdb" .into(), "cefbgd" .into(), "gcbe".into()]),
|
||||
Entry(["edbfga" .into(), "begcd" .into(), "cbg" .into(), "gc" .into(), "gcadebf" .into(), "fbgde" .into(), "acbgfd" .into(), "abcde" .into(), "gfcbed" .into(), "gfec".into()], ["fcgedb" .into(), "cgb" .into(), "dgebacf" .into(), "gc".into()]),
|
||||
Entry(["fgaebd" .into(), "cg" .into(), "bdaec" .into(), "gdafb" .into(), "agbcfd" .into(), "gdcbef" .into(), "bgcad" .into(), "gfac" .into(), "gcb" .into(), "cdgabef".into()], ["cg" .into(), "cg" .into(), "fdcagb" .into(), "cbg".into()]),
|
||||
Entry(["fbegcd" .into(), "cbd" .into(), "adcefb" .into(), "dageb" .into(), "afcb" .into(), "bc" .into(), "aefdc" .into(), "ecdab" .into(), "fgdeca" .into(), "fcdbega".into()], ["efabcd" .into(), "cedba" .into(), "gadfec" .into(), "cb".into()]),
|
||||
Entry(["aecbfdg" .into(), "fbg" .into(), "gf" .into(), "bafeg" .into(), "dbefa" .into(), "fcge" .into(), "gcbea" .into(), "fcaegb" .into(), "dgceab" .into(), "fcbdga".into()], ["gecf" .into(), "egdcabf" .into(), "bgf" .into(), "bfgea".into()]),
|
||||
Entry(["fgeab" .into(), "ca" .into(), "afcebg" .into(), "bdacfeg" .into(), "cfaedg" .into(), "gcfdb" .into(), "baec" .into(), "bfadeg" .into(), "bafgc" .into(), "acf".into()], ["gebdcfa" .into(), "ecba" .into(), "ca" .into(), "fadegcb".into()]),
|
||||
Entry(["dbcfg" .into(), "fgd" .into(), "bdegcaf" .into(), "fgec" .into(), "aegbdf" .into(), "ecdfab" .into(), "fbedc" .into(), "dacgb" .into(), "gdcebf" .into(), "gf".into()], ["cefg" .into(), "dcbef" .into(), "fcge" .into(), "gbcadfe".into()]),
|
||||
Entry(["bdfegc" .into(), "cbegaf" .into(), "gecbf" .into(), "dfcage" .into(), "bdacg" .into(), "ed" .into(), "bedf" .into(), "ced" .into(), "adcbefg" .into(), "gebcd".into()], ["ed" .into(), "bcgafe" .into(), "cdgba" .into(), "cbgef".into()]),
|
||||
Entry(["egadfb" .into(), "cdbfeg" .into(), "cegd" .into(), "fecab" .into(), "cgb" .into(), "gbdefca" .into(), "cg" .into(), "fgcdab" .into(), "egfdb" .into(), "bfceg".into()], ["gbdfcae" .into(), "bgc" .into(), "cg" .into(), "cgb".into()]),
|
||||
Entry(["gcafb" .into(), "gcf" .into(), "dcaebfg" .into(), "ecagb" .into(), "gf" .into(), "abcdeg" .into(), "gaef" .into(), "cafbge" .into(), "fdbac" .into(), "fegbdc".into()], ["fgae" .into(), "cfgab" .into(), "fg" .into(), "bagce".into()]),
|
||||
];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 61229);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = vec![
|
||||
Entry(
|
||||
[
|
||||
"be".into(),
|
||||
"cfbegad".into(),
|
||||
"cbdgef".into(),
|
||||
"fgaecd".into(),
|
||||
"cgeb".into(),
|
||||
"fdcge".into(),
|
||||
"agebfd".into(),
|
||||
"fecdb".into(),
|
||||
"fabcd".into(),
|
||||
"edb".into(),
|
||||
],
|
||||
[
|
||||
"fdgacbe".into(),
|
||||
"cefdb".into(),
|
||||
"cefbgd".into(),
|
||||
"gcbe".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"edbfga".into(),
|
||||
"begcd".into(),
|
||||
"cbg".into(),
|
||||
"gc".into(),
|
||||
"gcadebf".into(),
|
||||
"fbgde".into(),
|
||||
"acbgfd".into(),
|
||||
"abcde".into(),
|
||||
"gfcbed".into(),
|
||||
"gfec".into(),
|
||||
],
|
||||
["fcgedb".into(), "cgb".into(), "dgebacf".into(), "gc".into()],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"fgaebd".into(),
|
||||
"cg".into(),
|
||||
"bdaec".into(),
|
||||
"gdafb".into(),
|
||||
"agbcfd".into(),
|
||||
"gdcbef".into(),
|
||||
"bgcad".into(),
|
||||
"gfac".into(),
|
||||
"gcb".into(),
|
||||
"cdgabef".into(),
|
||||
],
|
||||
["cg".into(), "cg".into(), "fdcagb".into(), "cbg".into()],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"fbegcd".into(),
|
||||
"cbd".into(),
|
||||
"adcefb".into(),
|
||||
"dageb".into(),
|
||||
"afcb".into(),
|
||||
"bc".into(),
|
||||
"aefdc".into(),
|
||||
"ecdab".into(),
|
||||
"fgdeca".into(),
|
||||
"fcdbega".into(),
|
||||
],
|
||||
[
|
||||
"efabcd".into(),
|
||||
"cedba".into(),
|
||||
"gadfec".into(),
|
||||
"cb".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"aecbfdg".into(),
|
||||
"fbg".into(),
|
||||
"gf".into(),
|
||||
"bafeg".into(),
|
||||
"dbefa".into(),
|
||||
"fcge".into(),
|
||||
"gcbea".into(),
|
||||
"fcaegb".into(),
|
||||
"dgceab".into(),
|
||||
"fcbdga".into(),
|
||||
],
|
||||
[
|
||||
"gecf".into(),
|
||||
"egdcabf".into(),
|
||||
"bgf".into(),
|
||||
"bfgea".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"fgeab".into(),
|
||||
"ca".into(),
|
||||
"afcebg".into(),
|
||||
"bdacfeg".into(),
|
||||
"cfaedg".into(),
|
||||
"gcfdb".into(),
|
||||
"baec".into(),
|
||||
"bfadeg".into(),
|
||||
"bafgc".into(),
|
||||
"acf".into(),
|
||||
],
|
||||
[
|
||||
"gebdcfa".into(),
|
||||
"ecba".into(),
|
||||
"ca".into(),
|
||||
"fadegcb".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"dbcfg".into(),
|
||||
"fgd".into(),
|
||||
"bdegcaf".into(),
|
||||
"fgec".into(),
|
||||
"aegbdf".into(),
|
||||
"ecdfab".into(),
|
||||
"fbedc".into(),
|
||||
"dacgb".into(),
|
||||
"gdcebf".into(),
|
||||
"gf".into(),
|
||||
],
|
||||
[
|
||||
"cefg".into(),
|
||||
"dcbef".into(),
|
||||
"fcge".into(),
|
||||
"gbcadfe".into(),
|
||||
],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"bdfegc".into(),
|
||||
"cbegaf".into(),
|
||||
"gecbf".into(),
|
||||
"dfcage".into(),
|
||||
"bdacg".into(),
|
||||
"ed".into(),
|
||||
"bedf".into(),
|
||||
"ced".into(),
|
||||
"adcbefg".into(),
|
||||
"gebcd".into(),
|
||||
],
|
||||
["ed".into(), "bcgafe".into(), "cdgba".into(), "cbgef".into()],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"egadfb".into(),
|
||||
"cdbfeg".into(),
|
||||
"cegd".into(),
|
||||
"fecab".into(),
|
||||
"cgb".into(),
|
||||
"gbdefca".into(),
|
||||
"cg".into(),
|
||||
"fgcdab".into(),
|
||||
"egfdb".into(),
|
||||
"bfceg".into(),
|
||||
],
|
||||
["gbdfcae".into(), "bgc".into(), "cg".into(), "cgb".into()],
|
||||
),
|
||||
Entry(
|
||||
[
|
||||
"gcafb".into(),
|
||||
"gcf".into(),
|
||||
"dcaebfg".into(),
|
||||
"ecagb".into(),
|
||||
"gf".into(),
|
||||
"abcdeg".into(),
|
||||
"gaef".into(),
|
||||
"cafbge".into(),
|
||||
"fdbac".into(),
|
||||
"fegbdc".into(),
|
||||
],
|
||||
["fgae".into(), "cfgab".into(), "fg".into(), "bagce".into()],
|
||||
),
|
||||
];
|
||||
let result = part2(&input);
|
||||
assert_eq!(result, 61229);
|
||||
}
|
||||
}
|
||||
|
||||
152
src/day9.rs
152
src/day9.rs
@ -1,100 +1,108 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<Vec<u32>> {
|
||||
input.lines()
|
||||
.map(|s| s.chars().map(|c| c.to_digit(10).unwrap()).collect())
|
||||
.collect()
|
||||
input
|
||||
.lines()
|
||||
.map(|s| s.chars().map(|c| c.to_digit(10).unwrap()).collect())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn find_low_points(grid: &Vec<Vec<u32>>) -> Vec<(usize, usize)> {
|
||||
let mut low_points = Vec::new();
|
||||
let height = grid.len();
|
||||
for i in 0..height {
|
||||
let width = grid[i].len();
|
||||
for j in 0..width {
|
||||
if (i == 0 || grid[i-1][j] > grid[i][j])
|
||||
&& (i == height-1 || grid[i+1][j] > grid[i][j])
|
||||
&& (j == 0 || grid[i][j-1] > grid[i][j])
|
||||
&& (j == width-1 || grid[i][j+1] > grid[i][j]) {
|
||||
low_points.push((i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
return low_points;
|
||||
let mut low_points = Vec::new();
|
||||
let height = grid.len();
|
||||
for i in 0..height {
|
||||
let width = grid[i].len();
|
||||
for j in 0..width {
|
||||
if (i == 0 || grid[i - 1][j] > grid[i][j])
|
||||
&& (i == height - 1 || grid[i + 1][j] > grid[i][j])
|
||||
&& (j == 0 || grid[i][j - 1] > grid[i][j])
|
||||
&& (j == width - 1 || grid[i][j + 1] > grid[i][j])
|
||||
{
|
||||
low_points.push((i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
return low_points;
|
||||
}
|
||||
|
||||
pub fn part1(grid: Vec<Vec<u32>>) -> u32 {
|
||||
let mut sum = 0;
|
||||
for low_point in find_low_points(&grid) {
|
||||
let depth = grid[low_point.0][low_point.1];
|
||||
sum += depth + 1;
|
||||
}
|
||||
return sum;
|
||||
let mut sum = 0;
|
||||
for low_point in find_low_points(&grid) {
|
||||
let depth = grid[low_point.0][low_point.1];
|
||||
sum += depth + 1;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
fn find_basin_size(grid: &Vec<Vec<u32>>, location: (usize, usize)) -> u32 {
|
||||
let mut explored_spots = HashSet::new();
|
||||
let mut leaf_nodes = vec![location];
|
||||
let height = grid.len();
|
||||
let width = grid[0].len();
|
||||
let mut explored_spots = HashSet::new();
|
||||
let mut leaf_nodes = vec![location];
|
||||
let height = grid.len();
|
||||
let width = grid[0].len();
|
||||
|
||||
while leaf_nodes.len() > 0 {
|
||||
let leaf_node = leaf_nodes.pop().unwrap();
|
||||
explored_spots.insert(leaf_node);
|
||||
while leaf_nodes.len() > 0 {
|
||||
let leaf_node = leaf_nodes.pop().unwrap();
|
||||
explored_spots.insert(leaf_node);
|
||||
|
||||
let (i, j) = leaf_node;
|
||||
if i > 0 && !explored_spots.contains(&(i-1, j)) && grid[i-1][j] != 9 { leaf_nodes.push((i-1, j)); }
|
||||
if i < height-1 && !explored_spots.contains(&(i+1, j)) && grid[i+1][j] != 9 { leaf_nodes.push((i+1, j)); }
|
||||
if j > 0 && !explored_spots.contains(&(i, j-1)) && grid[i][j-1] != 9 { leaf_nodes.push((i, j-1)); }
|
||||
if j < width-1 && !explored_spots.contains(&(i, j+1)) && grid[i][j+1] != 9 { leaf_nodes.push((i, j+1)); }
|
||||
}
|
||||
let (i, j) = leaf_node;
|
||||
if i > 0 && !explored_spots.contains(&(i - 1, j)) && grid[i - 1][j] != 9 {
|
||||
leaf_nodes.push((i - 1, j));
|
||||
}
|
||||
if i < height - 1 && !explored_spots.contains(&(i + 1, j)) && grid[i + 1][j] != 9 {
|
||||
leaf_nodes.push((i + 1, j));
|
||||
}
|
||||
if j > 0 && !explored_spots.contains(&(i, j - 1)) && grid[i][j - 1] != 9 {
|
||||
leaf_nodes.push((i, j - 1));
|
||||
}
|
||||
if j < width - 1 && !explored_spots.contains(&(i, j + 1)) && grid[i][j + 1] != 9 {
|
||||
leaf_nodes.push((i, j + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return explored_spots.len() as u32;
|
||||
return explored_spots.len() as u32;
|
||||
}
|
||||
|
||||
fn find_basin_sizes(grid: &Vec<Vec<u32>>) -> Vec<u32> {
|
||||
let mut sizes = Vec::new();
|
||||
for low_point in find_low_points(&grid) {
|
||||
sizes.push(find_basin_size(grid, low_point))
|
||||
}
|
||||
return sizes;
|
||||
let mut sizes = Vec::new();
|
||||
for low_point in find_low_points(&grid) {
|
||||
sizes.push(find_basin_size(grid, low_point))
|
||||
}
|
||||
return sizes;
|
||||
}
|
||||
|
||||
pub fn part2(grid: Vec<Vec<u32>>) -> u32 {
|
||||
let mut basin_sizes = find_basin_sizes(&grid);
|
||||
basin_sizes.sort_by(|a, b| b.cmp(a));
|
||||
return basin_sizes[0] * basin_sizes[1] * basin_sizes[2];
|
||||
let mut basin_sizes = find_basin_sizes(&grid);
|
||||
basin_sizes.sort_by(|a, b| b.cmp(a));
|
||||
return basin_sizes[0] * basin_sizes[1] * basin_sizes[2];
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = vec![
|
||||
vec![2, 1, 9, 9, 9, 4, 3, 2, 1, 0],
|
||||
vec![3, 9, 8, 7, 8, 9, 4, 9, 2, 1],
|
||||
vec![9, 8, 5, 6, 7, 8, 9, 8, 9, 2],
|
||||
vec![8, 7, 6, 7, 8, 9, 6, 7, 8, 9],
|
||||
vec![9, 8, 9, 9, 9, 6, 5, 6, 7, 8]
|
||||
];
|
||||
let result = part1(input);
|
||||
assert_eq!(result, 15);
|
||||
}
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let input = vec![
|
||||
vec![2, 1, 9, 9, 9, 4, 3, 2, 1, 0],
|
||||
vec![3, 9, 8, 7, 8, 9, 4, 9, 2, 1],
|
||||
vec![9, 8, 5, 6, 7, 8, 9, 8, 9, 2],
|
||||
vec![8, 7, 6, 7, 8, 9, 6, 7, 8, 9],
|
||||
vec![9, 8, 9, 9, 9, 6, 5, 6, 7, 8],
|
||||
];
|
||||
let result = part1(input);
|
||||
assert_eq!(result, 15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = vec![
|
||||
vec![2, 1, 9, 9, 9, 4, 3, 2, 1, 0],
|
||||
vec![3, 9, 8, 7, 8, 9, 4, 9, 2, 1],
|
||||
vec![9, 8, 5, 6, 7, 8, 9, 8, 9, 2],
|
||||
vec![8, 7, 6, 7, 8, 9, 6, 7, 8, 9],
|
||||
vec![9, 8, 9, 9, 9, 6, 5, 6, 7, 8]
|
||||
];
|
||||
let result = part2(input);
|
||||
assert_eq!(result, 1134);
|
||||
}
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let input = vec![
|
||||
vec![2, 1, 9, 9, 9, 4, 3, 2, 1, 0],
|
||||
vec![3, 9, 8, 7, 8, 9, 4, 9, 2, 1],
|
||||
vec![9, 8, 5, 6, 7, 8, 9, 8, 9, 2],
|
||||
vec![8, 7, 6, 7, 8, 9, 6, 7, 8, 9],
|
||||
vec![9, 8, 9, 9, 9, 6, 5, 6, 7, 8],
|
||||
];
|
||||
let result = part2(input);
|
||||
assert_eq!(result, 1134);
|
||||
}
|
||||
}
|
||||
|
||||
189
src/main.rs
189
src/main.rs
@ -18,83 +18,140 @@ mod day17;
|
||||
mod day18;
|
||||
mod day19;
|
||||
mod day20;
|
||||
mod day21;
|
||||
mod day22;
|
||||
mod day23;
|
||||
mod day24;
|
||||
mod day25;
|
||||
|
||||
use std::{env, process};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::{env, process};
|
||||
|
||||
fn run(day: i32, part: i32, input_filename: &str) {
|
||||
let mut input_file = File::open(input_filename)
|
||||
.expect(format!("Input file '{}' not found", input_filename).as_str());
|
||||
let mut input_file = File::open(input_filename)
|
||||
.expect(format!("Input file '{}' not found", input_filename).as_str());
|
||||
|
||||
let mut contents = String::new();
|
||||
input_file.read_to_string(&mut contents)
|
||||
.expect("Failed to read input file");
|
||||
let mut contents = String::new();
|
||||
input_file
|
||||
.read_to_string(&mut contents)
|
||||
.expect("Failed to read input file");
|
||||
|
||||
// Janky solution so that I could specify what I want to run
|
||||
let parse_error_msg = "Failed to parse input";
|
||||
match format!("{}.{}", day, part).as_str() {
|
||||
"1.1" => println!("{}", day1::part1(&day1::parse_input(&contents).expect(parse_error_msg))),
|
||||
"1.2" => println!("{}", day1::part2(&day1::parse_input(&contents).expect(parse_error_msg))),
|
||||
"2.1" => println!("{}", day2::part1(&day2::parse_input(&contents).expect(parse_error_msg))),
|
||||
"2.2" => println!("{}", day2::part2(&day2::parse_input(&contents).expect(parse_error_msg))),
|
||||
"3.1" => println!("{}", day3::part1(&day3::parse_input(&contents).expect(parse_error_msg))),
|
||||
"3.2" => println!("{}", day3::part2(&day3::parse_input(&contents).expect(parse_error_msg))),
|
||||
"4.1" => println!("{}", day4::part1(&day4::parse_input(&contents).expect(parse_error_msg))),
|
||||
"4.2" => println!("{}", day4::part2(&day4::parse_input(&contents).expect(parse_error_msg))),
|
||||
"5.1" => println!("{}", day5::part1(&day5::parse_input(&contents).expect(parse_error_msg))),
|
||||
"5.2" => println!("{}", day5::part2(&day5::parse_input(&contents).expect(parse_error_msg))),
|
||||
"6.1" => println!("{}", day6::part1(&day6::parse_input(&contents).expect(parse_error_msg))),
|
||||
"6.2" => println!("{}", day6::part2(&day6::parse_input(&contents).expect(parse_error_msg))),
|
||||
"7.1" => println!("{}", day7::part1(&day7::parse_input(&contents).expect(parse_error_msg))),
|
||||
"7.2" => println!("{}", day7::part2(&day7::parse_input(&contents).expect(parse_error_msg))),
|
||||
"8.1" => println!("{}", day8::part1(&day8::parse_input(&contents))),
|
||||
"8.2" => println!("{}", day8::part2(&day8::parse_input(&contents))),
|
||||
"9.1" => println!("{}", day9::part1(day9::parse_input(&contents))),
|
||||
"9.2" => println!("{}", day9::part2(day9::parse_input(&contents))),
|
||||
"10.1" => println!("{}", day10::part1(&day10::parse_input(&contents))),
|
||||
"10.2" => println!("{}", day10::part2(&day10::parse_input(&contents))),
|
||||
"11.1" => println!("{}", day11::part1(&day11::parse_input(&contents))),
|
||||
"11.2" => println!("{}", day11::part2(&day11::parse_input(&contents))),
|
||||
"12.1" => println!("{}", day12::part1(&day12::parse_input(&contents))),
|
||||
"12.2" => println!("{}", day12::part2(&day12::parse_input(&contents))),
|
||||
"13.1" => println!("{}", day13::part1(&day13::parse_input(&contents))),
|
||||
"13.2" => day13::part2(&day13::parse_input(&contents)),
|
||||
"14.1" => println!("{}", day14::part1(&day14::parse_input(&contents))),
|
||||
"14.2" => println!("{}", day14::part2(&day14::parse_input(&contents))),
|
||||
"15.1" => println!("{}", day15::part1(&day15::parse_input(&contents))),
|
||||
"15.2" => println!("{}", day15::part2(&mut day15::parse_input(&contents))),
|
||||
"16.1" => println!("{}", day16::part1(&day16::parse_input(&contents))),
|
||||
"16.2" => println!("{}", day16::part2(&day16::parse_input(&contents))),
|
||||
"17.1" => println!("{}", day17::part1(&day17::parse_input(&contents))),
|
||||
"17.2" => println!("{}", day17::part2(&day17::parse_input(&contents))),
|
||||
"18.1" => println!("{}", day18::part1(&day18::parse_input(&contents))),
|
||||
"18.2" => println!("{}", day18::part2(&day18::parse_input(&contents))),
|
||||
"19.1" => println!("{}", day19::part1(&day19::parse_input(&contents))),
|
||||
"19.2" => println!("{}", day19::part2(&day19::parse_input(&contents))),
|
||||
_ => println!("Day {} part {} not found", day, part)
|
||||
}
|
||||
// Janky solution so that I could specify what I want to run
|
||||
let parse_error_msg = "Failed to parse input";
|
||||
match format!("{}.{}", day, part).as_str() {
|
||||
"1.1" => println!(
|
||||
"{}",
|
||||
day1::part1(&day1::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"1.2" => println!(
|
||||
"{}",
|
||||
day1::part2(&day1::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"2.1" => println!(
|
||||
"{}",
|
||||
day2::part1(&day2::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"2.2" => println!(
|
||||
"{}",
|
||||
day2::part2(&day2::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"3.1" => println!(
|
||||
"{}",
|
||||
day3::part1(&day3::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"3.2" => println!(
|
||||
"{}",
|
||||
day3::part2(&day3::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"4.1" => println!(
|
||||
"{}",
|
||||
day4::part1(&day4::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"4.2" => println!(
|
||||
"{}",
|
||||
day4::part2(&day4::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"5.1" => println!(
|
||||
"{}",
|
||||
day5::part1(&day5::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"5.2" => println!(
|
||||
"{}",
|
||||
day5::part2(&day5::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"6.1" => println!(
|
||||
"{}",
|
||||
day6::part1(&day6::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"6.2" => println!(
|
||||
"{}",
|
||||
day6::part2(&day6::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"7.1" => println!(
|
||||
"{}",
|
||||
day7::part1(&day7::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"7.2" => println!(
|
||||
"{}",
|
||||
day7::part2(&day7::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"8.1" => println!("{}", day8::part1(&day8::parse_input(&contents))),
|
||||
"8.2" => println!("{}", day8::part2(&day8::parse_input(&contents))),
|
||||
"9.1" => println!("{}", day9::part1(day9::parse_input(&contents))),
|
||||
"9.2" => println!("{}", day9::part2(day9::parse_input(&contents))),
|
||||
"10.1" => println!("{}", day10::part1(&day10::parse_input(&contents))),
|
||||
"10.2" => println!("{}", day10::part2(&day10::parse_input(&contents))),
|
||||
"11.1" => println!("{}", day11::part1(&day11::parse_input(&contents))),
|
||||
"11.2" => println!("{}", day11::part2(&day11::parse_input(&contents))),
|
||||
"12.1" => println!("{}", day12::part1(&day12::parse_input(&contents))),
|
||||
"12.2" => println!("{}", day12::part2(&day12::parse_input(&contents))),
|
||||
"13.1" => println!("{}", day13::part1(&day13::parse_input(&contents))),
|
||||
"13.2" => day13::part2(&day13::parse_input(&contents)),
|
||||
"14.1" => println!("{}", day14::part1(&day14::parse_input(&contents))),
|
||||
"14.2" => println!("{}", day14::part2(&day14::parse_input(&contents))),
|
||||
"15.1" => println!("{}", day15::part1(&day15::parse_input(&contents))),
|
||||
"15.2" => println!("{}", day15::part2(&mut day15::parse_input(&contents))),
|
||||
"16.1" => println!("{}", day16::part1(&day16::parse_input(&contents))),
|
||||
"16.2" => println!("{}", day16::part2(&day16::parse_input(&contents))),
|
||||
"17.1" => println!("{}", day17::part1(&day17::parse_input(&contents))),
|
||||
"17.2" => println!("{}", day17::part2(&day17::parse_input(&contents))),
|
||||
"18.1" => println!("{}", day18::part1(&day18::parse_input(&contents))),
|
||||
"18.2" => println!("{}", day18::part2(&day18::parse_input(&contents))),
|
||||
"19.1" => println!("{}", day19::part1(&day19::parse_input(&contents))),
|
||||
"19.2" => println!("{}", day19::part2(&day19::parse_input(&contents))),
|
||||
"20.1" => println!("{}", day20::part1(&day20::parse_input(&contents))),
|
||||
"20.2" => println!("{}", day20::part2(&day20::parse_input(&contents))),
|
||||
"21.1" => println!("{}", day21::part1(&day21::parse_input(&contents))),
|
||||
"21.2" => println!("{}", day21::part2(&day21::parse_input(&contents))),
|
||||
"22.1" => println!("{}", day22::part1(&day22::parse_input(&contents))),
|
||||
"22.2" => println!("{}", day22::part2(day22::parse_input(&contents))),
|
||||
"23.1" => println!("{}", day23::part1(day23::parse_input(&contents))),
|
||||
"23.2" => println!("{}", day23::part2(day23::parse_input(&contents))),
|
||||
"24.1" => println!("{}", day24::part1(day24::parse_input(&contents))),
|
||||
"24.2" => println!("{}", day24::part2(day24::parse_input(&contents))),
|
||||
"25.1" => println!("{}", day25::part1(day25::parse_input(&contents))),
|
||||
"25.2" => println!("{}", day25::part2(day25::parse_input(&contents))),
|
||||
_ => println!("Day {} part {} not found", day, part),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() < 3 {
|
||||
println!("Usage: {} <day> <part> [input-file]", args[0]);
|
||||
process::exit(0);
|
||||
}
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() < 3 {
|
||||
println!("Usage: {} <day> <part> [input-file]", args[0]);
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
let day = args[1].parse::<i32>()
|
||||
.expect("Failed to parse day");
|
||||
let day = args[1].parse::<i32>().expect("Failed to parse day");
|
||||
|
||||
let part = args[2].parse::<i32>()
|
||||
.expect("Failed to parse part");
|
||||
let part = args[2].parse::<i32>().expect("Failed to parse part");
|
||||
|
||||
let input_filename;
|
||||
if args.len() > 3 {
|
||||
input_filename = args[3].clone();
|
||||
} else {
|
||||
input_filename = format!("input/{}.txt", day);
|
||||
}
|
||||
run(day, part, &input_filename);
|
||||
let input_filename;
|
||||
if args.len() > 3 {
|
||||
input_filename = args[3].clone();
|
||||
} else {
|
||||
input_filename = format!("input/{}.txt", day);
|
||||
}
|
||||
run(day, part, &input_filename);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user