Compare commits
63 Commits
a1f44e5886
...
main
Author | SHA1 | Date | |
---|---|---|---|
48c96ce7ea
|
|||
342f4c1883
|
|||
881d0b08ad
|
|||
c1eb7761e3
|
|||
98456ed98d
|
|||
d6d4c0d056
|
|||
3bb3b3d6b6
|
|||
dd91259fe2
|
|||
8495969877
|
|||
190fc92842
|
|||
eb6c1f42cd
|
|||
512b05f624
|
|||
877101f9a2
|
|||
cdfecf821c
|
|||
2b921b5fb2
|
|||
a5dea64b32
|
|||
8200c1a8cf
|
|||
8d178ddfc6
|
|||
3bc073f9b8
|
|||
0a9fa8e32f
|
|||
e65c17c8e6
|
|||
3ee26cefe5
|
|||
9e37b2ce66
|
|||
d422c9b84e
|
|||
5efa9853ca
|
|||
da25b73eca
|
|||
842def62dc
|
|||
427a0c766b
|
|||
332620db0f
|
|||
a8ec929818
|
|||
f04078fbd7
|
|||
498c96eaeb
|
|||
84bcbd550b
|
|||
e12c0134b0
|
|||
eac460417c
|
|||
24c534ff88 | |||
4f1f838d62 | |||
ca3254e1e1 | |||
78fb884c03
|
|||
7926475a56
|
|||
e062ef5078
|
|||
11a7837400
|
|||
5666aee5f2
|
|||
f12e99c1f4
|
|||
c797e874d5
|
|||
a431c4b75f
|
|||
20e2a9f7be
|
|||
96ea3c317d
|
|||
ebd1d0ff94
|
|||
26f990840a
|
|||
b84b0b04e2
|
|||
37b645c341
|
|||
d2718db633
|
|||
be0ed3e377
|
|||
c8eb06a5ec
|
|||
9ab450d258
|
|||
9718b8ab04 | |||
de6e826c31 | |||
077f4ff8ee | |||
0665e109af | |||
6d1174e2db | |||
25daf558e6 | |||
db4a8b0d24 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
**/target
|
||||
input
|
||||
|
1
.rustfmt.toml
Normal file
1
.rustfmt.toml
Normal file
@ -0,0 +1 @@
|
||||
max_width = 120
|
7
10/Cargo.lock
generated
Normal file
7
10/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day10"
|
||||
version = "0.1.0"
|
8
10/Cargo.toml
Normal file
8
10/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day10"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
140
10/input
Normal file
140
10/input
Normal file
@ -0,0 +1,140 @@
|
||||
F-|F|7LJ7F7.L-J7L-L-7L-J7.FF.F|--J.L-7--7.L-7FFFF7-F|---F--L-FF-FF|.L.F|77|--7-.FF7-7--L7.-7F-7FL-7FFF-777FF-L-L.L-F.|--7.77-LF7-|F--|---777
|
||||
|-7FF|||F7J.FJL|.L7LL7F|J7.J.|.|JF-7LLJJL-JJLFJLL7F||.FFJ||.LFJF7.LJ.F7|L-J7J|.L-JF7|F77F7J|7.LJ|LFJLLLLJ7F|.L-.-F-J7LJ-7FJL7FLL7L7JJ..JL-7|
|
||||
F7|-LJF-F--LJ-FF7L|7FJJLF7FF-J-|-F.L.L7LLL7|F7JLF---.F-LJ|F-JL7L7-7.FLLJFF-|L-L7JJJ.--LJ-JJL--7L||F7.|-J.FFFJ.|.LL7L-.FFLJJ-JL-FJJL-77-|JLLJ
|
||||
-J|.|F7LJ..|LFJ-J7|J|J-||JF|7||..|-7F7L-7.|-LF7.F7|7.-J|LF|---J7|||F7|L|-|.|F.LL-7-|||JLFLF7JLL-L-LJFF7-7-LJFFL..FJ.|.FFJLJ|JJ7|7L7J7--J.|F|
|
||||
FFFJ||J.LFJJLJ7.J7|-77-L|-FL-L-F.LL|LJ|FJ-FJF||-F7F7-|FF7FF7J7|--J.-.J-L-FFLJ.FL7L|.|L|FJ.L|.7J|LJ|.||L7L7J.-J||F77F77L|J7LLJ.FL7J|LL7FLJFJ7
|
||||
J7.|-L-|-LJ|7.|-L-J7L7-|F-7.7|F|.|JF7.LJL|L7F||FJLJL-7-FF7||-7LJFJJ.FJ7J.LJ7.7JLLF7L|7L|LF-LFF7-.|F-LJJF7LJ-|.7J77||F7J.|J-F---J|-|7||F|-7-J
|
||||
|L77J-7J77|-|--..|L7FJ||L7LJLJ||.FFJF-L7FF-F-J||F----J-FJLJ|F77L7|.7LLL.-J7L-J-F-JL--7FL.|-7||||.77JFJ-F|L7.-LJL|7LF|J|FJ7-LJ..FL--.F7.7-LF7
|
||||
||.---FJF-|.7J.L-77.F.FL7.-J77L|7L|FL|J|-J.L-7LJ|F77|7.L--7LJL-7JF-F7JF7J.777L77JFF--FF7-LJFF7F--7..||LLL7L7J-7JJ|7|L|-7F7.|FFJ||-J-7JFF.FL7
|
||||
LF-L-F|7|.7.F-FJ-|---7||.FL--JJJL-77FF7|FJ7..L-7||L7JF----JF---JFF7||JF-7-L77-J--|LJF-7777FFJ||F-J--LJ.L-L7JJF-77LFL-7-|-J|-F7JF.F|-J|7L-7-|
|
||||
-|7.-LJJ-LL.F7|.|..|-LJF-7|7.F|.L-LLFF-7JFFF--7|||FJLL----7L7F7|FJLJL77.|J-F77J|-7JL|FJF7F7L7||L-77.|J7..|F7-F7||-F-FJ|J|FJF-J7|7JLJJL|LL-7|
|
||||
|L-7L|FL-||7|L|J7F|77..LFJF---L-|JF7FL7L7F7L-7LJLJL7F7-F--JFJ||FJF---J.F|FF||J.F--7FJ|F||||FJ||F-JF7F--7F-J|F77---JJF-F-F|J|.LFJJF.|LJ.L7L-J
|
||||
77JFF|-|--7--J.|.FJ.F7-FJ.J7|.|L7-|FF7L7|||F7L7F7F7||L7L--7L7||L7|F----7FF7||-FJF-JL7|FJLJ|L7||L-7||L-7|L-7LJ||F|77.|J|LF|F-7JL-7J-L7F|.L7FL
|
||||
L|.FF-7JJLLJF|-7FJJ7L7F-77F-7FL-F-F7||FJ|||||FJ|LJ|||FJF7FJFJ|L7|LJF---JF|LJL7L7L7F7||L-7FJJ|LJF7LJ|F-JL-7|F-JF-7-|-|-J7LL|FJ...77LFL|J7LFJ.
|
||||
7.|L77L77.F7-J--|J.|FFL7L-J-JFFJ|.|LJLJFJ||||L-JF7|LJL7||L7L7L7||F-JF7F-7|F-7L-JFJ|||L7F||F7L7FJ|F-JL-7F-J|||FJFJ-7J|77|-L|L7F7F7----LL--|.F
|
||||
--7-|JL7-.F7JF-7LL-.L|L--77|.|-F-7L---7L7|||L7F7||L-7FJ||L|FJFJ||||FJLJFJ||L|F--JFJLJFJFJ|||FJL7LJF7F7|L7FJL7L7L-7|-|-||F7|FJ|LJ|||.L|.L-J-L
|
||||
J7FFJJ-LJ7||FJ.F7||.FJJ7F|--7JLL7L7F-7L7|||L7LJLJL7||L7||FJL7L7LJL7|F--J-LJFJL7F7L--7L-JFJ||L-7L7FJLJ||FJL7FJFJF-J7F7-F7|LJ|FJF-J77L-|---|.J
|
||||
FF7L7|-J.F--FJ7LJFF-J7LJ-JFL|7J|L7||FJ|||||LL7F--7L7|FJ||L-7|-|F--J||F77F7FJF7LJL7F7|F-7L-JL7FJFJL--7||L7FJL7L7|F77||FJLJF7||FJF--7J.--F-F7.
|
||||
7.J.L--L--JFJLJJ7L|JF7.|.|J-|J|F-JLJL7FJ||L7FJ|F-JFJ||FJ|F-JL-JL7F7|LJL7||L-J|F-7|||LJ|L7F--JL7|LF7FJ||FJL-7L7|||L7|FL--7||LJL-JF-JFJJ||F7--
|
||||
--L--JF|7||L-F.L77..||FJ-LJ.77-L----7|L7|L7LJFJL-7|||LJFJ|F7F-7FJ||L--7|||F7-|L7LJ||F7F7|L7F7FJL-J|L7|||F7FJFJ|||FJ-F-F7LJL-7F--JFJ7-F--||L|
|
||||
|-L7F|-L-7|L-JF7-F7-J77FJFJ.F7-|F-77||FJL7L--JF-7|L7|F7L7LJLJFJL-JL7LFJLJLJ|FJFJF-J||||LJFJ|LJF---JFJ|||||L7|L|LJL7JFJ||F-7J||7LJF||-LL-FJ-|
|
||||
77-F.JL|L-|FLF|L|.F-|.FL7|JFJL-7|FJFJ||F-JF7F7L7|L7|||L-JF-77L--7F-JFJF7F--JL7|J|F-J||L-7L7L-7|F--7L7||LJL7|L7L--7||F7||L7|FJL7L7LF77LL-FJF7
|
||||
.|7LJ7FF7|LL-7J7L-7FL-J.|JFL--7||L7L7LJL77||||FJ|FJLJL7F7L7|F---JL7FJFJ|L77F7|L7|L7FJ|F7L7L--J||F-JFJ||F--J|FJFF7||FJ|||FJ|L7FJ.LFJ|7JFL.L7J
|
||||
F|L7|-F|-77LFL-F77|-J7|-|.FF--J||FJ-L-7FJFJ|||L7|L-7F-J||FJ|L--7F7||FJ-L7|FJLJFJ|FJL7LJL7L-7F-J|L7FJFJ||F7FJ|JFJ|||L7|||L7|FJL-77L7L-77L-7JJ
|
||||
L|JLJ--F-L-JL7JL-J.LFFFF7F7L--7LJL-7|FJL7L7LJ|7||F7||F7|||FJLF7LJ|LJL7F7LJL7F7L7|L--JF--JF-JL-7L7|L7|-||||L7L7|FJ||FJLJ|FJ|L7F-JF7|F-J77.|F7
|
||||
FJL7JJ.J-J.-J|7.|-|F-F-JLJ|7-LL--7FJFJF-JFL7FJFJLJLJLJLJ||L-7||F-JF-7LJL--7||L7|L7F-7L7F7L-7F-JFJ|FJ|FJLJ|FJFJ||FJ|L--7|L7|FJL--JLJL--7-7-|J
|
||||
FLJ.7F7.|.FJ|-|7F.F7LL--7FJF7F7F7|L7|FJF7F7|L7|F7F----7FJ|F-J||L-7L7L-----JLJ||||LJFJFJ||.FJL7FJFJL7LJF--J|FJFJ||FJF7FJ|FJ||F---7F-7F-JJ7.L7
|
||||
F7F|LF7-JF7.7JL-JL||F7J|||FJ||LJ|L7||L7||||L7|||||F--7||F|L-7||F7|FJF--7F--7F-JL7JFJFJFJL7|F7|L7|F-JF7L7JFJL7|FJ|L7|||FJL7LJ|.F7LJFLJ||L7-L|
|
||||
J7J|FLL7.LL7J.LJ7||LJ|F7||L7|L-7|F|LJFJ|LJ|FJ|||LJL-7||L7|F-J|LJ||L7|F-JL-7|L--7|FJFJFJF-JLJ||FJ|L7FJL-JFJF7LJL7|FJ||||7-|F-JFJL7F7F777LF7.7
|
||||
|JF-JLFJ.LJ|.F77FL|F7LJLJ|FJ|F7|L-JF7L-JF-JL7|LJF7F-JLJFJ|L77L-7|L7||L--7FJL---JLJFJ7L7|.F7-||L7|FJL7F7|L-JL7F-J|L-JLJL7FJL--JF7||LJL-7-||.L
|
||||
|J-LJ7LJF-77-LF-F|LJL---7|L7|||L---J|F-7L7F-J|F-J|L---7|FJFJF7FJ|FJLJF--JL7F-----7L-7FJL7|L7||-||L-7LJL7F7F7||F-JF-----J|F-7F7|LJ|F7F-JF-J77
|
||||
|.L|L|LF--J|L|J---F-7F7|||F||||-F7F-J|F|FJL-7|L7FJF---J|L7|||||FJL--7L7JF7LJF7F-7|F7||F7||FJ|L7||F7L7F-J|||||LJF7|F-----JL7|||L--J||L777JJFJ
|
||||
L..F7L-..|-|F||.|7L7LJ|FJ|FJLJL7|||F7L7LJF7FJL7|L7L---7L7||FJ|||F7F7L7L7|L7FJ|L7LJ|LJ||LJ||JL7LJ||L7|L--J||||F-JLJL----7F-JLJL-7F7|L7L7||FL.
|
||||
L---|-LJFL-FLF--7F||F7|L7LJF--7|||LJL7|F7||L-7||FJF7F7L7|||L7|||||||7L7||FJL7|FL7FJF7||F7||F7L7FJL7||F---J|||L7F7F7.F--JL---7F7LJLJ-L7|-7F-7
|
||||
LJ-LJ-|FJ--.L|F-JF7LJ|L7L--JF7|||L7F7||||||F-J||L7|LJL7||||FJ||||LJL7FJ||L7FJ|F7|L7|||||LJ|||FJ|F7|||L7F7FJLJFJ|LJL7L-7F----J|L7F77-L||F-7-J
|
||||
|..L..-|L77F-JL-7||F7L7L----JLJLJFJ||||||||L7FJ|FJL-7FJ||||L7||||F--JL7||FJ|FJ|||FJ||||L7FJ|||FJ|||||FJ|||F--JFJF--J.FJL----7|FJ||77|LJ7LJ||
|
||||
F|7-JJ--7F-JF7F7LJLJ|LL---------7|FJ|||||||FJ|FJ|F7FJ|FJ||L7|||||L7F7FJ||L7||FJ||L7|||L7|L7||||FJ||LJL7|LJL--7L7|FF7FJF--7F-J|L-JL7F7.|JJFL7
|
||||
||F7|JF7FL7FJ|||F--7L-7F7F----7J||L7||||||LJFJ|-LJ|L7|L7||FJ||||L7||||J||FJ|||FJ|FJ||L7LJLLJ|||L7LJF--J|F----JFJL-J|L7|F7LJ|FJF-7FJ|L7|F-7J|
|
||||
-LLJL-|F-LLJ|LJLJF-JF7LJ|L---7L-JL-JLJ|||L-7L7L7F-JFJL7||||FJ|||FJ||LJFJ|L7|LJL7||FJL7L-7.F-J|L7L-7L7F-JL----7L7F--JFJLJL---JFJFJL-JFJ-|JF-7
|
||||
FJF|-LL--|F---7F7L7FJL7FJF7F7L-------7||L7FJFJFJL7FJ.FJ||||L7LJ||7LJF7|FJFJ|F--J|||F7L-7L7L-7|FJF-JF||F7F----JFJL---JF--7F---JLL-7F-JF7J.|FJ
|
||||
L|-JF|J---L--7LJL7LJ|FJ|FJ||||F7-F---JLJFJL7L7|F-JL7FJFJ|||FJF-JL-7L||||-L7||F--J|LJL-7|FJF-J|L7L7F7LJ||L-----JF-7F7FJF7|L--7F7F7LJF-J|FFJL7
|
||||
LLLJFJF7JJJ7FJF-7L7F7L7|L7LJL-JL7L----7JL-7L7|||F-7|L7|FJ|LJFL-7F7L-J|||F-J|||F--JF-7FJLJFJF7L7|FJ|L--JL7F7F---JFJ||L-J|L--7||LJ|F7|F-JFJF-J
|
||||
LFF7L7L|7JFFL7L7L7LJ|FJL7L-----7L-----JF7J|FJ||LJFJL7||L7L--7F-J|L7F7|LJL-7|LJL7F7|FJL-77L-JL7|LJFJF7F-7|||L-7F7L-JL7F7L-7FJLJF-J||||F-JFJJJ
|
||||
.-|JJFLF777F-L-J7L-7|L-7|F7F---JF------JL7|L7|L7FL-7|||7|F-7|L-7L7LJ|L7F--JL7F-J|||L7F7L--7F7LJ7FJFJ||FJLJL-7LJL---7||L7FJL---JF7|||LJF-J|FJ
|
||||
.F|JLF7|L7-|.F7-F7FJL--J|||L----JF-----7FJL-JL7L--7LJ|L7|L7||JFJFJ-FJFJL----JL7FJ|L7|||F-7||L---JFJFLJL7F7F7L------J|L7|L7F----JLJLJF7L-7JF|
|
||||
-FJJJ|||FJFF7||FJLJF7F-7|||F7F7F7L----7||F7F77L---JF-JFJ|FJ|L7L7L-7L-JF-7F7F--JL7L-J|||L7|||F7F-7L-7F-7LJLJL-------7|FJL7LJF-7F7F--7|L-7|FJ7
|
||||
F7JF7|LJ|-FJ|||L---JLJFJLJ||LJ|||F----JLJ|LJL----7.L-7L7|L7|FJJ|F7L-77L7LJLJF-7FJF--J||FJLJLJLJFJF-JL7L-----7F-7F--JLJF7L-7L7LJ|L-7LJ.LLJFJ7
|
||||
FLFJ|L-7L-JFJ|L------7L7F7|L-7|||L-------JF--7F--JF-7|FJL-J|L-7LJ|F-JF-JF--7|.LJ.L-7FJ|L7F-7|F7L7L7F-JF--7JFJL7|L-----JL-7L7L-7|F7|F7-F-77|.
|
||||
-7L7|F7L--7L7L-7F7F-7L-J||L--JLJL-7F7F7F7FJFFJL-7JL7LJL--7FJF7|F-J|F7L-7|F-JL--7F--J|LL-JL7L-JL-JFJL7FJF7L7L7FJL---------J7L-7|LJ|LJ|FJFJ.F7
|
||||
LLJ|LJL--7|FJFFJ|LJ-L---JL7F7F---7LJLJLJ||F7L7F-JF7L-7F7FJL7|||L-7LJ|-FJ|L7F7F-JL7F7L----7L7F-7F-JF7LJFJL-J|LJ-F7|F----7F--77LJF-JF7|L7|F7||
|
||||
|LFL-7F-7LJL-7|FJF--7F--7FLJLJLF7L-----7|LJ|FJL--J||FJ||L-7||||F-JF7L7|FJFJ||L-7|LJL7F---JFJL7||F-J|F7L---7F--7||FJF7F-J|F7L--7L-7|LJFJLJLJ|
|
||||
7|..FJ|FJF-7FJLJFL-7LJF7L------JL------JL7FJL7F--7|FJFJL7FJLJ||L7FJL7||L7L7||F7L-7F7|L--7FJF7|LJL-7|||F77FJ|F-J|LJFJLJF7||L---JF7|||FJF7F7FJ
|
||||
|LF-L-JL7|FJL------JF7|L-7F-7F----------7|||FJL7FJ|L7L-7LJF7J||FJ|F-J||FJFJ|LJ|F7||LJF-7|L-JLJJF7FJLJLJL-JJ||FFJF7L---JLJL-7-F7||LJFJFJLJLJJ
|
||||
JJLF--7FLJL-7F-7F7F7|LJF-J|7LJF-----7F--J|L7L--JL-JFJF7L--JL7||L7||F7|||FJFJF7||LJ|F7L7LJF7F-7FJLJF7F7F----JL-JFJL7F------7L-J|||F-JFJJ-LJ|.
|
||||
|F|L-7L--7F-J|FJ|||LJ|FJF7|F--JF7F-7LJ-F7L-JF--7F7|L7||F7F7FJLJJ|||||||||FJFJLJL-7LJL7L-7||L7|L---JLJLJF----7F-J7FJL-7-F77L---J||L7FJJJJJJJ.
|
||||
L7F|FL--7||F7|L-J||F--JFJLJL--7|LJFL---JL7F7|F-J|L-7||||||||F---J|||LJ||||FL-7F7FJF-7L7FJ|L-JL-7FF7F7F7L---7|L--7L--7L-JL7FF7JFJL-JL--7-|-77
|
||||
L|J|FLF-JLJ||L--7LJL---JF-----J|-F---7F-7LJ|||JFJF7|||||LJ||L-7F-J|L-7||||F--J||L7L7L7||FJF7F-7L-JLJLJL-7F7|L-7FJF7-|F7F7L-JL-JF------JL7L|7
|
||||
.|F-FFJF--7|L7F-JF---7F7L---7F-JFJF7-LJ||F7LJL-JFJLJLJLJF7LJF7||JLL7FJLJ|||F7FJL7L-JFJLJL-J|L7L7F7F7F7F7LJLJF7LJFJL7LJLJL7F7F-7L-7F7-F7||-J|
|
||||
LJ7FLL-JF-JL7|L7FJF-7LJL----J|F7L-JL--7FJ||F--7FJJF--7F7|L7FJLJ|7-LLJ-LJLJ|||L7.L7F7L-7F---JFJ|LJLJLJLJL--7FJL7FJF-JF7F7|||||-|F7LJL-JL7|.F|
|
||||
|L-F-LL-L7F7|L7|L-JL|F----7F-J|L----7FJL7|||F-JL--JF7LJLJFJL7F7|--|L7..|LFJ||FJF7||L--JL----JF--7F7F7FF---JL7FJL7L--JLJL7LJ||FJ||F-7F7FJ777J
|
||||
J.|L-7|.|||||JLJF---J|F---J|F7L----7LJF7LJLJL-7F-7FJ|F7F7|7.LJLJ|F7LFF-LLL-JLJFJLJ|F-7F7F7F77|F7LJLJL-JF--7FJL--JF7F-7F7L-7|||FJ|L7||LJF7.|F
|
||||
LLJ7LJ7-LLJLJFF-JF---JL7F--J|L----7L--JL7F7F7FJL7LJFLJ|||L7-LL|.7L|JLL7.|-|.LFJF-7|L7LJLJLJL7LJL--7F7F7|F-J|F----JLJJ||L--J||LJFJFJ|L--J|-|J
|
||||
FJL7.L|L|.LF--JF7|7F77FLJF-7L----7L---7FJ|||||F7L-7F-7LJ|FJ7.LL-JFJJ7-LJ--LF-L7|FJL7|F7F-7F7L7JF7LLJLJLJL--JL-7F--7F7|L7FF7LJF7L7|FJF-7FJJ.L
|
||||
LF.L77JF-.FL7F7|LJFJL7F-7L7L77F7.L---7LJFJLJ|LJL--J|FJLFJ|J7..FLLJ.F7.7JJ||J.LLJL--JLJ||FJ|L7L7||F7F7F----7F-7LJF7LJ|L-JFJL-7|L7|||FJ|LJJF-7
|
||||
FF-7L|F-JF-LLJLJF7L-7|L7|F|FJFJL7F---JF7|F--JF-----J|F7L7|-L-F77|L.FJFJFF-|.F7LF7F-7F7LJL7|7L7LJLJ|||L---7|L7L--JL--JF7F|F--J|FJLJ|L7--LLJ-7
|
||||
F--J--LJFJLF7F7FJ|F-JL7||FJL-JF7|L----J||L---JF7F7F-J|L7LJ7J..LL-JFF-FLLJJL7-|F||L7|||F--JL7-L---7||L----JL7L--------JL-JL-7L|L--7L-J|JLFJ||
|
||||
|-|-7JFFJ7.|LJLJFJL7F7LJLJF7F-J|L------J|F----J||||F7|FJLF7|-7-|L|L7--J|LJ|L-LL|L-JLJLJF7F-JF----J||F7F---7|F-7F--7F---7F-7L-JF--JF7F7.|FF--
|
||||
J7FF-7FJ||FJF--7L-7LJL---7|LJF-JF--7F---JL-7F7JLJLJ|LJL7FJ|F77.J--JLL|F7L-LJ..LL-7F7F7FJLJF7L-7F-7|LJLJF--JLJ-|L-7|L--7LJFJF-7|F7F||||.|JL|.
|
||||
|LL-|-7F--L-JF-JF7L------JL7LL--JF-J|F--7F7LJL7F7F-JF-7LJFJ7LJ-J.|.F.J-J-J|F77F--J||||L-7FJL7FJ|FJL--7-L---7F7L--JL7F7L-7|FJ||LJ|7|||L-7-.|L
|
||||
7.|.|JL|J7LF-JF7||F7F------JF-7F7L--JL-7||L---J|||F7|L|F7L7J777.7-L7.L-7|7J|LFL---J|||F-JL7FJL-J|F-7FJF----J||F7FF7|||F-J|L-7|F7L-JLJF7|LFFJ
|
||||
|J-F7--J.L.L7FJLJLJLJF--77F7L7|||F--7F-JLJFF7F7|LJ||L7LJL-JJ.77JJ.F|.LF-FJ.F7.F----J|LJ|F-JL----J|FJL7L--7F-J||L-J||||L7FL--JLJL-7F7FJLJ7F-7
|
||||
|F|.LJ||FJ.FJ|F-----7L-7L-JL-JLJ|L-7|L--7F7|LJ||F-JL-JF---7..7J.FJ-F7L-.|--L7-|F-7F7|F-7L------7FJ|F7L7F7||F-J|F--J||L7L-7F7F---7||LJ.|J7JL-
|
||||
FL|-LJL7JJFL-JL--7F7L7FJF-7F7F-7L--JL7F-J|||F7LJL--7F7L7F-J77.F-L|.J|FJ.L7..F7LJ.LJ||L7|F7F7F--JL7||L7LJLJ|L7FJL--7|L7|F7||LJF7FJLJ7-||FL7.|
|
||||
.LJ-J-LL77-|LF---J|L7LJFJ.|||L7L7F--7|L--JLJ||F7F-7LJL-JL-7-7F77-.|J7|FLLJ.FLJ7F-|LLJFJLJLJLJF-7FJ|L7L7F-7|FJ|F---JL-JLJLJ|F-JLJJFLL-L-FJ-J7
|
||||
F|J..L||LJ7LFL-7F7|-L-7L7FJ|L-JFLJFFJL------JLJ|L7L7F--7F-J-L-J-JFJ--7F.|F7.L.|JL|-F-JF---7F7|FLJ7L-J.LJ.LJL-JL-7F7F7F7F7FJL-7F7-F7|.|.LFJLJ
|
||||
7---7F-7JF||L|FLJLJF7FJFJL-J|F7F7F7L----------7L7L7||F7|L-7-FJFJ-JLFJ|J-F||7.LJ|LF7L-7|F--J||L7F--7F7F------7F7FJ|LJLJ|||L7F-J||7||F--77.F7|
|
||||
LJ||L|.L.JLJ|.F7F-7||L-JF7-F-JLJLJL-7F--------JLL-JLJ||L--JF-777FLFF7.|7FJL7-.LF-JL-7LJL-7FJ|FJL-7|||L-7F--7LJLJJ|F---J|L-JL-7|L7|LJF7||LJ-7
|
||||
-J-|J|..F|.LF-J|L7LJL---JL-JF7F7F7F7|L----7F---7F----J|F7J|||LF-7J.F7-7FJF7|.F|L---7|F7F7LJ-LJF--JLJL-7LJF-J-F7F7||F7-FJF7F7FJ|FJL7FJLJ-L|7F
|
||||
|7LL-J.L--7F|F7L-JF---7F----JLJ||LJ||F----J|F--J|F7F7FJ|L--77LL7||F||FFJFJ||-FF7F--JLJLJL7F-7FJF7F---7L--JF--JLJLJLJL-JFJ|||L-JL--JL--7J7F--
|
||||
|F.FL-L-F-FLLJ|F-7|F-7LJF7FF---J|F-JLJF7F7FJL---J|LJ|L-JF7FJ7FFJL7FJL-JFJ|||-||LJF7F7F7F7LJFJL-JLJF77L----JF-7F--7F7F--J-|||F7F-7F7F7FJ-L.FL
|
||||
L--L.7J-J|.|L|LJLLJL7L--JL-JF-7FJL----JLJLJF7F7F7L-7|F--JLJ|.FL-7LJF--7L-7LJF7L--JLJLJLJL-7L7F-7JFJL7F7F7F-JFJL-7|||L---7LJ||||7LJ||LJJ|L-F7
|
||||
FJJ.-.F.7LF|.F-----7L---7F-7|FJ|F----7F----JLJLJL--JLJ.F-77F77LLL--J.FJF7L-7||F7F--7F-----JFJL7|FJF7LJ||LJF7L---J||L-7F7L7LLJ|L-7FLJJLFFJ|L-
|
||||
|J7LL-7F7.-J7L--7F7|F---JL7||L-JL---7|L----7F7F7.F7LF--JFJFJ|JLF-7F-7L7|L--J|LJLJF7|L-7F--7L--JLJFJ|F7LJF-JL----7|L-7LJL-JF-7L7FJF7|7F-|F|J|
|
||||
|||-LLL|-LF-7JFFJ||LJF7F7FJ||F------JL----7LJLJL-JL-JF7FJJ|FJ7FL7LJFJFJL---7L---7|LJ.FJ|F-JF-7F-7L7LJL7FJF-----7|L7FJF-7F7|FJFJL-JL--7-.|J--
|
||||
LJ--7JL|7||-77FL-JL-7|||||7LJL-----------7L7F-7F7F---JLJF-JL-7F7L-7L-JF----JF---J|F7FJFJ|F7|FLJLL7|F-7LJFJF--77LJ|LJ||FJ|||L7|F-7F7F7|JFFJ|L
|
||||
LJ-FL.LL--JFJF7JFF--J|||LJF7-F---------7FJJ|L7LJLJ-F---7L--7FJ||F7L--7|F7.F7L---7|||L7|-LJ||F-7F7LJL7|F7L-JF7L7.F7JF-JL-JLJFJ||FJ|LJLJFFL-JJ
|
||||
.|J|L-77.JFL-||7FJF-7|||F-JL7L--------7LJF7L-JF7.F7|F--JF7FJL7||||.F7|||L-JL-7.FJLJ|-LJF7FJ|L7LJ|.F-JLJL---JL7L-JL-JF7F7F-7L7LJL7L7J-L-.LL7.
|
||||
LJ-F|JF|.F7J-|L-JFJ.LJLJL--7|F7F7F7F-7L--J|JF7||FJLJL7F7||L7FJ|||L7|LJ||F----JFJF-7|F--J|L-J7L7FJFJF---7F---7|F--7F-J||LJ7|FJJ-LL-JF7LL-7L77
|
||||
|.|.|.-JFFLJFL-7FJF-7F7F--7|LJLJLJLJFL-7F7L-J||LJF7F7|||||FJ|FJ||FJL-7LJ|.F--7L-JFJ|L-7FJF7|F-JL7L-JF--J|F7FJLJF7|L-7LJF-7||JL77.|-7J.L|FJL7
|
||||
.F7.-7FF777FLJ|||.L7|||L-7|L7F7F------7|||F-7LJF-JLJLJ||||L7|L7LJL7F-JF-JFJF7L7F7L7L7FJ|FJL7L--7L---JF7FJ|LJF7F||L--J-FJFJLJJ.J7-JJL.|-FJFFJ
|
||||
F77FL-7LJL-JL-FJ|F-JLJL7FJL7||LJLF----JLJ|L7|F7L----7FJ|||F||-L7F-JL-7L7FJFJL-J||FJFJL7||F-JF7FJF7F7FJLJ|L--J|FJL-----JFJF77F7JJ|.-7.|..F7L-
|
||||
F7-JLJ-77FLF--|FJL----7|L-7|||F--JF7F7F7FL-JLJ|F--7FJL7|||FJL7FJL7F77L7||FJ7F-7|||FJF7||||F-JLJFJLJ||F7|FF---JL7F---7F-JFJ|F-7|F7-|7.L7-F|-J
|
||||
||J-FJFLFJL-.FLJJLF--7|L--J|LJL---JLJLJ|F7F--7|L-7LJF-JLJ|L-7|L-7|||F-J||L-7|FJ|LJL7|LJ|||L7F-7|F--J||L7FJF7F7-|L-7.LJF7L7LJFJF7L7.7-L|7|.|.
|
||||
|J.||LL7L7-|.|LF77L-7LJF--7L--7F-------J|LJF-JL7FJF7L---7L-7||F-J|||L-7||F-J|L7L--7|L7FJ|||LJ-LJ|F--JL7|L-JLJL-JF7L7F-JL-JF7L-J|-F7J-F-JL77.
|
||||
|LFL7J.|-F7|-JF|L--7L--JF7L--7LJF----7F-JF7L-7JLJFJ|F7.FJF-J||L-7||L7FJLJ|F7|FJF-7|L7||FJL7JF7F7LJF7JFJL----7F7FJL7LJF7F--JL---J7||.||J..JJF
|
||||
..77|..|-|||F--L--7L7F--JL---JF7|F--7LJF-J|F7L--7L7|||FJFJ|FJL-7|LJFJL-7FJ||||FL7|L7|||L7FJFJ||L7FJ|FJF7F7F7LJLJF7L--JLJFF7F7F--7||F-7|F|.-7
|
||||
FFF7FF7|7.7L777F7-L7|L------7FJ||L-7|F7L-7LJ|F--J.||||L7|F7L-7FJ|F-JF7FJL7|||L7FJL7||||FJ|JL7LJFJL7LJFJLJLJ|F7F-JL7F7F7F-J||LJF-J|||FJ7-777F
|
||||
FF||--JL|-F7F7FJL--JL-7F7F--J|FJ|F-JLJL--JF7|L7F-7||||FJ|||F-JL7|L-7||L7FJ|||FJL7FJ||||L7L-7L7FJ|LL-7|F----J|||F--J|||LJF-J|F-JF7|||L--7|7FJ
|
||||
LLLJ7.F-LF|||LJF7F7F-7|||L---JL-JL----7F-7||L-JL7LJ|||L7|||L-7FJ|F-J||FJL7|||L7FJL7|||L-JF-JFJL-77F7LJL7F---JLJL---JLJF-JF7||F7|LJLJF--J7JJ|
|
||||
|LJ.F|JLLFJLJF7|LJLJ||||L7F7F-----7F--J|FJ|L7FF7L-7|||FJ||L7FJL-JL7-||L7FJ|||FJL7FJ||L--7L7FJF--JFJL7F7LJF7F-7F-------J7FJLJLJLJF--7L--7L|-F
|
||||
L7J.F|7||L-7FJ||F----J||FJ||L----7LJF7FJL7L7|FJL-7||||L7||FJL--7F-JFJL7||FJLJL7FJL7||F77L7LJFJJF7L7FJ|L-7|LJFJL---------JF-7F7F7L-7L---JF-7J
|
||||
JJFFF|7-FJFLJ|LJL----7LJL-J|F7F7-L-7||L7FJ|||L7F7LJ|||J|||L-7F-J|F7L-7|||L-7F-JL-7||||L--JF-JF7||FJL7|F7LJF7L---7F-7F7F7FJF|||||F7L--7JF7JLF
|
||||
L-|J||-J|.7JLLF------JF-7F7|||||F7.LJL7||F7|L7LJL-7||L7||L7FJL-7LJ|F7|LJL7FJL--7FJLJ|L--7FJF-J||LJF-J||L--JL--77LJFLJ|||L7FJ|LJLJL7F-J-F|-J|
|
||||
L7JFJ|FFJ-JJ7||F---7F7|FJ||LJLJLJL----J||||L7L7F-7||L7||L-JL77FJF-J|LJF--JL-7F-JL--7|FF-JL7L-7|L7FJF7LJF---7F-JF7F7F7LJ|FJL7L--7-FJ|-JL7LLL-
|
||||
FLF7L|J-L--F|7LJF7FJ|||L-JL7F7F7F---7F7||||FJFJL7||L7|LJF7F-JFJFJF7L-7L-7F-7||F7F7FJL7L--7L7FJ|FJ|FJ|F-JF-7|L--JLJLJL-7LJJ-L7F-JL|FJ7-7.--7|
|
||||
7-FF7LL|||FFF-7-||L7||L7F--J|||LJ-F-J|||||||FJF7||L7|L-7|LJF7L7||||F7L-7|L7|||||||L7FJF7FL7||FJ|FJ|FJL--JFJ|F--7F--7F7L-7FFFJ|F7F||L|7F-|-LJ
|
||||
.F--L--||7-FJFJFJ|FJ|L7|L7F-JLJF-7L7FJLJLJ||L7||||FJ|F-J|F7|L7||FJLJ|F7|L7|||||||L7|L7||F7||||FJL7|L7F7F7|FJL7L|L-7LJ|F-J7.L7||L7||.7-|JL--J
|
||||
-|JL||.FLF7L7|LL7|L-JLLJFJ|F-7F|FJFJL--7F-J|.|||||L7|L-7LJLJFJ|||FF-J|LJ7LJ|||||L7||F||||||||||F-J|FJ|||LJL-7L7|F7L-7LJF77FFJLJFJLJJL|...L7.
|
||||
.L7|LJF7J||F||F-J|F--7F7L-JL7L-JL-JF7F-J|F-JFJ|LJL7|L7FJF---JFJ|L7L-7L----7||LJ|FJ||FJ|||LJ||LJ|F7||FJ|L---7|FJ||L--JF-JL7FJF--J|FLJ-7.L7LF-
|
||||
J.-J7-|L-JL7||L-7|L-7LJ|F7..L--7F7FJ|L7FJ|F-JFJF7F||-|L7|F7F-J7L7|F7|F7F7FJ|L7FJL7||L7||L-7LJ|FJ||||L7L7F--J|L7|L----JF-7|L7L--7F-.L|.|F7L-7
|
||||
FJ.F-7L-7F7LJL--JL--JF7LJL7F7F7LJ|L7|FJ|FJL-7L-J|FJL7|FJ|||L---7|||LJ||||||L7|L7FJ||FJ||F-J7F-JFJ|||FJFJL--7L-J|F----7L7LJF|F--J7.L-7|-LJF7L
|
||||
FJF|-|7FJ||F-7F-7F--7|L-7FJ|LJL--JFJ|L7||F--JF7FJ|F7|LJ7LJL7F-7|LJ|F7||||L-7LJL|L7||L-J|L7F-JF7L7LJ|L7|F-7FJF7-|L---7L-JJLF|L-7J|F.FLJL--JFL
|
||||
-.F|7|FL7|LJFJL7||F-J|F-JL-JF-7F7FJ|L-JLJL-7FJ||7|||L---7F7||-LJF-J|||||L7FJ|F-JFJLJF--JFJL-7||FJLFJFJ||FJ|FJL7|F7F7L----7.L7FJ7|.FJ--77|7||
|
||||
J7.LFLJFLJ-|L7FJLJL-7|L-7F7FJFJ||L-7F---7F7|L7||FJ|L7F--J|LJL--7L--J||LJF||F7L-7L--7L-7FJ-F-J|||F-JFJFJ|L7LJF7||||||F----J-JLJJ7||J|F|7-FFJ.
|
||||
|.|-7-L7L|F-FJL7-F--JL7FJ|||FL7||F-JL--7LJLJFJ|||FJFJ|F7.|F-7F-JF---JL--7|||L--JF-7|F-J|F7|F7|||L-7L7L7|7L7FJLJ|||||L---7JLFJLF-7|L|LLJJJ|LL
|
||||
7-FFL-J|F.FL|F-JFJF--7||FJ||F-J||||F7F7L--7FJ|LJ|L7L7LJ|FJ|FJL-7L-7F7F7FJ||L---7L7||L-7LJ|LJLJLJF7|FJFJL7||L--7LJ||L--7FJLF7J7|J7|-7|.LJLLF.
|
||||
|.L-L7.|.FF-J|F-JFJJFJ|||FJ||F7|||FJLJL---JL--7FJFJFJF7|L7||F-7L-7||||LJLLJF7F-JFJ|L-7|F7L7F--7FJLJL7|F7L7|F--JF-JL--7||J7J|-F-7L-J|-7|7.FL-
|
||||
--|-JL|-F-L-7|L--JF7L-JLJL7|||||||L---7F7F7F--JL7|FL7|||FJ|||FJF7|LJ|L-7F7FJLJF7L7L-7||||FJL-7LJF-7FJ||L7||L-7L|F7F-7|LJJ|J|J.L|JJF|7F-|F7FJ
|
||||
..F7-F.L||.L||F7F7|L------J|||||||F---J|LJ|L-7F-JL7LLJLJL7|LJL7|||F-JF7|||L-7FJL7L-7||LJ|L-7FJF-JFJL7|L7|||F7L7LJ||7LJJJ77F.F|FJJL-|L|-J7|LJ
|
||||
F|L|.L|-LJ-|LJ|LJLJF7F-7F-7|||||LJL---7|F-JF-JL-7FJF7F--7LJF7FJ||||F-JLJ|L--JL77|F-JLJF-JF7|L7|F-JF-J|FJ||||L7L-7|L7|LL---J-L7LJ-FLLFL-..|F7
|
||||
LL7JFJL7.L--JFL-7F7|||FJ|FJ|||||F-----J||F7L--7FJL-JLJF7|LFJLJFJLJ||7F-7L-7F-7L7LJLF77L-7||L7LJL-7L-7|L7|||L7L7FJ|FJ77|FJ-JJLJ7J.LJ|.F|J7.FJ
|
||||
.LJ.|LFF-L.L|F|F||||LJL7|L-JLJ|||F----7||||F--J|F7F7F-JLJFJF-7L7LFJL-JFJF-JL7L7L---JL7F7LJL7|F---JF7||FJ||L7L7|L7LJ|JLJ-7FJ|7|F7.FF|J7JL7F|7
|
||||
F.F7-F.||LFF7.|L||||7F7|L-7F77||||F---J||||L-77|||||L-7FFJFJFJFJFJF7F7|FJF7FJFJF7F7F7LJL--7LJL7F7FJ|||L7|L7L7|L7L--7L|7L|.|F-LJ--7JFJLF7L-JJ
|
||||
L|7|J.FL7-L7J-|LLJ|L7|LJF-J|L-J|LJL---7|LJ|F7L7LJ|||F-JFJFJFL7L7L7|LJ||L7||L7L7|||||L--7F-JF--J|||FJ||FJL7|FJL7|F-7L7|FJ|7||||JJ|L7JJLLJJJF7
|
||||
F-.|7FF-||.-JFL7|FJFJL-7L-7L7F7L7F----J|.FJ|L7|F7LJ|L-7|FJJF7L7L7|L-7|L7|||FJ7||LJ|L--7|L7.L--7|||L-J|L-7||L7FJLJJ|FJ-L77F|FF||||J|.7.L|7|-|
|
||||
-JL|-||||F|F---F-JFJF--JF7|7|||FJL-----JFJFJJ|LJL-7|F-JLJF7||||FJL-7||FJ|||L-7||F-JF7FJL7|F---J||L--7|F-JLJJ|L-7--|||L-|---F-LJ-|FL7.|.--F.|
|
||||
F-.|7|JFF7-JLLF|F7|FL7F7|||FJ|LJ|F------JFJF-JF7F7|||F--7||||FJL--7|||||LJ|F-JLJL7FJ|L7-LJ|F-7FJ|F-7||L7JF--JF-JFFLJJLLLFJ-LJ.LFLF-J.L7JFJF7
|
||||
JFF|-LF|-FJ7.F-LJLJF-J|LJ|||FJJF-JF7F--7FJFJF7|LJLJLJ|F7LJLJLJF--7|||LJF7.|L---7FJL7L7L--7||FJ|FJL7|||FJFJF-7L--7-J|F-JL|7F|.LFJ.|L|-FJ||-7|
|
||||
|-JL--7.LJ|FF|.LLJFL7FJFFLJ|||-L-7|LJF-JL7|FJ|L----7|LJL7F7F-7L-7||||F7|L-JF7F-J|F-JFJF7FJ||L7|L-7|LJ||-|FJJ|F7FJJ|FJJ.F7F-J.|.LL7-J.7.FJ7LJ
|
||||
|L---J|7L-7LLF-J..FLLJLF-J.||7-L|LJ.SJF7FJLJFJF7F--JF---J|||FJF-J|||||LJF7FJLJF7LJFL|FJ||FJ|FJ|JFJL-7LJJ||7.||LJL7FF7.7FL7|J.F7-||FJ-LLJ.||.
|
||||
F-J-|FFL77FF7|L-7-|J-J-J|.FLJJ7LLLF7L-J||F7.L7|LJF-7L----J||L7L7LLJLJL7FJ||F--JL--7J|L7||L7|L7L7|F7FJF|.LJ7-LJ-|J|FJF-77L|LF.F-JF|J|F.|.J7F7
|
||||
|F|7.JJ|LJ|L-.F-J||.FL--7FLLJ||77L||F--JLJL-7||F7L7L------JL7L7L-7F---JL7|||F-7F-7L7|FJ||-LJJ|FJLJ|L-7J7.||.|.F|.F|L||.-.|L|JJLFL7FJJ||||.7|
|
||||
LJFJ77J|J-LJ.7J-LF-F7L--|J7LLJJJLFJLJF-7F7F7||LJL7L-7F-7F7F7L7|F-JL--7F7||LJL7|L7L-JLJLLJL|F7|L-7||F7|77J.L-LJ7--|J-JJF|7L-J.LFJ-|-.LLJLLJ77
|
||||
FLL-F-.LFFJJ.L77..|L--|7||LJ....|L---JFJ|LJ|||F7FJF-JL7LJ|||FJ|L-7F7FJ|||L7F-JL-JJLJ|LJ|JFFJLJF7|-LJLJJJ7..FL||-7|L.L7FLJLL77-L7.-.F--|7.LF|
|
||||
F|LFJ.7J|.7.FF-L7FLJJ7|.LF7.77FFF----7L7L7FJ|LJ|||L7F7|F-J|||FJF7||LJFJLJ-|L---7-F-7|-F---L--7|LJJL|7L77FFJ7.J--LL7.FL7.F|-F-.|FFJ.|JJF|--J|
|
||||
||-|-7-7777|-7-FLLJ|.J.F7|J-.L--L-7F7L7|FJL7|F-JL7FJ|||L7FJLJL7|LJL7FJ7LF-JF--7L-7J7J|.FJ|.JL|L77FFL-.-F-J-|-7||LLF7.F--77.|.FJ|.||||7L-7JJ|
|
||||
LL-7-.LLJL-JFJJL||JL77F|J-7|.7.|||LJL7LJL7LLJL-7FJL-J|L7||7-F-JL-7FJ|F--JF7L7-L7FJ.|7|FL-7.|-L-JJFL7L7|LJ|-|.-L|7J|L--JFJ7--F7.J-||LF-LL-J||
|
||||
FL7J---JL-L--.F.L77L--FLJ|-7-J7LF----JF-7L-7F7JLJJ7|.L7|LJ-FJF7F-JL-J|F7FJL7|JLLJFFJLL7-|J.L-7.L-|.|7.|7-|.L7LL|JFL7FL-7-J.FLJ-|FJ||L7LFJ.F-
|
||||
F.J.||7L|..-|--JL|F--FL7FL.F.LF-L---7FJFJF7LJ|J-FL|--LLJ.JJL-J||-LJ.LLJ|L7FJL7..J-L-|-J7|F-LL|-7FLF--.F7JL-.-J.L-|LFLFJJ|LF-FJ--L7L-L|-J7F7|
|
||||
|F|FLF|F--F--J.J7||7--7|7..-.FJ.|J.||L7|FJL7FJJFFJL-7J.J-7L||F|L7FFLJ.LL7|L7FJJ7LLL7|||L.L.F||7-LFJ.LFJ-77LJJF77.LF-JF-J-FJ-LJ.|F|LF-L.LLF7J
|
||||
J-FJ.-JL|J.-L--JFJL-FJ-L|J--|LL-7.-LL-JLJ-LLJJ-L7-L7J--J-7.7--L-J-JL|-LLLJLLJ-LJ.L-LJ--..L-|-JJ-L|---|7JFL-L--J|-F-J-|-JJFJ-LJ-LL7-7LJ-7L-JJ
|
311
10/src/main.rs
Normal file
311
10/src/main.rs
Normal file
@ -0,0 +1,311 @@
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Problem 1 solution: {}", problem1(get_input()));
|
||||
println!("Problem 2 solution: {}", problem2(get_input()));
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MapCell {
|
||||
dist: u64,
|
||||
kind: char,
|
||||
inside: bool,
|
||||
}
|
||||
|
||||
impl From<char> for MapCell {
|
||||
fn from(c: char) -> Self {
|
||||
MapCell {
|
||||
dist: 0,
|
||||
kind: c,
|
||||
inside: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PipeMap {
|
||||
map: Vec<Vec<MapCell>>,
|
||||
start: (usize, usize),
|
||||
}
|
||||
|
||||
const ALL_ADJ: [(isize, isize); 8] = [
|
||||
(-1, -1),
|
||||
(0, -1),
|
||||
(1, -1),
|
||||
(-1, 0),
|
||||
(1, 0),
|
||||
(-1, 1),
|
||||
(0, 1),
|
||||
(1, 1),
|
||||
];
|
||||
|
||||
impl PipeMap {
|
||||
fn adjacencies(c: char) -> Option<[(isize, isize); 2]> {
|
||||
match c {
|
||||
'|' => Some([(0, -1), (0, 1)]),
|
||||
'-' => Some([(-1, 0), (1, 0)]),
|
||||
'L' => Some([(0, -1), (1, 0)]),
|
||||
'J' => Some([(0, -1), (-1, 0)]),
|
||||
'7' => Some([(0, 1), (-1, 0)]),
|
||||
'F' => Some([(0, 1), (1, 0)]),
|
||||
'.' => None,
|
||||
'S' => None,
|
||||
_ => panic!("unhandled type"),
|
||||
}
|
||||
}
|
||||
fn valid_pos(&self, pos: (isize, isize)) -> bool {
|
||||
pos.0 >= 0
|
||||
&& pos.0 < self.map[0].len() as isize
|
||||
&& pos.1 >= 0
|
||||
&& pos.1 < self.map.len() as isize
|
||||
}
|
||||
|
||||
fn apply_adj(&self, pos: (usize, usize), adj: (isize, isize)) -> Option<(usize, usize)> {
|
||||
if self.valid_pos((pos.0 as isize + adj.0, pos.1 as isize + adj.1)) {
|
||||
Some((
|
||||
(pos.0 as isize + adj.0) as usize,
|
||||
(pos.1 as isize + adj.1) as usize,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn adjacent_positions(&self, pos: (usize, usize)) -> Option<[(usize, usize); 2]> {
|
||||
let adj = Self::adjacencies(self.map[pos.1][pos.0].kind);
|
||||
if let Some(adj) = adj {
|
||||
let mut positions = adj.iter().filter_map(|adj| self.apply_adj(pos, *adj));
|
||||
Some([positions.next().unwrap(), positions.next().unwrap()])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn start_adjacencies(&self) -> [(usize, usize); 2] {
|
||||
let mut adj_positions = Vec::new();
|
||||
for neighbour in ALL_ADJ
|
||||
.iter()
|
||||
.filter_map(|adj| self.apply_adj(self.start, *adj))
|
||||
{
|
||||
if let Some(neigh_adjs) = self.adjacent_positions(neighbour) {
|
||||
if neigh_adjs.contains(&self.start) {
|
||||
adj_positions.push(neighbour)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[adj_positions[0], adj_positions[1]]
|
||||
}
|
||||
|
||||
fn mark_inside(&mut self) {
|
||||
let start_adj = self.start_adjacencies();
|
||||
|
||||
let start_kind = if start_adj.contains(
|
||||
&self
|
||||
.apply_adj(self.start, (0, -1))
|
||||
.unwrap_or((99999, 99999)),
|
||||
) && start_adj
|
||||
.contains(&self.apply_adj(self.start, (0, 1)).unwrap_or((99999, 99999)))
|
||||
{
|
||||
'|'
|
||||
} else if start_adj.contains(
|
||||
&self
|
||||
.apply_adj(self.start, (-1, 0))
|
||||
.unwrap_or((99999, 99999)),
|
||||
) && start_adj
|
||||
.contains(&self.apply_adj(self.start, (1, 0)).unwrap_or((99999, 99999)))
|
||||
{
|
||||
'-'
|
||||
} else if start_adj.contains(
|
||||
&self
|
||||
.apply_adj(self.start, (0, -1))
|
||||
.unwrap_or((99999, 99999)),
|
||||
) && start_adj
|
||||
.contains(&self.apply_adj(self.start, (1, 0)).unwrap_or((99999, 99999)))
|
||||
{
|
||||
'L'
|
||||
} else if start_adj.contains(
|
||||
&self
|
||||
.apply_adj(self.start, (0, -1))
|
||||
.unwrap_or((99999, 99999)),
|
||||
) && start_adj.contains(
|
||||
&self
|
||||
.apply_adj(self.start, (-1, 0))
|
||||
.unwrap_or((99999, 99999)),
|
||||
) {
|
||||
'J'
|
||||
} else if start_adj.contains(&self.apply_adj(self.start, (0, 1)).unwrap_or((99999, 99999)))
|
||||
&& start_adj.contains(
|
||||
&self
|
||||
.apply_adj(self.start, (-1, 0))
|
||||
.unwrap_or((99999, 99999)),
|
||||
)
|
||||
{
|
||||
'7'
|
||||
} else if start_adj.contains(&self.apply_adj(self.start, (0, 1)).unwrap_or((99999, 99999)))
|
||||
&& start_adj.contains(&self.apply_adj(self.start, (1, 0)).unwrap_or((99999, 99999)))
|
||||
{
|
||||
'F'
|
||||
} else {
|
||||
panic!("invalid start");
|
||||
};
|
||||
|
||||
for row in &mut self.map {
|
||||
let mut inside = false;
|
||||
for cell in row {
|
||||
let mut kind = cell.kind;
|
||||
if cell.dist == 0 && kind != 'S' {
|
||||
cell.inside = inside;
|
||||
} else {
|
||||
if kind == 'S' {
|
||||
kind = start_kind;
|
||||
}
|
||||
if kind == '|' || kind == 'L' || kind == 'J' {
|
||||
inside = !inside;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for PipeMap {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
let mut map: Vec<Vec<MapCell>> = Vec::new();
|
||||
for line in lines {
|
||||
map.push(line.unwrap().chars().map(MapCell::from).collect());
|
||||
}
|
||||
|
||||
let start = map
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, row)| (row.iter().position(|p| p.kind == 'S'), idx))
|
||||
.find(|(x, _)| x.is_some())
|
||||
.unwrap();
|
||||
let start = (start.0.unwrap(), start.1);
|
||||
|
||||
let mut pipemap = PipeMap { map, start };
|
||||
|
||||
let mut cur_positions = pipemap.start_adjacencies();
|
||||
let mut cur_distance = 1;
|
||||
loop {
|
||||
for pos in cur_positions {
|
||||
pipemap.map[pos.1][pos.0].dist = cur_distance;
|
||||
}
|
||||
cur_distance += 1;
|
||||
|
||||
if let Some(new_pos1) = pipemap.adjacent_positions(cur_positions[0]) {
|
||||
if let Some(new_pos1) = new_pos1.iter().find(|pos| {
|
||||
pipemap.map[pos.1][pos.0].dist == 0 && pipemap.map[pos.1][pos.0].kind != 'S'
|
||||
}) {
|
||||
cur_positions[0] = *new_pos1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(new_pos2) = pipemap.adjacent_positions(cur_positions[1]) {
|
||||
if let Some(new_pos2) = new_pos2.iter().find(|pos| {
|
||||
pipemap.map[pos.1][pos.0].dist == 0 && pipemap.map[pos.1][pos.0].kind != 'S'
|
||||
}) {
|
||||
cur_positions[1] = *new_pos2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if cur_positions[0] == cur_positions[1] {
|
||||
pipemap.map[cur_positions[0].1][cur_positions[0].0].dist = cur_distance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pipemap
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let map = PipeMap::from(input);
|
||||
|
||||
map.map
|
||||
.iter()
|
||||
.map(|row| row.iter().map(|cell| cell.dist).max().unwrap())
|
||||
.max()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut map = PipeMap::from(input);
|
||||
map.mark_inside();
|
||||
|
||||
for row in &map.map {
|
||||
for cell in row {
|
||||
print!("{}", cell.kind);
|
||||
}
|
||||
print!(" ");
|
||||
for cell in row {
|
||||
print!(
|
||||
"{}",
|
||||
match cell.inside {
|
||||
true => 'I',
|
||||
false => 'O',
|
||||
}
|
||||
);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
map.map
|
||||
.iter()
|
||||
.map(|row| row.iter().filter(|cell| cell.inside).count())
|
||||
.sum::<usize>() as u64
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"..F7.
|
||||
.FJ|.
|
||||
SJ.L7
|
||||
|F--J
|
||||
LJ...";
|
||||
|
||||
const EXAMPLE2: &str = &"FF7FSF7F7F7F7F7F---7
|
||||
L|LJ||||||||||||F--J
|
||||
FL-7LJLJ||||||LJL-77
|
||||
F--JF--7||LJLJ7F7FJ-
|
||||
L---JF-JLJ.||-FJLJJ7
|
||||
|F|F-JF---7F7-L7L|7|
|
||||
|FFJF7L7F-JF7|JL---7
|
||||
7-L-JL7||F7|L7F-7F7|
|
||||
L.L7LFJ|||||FJL7||LJ
|
||||
L7JLJL-JLJLJL--JLJ.L";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE2);
|
||||
assert_eq!(problem2(c.lines()), 10);
|
||||
}
|
||||
}
|
7
11/Cargo.lock
generated
Normal file
7
11/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day11"
|
||||
version = "0.1.0"
|
8
11/Cargo.toml
Normal file
8
11/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day11"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
140
11/input
Normal file
140
11/input
Normal file
@ -0,0 +1,140 @@
|
||||
............#..................#..........................................................#..........................#......................
|
||||
.................................................................#...............#..............#...............#......................#....
|
||||
...................................#.....................#..................#............................#...................#..............
|
||||
#.....................#.....................#...............................................................................................
|
||||
........................................................................................#............#......................................
|
||||
.....#..............................................#.......................................................................................
|
||||
.......................................#................................#..........#...........#......................................#.....
|
||||
..................#...........#.............................................................................................................
|
||||
.............................................#............#.................................................................................
|
||||
.#............................................................................#..................................#..........................
|
||||
............#......................#....................................................................#...................#.............#.
|
||||
.......#............#....................#........#...................................#......................#..............................
|
||||
...................................................................#................................#.......................................
|
||||
..............................#.................................................................................................#...........
|
||||
..#...........................................................................................#.......................#.....................
|
||||
..............................................................................#.............................................................
|
||||
.......................................#.........#............#...........................#................#..............................#.
|
||||
........................................................#.............#.....................................................................
|
||||
.....#..........................#....................................................................#....................#.................
|
||||
....................#.......................#...................................#...............#...............#......................#....
|
||||
...............#..................................................................................................................#.........
|
||||
..#......................................................................#...................................................#..............
|
||||
.................................................#............#.........................................#.............#.....................
|
||||
....................................#.......................................................................................................
|
||||
...........#..........................................................................#.....................................................
|
||||
.................#..........................................................................................................................
|
||||
.............................................#............................#....................................................#............
|
||||
.........................#.......#..........................#...............................................................................
|
||||
.......#............#....................................................................................................#..........#.......
|
||||
...................................................................#................#...........................#...........................
|
||||
..............#....................................#..........................#..............#..............................................
|
||||
..#....................#....................................................................................#........#......................
|
||||
.........................................................................#......................................................#...........
|
||||
......................................#.........#...........................................................................................
|
||||
..........#.................................................................................................................................
|
||||
.....................#......................#...............#.................................................#.............................
|
||||
...............................#...................................................#....................................#.................#.
|
||||
.............................................................................................#..............................................
|
||||
...................................................................#........................................................................
|
||||
................#..........#.....................#..................................................................................#.......
|
||||
...................................#............................................#..................#........................................
|
||||
.....#.....................................................................#...............................#.....#..........................
|
||||
............#.........................................................................................................#.....................
|
||||
.....................#.............................#.......................................................................#................
|
||||
..............................................................#...............................#..........................................#..
|
||||
.....................................#.......#.................................................................#............................
|
||||
...............#...................................................................#.....#..............................#...................
|
||||
...#.....................#.........................................#......#...........................#.....................................
|
||||
.........#......................................................................................#.............................#.............
|
||||
..........................................................#.................................................................................
|
||||
..................................#.......#...........................................#......................#......................#.......
|
||||
.............................................................................#..............................................................
|
||||
.....#...........................................#..................................................#....................#..................
|
||||
............................................................................................................................................
|
||||
............................................................................................................................................
|
||||
.................#...................#........................#......#..................................#...................................
|
||||
..........................#.........................#.....................................#......#.........................#................
|
||||
..............................................#...........................#.....................................#...........................
|
||||
#.....................#.................#............................................................................................#......
|
||||
...............................#..........................#.....................................................................#...........
|
||||
..........#.........................#.............................#...........#....................................#........................
|
||||
.....................................................#......................................................................................
|
||||
.............................................................................................#..............................................
|
||||
............................................................................................................................................
|
||||
...............#...........#..........#.....#..................#.......................#......................#.......#..............#......
|
||||
........#...........#.............................#.....#...................................................................................
|
||||
............................................................................................................................................
|
||||
.#................................#.............................................#................................................#..........
|
||||
............................................................................................................................................
|
||||
..........................................................................#...............................................................#.
|
||||
..............................#...............#......................................#........#.............#.........#.....................
|
||||
...#................................................#.......................................................................................
|
||||
............................................................................................................................................
|
||||
.......................#...............#...........................................................#..........................#.............
|
||||
.................................................#...........#......................................................#.......................
|
||||
...........#............................................................................#...................................................
|
||||
.....#..................................................#.....................................#.............#..............................#
|
||||
..................#..........#..............................................#..........................#..............................#.....
|
||||
....................................................#.......................................................................................
|
||||
..#............................................................................................................#................#...........
|
||||
.............................................................#........#..........#.....#....................................................
|
||||
...........#..........#............#.......#...............................................................................#................
|
||||
............................................................................................................................................
|
||||
......................................................#..............................................#......................................
|
||||
.........................#.....#...............................................#................................#................#..........
|
||||
...#.......................................................................................................#...........................#....
|
||||
........#...........................#....................................#...............#..................................................
|
||||
..........................................#.......................#.........................................................................
|
||||
............................................................#.............................................................#.................
|
||||
...........................#...................................................................#.....................#......................
|
||||
...............#.................#............#.............................................................................................
|
||||
...#......#..........................................#..................................#...............#...................................
|
||||
.................................................................#......................................................................#...
|
||||
.......................#..................#...............#..................#..............................................................
|
||||
.................................................#...................................#.............#............................#...........
|
||||
................#...........................................................................................................................
|
||||
...................................#.........................................................#........................#.............#.......
|
||||
.............................................................#..........................#......................#............#..............#
|
||||
...#..................#.............................#..........................#............................................................
|
||||
........#......................................#............................................................................................
|
||||
..............#............#...........#............................................................#.......................................
|
||||
....................................................................#.......................#...............................................
|
||||
.#....................................................................................#........................................#.......#....
|
||||
...........#...................#............................................................................................................
|
||||
.........................#..........#.......#.........#..................#..................................#...............................
|
||||
................................................................#....................................................#......................
|
||||
...#.............................................................................................#.....#....................................
|
||||
.................................................#....................#.....................................................................
|
||||
.......................#.........#..................................................#.......#...................#........#..................
|
||||
........................................................................................................................................#...
|
||||
...........#................................................#..............................................#................................
|
||||
.....................................#..........................................................#...........................................
|
||||
....#.......................................#....................................................................................#..........
|
||||
...................#..............................................#.........#..........#.............#......................................
|
||||
............................................................................................................................................
|
||||
............................................................................................................................................
|
||||
.............#.......................................#...............#......................#......................#...............#........
|
||||
...............................................#............................................................................................
|
||||
....#.................................#.......................................................................................#.............
|
||||
............................#.................................................#......#.....................................................#
|
||||
...................#..............#.......#...............#.....................................................#.........#.................
|
||||
..................................................................#.....................................#...................................
|
||||
...................................................#..............................#......#.......#..............................#...........
|
||||
.......................................#.....................#..............#......................................#........................
|
||||
.................#..........................................................................................................................
|
||||
..............................................#.......#.................#.................................#.................................
|
||||
.........#...............#.............................................................#.................................#.............#....
|
||||
..#..............................#..................................#.......................................................................
|
||||
...............................................................#...........#.......................................................#........
|
||||
............................................................................................................................#...............
|
||||
................#...........#............#.........#........................................................................................
|
||||
........#.............#........................................................................................#...........................#
|
||||
..........................................................#...............................#..............#...........................#......
|
||||
...............................#................................................................#...........................................
|
||||
..................#.............................................#.........#..........................................#......................
|
||||
.....#................................................#.........................................................................#...........
|
||||
............................................#.....................................#.........#...............................................
|
||||
.......................................................................................................................................#....
|
||||
#..........#.............#......#.................................#...................................#.....................................
|
||||
.....................................#.........#.........................#.....#............................................................
|
211
11/src/main.rs
Normal file
211
11/src/main.rs
Normal file
@ -0,0 +1,211 @@
|
||||
use std::fmt::{Display, Write};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::iter::repeat;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Problem 1 solution: {}", problem1(get_input()));
|
||||
println!("Problem 2 solution: {}", problem2(get_input()));
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
struct GalaxyMap {
|
||||
map: Vec<Vec<char>>,
|
||||
galaxy_positions: Vec<(usize, usize)>,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for GalaxyMap {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
let map = GalaxyMap {
|
||||
map: lines.map(|line| line.unwrap().chars().collect()).collect(),
|
||||
galaxy_positions: Vec::new(),
|
||||
};
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
impl GalaxyMap {
|
||||
fn universe_expansion(&mut self) {
|
||||
let mut columns_to_insert = Vec::new();
|
||||
|
||||
for col in 0..self.map[0].len() {
|
||||
if self.map.iter().map(|row| row[col]).all(|c| c != '#') {
|
||||
columns_to_insert.push(col);
|
||||
}
|
||||
}
|
||||
|
||||
for row in &mut self.map {
|
||||
let mut offset = 0;
|
||||
for col in &columns_to_insert {
|
||||
row.insert(*col + offset, '.');
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let rows_to_insert: Vec<_> = self
|
||||
.map
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(idx, row)| if !row.contains(&'#') { Some(idx) } else { None })
|
||||
.collect();
|
||||
let gen_row: Vec<_> = repeat('.').take(self.map[0].len()).collect();
|
||||
let mut offset = 0;
|
||||
for idx in rows_to_insert {
|
||||
self.map.insert(idx + offset, gen_row.clone());
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
fn universe_expansion2(&mut self) {
|
||||
let mut columns_to_grow = Vec::new();
|
||||
|
||||
for col in 0..self.map[0].len() {
|
||||
if self.map.iter().map(|row| row[col]).all(|c| c != '#') {
|
||||
columns_to_grow.push(col);
|
||||
}
|
||||
}
|
||||
|
||||
for row in &mut self.map {
|
||||
for col in &columns_to_grow {
|
||||
row[*col] = 'x';
|
||||
}
|
||||
}
|
||||
|
||||
let rows_to_grow: Vec<_> = self
|
||||
.map
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(idx, row)| if !row.contains(&'#') { Some(idx) } else { None })
|
||||
.collect();
|
||||
let gen_row: Vec<_> = repeat('x').take(self.map[0].len()).collect();
|
||||
for idx in rows_to_grow {
|
||||
self.map[idx] = gen_row.clone();
|
||||
}
|
||||
}
|
||||
fn find_galaxies(&mut self) {
|
||||
for (y, row) in self.map.iter().enumerate() {
|
||||
for (x, _c) in row.iter().enumerate().filter(|(_x, c)| **c == '#') {
|
||||
self.galaxy_positions.push((x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn galaxy_distance(&self, a: usize, b: usize) -> u64 {
|
||||
let (a_x, a_y) = self.galaxy_positions[a];
|
||||
let (b_x, b_y) = self.galaxy_positions[b];
|
||||
|
||||
let x_dist = b_x.abs_diff(a_x);
|
||||
let y_dist = b_y.abs_diff(a_y);
|
||||
|
||||
x_dist as u64 + y_dist as u64
|
||||
}
|
||||
fn galaxy_distance2(&self, a: usize, b: usize) -> u64 {
|
||||
let (a_x, a_y) = self.galaxy_positions[a];
|
||||
let (b_x, b_y) = self.galaxy_positions[b];
|
||||
let x_dist = b_x.abs_diff(a_x);
|
||||
let y_dist = b_y.abs_diff(a_y);
|
||||
|
||||
let mut dist = x_dist as u64 + y_dist as u64;
|
||||
|
||||
for row in a_y.min(b_y)..a_y.max(b_y) {
|
||||
if self.map[row].iter().all(|c| *c == 'x') {
|
||||
dist += 1000000 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
for col in a_x.min(b_x)..a_x.max(b_x) {
|
||||
if self.map.iter().all(|row| row[col] == 'x') {
|
||||
dist += 1000000 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
dist
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for GalaxyMap {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for row in &self.map {
|
||||
for c in row {
|
||||
f.write_char(*c)?;
|
||||
}
|
||||
f.write_char('\n')?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut map = GalaxyMap::from(input);
|
||||
map.universe_expansion();
|
||||
map.find_galaxies();
|
||||
println!("{}", map);
|
||||
|
||||
let mut galaxies: Vec<_> = (0..map.galaxy_positions.len()).collect();
|
||||
let mut sum = 0u64;
|
||||
while let Some(target) = galaxies.pop() {
|
||||
sum += galaxies
|
||||
.iter()
|
||||
.map(|source| map.galaxy_distance(*source, target))
|
||||
.sum::<u64>();
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut map = GalaxyMap::from(input);
|
||||
map.universe_expansion2();
|
||||
map.find_galaxies();
|
||||
println!("{}", map);
|
||||
|
||||
let mut galaxies: Vec<_> = (0..map.galaxy_positions.len()).collect();
|
||||
let mut sum = 0u64;
|
||||
while let Some(target) = galaxies.pop() {
|
||||
sum += galaxies
|
||||
.iter()
|
||||
.map(|source| map.galaxy_distance2(*source, target))
|
||||
.sum::<u64>();
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"...#......
|
||||
.......#..
|
||||
#.........
|
||||
..........
|
||||
......#...
|
||||
.#........
|
||||
.........#
|
||||
..........
|
||||
.......#..
|
||||
#...#.....";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 374);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 0);
|
||||
}
|
||||
}
|
106
12/Cargo.lock
generated
Normal file
106
12/Cargo.lock
generated
Normal file
@ -0,0 +1,106 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day12"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
8
12/Cargo.toml
Normal file
8
12/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day12"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.12.0"
|
||||
rayon = "1.8.0"
|
219
12/src/main.rs
Normal file
219
12/src/main.rs
Normal file
@ -0,0 +1,219 @@
|
||||
use itertools::Itertools;
|
||||
use rayon::prelude::*;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SpringRow<'a> {
|
||||
springs: Vec<char>,
|
||||
spans: Vec<usize>,
|
||||
cache: RefCell<HashMap<(usize, &'a [usize], usize), u64>>,
|
||||
}
|
||||
|
||||
impl<'a> From<&str> for SpringRow<'a> {
|
||||
fn from(s: &str) -> Self {
|
||||
let (springs_s, spans_s) = s.split_once(' ').unwrap();
|
||||
SpringRow {
|
||||
springs: springs_s.chars().collect(),
|
||||
spans: spans_s.split(',').map(|x| x.parse().unwrap()).collect(),
|
||||
cache: RefCell::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SpringRow<'a> {
|
||||
fn possible_arrangements(&self) -> u64 {
|
||||
let mut permutations = vec![self.springs.clone()];
|
||||
while let Some(cur) = permutations.iter().position(|perm| perm.contains(&'?')) {
|
||||
let perm = permutations.remove(cur);
|
||||
let rep_pos = perm.iter().position(|c| *c == '?').unwrap();
|
||||
|
||||
let mut new_elem = perm.clone();
|
||||
|
||||
new_elem[rep_pos] = '.';
|
||||
permutations.push(new_elem.clone());
|
||||
new_elem[rep_pos] = '#';
|
||||
permutations.push(new_elem);
|
||||
}
|
||||
|
||||
permutations
|
||||
.iter()
|
||||
.filter_map(|perm| {
|
||||
let groups: Vec<usize> = perm
|
||||
.iter()
|
||||
.group_by(|c| **c == '#')
|
||||
.into_iter()
|
||||
.filter_map(|(key, group)| if key { Some(group.count()) } else { None })
|
||||
.collect();
|
||||
if groups == self.spans {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.count() as u64
|
||||
}
|
||||
fn memoize_arrangements_r(
|
||||
&self,
|
||||
idx: usize,
|
||||
spans_left: &'a [usize],
|
||||
cur_span_left: usize,
|
||||
) -> u64 {
|
||||
if let Some(value) = self.cache.borrow().get(&(idx, spans_left, cur_span_left)) {
|
||||
return *value;
|
||||
}
|
||||
let result = self.possible_arrangements_r(idx, spans_left, cur_span_left);
|
||||
self.cache
|
||||
.borrow_mut()
|
||||
.insert((idx, spans_left, cur_span_left), result);
|
||||
result
|
||||
}
|
||||
fn possible_arrangements_r(
|
||||
&self,
|
||||
idx: usize,
|
||||
spans_left: &'a [usize],
|
||||
cur_span_left: usize,
|
||||
) -> u64 {
|
||||
if cur_span_left == 0 && spans_left.len() == 1 {
|
||||
// everything is consumed. if we're at the end, we good
|
||||
// if we have stuff left, as long as it doesn't contain a fixed broken spring we good
|
||||
if idx == self.springs.len() || !self.springs[idx..].contains(&'#') {
|
||||
// println!("{:?} valid", self.springs);
|
||||
return 1;
|
||||
}
|
||||
// something invalid
|
||||
return 0;
|
||||
}
|
||||
if idx >= self.springs.len() {
|
||||
// reached the end of the string without consuming all our spans
|
||||
// println!(
|
||||
// "{:?} invalid idx: {} spans_left: {:?}",
|
||||
// self.springs, idx, spans_left
|
||||
// );
|
||||
return 0;
|
||||
}
|
||||
// println!(
|
||||
// "call idx: {} str: {:?} spans_left: {:?} cur_span_left: {}",
|
||||
// idx,
|
||||
// &self.springs[idx..],
|
||||
// spans_left,
|
||||
// cur_span_left
|
||||
// );
|
||||
return if cur_span_left == 0 {
|
||||
match self.springs[idx] {
|
||||
'#' => 0, // a broken spring after we have completed our span is invalid
|
||||
// a space or a ? (becomes a space) starts a new span
|
||||
'.' | '?' => self.memoize_arrangements_r(idx + 1, &spans_left[1..], spans_left[1]),
|
||||
_ => panic!("invalid spring"),
|
||||
}
|
||||
} else {
|
||||
// we are mid span
|
||||
match self.springs[idx] {
|
||||
// cur_span_left != 0, so we still have work to do with broken springs
|
||||
'#' => self.memoize_arrangements_r(idx + 1, spans_left, cur_span_left - 1),
|
||||
'.' => {
|
||||
if spans_left[0] == cur_span_left {
|
||||
self.memoize_arrangements_r(idx + 1, spans_left, cur_span_left)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
'?' => {
|
||||
if spans_left[0] == cur_span_left {
|
||||
self.memoize_arrangements_r(idx + 1, spans_left, cur_span_left - 1)
|
||||
+ self.memoize_arrangements_r(idx + 1, spans_left, cur_span_left)
|
||||
} else {
|
||||
self.memoize_arrangements_r(idx + 1, spans_left, cur_span_left - 1)
|
||||
}
|
||||
}
|
||||
_ => panic!("invalid spring"),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let rows: Vec<SpringRow> = input
|
||||
.map(|row| SpringRow::from(row.unwrap().as_str()))
|
||||
.collect();
|
||||
|
||||
rows.iter()
|
||||
.map(|row| row.possible_arrangements_r(0, &row.spans, row.spans[0]))
|
||||
.sum()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut rows: Vec<SpringRow> = input
|
||||
.map(|row| SpringRow::from(row.unwrap().as_str()))
|
||||
.collect();
|
||||
|
||||
for row in &mut rows {
|
||||
let orig_slice = &row.springs.clone();
|
||||
for _i in 0..4 {
|
||||
row.springs.push('?');
|
||||
row.springs.extend_from_slice(orig_slice);
|
||||
}
|
||||
|
||||
let orig_span_slice = &row.spans.clone();
|
||||
for _i in 0..4 {
|
||||
row.spans.extend_from_slice(orig_span_slice);
|
||||
}
|
||||
}
|
||||
rows.iter()
|
||||
.map(|row| row.possible_arrangements_r(0, &row.spans, row.spans[0]))
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"???.### 1,1,3
|
||||
.??..??...?##. 1,1,3
|
||||
?#?#?#?#?#?#?#? 1,3,1,6
|
||||
????.#...#... 4,1,1
|
||||
????.######..#####. 1,6,5
|
||||
?###???????? 3,2,1";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 21);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 525152);
|
||||
}
|
||||
}
|
7
13/Cargo.lock
generated
Normal file
7
13/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day13"
|
||||
version = "0.1.0"
|
8
13/Cargo.toml
Normal file
8
13/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day13"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
227
13/src/main.rs
Normal file
227
13/src/main.rs
Normal file
@ -0,0 +1,227 @@
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::ops::Index;
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Pattern {
|
||||
mirrors: Vec<Vec<char>>,
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
fn width(&self) -> usize {
|
||||
self.mirrors[0].len()
|
||||
}
|
||||
fn height(&self) -> usize {
|
||||
self.mirrors.len()
|
||||
}
|
||||
fn col(&self, idx: usize) -> Vec<char> {
|
||||
self.mirrors.iter().map(|row| row[idx]).collect()
|
||||
}
|
||||
|
||||
fn find_horizontal_reflection(&self) -> Option<usize> {
|
||||
(1..self.height()).find(|idx| self.is_horizontal_reflection(*idx))
|
||||
}
|
||||
|
||||
fn is_horizontal_reflection(&self, idx: usize) -> bool {
|
||||
let row_pairs = std::cmp::min(idx, self.height() - idx);
|
||||
(0..row_pairs).all(|offset| self.mirrors[idx - offset - 1] == self.mirrors[idx + offset])
|
||||
}
|
||||
|
||||
fn find_vertical_reflection(&self) -> Option<usize> {
|
||||
(1..self.width()).find(|idx| self.is_vertical_reflection(*idx))
|
||||
}
|
||||
|
||||
fn is_vertical_reflection(&self, idx: usize) -> bool {
|
||||
let col_pairs = std::cmp::min(idx, self.width() - idx);
|
||||
(0..col_pairs).all(|offset| self.col(idx - offset - 1) == self.col(idx + offset))
|
||||
}
|
||||
|
||||
fn find_smudged_horizontal_reflection(&self) -> Option<usize> {
|
||||
(1..self.height()).find(|idx| self.is_smudged_horizontal_reflection(*idx))
|
||||
}
|
||||
|
||||
fn is_smudged_horizontal_reflection(&self, idx: usize) -> bool {
|
||||
// Same algorithm for problem 2, but count errors breaking reflection.
|
||||
// If the count == 1 after all checks, then it is our smudge
|
||||
let row_pairs = std::cmp::min(idx, self.height() - idx);
|
||||
(0..row_pairs)
|
||||
.map(|offset| {
|
||||
self.mirrors[idx - offset - 1]
|
||||
.iter()
|
||||
.zip(self.mirrors[idx + offset].iter())
|
||||
.filter(|(a, b)| **a != **b)
|
||||
.count()
|
||||
})
|
||||
.sum::<usize>()
|
||||
== 1
|
||||
}
|
||||
|
||||
fn find_smudged_vertical_reflection(&self) -> Option<usize> {
|
||||
(1..self.width()).find(|idx| self.is_smudged_vertical_reflection(*idx))
|
||||
}
|
||||
|
||||
fn is_smudged_vertical_reflection(&self, idx: usize) -> bool {
|
||||
let col_pairs = std::cmp::min(idx, self.width() - idx);
|
||||
(0..col_pairs)
|
||||
.map(|offset| {
|
||||
self.col(idx - offset - 1)
|
||||
.iter()
|
||||
.zip(self.col(idx + offset).iter())
|
||||
.filter(|(a, b)| **a != **b)
|
||||
.count()
|
||||
})
|
||||
.sum::<usize>()
|
||||
== 1
|
||||
}
|
||||
|
||||
fn reflection_cost(&self) -> u64 {
|
||||
if let Some(refl) = self.find_horizontal_reflection() {
|
||||
100 * refl as u64
|
||||
} else if let Some(refl) = self.find_vertical_reflection() {
|
||||
refl as u64
|
||||
} else {
|
||||
panic!("no reflection");
|
||||
}
|
||||
}
|
||||
|
||||
fn smudged_reflection_cost(&self) -> u64 {
|
||||
if let Some(refl) = self.find_smudged_horizontal_reflection() {
|
||||
100 * refl as u64
|
||||
} else if let Some(refl) = self.find_smudged_vertical_reflection() {
|
||||
refl as u64
|
||||
} else {
|
||||
panic!("no reflection");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Patterns {
|
||||
patterns: Vec<Pattern>,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Patterns {
|
||||
fn from(mut lines: Lines<T>) -> Self {
|
||||
let mut patterns = Vec::new();
|
||||
let mut cur_lines = Vec::new();
|
||||
while let Some(Ok(line)) = lines.next() {
|
||||
if line.len() == 0 {
|
||||
patterns.push(Pattern { mirrors: cur_lines });
|
||||
cur_lines = Vec::new();
|
||||
} else {
|
||||
cur_lines.push(line.chars().collect());
|
||||
}
|
||||
}
|
||||
patterns.push(Pattern { mirrors: cur_lines });
|
||||
Self { patterns }
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let patterns = Patterns::from(input);
|
||||
|
||||
patterns
|
||||
.patterns
|
||||
.iter()
|
||||
.map(|pat| pat.reflection_cost())
|
||||
.sum()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let patterns = Patterns::from(input);
|
||||
|
||||
patterns
|
||||
.patterns
|
||||
.iter()
|
||||
.map(|pat| pat.smudged_reflection_cost())
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"#.##..##.
|
||||
..#.##.#.
|
||||
##......#
|
||||
##......#
|
||||
..#.##.#.
|
||||
..##..##.
|
||||
#.#.##.#.
|
||||
|
||||
#...##..#
|
||||
#....#..#
|
||||
..##..###
|
||||
#####.##.
|
||||
#####.##.
|
||||
..##..###
|
||||
#....#..#";
|
||||
|
||||
#[test]
|
||||
fn problem1_find_horizontal() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
let patterns = Patterns::from(c.lines());
|
||||
assert_eq!(patterns.patterns[1].find_horizontal_reflection(), Some(4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem1_find_vertical() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
let patterns = Patterns::from(c.lines());
|
||||
assert_eq!(patterns.patterns[0].find_vertical_reflection(), Some(5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 405);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_find_horizontal() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
let patterns = Patterns::from(c.lines());
|
||||
assert_eq!(
|
||||
patterns.patterns[0].find_smudged_horizontal_reflection(),
|
||||
Some(3)
|
||||
);
|
||||
assert_eq!(
|
||||
patterns.patterns[1].find_smudged_horizontal_reflection(),
|
||||
Some(1)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 400);
|
||||
}
|
||||
}
|
73
14/Cargo.lock
generated
Normal file
73
14/Cargo.lock
generated
Normal file
@ -0,0 +1,73 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "day14"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ndarray",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||
dependencies = [
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
9
14/Cargo.toml
Normal file
9
14/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "day14"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ndarray = { version = "0.15.6" }
|
100
14/input
Normal file
100
14/input
Normal file
@ -0,0 +1,100 @@
|
||||
O..#OO..#...O..O#O.O...O##.O#..#O#...O.O.....O..........O..#...#.....O.O.O.O#..O........O...........
|
||||
.....O#.#O..OO.#......O.O..#...#..OO..O..###..#...O.#...#..O..O.#..#O...#O...............##O..O....#
|
||||
..#...O...OO.#........O......O#O#......O.#OO....OOO..#...O....O.O.O#..#OO.##...OOO#.#.OO.#O.#....O..
|
||||
..#...#..#....O...#.#O......O.....#O##.#..#.O..#.....#O.O#...#.......O.....O.##.O.O..#.....O.#.O.OOO
|
||||
O....#..#.O.O..O.#.#....#.#..##O...O#..O.#.O.OOO.O.O..O..............O.#O.O....#..O.O..O..O.O.O.O.O.
|
||||
.O.#.#..#.OO.#O....O.O.O#O..O.O.O..O.##..O...OO#.#...O.OO.O..#..#..#.O#..#.....#OO....O.###....#O...
|
||||
.......#.O.......O.O####OOO..#.O#..#.O.......OOO..O....#........O##....O#O....O...#.O.##OO.O..OO...#
|
||||
..O.....O.#O#O....O......O..##.#...O.#.O##.....O.#..O.........#...#.#.O#OO.....#O.....O#..##.....O..
|
||||
.#..O...##....O##O...#O....O..#...O...OOO..OO...OO...#..O.OO#..#.O...##.#..O..O..........O#..#O.O#..
|
||||
#..#OO#.O#.#........#.........O......##....#...O....#O.....O..##..#O.OO#......O..O.O.OO...O#O.......
|
||||
#........#.....O.#....O...OO..OO......###..........##O##O.#.....#....###...#.#...O...#.O#.........O.
|
||||
...O.OO.....O..#...O.#.O#.OO#OO..#.#OO#......#.O.O#..#..OO..#O.O.....O.#..........##..O#.OO.....#...
|
||||
.O#..#.....O.#..O.....#O...#....#.O.OO....O...#.#..O......#.O...OO..#.O...O#......##O.OO...#....O.##
|
||||
O#O......O.O....O.O#OO.......OOO..#..#..OO.#.##O#.....#.#O.O.........##........#O....##..#O.O#.#.O..
|
||||
.....O.OO.O...O..O...OO.#.......##....O..#....#.......O.O#.#.O...O.#O....##...#.O..#.#....O#........
|
||||
O..#.#O...O.O..OO.....#........OO.#......O.O....O..#.O#.#.O.#....OO.O#..OO.....#.##.####.O##...O.O.#
|
||||
...O..##O....#....O.O.....#......OO..#OO...#O#..O.......O.#.O.O...O.#.O......#...O...#O...#..##.O...
|
||||
OOO..#.#....#..#.O.#O#......O......OO.......O..#..#.O#.....O.......#.OO.O.O.......#.O#.O............
|
||||
.O##O.....OO..O..O....#.O...#.#.#O.#.O#.O.#...##O..OO.O#......O.OO..#O.OO..O.O...O.O#......#...OO#..
|
||||
..#.OO#..#O....O...O...#........#.O.......O#..O..#.#O.O#...O.............OO...#...O...#....O..#.O...
|
||||
O..#..##O..O...O.O#.O.#..O.O.....#..O.##.##.O..#..OO...#...#.OOO......#.#.....O##.....#.OOO...O.#...
|
||||
#.O#..O..#..O..#.#..#..#O#......O#.##O.........#..O.....#..O..#....##......OO#..O....##.O.....O#O.#.
|
||||
.O.......O.......O..O.#.#O....O.O..#.....O.#O#O.#.......##...O.#O..........O.###...#.##...O........O
|
||||
.......O.....O..#...##.O.#.#O...O##..O....O..O.##....#.O..#.##O.....O.#...#..OO.......#.....#O.##O..
|
||||
......#O.........#..O#..#O....O.#..#.O...OO...O....###....O##O..O.O...O..#O.....O.#.......#...#..#..
|
||||
#..#..#.OO##....O.###.#.....#O#.O....O.#.O......O....#.O..OO....#...O#.O#.....O#O..#.O..OO...OOO.O.#
|
||||
.#....O.......#O..##.#OO#....OO#....#..OO..#.....O.O.OO.O#OO##...O#..#..#..OO..OO.#..O..........O..#
|
||||
.O...O#..OO.O..O.#.O..##.O...O.O.....#O.....O.O#..OO...#.O....#O..#...##..#.#...O.O..OO#O...O..#...O
|
||||
#O.##...O...OO.##.O.....O.......##..#.###...#.O..#.....#O.#....O......#.O#.#.O...O.....OOO.O.....O#O
|
||||
...O.#....#....#..OO...#...##..O.O.O......O.#..O..OO....O...#..OO......O.#.O.OOOO...O.#OOOOO.OO#.#..
|
||||
.......O#.O#.O..O.#.O..#.OO.O..#.#.##.....O.#.O##...##..O...O...O.O.......#O.#......#......O.......#
|
||||
...#..#O.......#O...O..OO....OOOO......OO...#....O............#.........#O...#.#.......OO.....O..#O.
|
||||
O...OO###.....O.OO......#O.O...O..#..##..O..O...O#.#......O#O.O.OO.#O..#O.O.#.O##O.O.O..#..O........
|
||||
.O.O.O..#.O...#.##O..#OO###.O..O..#...O..#O........O#O.#.##..O.O....O...#...O.O#...OO.....OO.......#
|
||||
O.O..O...#O#...#.#....#......OO..O#...O..OOO..O..O.....#...#...O.......#.....#O..O.....O#..O.O...O.#
|
||||
...##..OOO..OO#.O#OOO.#......O...O.......##........OO..O.#....O....##..##O#...#.#..O.#O........#.O..
|
||||
.......##O#........O......O......#.............O..O..#.O....#.#OO##...#O...O.O.O#.#......##..O.##O#.
|
||||
OO.OO##.O...O#..O..O#...#.###....##.O...O.OO.#..#.O.#...#...##...#.....O..O..O.O.#..#..O....#....##.
|
||||
O.#...##...#.#OO..##...#......O.OO.#O#O......OO...O#OOO...#...O.............OO.O.O.#..#O......#.O.#.
|
||||
.O.O.....O....#.......O......#O.O..##.O#...O....#O....O..#.OO..O#.O.#.....O.O##...........O#..#O...#
|
||||
....#OO....#..###..O.O#O......##.#.#.O#O.#.##........##.O...#.OO.......O......O.....#.#O.#.O..#...O#
|
||||
.....O..#..#...#.###.##....#O.O.O..O....OOO.##...O##..O.#...##..#..O......##....#.O....#O........#.#
|
||||
...#OO#......O...O#.#..........OOO...#.##O.O..##..#.#.O......O#.....OO......O.#O..###..O...OOO..O..O
|
||||
.#.O.#.O.O.O.O.#..OO.O...OO...O..O........OO.........#.....##.....O#..#...#.#.#.O...O.......O#...OO.
|
||||
.....OO.O....O....O.#..##OO...#O#.......O....#....O.O..........O##.#...O..O.#..#..O....OO...#.......
|
||||
....##...O.#.....##O...##.....O..O...#.##.O##...O....O..O...##.....O....#.OO...O..OO#.O....OO......O
|
||||
.O....#.....O.#O.#OO.O.##..O.....O..O...#.##.O##...O...O#OO#.O.OO...O.O.#O#....#.O#.O...O....O......
|
||||
..O#O#.#.#.#....##.#O.O.O....#.##O..#O..O..O....O.....O.O..#...OO#O...#OO...#O..O...OO#O#...#..#....
|
||||
.#O......O.O.O#..OO.OOO.#......O...#.O......OOO#....O.#..O.......O.......#.....#....#O.....O#O....O.
|
||||
.....O..O..O#........#............O....O#OO.O..O.#O..O.OO...OO....O.#.O..#.OO.......O.O.OO..OO.##O..
|
||||
..O#O......#.............#..#.O.O.........O.#OO.OO..##.O#O........#.....O..OO...O.##.##.O.O#....OO.O
|
||||
O..#..#....#.....#O.O..O.O..O.#.O.O.#OO..O##O..#.#.O...O....OOO.O.#...........#...#...#O...#O.#.O...
|
||||
OO.....O#..#.#...#...#...##..O...O.....#O..O#O..OO.....##.#.#.OO.....O##O.....#O.O.#.#...OO...O#.#..
|
||||
....#...O#..O.OO#........O..#..O....#.O.....OO#..#....O..OO.........O..#..#...O...OO.......O.......#
|
||||
##.O#.........O#.OO..O..#.OO.#O.....O#O...O......#O#.O..O.....#.#O.#O.O#......OO.O........O.....#...
|
||||
.#.O.OO....O#O..#..O.#.#O....OO...O#..#.O.##..#..O.#O#O..O.......O..#.O#.#.##...O.OO.O#O.#..#.#..O..
|
||||
...O#.......O#......O#........O..O..#..O#.O...O#..#...O......#...#.#O....O..#.#....OOO.O.......O....
|
||||
..O....#.....O.##..O..##O....#O..O.###.....O#..OOO..##........#O.O..O.....#......#O#.........#OO..#.
|
||||
#.##...#.#...#.....#O.O.#..##.O..O.O.....#.#OO.........O.#...O....#......##.#.OOOO.O.OO...O.OO.O....
|
||||
..#....#...OO..#O.....#..#O..##....#......#O.#..O.#OO.......OO.O....#.......OO..#.#..OO...O.....#OO.
|
||||
O.....O.#.....#..#.O#......#O#...#....O......O#O.O#.O....#.OO##........O...O#..O#.OOOO.#O#O..##....#
|
||||
.O........OO.#.....O#O..OO.O#O#..O.......#.O..##.#.#.....#.OOOO...O..OOO.OO#....O....#....O.#....OOO
|
||||
.O#O.O.......O#O...O.#O...O.OO#O..O.#..#O...O.O.#.#OO....##..##..#......#..O#......#O.O.O#O#.#...#..
|
||||
..O..O#.#..O#.O..OOOO...O..OOO#O......##.O..O..O..OO#O.#....O.......#..O#.O..O..#..O...OO.....##O#..
|
||||
...OOO..O........OOO....#..#.O.O..##.O.O..#....O........#...##O#O..O.#OO.#...#..#O#......O.O....O...
|
||||
.#O#.#.#.O.#..#.O..O.....O.O..O.#.O#........#....##.O#O..#..#O#.#..O#O#.#.#..#......O...O#.O.....#..
|
||||
.#..O.#OO.#..#O...O...O..#O...#...O#..O.............#.....O.#O....#..#...#.#...OO.O.OOO.O....##O#O.#
|
||||
OO..O...O....##...#.O...#.#....O.#....O..O##..O.......#O.#...O..##...OO.O#O.....OO...#....#.......O.
|
||||
.#O.O....#.#O........#.#..O....O.......#..O#.....O..O.O..##..O.O.O...O..O...OO......O.OO...#.#....OO
|
||||
.#.O..#O.....OO..O..#.O#.O.OO.#....#O....#.OO.....O.OO..#.O.O..OO.....O..##..O..#.#..O......O..OO..O
|
||||
.O.......OO#.#.O.OO..#OO.OO..#O..O##O..#......#.#O.O.#O..#.O.#..#O.OOO..OO...#.#.#.#.OO.O...#O##O...
|
||||
O#...O.O.O........O#..OO.#.#.....#..O##....#.#...OO##..#..O..#..O.OO.O.O.......O.O#........OO.##O...
|
||||
.#.O.#.#...#.O..O##....#.O.#.O#O........#..#.#....O.....#..O#.##...#....#.##.#O.O#O.O..OO##.#..O#O..
|
||||
O...##..#..#OO#.OO.#...##..O...#.O.O#.#....#O.O##....O........OO#O..O..#.......O.#OOOO........#O...#
|
||||
O...#...#.O...#....O#O#......O#.OO#..#....#.#O...O#...OO##...O#.OO....####.......#.......O.........#
|
||||
#O..OO.OO....#.....#....#O.#..OO.#....##.....#...OO.O#O......O.O.O........##..O..O....#..O..O#.O....
|
||||
#O#.OOO.#O#.#.....#O.O....O.#.....OO...##....##O.#....O.O.#O.##O..#O#.O....O...O.#O.#.OO..#...OO..O.
|
||||
....O.........O.O.....#.#...O.O....O..#.#...#..#..#..OO..OO.#..O..O....O........O#.O.O.O#.....#O.O.#
|
||||
#...#O...#OOO...#..O.#..O..O...#.....OO#...##....#.##.##O.OOOO.#O.#...OO##.OO....#...OOO..###...O.##
|
||||
..........#...#.#.....#O...O#OO....OO#...#..##..O..O...#.#.#..#.......#...OO....#O.......O..O....O.O
|
||||
..O......#..OO..O#O.......#O...OO......#..O..OO..#.#O#OO..#.......OO#OO.O...#..O...O..##..OOOO.#...O
|
||||
..OO.O#.#....O#O#O#..O....##..O.O#.O.O..O...O....O...#..O...#O.O..O#.#O..........O.........O..O.O.#.
|
||||
...#....O#.#.#..OO....O.#.......#O#....OOOO.#O#O.O##.OO.#.#O##.....O.#OO#....O...#..OO#.O..........O
|
||||
.#......#O#.#.....O...OO..O.#.......OO..O.O...O.O.#O....#....O..OO.O#.....##.#....O.O....#.#O.O#.###
|
||||
...##O.....#O......O.......O.O.....#.O...O.O....OO..#O...O......#......O...#....O...#.O.....O#.#..OO
|
||||
O..#.....#O..........#..OO........OOO.O..O#O#...#OO....O.#...OO..O..#....O.O.#.O#........#O.#.#...#O
|
||||
O...#..OOOO...#.....#........##..OOO#OO#..#..#.#.O.#.O.O......O.....#.#O#..##....O.#O#O.O.#...O.....
|
||||
.O.#.O....O.OOO..##.....O#.OO........................O..O..#.OOO......#OOO......#...OO........#..OOO
|
||||
.###...O##..#.O#..O#..#.O#.#.O..O.##..O...#.O..O.#.#.....OO..O.#O.O....OO.O.O..#....#O.OO#.O..O.....
|
||||
.......O.O.....O.....O#.....O.....OO#.O..#...O..O..##.O..OO.O....#O......###..#...O........#....O.OO
|
||||
O..O..O...O.O.O.O.O.O...OO........OO..OO..O.#O.#.O....#..OOO.O.#...OO.#...O......OO.OO#.#...O#...##.
|
||||
O#O.##...O#.#..O.#.O..#..#....#..O##...##....OO.#..##OO....##......O....#OO.O...#OO..OO#...O.OO.#.#.
|
||||
..O.#OOO....O....#....#..O#O..O..O...O...O.........#..#.#O..#.#...OO.....##.O.......O#..O#.#...OO...
|
||||
.O.O.O.O..O.##...#..........O.O..............#....#.#O...OO.#..OO...#....O.O..#.......O.#..#..##.O##
|
||||
..OO.#.....O..O.OO.#.##.O....#...#O....##..O#.O.....O.....#....OO#....##..#O..OO...#O#O#....#.O.O.O#
|
||||
..O.#O....O.#..#.#.OO.##..OO......#...#....#O...OO....#.O..#.OO#.......O.#.#......O#O...#..OO.....##
|
||||
#.........O....#..#O.....##....#O......##..O....OO.....O.....#..#O...O...O..#.OOO.O..#......#.....#.
|
||||
O.##.O.#OO...#..#O.OO.....#.#.....O..##.O.#......#O##......OO..O..O.O.....#..O.O.#..O......O.OO.##..
|
||||
....O....O#.##..O.O.O..#..##O#......O#.....O......O.#....O......#O.O..#..O..O..##..#O##..........O..
|
||||
O#..##O..#...OO...#.OO....#..O.....O.......OOO#...##...OO.##....#O..#..#O.#.O#O..O...O.#..O.#O.O#...
|
240
14/src/main.rs
Normal file
240
14/src/main.rs
Normal file
@ -0,0 +1,240 @@
|
||||
use ndarray::*;
|
||||
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Platform {
|
||||
matrix: Array2<char>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Platform {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
let rows: Vec<Vec<char>> = lines.map(|line| line.unwrap().chars().collect()).collect();
|
||||
let width = rows[0].len();
|
||||
let height = rows.len();
|
||||
Self {
|
||||
matrix: Array2::from_shape_vec(
|
||||
(height, width),
|
||||
rows.iter().flat_map(|row| row.iter().map(|c| *c)).collect(),
|
||||
)
|
||||
.unwrap(),
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum Axis {
|
||||
Rows,
|
||||
Columns,
|
||||
}
|
||||
|
||||
struct North;
|
||||
struct South;
|
||||
struct East;
|
||||
struct West;
|
||||
|
||||
trait Direction {
|
||||
const REVERSED: bool;
|
||||
const AXIS: Axis;
|
||||
const ROTATIONS: usize;
|
||||
}
|
||||
|
||||
impl Direction for North {
|
||||
const REVERSED: bool = false;
|
||||
const AXIS: Axis = Axis::Columns;
|
||||
const ROTATIONS: usize = 0;
|
||||
}
|
||||
impl Direction for South {
|
||||
const REVERSED: bool = true;
|
||||
const AXIS: Axis = Axis::Columns;
|
||||
const ROTATIONS: usize = 2; // 180
|
||||
}
|
||||
impl Direction for East {
|
||||
const REVERSED: bool = true;
|
||||
const AXIS: Axis = Axis::Rows;
|
||||
const ROTATIONS: usize = 1; // CCW
|
||||
}
|
||||
impl Direction for West {
|
||||
const REVERSED: bool = false;
|
||||
const AXIS: Axis = Axis::Rows;
|
||||
const ROTATIONS: usize = 3; // CW
|
||||
}
|
||||
|
||||
impl<'a> Platform {
|
||||
fn roll<T: Direction>(&mut self) {
|
||||
// Get a view into the rotated matrix with the target direction to the north
|
||||
let mut view = self.matrix.view_mut();
|
||||
|
||||
match T::ROTATIONS % 4 {
|
||||
0 => {}
|
||||
1 => {
|
||||
view.invert_axis(Axis(1));
|
||||
view.swap_axes(0, 1);
|
||||
}
|
||||
2 => {
|
||||
view.invert_axis(Axis(0));
|
||||
view.invert_axis(Axis(1));
|
||||
}
|
||||
3 => {
|
||||
view.swap_axes(0, 1);
|
||||
view.invert_axis(Axis(1));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Self::roll_rocks(view);
|
||||
}
|
||||
fn roll_rocks(mut view: ArrayBase<ViewRepr<&mut char>, Dim<[usize; 2]>>) {
|
||||
let axis_len = view.len_of(Axis(1));
|
||||
for mut col in view.columns_mut() {
|
||||
for inner_idx in 1..axis_len {
|
||||
if col[inner_idx] == 'O' {
|
||||
let lower_limit = (0..inner_idx).rev().find(|i| col[*i] == '#').unwrap_or(0);
|
||||
if let Some(empty_pos) = (lower_limit..inner_idx).find(|i| col[*i] == '.') {
|
||||
col.swap(inner_idx, empty_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn score<T: Direction>(&self) -> u64 {
|
||||
match T::AXIS {
|
||||
Axis::Columns => self.score_columns::<T>(),
|
||||
Axis::Rows => self.score_rows::<T>(),
|
||||
}
|
||||
}
|
||||
fn row_or_column_score<T: Direction>(&self, idx: usize) -> usize {
|
||||
if T::REVERSED {
|
||||
idx + 1
|
||||
} else {
|
||||
match T::AXIS {
|
||||
Axis::Rows => self.width - idx,
|
||||
Axis::Columns => self.height - idx,
|
||||
}
|
||||
}
|
||||
}
|
||||
fn score_columns<T: Direction>(&self) -> u64 {
|
||||
self.matrix
|
||||
.rows()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(idx, row)| {
|
||||
row.iter().filter(|c| **c == 'O').count() * self.row_or_column_score::<T>(idx)
|
||||
})
|
||||
.sum::<usize>() as u64
|
||||
}
|
||||
fn roll_cycle(&mut self) {
|
||||
self.roll::<North>();
|
||||
self.roll::<West>();
|
||||
self.roll::<South>();
|
||||
self.roll::<East>();
|
||||
}
|
||||
|
||||
// find the first loop, return the iteration count when we first saw it and when we saw it again
|
||||
fn find_loop(&mut self) -> (usize, usize) {
|
||||
let mut first_seen = Vec::new();
|
||||
first_seen.push((self.matrix.clone(), 0));
|
||||
let mut i = 0;
|
||||
loop {
|
||||
self.roll_cycle();
|
||||
i += 1;
|
||||
if let Some((_, first_idx)) = first_seen.iter().find(|(val, _)| *val == self.matrix) {
|
||||
return (*first_idx, i);
|
||||
} else {
|
||||
first_seen.push((self.matrix.clone(), i));
|
||||
}
|
||||
}
|
||||
}
|
||||
fn score_rows<T: Direction>(&self) -> u64 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Platform {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.matrix.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut p = Platform::from(input);
|
||||
p.roll::<North>();
|
||||
p.score::<North>()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
const ITERATIONS: usize = 1000000000;
|
||||
let mut p = Platform::from(input);
|
||||
let first_loop = p.find_loop();
|
||||
let loop_length = first_loop.1 - first_loop.0;
|
||||
let cycles_to_skip = ((ITERATIONS - first_loop.0) / loop_length) * loop_length;
|
||||
let iterations_remaining = ITERATIONS - first_loop.0 - cycles_to_skip;
|
||||
|
||||
for _ in 0..iterations_remaining {
|
||||
p.roll_cycle();
|
||||
}
|
||||
|
||||
p.score::<North>()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"O....#....
|
||||
O.OO#....#
|
||||
.....##...
|
||||
OO.#O....O
|
||||
.O.....O#.
|
||||
O.#..O.#.#
|
||||
..O..#O..O
|
||||
.......O..
|
||||
#....###..
|
||||
#OO..#....";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 136);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 64);
|
||||
}
|
||||
}
|
7
15/Cargo.lock
generated
Normal file
7
15/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day15"
|
||||
version = "0.1.0"
|
8
15/Cargo.toml
Normal file
8
15/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day15"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
172
15/src/main.rs
Normal file
172
15/src/main.rs
Normal file
@ -0,0 +1,172 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// COMMON
|
||||
|
||||
fn hash_string(s: &str) -> u64 {
|
||||
s.bytes().fold(0u64, |mut accum, val| {
|
||||
accum += val as u64;
|
||||
accum *= 17;
|
||||
accum %= 256;
|
||||
accum
|
||||
})
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(mut input: Lines<T>) -> u64 {
|
||||
let line = input.next().unwrap().unwrap();
|
||||
line.split(',').map(|s| hash_string(s)).sum()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct LensBox {
|
||||
// lenses k: lens label v: focal length
|
||||
lenses: HashMap<String, u8>,
|
||||
// order is the lens stack, values are labels into lenses
|
||||
order: Vec<String>,
|
||||
}
|
||||
|
||||
impl LensBox {
|
||||
fn add_lens(&mut self, label: &str, focal_length: u8) {
|
||||
// If there is not already a lens in the box with the same label, add
|
||||
// the lens to the box immediately behind any lenses already in the box.
|
||||
// Don't move any of the other lenses when you do this. If there aren't
|
||||
// any lenses in the box, the new lens goes all the way to the front of
|
||||
// the box.
|
||||
if self.lenses.insert(label.to_owned(), focal_length).is_none() {
|
||||
self.order.push(label.to_owned());
|
||||
}
|
||||
}
|
||||
//If the operation character is a dash (-), go to the relevant box and
|
||||
//remove the lens with the given label if it is present in the box. Then,
|
||||
//move any remaining lenses as far forward in the box as they can go without
|
||||
//changing their order, filling any space made by removing the indicated
|
||||
//lens. (If no lens in that box has the given label, nothing happens.)
|
||||
fn remove_lens_if_present(&mut self, label: &str) {
|
||||
if let Some(_) = self.lenses.remove(label) {
|
||||
self.order.remove(
|
||||
self.order
|
||||
.iter()
|
||||
.position(|s| s == label)
|
||||
.expect("We had the lens in lenses but not in order?!"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn total_lens_power(&self) -> u64 {
|
||||
self.order
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(lens_idx, label)| (lens_idx + 1) as u64 * self.lenses[label] as u64)
|
||||
.sum()
|
||||
}
|
||||
}
|
||||
|
||||
enum Instruction {
|
||||
Replace(String, u8),
|
||||
Remove(String),
|
||||
}
|
||||
|
||||
impl From<&str> for Instruction {
|
||||
fn from(s: &str) -> Self {
|
||||
let op_pos = s.find(|c| c == '-' || c == '=').expect("No operation?!");
|
||||
let op = s.chars().nth(op_pos).unwrap();
|
||||
let (label, op_focal) = s.split_once(|c| c == '-' || c == '=').unwrap();
|
||||
|
||||
match op {
|
||||
'-' => Self::Remove(label.to_owned()),
|
||||
'=' => Self::Replace(label.to_owned(), op_focal.parse().unwrap()),
|
||||
_ => panic!("unexpected op {}", op),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
fn execute(&self, boxes: &mut [LensBox; 256]) {
|
||||
match self {
|
||||
Self::Remove(label) => boxes[hash_string(label) as usize].remove_lens_if_present(label),
|
||||
Self::Replace(label, focal) => {
|
||||
boxes[hash_string(label) as usize].add_lens(label, *focal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_boxes(boxes: &[LensBox; 256]) {
|
||||
for (idx, b) in boxes.iter().enumerate() {
|
||||
if !b.order.is_empty() {
|
||||
print!("Box {}:", idx);
|
||||
for label in &b.order {
|
||||
print!(" [{} {}]", label, b.lenses[label]);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn problem2<T: BufRead>(mut input: Lines<T>) -> u64 {
|
||||
let line = input.next().unwrap().unwrap();
|
||||
|
||||
let instructions: Vec<_> = line.split(',').map(|s| Instruction::from(s)).collect();
|
||||
let mut boxes: [LensBox; 256] = std::array::from_fn(|_| LensBox::default());
|
||||
|
||||
for inst in instructions {
|
||||
inst.execute(&mut boxes);
|
||||
}
|
||||
|
||||
boxes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(box_idx, b)| (box_idx + 1) as u64 * b.total_lens_power())
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7";
|
||||
|
||||
#[test]
|
||||
fn problem1_test_hash() {
|
||||
assert_eq!(hash_string(&"HASH"), 52);
|
||||
}
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 1320);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 145);
|
||||
}
|
||||
}
|
7
16/Cargo.lock
generated
Normal file
7
16/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day16"
|
||||
version = "0.1.0"
|
4
16/Cargo.toml
Normal file
4
16/Cargo.toml
Normal file
@ -0,0 +1,4 @@
|
||||
[package]
|
||||
name = "day16"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
110
16/input
Normal file
110
16/input
Normal file
@ -0,0 +1,110 @@
|
||||
\.....................\.......................|..../......-.........../.|.....\.............|..........|..\...
|
||||
.../...................\..................../...|.......|........||...................../...........\.........
|
||||
././....|......./................\............|..\...........-....../............../|........-................
|
||||
....\..\...........-/..|......|......\............|............../.................-........./...-...|.......\
|
||||
..................................|.\.......|...../.........................-...../......\..|...............\.
|
||||
.....\.............................................|../.\............../--.......................\............
|
||||
|.......-.|........\.................\..............|........./....\.........|...................\-.-...|.....
|
||||
....\........./....-.........................--.....\..../......................|.\......................\...-
|
||||
\..-..../.....|..........\......................-|......|...................../...../........./...........-...
|
||||
........................\.\|......../........../......................\.............|./../....................
|
||||
.....\...................|.............................|......-........|.........-./.../.|....................
|
||||
..-................./.........................................\..\........-..-........-.......\../............
|
||||
-................-............................\................./..--................-............../.|.......
|
||||
..-.....|.............|................./.......-.-........................-............-...........\.........
|
||||
..........|..........................-...|..\...............................................\-....\...........
|
||||
/................../..........|....\..-......................../....\...\..........-....../.........../.....\.
|
||||
................\....-................-|.\...-...........-.....-........\..........................\..........
|
||||
...................................\../..|.../../...........................\.........../.\-......|.........-.
|
||||
/....|....|..........................\............./.....|/................./....-......................-.....
|
||||
....-.............../.....|...........|../......\../.............../........................|............./...
|
||||
......./..............|./../.................-.\.........../.....................|.........../........\.......
|
||||
...................-...............\/.......|........|....................../.......................-/......\.
|
||||
................\...../....-/......-.........-.....\/.\...............\....../...-....|......|.........\......
|
||||
....-.........-.........................-......................../.......|...............................\....
|
||||
......../..................|...../......\..\..-|-..../..............|......../............|.-.......-.........
|
||||
......./............-..........-............................../.........................|\..-..-\.\......-..\.
|
||||
.\-.....|......................-..\................/.-................|.\..............\..................|...
|
||||
-..........................-............../.|.-......\......-..-...../......./................................
|
||||
....|.................................................\....|..........\...................-......|........./..
|
||||
................../...........-..............\......................................|.-........|..............
|
||||
...-............|..............-...........-.\.......................|..|..../......................../.|....-
|
||||
.......-..-......./...../.........-.......\.....-.../............-./......../.../............-.....|...|......
|
||||
...............|.........../..........|/..........|..........-.-...../...../..|..........\.....-./.|./....|...
|
||||
.........|......................\.|.....|......................-.-........|.............................-...|.
|
||||
.-...|..\...-...............\..............\......./........-............/.-..\........../...../....-....\....
|
||||
...........\.-.......|.......|....-.............|-.|........../..../...\....\............|.|..|\..............
|
||||
.....................|.\....|......|../...\......|........................\......|.......-./..../.............
|
||||
......................\--................................\.................|................-.................
|
||||
-...............\...-.....................................-.\...../....\...........................|..........
|
||||
.....|.......\.......................-/...\..-.........-..../\|..................\........-...................
|
||||
..|........./....|..-./..\..\................-|..........\../......\...............\............\............|
|
||||
......-................../.............|.............\................................-..\...../........-.....
|
||||
....................../......../..\.-.........................|....\..|...\...../../.....|............../.....
|
||||
...\................................/..............................\........|.........\.-............\........
|
||||
/.................../................-...........-.|.............\.................................|.....-....
|
||||
.|...-..|/./../.........-./.............................................../..........-.........-.|./..........
|
||||
..../..................|......................|../..........\........-......../.........\...|.................
|
||||
........./..................|..-..........|\............\......-..-..\...|....|.....................|....-....
|
||||
.....|/....|........\.........-................../..........|............|...........-.....|......./......//..
|
||||
..........\.|../...|........................\.........\.|......||....-...............\\.....|.|..............|
|
||||
............-................|.....-....||......../.../.......................|..\...........\................
|
||||
...............-..../......-..../.......|-.....-.....\..................................../..|................
|
||||
/......-...............\/...././..................\..................\..........-......................|......
|
||||
...................\.....\.................\...|.................-............/........-..............\./.....
|
||||
.-.\....\........\........-../.-............../...../..-..|...................../.-.....\.....-........../..\.
|
||||
|...|...............................|............../.............../....................|...../...............
|
||||
....../....../...|..............-.-........-..|.../....................\|.....\......................|....../.
|
||||
...\\.......|...|-............|..........-...........................................\/...../..-.-............
|
||||
.........|.............|..|......\............\...............|......\......\.............\...\-.......\.....\
|
||||
...........\..-.|.......|\..\..................-........\/...............................-....................
|
||||
...\.................\..............................................\...............\.......-.../.............
|
||||
..\.............\....---....................//.......................................|./.............../\.....
|
||||
.\...........|..................................\........-......|.........\.................-........-........
|
||||
..............-...............-.../....-........|.....-../......................./..../........../../--..\....
|
||||
.........-......\......-.........../...\./.|.................\...................--..-........|..\......\....|
|
||||
....../.........................................|...../........../..............\\...-/.......-......\..\.....
|
||||
.........../...\.|..................../.\.................|......\.\..|.........../...../.....\.\...........|.
|
||||
..../\..-...../.............................../..../............................-...-......\...........\......
|
||||
..-..\.............................\...........|..........|.........|..........................-......./......
|
||||
-..|.................-\.....\...............\/.....|...........................././...\......\.......\...-....
|
||||
......\..............|..|..............-............../....................-....\\........\....|..............
|
||||
|.............\....\./.....-|-....\.....\..............\/........-.|..|...........-..\......-..../.......|....
|
||||
............................-.......................|........................../................|.............
|
||||
/................|../............\/.....\/....-.....\......\...../|..\..........|............../..............
|
||||
.|....../...../....................../..|.....................-................./...../-.........-............
|
||||
......................\|........../......./..\........\.........-......../.........../.|/.......\.../.........
|
||||
...............\......-|............\..\....../.........\.....|...|\............/............\.\..|.......\...
|
||||
......|...........\....../....\./......./-....\../.......\...-...............\./...\.....-.......-..../.......
|
||||
...|..|.............................\.....-.|........./......../......................-......./............\..
|
||||
.....|........\.........|...-.-.........\..../....../..-.......-...............\..../.....-..../..............
|
||||
........./.\/........................-..........\.....................|.......-..............\./.\............
|
||||
..../................/................................|.....||..............\........-...............|........
|
||||
....\./.........../\-.....-...\............//.\..............\...../................|.....\..-................
|
||||
..../|........./............|.....................|......................-..|...............................\.
|
||||
..................\............................\.......\.........-.............|...../.-.............-......|.
|
||||
..............|.-...........................\.\./.......\........../...\................/....-................
|
||||
.......|................/-............\............/...........-..../...........\......../...\.......\........
|
||||
..............|..../......................-...........-..\.................................................-..
|
||||
..............................-..-................-.......-.................-..........\.../...............|..
|
||||
......-.........-........................./.....................\....|........................................
|
||||
.....\........./.....-.................../................|...................|........................|......
|
||||
........../.../........................./.|................-...........\...........-....|.....................
|
||||
.....-.......\././/.......|..............|......../..\...........\.............................-......|../-.-.
|
||||
........|-....-....................\.....|\...\/.....\........\......./..........|.\-..|......................
|
||||
../...-...-...|...../............\.......................-..........\...\.....-...\...............|....../...|
|
||||
............|..\....|..................\/...................../../....|...................|.............../...
|
||||
.............-................./............|.......|............\....................................\.-.....
|
||||
-...../|..............-......\..../..................|..\....-............................................\...
|
||||
........|.........-........\................/....\..................../.|...................................|.
|
||||
.....|................./.........-|\...-...................|....-................-......../...............|..-
|
||||
.|.........|...........|...-.............................\............................|................\......
|
||||
....|.....-......|......./.-.|...........\..-........|.........................-....-..-.....|................
|
||||
........................................\.....................-.../........................../../..........|..
|
||||
-................/....\.......//....-........................../.\.........-......./..|\..........\...........
|
||||
-............................./......................................../-...........................\|........
|
||||
........................................../-.....//......\......\...........\........|./....../.......--......
|
||||
../..............-....../......../................../......./....-...........|../.......\.\.......-......./..\
|
||||
..............-............../......|.........-...............|................................-..........\...
|
||||
.....................\..........|..\......|...............................................-...................
|
||||
...../..|.../.........|.../.......-...................................\.....................................|.
|
265
16/src/main.rs
Normal file
265
16/src/main.rs
Normal file
@ -0,0 +1,265 @@
|
||||
use std::fmt::Display;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::iter::repeat;
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
enum Interaction {
|
||||
One(FromDirection),
|
||||
Two((FromDirection, FromDirection)),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
enum FromDirection {
|
||||
Left = 0,
|
||||
Above = 1,
|
||||
Right = 2,
|
||||
Below = 3,
|
||||
}
|
||||
|
||||
impl FromDirection {
|
||||
const fn mask(&self) -> u8 {
|
||||
1 << *self as u8
|
||||
}
|
||||
// return the new pos for a ray that will be from the direction.
|
||||
// a ray 'from' left 'goes' right
|
||||
const fn goes_pos(&self, pos: (i64, i64)) -> (i64, i64) {
|
||||
match self {
|
||||
Self::Left => (pos.0 + 1, pos.1),
|
||||
Self::Right => (pos.0 - 1, pos.1),
|
||||
Self::Above => (pos.0, pos.1 + 1),
|
||||
Self::Below => (pos.0, pos.1 - 1),
|
||||
}
|
||||
}
|
||||
const fn reflect_ne(&self) -> Self {
|
||||
match self {
|
||||
Self::Left => Self::Below,
|
||||
Self::Right => Self::Above,
|
||||
Self::Above => Self::Right,
|
||||
Self::Below => Self::Left,
|
||||
}
|
||||
}
|
||||
const fn opposite(&self) -> FromDirection {
|
||||
match self {
|
||||
Self::Left => Self::Right,
|
||||
Self::Right => Self::Left,
|
||||
Self::Above => Self::Below,
|
||||
Self::Below => Self::Above,
|
||||
}
|
||||
}
|
||||
const fn reflect_se(&self) -> FromDirection {
|
||||
self.reflect_ne().opposite()
|
||||
}
|
||||
fn interact(&self, tile: char) -> Interaction {
|
||||
match tile {
|
||||
'.' => Interaction::One(*self),
|
||||
'/' => Interaction::One(self.reflect_ne()),
|
||||
'\\' => Interaction::One(self.reflect_se()),
|
||||
'|' => match self {
|
||||
FromDirection::Above | FromDirection::Below => Interaction::One(*self),
|
||||
FromDirection::Left | FromDirection::Right => {
|
||||
Interaction::Two((FromDirection::Above, FromDirection::Below))
|
||||
}
|
||||
},
|
||||
'-' => match self {
|
||||
FromDirection::Left | FromDirection::Right => Interaction::One(*self),
|
||||
FromDirection::Above | FromDirection::Below => {
|
||||
Interaction::Two((FromDirection::Left, FromDirection::Right))
|
||||
}
|
||||
},
|
||||
c => panic!("invalid tile {}", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FromDirection {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Above => f.write_str("above"),
|
||||
Self::Below => f.write_str("below"),
|
||||
Self::Left => f.write_str("left"),
|
||||
Self::Right => f.write_str("right"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Contraption {
|
||||
tiles: Vec<Vec<char>>,
|
||||
}
|
||||
|
||||
struct VisitState {
|
||||
visited_from: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl VisitState {
|
||||
fn visit(&mut self, pos: (i64, i64), dir: FromDirection) -> bool {
|
||||
let pos_state = &mut self.visited_from[pos.1 as usize][pos.0 as usize];
|
||||
if *pos_state & dir.mask() > 0 {
|
||||
false
|
||||
} else {
|
||||
*pos_state |= dir.mask();
|
||||
true
|
||||
}
|
||||
}
|
||||
fn score(&self) -> u64 {
|
||||
self.visited_from
|
||||
.iter()
|
||||
.flatten()
|
||||
.filter(|c| **c != 0)
|
||||
.count() as u64
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
fn dump(&self) {
|
||||
println!("Score {}:", self.score());
|
||||
for line in &self.visited_from {
|
||||
println!(
|
||||
" {}",
|
||||
String::from_iter(line.iter().map(|b| if *b == 0 { '.' } else { '#' }))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Contraption {
|
||||
fn height(&self) -> i64 {
|
||||
self.tiles.len() as i64
|
||||
}
|
||||
fn width(&self) -> i64 {
|
||||
self.tiles[0].len() as i64
|
||||
}
|
||||
fn cast_ray(&self, pos: (i64, i64), dir: FromDirection) -> VisitState {
|
||||
self.cast_ray_inner(self.empty_state(), pos, dir)
|
||||
}
|
||||
fn cast_ray_inner(
|
||||
&self,
|
||||
mut state: VisitState,
|
||||
pos: (i64, i64),
|
||||
dir: FromDirection,
|
||||
) -> VisitState {
|
||||
if pos.0 >= 0
|
||||
&& pos.1 >= 0
|
||||
&& pos.0 < self.width()
|
||||
&& pos.1 < self.height()
|
||||
&& state.visit(pos, dir)
|
||||
{
|
||||
match dir.interact(self.tiles[pos.1 as usize][pos.0 as usize]) {
|
||||
Interaction::One(dir) => self.cast_ray_inner(state, dir.goes_pos(pos), dir),
|
||||
Interaction::Two((dir1, dir2)) => self.cast_ray_inner(
|
||||
self.cast_ray_inner(state, dir2.goes_pos(pos), dir2),
|
||||
dir1.goes_pos(pos),
|
||||
dir1,
|
||||
),
|
||||
}
|
||||
} else {
|
||||
state
|
||||
}
|
||||
}
|
||||
fn empty_state(&self) -> VisitState {
|
||||
let mut visited_from = Vec::new();
|
||||
for _ in 0..self.height() {
|
||||
visited_from.push(Vec::from_iter(repeat(0).take(self.width() as usize)));
|
||||
}
|
||||
VisitState { visited_from }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Contraption {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
let mut tiles = Vec::new();
|
||||
for line in lines {
|
||||
tiles.push(line.unwrap().chars().map(|c| c.into()).collect());
|
||||
}
|
||||
Contraption { tiles }
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let contraption = Contraption::from(input);
|
||||
|
||||
contraption.cast_ray((0, 0), FromDirection::Left).score()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let contraption = Contraption::from(input);
|
||||
|
||||
let rows_max = (0..contraption.height()).fold(0, |max_tiles, y| {
|
||||
std::cmp::max(
|
||||
max_tiles,
|
||||
std::cmp::max(
|
||||
contraption.cast_ray((0, y), FromDirection::Left).score(),
|
||||
contraption
|
||||
.cast_ray((contraption.width() - 1, y), FromDirection::Right)
|
||||
.score(),
|
||||
),
|
||||
)
|
||||
});
|
||||
|
||||
let cols_max = (0..contraption.width()).fold(0, |max_tiles, x| {
|
||||
std::cmp::max(
|
||||
max_tiles,
|
||||
std::cmp::max(
|
||||
contraption.cast_ray((x, 0), FromDirection::Above).score(),
|
||||
contraption
|
||||
.cast_ray((x, contraption.height() - 1), FromDirection::Below)
|
||||
.score(),
|
||||
),
|
||||
)
|
||||
});
|
||||
|
||||
std::cmp::max(rows_max, cols_max)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &r".|...\....
|
||||
|.-.\.....
|
||||
.....|-...
|
||||
........|.
|
||||
..........
|
||||
.........\
|
||||
..../.\\..
|
||||
.-.-/..|..
|
||||
.|....-|.\
|
||||
..//.|....";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 46);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 51);
|
||||
}
|
||||
}
|
141
17/Cargo.lock
generated
Normal file
141
17/Cargo.lock
generated
Normal file
@ -0,0 +1,141 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "day17"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"termcolor",
|
||||
"test-case",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8"
|
||||
dependencies = [
|
||||
"test-case-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-core"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-macros"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"test-case-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
11
17/Cargo.toml
Normal file
11
17/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "day17"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.12.0"
|
||||
termcolor = "1.4.0"
|
||||
test-case = "3.3.1"
|
141
17/input
Normal file
141
17/input
Normal file
@ -0,0 +1,141 @@
|
||||
325324343122414426341311521355436756516735365767735336243266456152424263655442375437323425146317632655141433156665635625563452536534233413111
|
||||
445243425411645566112351545244163515223165477656331552463117221625365717275545124476464451442531715677337534443363223313661263112221651414352
|
||||
434514252414363452511152554236546325615346321237216231776737145123246363247221568835776177657563335176174462444145653231645541641352324222432
|
||||
512344115556454364551122335531173547353527264165771324616431564154352161434333624143426673724271674725735171453732677454152514121553642514342
|
||||
245335631545534511262451241637156561454332212544137121477616833536676467486356424113643275743254655271257165273233333713436363316152215525412
|
||||
525134431665424254245311755242225774344146256415414763387571367658688754454216857288228327638844315166557547372743531744154253555366125322251
|
||||
242226151434514231642522163777343413375375427786665751532313584425311152314384883312415875143615383175544722257361643371324456124635121426143
|
||||
355256351224414362134546117516475527772757412718633456138147647447166316435131753115166364762163147767575652646664125323524233344211152621644
|
||||
423662265151444333172175576611421743625662125375255611436332835555433412245516663422413367584728254346217161613476513362411124354554141656661
|
||||
343132241425514222366532375754443311661867761827448367742356551447788222565282822336472646562481274186323321263463733172737523415231263231452
|
||||
414512633246125157451572561554537454722163673577424576376853177774626628186236767857316633668123264385753152773455553614673334436441316224135
|
||||
212324565521155353412567475573615133714344617411175657288438127655616781713123465347422118615674666483872652757672245614227473525561435343566
|
||||
445221414451625675624645665212427183844173224183625244868437762281745333878761243125126616283437123288348253513642236266513777143336423452244
|
||||
363544111542646272625122735154448186467255668146344132826437421272718576129612166754885626667262876277185872166576146412755315427431235361345
|
||||
264656533336664366256136422751241622361444458382586165836578937121934658199719386351541531343455316352721641517715741643374346623641245141642
|
||||
112445611653647577632776715757651127562631764334214565265123726662877597342896255454454353581576436364858847152147334456111671241736213243235
|
||||
555625554155515642753141133472357442522378575788761684343125889676496481416737941365773489236312262742358647378637816625524652376464221145552
|
||||
166212536136161764262663264151715412324265162172461388359546247927137713732357391885873753572632213528125746133582543132557354616253656161125
|
||||
262214154431312345513141264637587481623632438762129328373598884879612652692926671574635499263972534168721832253467846424556241116716116355662
|
||||
135241432555162671524462538183836241418472746146531476679922477637662841812239647283188595978522895688251211412744783771567244452546153345245
|
||||
532216637311743517223634115741886133752415248862823922293142226987777614157674447415432957111246289861372245785828235814464543732552357524115
|
||||
146561263436471442615526287283328418146343943213682363991837281378678451857923183343659739289952517643483666668454477612872264623531527114156
|
||||
553563547345231122325535834576322628262281752991871677465471578556275546387834293362893217319352873468631622524488454757543336657573343346231
|
||||
266564156547622167463643435425825221285933354618914693416371827482999473949778132544823891982233412759525148822255432468651261727135416714414
|
||||
241435326144677632666655834466775762193454726392523657676252731186895484227244331982511164875543224648614243615642216164551727621224255321645
|
||||
165625766274415126221387567754684125769562911449418567328954999269442383397657742111976735747616543945193885678317732613823354147551434172254
|
||||
663471266547665567383385744766857544125555773727948178721595766362768764763389283465275425521861727174339179777676482636283377221474131172664
|
||||
552267351614751263715528842613544492131357823275224224529882976386327823433479377684379863655876688634865837667534467375571818473234352527123
|
||||
417167733326125612732158464675728774915115736789599864674655267296528289764653496935556672211933382185491674889326327638863358225141641776661
|
||||
553433447763465113852224382474727588458713673836733584749236658844822472658497492547688383864951836467139432662174767657312876885715517172566
|
||||
667541167336254488524837342876671664656562954852183656576233333873254363945623456596769545333862526193411672878826354158866344875721272113745
|
||||
742742423566122778386568143632291815363624774439785729782249926489483479225989595798258826325346485866553327934443377824316727757316672416437
|
||||
422416173617118884742181153285466515613425316646999647735464985688784946488843572663439527248557925282489796183853745584334188218713316517611
|
||||
763175754752411761475574463499814429498138728567958989277844494897966247687976299566598923968224276327562217938234278212488752542237314351724
|
||||
556357515132757111313386163174758761223833727635896636363788757464722947589395479356794346762935869851131172237499953267126584137242266563332
|
||||
553452514551382115465845459551888517462873873925388334689354634986788558835365333394575696667743754281865874432573149225448868716422314153151
|
||||
727477115766217727216544583899411845473274393224259527268426677665382498542244536749359523368784334883684284657479479623145838735713142311641
|
||||
623775723417856274672723115245954791372868276248326532785676923354468396436867556933672689642689493334426665994793891938554866266411441635464
|
||||
357655727381528486471438934682246867878728953726863365263395378599979499989445494543554685888797994457246284425146494523847682845162841467676
|
||||
713225442368616642825874251457728254726498336436857496884894665436838647759737379449974974472942976778385826682519218241645473616645531255227
|
||||
143115132751882814645234335693993315693492273544964459798578395446856796646994466763377345499557552788438771441525234336612412423834346523211
|
||||
563124357115326738651179813293721543858493473499475888785648678877598767685393985868373765343793387586922432532313835672612126152631344576713
|
||||
161643744871583517778716716592732854695358997554424874653584484749995659355969399657538739855335364842584499341554829664297243422443742217627
|
||||
314417571311644786676857812476382568772944752389723949877773676947654886977363564564656448787568736238564893432112877333626254348575386766736
|
||||
776344328255614461719768964778491246343236536693785358783954458767465334474845788383458739454343787762929647765239152374349167566558438427423
|
||||
352364825562284245598758827867146952949744839636858679487354649333897878699343577583358936494456794644762845245583132395957674685442674213657
|
||||
165116474648463674164854916648534936489844557493948573494559834384533436539877799979968846353597267726398358327688234857762963775536887664434
|
||||
636244476616574846647739459365589464485573472239755849649363338696465548697637638734975433686777966529489995479371427436795444712248542244242
|
||||
637735864354122638598582193357329687493754334369459855467953667653894978798833698638878588356346875628939527283866627761726597671516685427174
|
||||
234265787355773655768346666121735692698653744885738497856483393689674898649577997399958433373787955768454347876736595261379656126328146286411
|
||||
112767655742256845212962577375777649885299555457767374476434484654767654957948859747787796354688878783666798563553685971677619173751653125632
|
||||
571453132563374754428433649129699672752544276898858748974354969458677564456979779546475974859365475874946272453658976328163915151248617627547
|
||||
142583162475317422481573625624997475387877377975334869858698855546579585985975987879498939886539444982256287887973954241619679433725388527327
|
||||
533247585173848868728351547857844568874594368494696993398568756785849787865568456854549687887848656666299259336837539132384839771741428127655
|
||||
615468573841357563119491171796494694742954878467956458799956898567956945658585548466878737443834395395589454855236733372996957432151473455417
|
||||
712281822873644374327211127428577898932274866883739393844879649754568787996648688464479984398399388463589596822886624259697865457588148666664
|
||||
136562416585765349961939548589267679836968874647535938986445975695988894954468499449998546743964657957566429465497651995126318134132576252611
|
||||
664553248645533826876894472974728737829658753737385958889458749467497446995476987665554788833743998485535738446299878511223783418241123523523
|
||||
216673485271213882299775989884276937282689933697933446545787966965866999969865545756445677989389673844562259846887466538876636858727352514172
|
||||
561327416424626319323885947575483566432886775386986678477789875855676946594954878464446759874339786347647885563257274772479849452341218853328
|
||||
543414611273635871798538959594987265275776698754487659699789747885978996899658685697449894894533384458736853354975392764758672388138231227341
|
||||
432177431672385492997519159785924344863965869338385868446897566987758776679699779999948444794449339687467966733362773574493894412663521343826
|
||||
347125512661263615493994284268932764773443456439595658497689867498656657588955796748798799774383987946863496648669435744485628519485388635745
|
||||
234414266212352323439914355995663935835737889578994846678946665969895859876758767589746666587937363599875397364293757755772863517557747336667
|
||||
165677453767745981471984424575369862567689838893465684578767899768788798796576788458996788867998737468547692998985973389685897556471872623552
|
||||
116786112155152692399989767286933237247737645595776648974959499775699595868698769845975468987579485487885883286826659428468372838324282111512
|
||||
377586871572362673428351636972532524637489943754658469776969888985756695665668759579764745956864346579749772568358833311888124717127726527183
|
||||
318164852453224592729434559244754674699557743559876747474974585695598957859985857696997477665456486667857796243525567741256626585522827113358
|
||||
256655568346617621446653354665386832434445968933784544487764789798668576865577679764775445666453683457777446985583583616592962898181266224478
|
||||
722447327541895771712452547924633958699394955868486968595868665886977559577966765766677478787645777643444882329378355275571729256528663733353
|
||||
681245847143816872485464897478336665868833439643778745577556798997858795969859958658867557947956848853484479399665572351893714995112671712542
|
||||
311381662366127117979691628467662497783389559654568448976988776969785977759865769596989799759496863598934465593797484374132873555158552238226
|
||||
457474782125292676291123633778348492667699397478487495797899579777688999595566576657978586657959548666375867799586695984632767442686385738552
|
||||
446616157875894869538721247895884644444883958939694686857454797576766596769678977878866756444843564374954453689422974856237432393117533128483
|
||||
328513874786178732292652989455568257546978333547685649556859556989785958697896996969558664777693669444863357795442386542131312425674116545188
|
||||
747847212285726534863559799474986827436555837479976774676546886866957568785596798586957654994685373975436492788443972514832361138572512654161
|
||||
655775232613722364914271538968599287798576387849966696886855689868858988569956769648644589884777963696793654854647956227921717275975785623654
|
||||
133381381437798727198762329677547326989373878353369696599978596599769677757779877555897759958668785498543442888697699371483636586223726547367
|
||||
166558274267818548162234882895355743538677453683879454994868498865956757789887798484954454444478588833833824986689655715894154174185774415242
|
||||
744372761363824188479933164279993635485947644456865846757657575569785868879855879598958794566895394956885434499837577347367422731518858612887
|
||||
542154878866234222341249936289547276863933653697495455886575579875575878577655884578868949868795478447448539675945826676344156515447648384546
|
||||
727648137147279312991745915569869748967897863693484548957585769676995776768899556467797877594595457565597942644325989896333716781667423243534
|
||||
736513883717638924144115229662225798979374855467873564897654895888778776656646759488994944578647478549466472243343448517571862675853473616864
|
||||
472573641838727179484843174326596238323797674954847658846499779979687897698786957488978957887393589648535875663387463691985638774236788623553
|
||||
124821288351532635578793553795832779774448696673767567977447858477887878676469566499588899639674834547757355447365486454925564374273415537754
|
||||
473366376825217384388358298858346676865647498858449537467576484448696554994844568658866985448999588568865694253572422898257449323363556414355
|
||||
756585744556785281389581638793733695364655945467738676966784699696586944796568967556964687873563733383939393423897564823324453861637182853267
|
||||
565377885838215871729589251946467492483786596678474736965759584646969695859846694554478644897956448493988952388686515531438553966563718473673
|
||||
441237555152315781715534724764569644764966484434597935577849549996797944445598866585975464985538857347348739935777224728123383154322783665212
|
||||
251538277583635525788213179949236983839585564657438535396857976586555596886987597784677479797768335698476345286595542471641181174621263365826
|
||||
462645455814621845373415692662396785686584794946537846843758755467475597488876849747653439958865548869549767695386323199852847441248375338541
|
||||
463546443547812219518172999856822775645249657899384888764384466588464496998699844799448386644993497387873285579539449217398533624347675543541
|
||||
627134585837711668423259691198344552573775794347737374846947567564477798747547569756586957548779437697554747233864289854679427672835612465345
|
||||
453427178468376465724244651434249467592372777377954886698995943799758965795489579878489647936487995475548384882447855836557219515272555272172
|
||||
646164887363484557947971139665942397924584239956839476743645386597748689975975793667755335566355545754464596682873886675359686766371416867421
|
||||
242564673372458178195363168781494567985469634643657747396363336558884388469558778894739837494797653627595967524589231722865526482421344174765
|
||||
527234341744655648884683415323364239475568742248669646473336993435343838488698565959659888897554832493926543963268996957491745744384373681642
|
||||
551517286282283171869299626636836973839926825529596737846853348847465543768893358499548363898668447899594793834437575675969522241126258282432
|
||||
615113281186772747348241311277589768978579523525454785944673364478779885777788637938457768565594782776753548337442956913497758522663855544746
|
||||
642722552558282717243186261369979747472328286247489597466575759788373865579784983835765597583957266269348476872977744141394534221775432834361
|
||||
123255132786848881171289778858576544965558689395978795886845857873584539756667349675894535384688837649796799842596341266977334763116825677354
|
||||
135221265824413236323157332895552381288822335555367339575879847894968958335438953379578775739548683874737377552721612721268151575627367374516
|
||||
531372144561436544581261647461429475295794262997752694655885563973854977878549545376756598298288663367593432222189358593241862862567851525633
|
||||
626241253623585223276449612369373315149376774267977495966454874953877799753954666837937985625362576929726958529984811986441465531615443642317
|
||||
122237265686782174111763222458711389313762597662727299449372464353975654883644949566273662646296682598256439817316833461554838162575673712517
|
||||
723263336441628827211586677967134954541492446275676949475759793974657373976875788542576364482493264736749878125328845632357141826286877316536
|
||||
746376624247554234116778248423662686389547589753843874724295634799738747329256738622227935656823782646258367494222758652264524554281143475725
|
||||
247227652554571866348233254561957766785945979683577957537487658236743744853762365675828364963779438767411174735912626572384742318221667753414
|
||||
461752271733674688288542747127735521232319836579345595948435736687542357563568686627638662657552627936242586561889286338386747748155235227226
|
||||
141456214273548658577623736731491554843413163948364432765456955986253284949329344329743583497259864561513822597516642174356653353313422722126
|
||||
577514122213115543664523815812933592181557923163353748687669465747247978699468957873884592954895372236525435898266267231166186788652617642555
|
||||
733555724377412472456818878267576986747564915594433739398666323228924448924829375982299639364766271435835929364781825316741447833326252417676
|
||||
125222215152346652574685537442585295255477117856958664574265466997244968429967625364878556825897669923262572691766582725557644262753327717362
|
||||
467157357433453135876225656776561727957327836923637932444972557496674222793666868922685325945691218298588167748387555736343614515634266527674
|
||||
661776217564727341161434734284475862238735522767927168825678229454593732375258543947793974965685418316392331831342662517514464432121762671112
|
||||
322226175666414714887813726538477315884488153872775481665957678523393653399286989356544792237258381256625891911364264883241763171167313676775
|
||||
535433463745172562637474314438863546768596275157472615456823332796577429439255648883176346627241779499894798781815684141341115432556456643611
|
||||
114516531415276157226232376712646274882692898428926131576766198472672582965649659239179984932272293221585428551187274518216722651334142336632
|
||||
442465354622731723346571118328123567571116964772317433275893126613648877241944321925876477183764936251413286113213668326238173555355732216511
|
||||
464545125331445744558616761437753623789891666294688255519735998824794952561825912628843557695114221545433384531731727161876473665573223373362
|
||||
212622623666153674544543171825717224778543394854587565145835173211764734896255693756825741544633558375382657436484353324273475751235436535462
|
||||
426456174161671373114214337372228811531433159234863841562359873663253579618768533225871676475124418634651463174367571421653316524135337216611
|
||||
113264262762756157661221337642236412865163476628461551865256687522447798169631776999765762811667378264167441455366366874635763265145354445246
|
||||
426635433223761674317156651435514314141128668545421467652684475967588596316618624557527821975129731666663738726663526335152162713322637353345
|
||||
462625221553613622135255778417362232144315611424115765534629998153728136584747684638152634448139174522524258188274866446444754542614324644434
|
||||
636534326173461144145272421245357854354484176813154881324324289844919955923398583536826126465974374482435317112341641177362167413653631136334
|
||||
416121433661766275322466215778242625365252727337453283172471359263773988811988214463424763681262168421538852447148623325417465263633614152511
|
||||
124165661313426677723346621157741741434378575443131887844322537341118644829916279535424761288166365435817422811564415651251116735711112164331
|
||||
662213565461615664773261415161352365348334351167211364117737811331482474651845215456825315271337675186362621741624741731455143163362536213464
|
||||
353163654655614552631221351147137158834856172472651447352645383627716833776783781867423336224623844544643183687212315514251544774456463166616
|
||||
362441211445555544364416561477266288188517416482572255534821166861673587523181878873186281844855832334752187362742345667727277112563315642334
|
||||
431663234654426537411563411631545147111423513725427621386471155234676712466243246352318626253227328241736815415232666553761366744242426616315
|
||||
226531133633364435742641727266657131716261514281311262288684766444656242277146665425754546527885447432126232726412333341234543363451443141151
|
||||
132441514114413263365254644654352543741828713741248814178464374241323848417341456825584538518825768881832262324114555671261641363331666134362
|
||||
214126421452663325372554676727131463574734212374262156347777366377688162741748146151838743887681761444327446474521671324576334665511114122421
|
||||
351531625361155425124432552645227655625173237845122258431184132246265282346434414371684686452682717564246721521767254276776656342611514416424
|
||||
524134632564656514234312513351122255327641524888853223216877477886352121843137683831631511821167821614336237522461471235761565432361122352514
|
||||
345434525245243335351164562536536325371562644423648433177446878843262728235726362818655267541335336453673667665743636625434415221611313542325
|
||||
352232633361461221226332237671657471766723622375425212675228865561486835238657116512354337544131231554276255267433543145221253624656265664213
|
||||
533341362332521262331624612755675274227615131761716775227664373273765866252331525736334615365731142562664711644136322541112142123112632614445
|
||||
335424225554551224465145365617415232333565263422662657463575357742412565884351458348627343152461236262431544374247365213446446134632223333414
|
531
17/src/colormap.rs
Normal file
531
17/src/colormap.rs
Normal file
@ -0,0 +1,531 @@
|
||||
use termcolor::Color;
|
||||
|
||||
pub struct ColorMap(&'static [Color]);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const COLORMAP_SMOOTH_COOLWARM: ColorMap = ColorMap(&[
|
||||
Color::Rgb(59, 76, 19),
|
||||
Color::Rgb(60, 78, 19),
|
||||
Color::Rgb(61, 80, 19),
|
||||
Color::Rgb(62, 81, 19),
|
||||
Color::Rgb(63, 83, 19),
|
||||
Color::Rgb(64, 85, 20),
|
||||
Color::Rgb(66, 87, 20),
|
||||
Color::Rgb(67, 88, 20),
|
||||
Color::Rgb(68, 90, 20),
|
||||
Color::Rgb(69, 92, 20),
|
||||
Color::Rgb(70, 94, 20),
|
||||
Color::Rgb(72, 95, 20),
|
||||
Color::Rgb(73, 97, 21),
|
||||
Color::Rgb(74, 99, 21),
|
||||
Color::Rgb(75, 100, 21),
|
||||
Color::Rgb(76, 102, 21),
|
||||
Color::Rgb(78, 104, 21),
|
||||
Color::Rgb(79, 106, 21),
|
||||
Color::Rgb(80, 107, 21),
|
||||
Color::Rgb(81, 109, 21),
|
||||
Color::Rgb(83, 111, 22),
|
||||
Color::Rgb(84, 112, 22),
|
||||
Color::Rgb(85, 114, 22),
|
||||
Color::Rgb(86, 116, 22),
|
||||
Color::Rgb(88, 117, 22),
|
||||
Color::Rgb(89, 119, 22),
|
||||
Color::Rgb(90, 120, 22),
|
||||
Color::Rgb(91, 122, 22),
|
||||
Color::Rgb(93, 124, 23),
|
||||
Color::Rgb(94, 125, 23),
|
||||
Color::Rgb(95, 127, 23),
|
||||
Color::Rgb(97, 129, 23),
|
||||
Color::Rgb(98, 130, 23),
|
||||
Color::Rgb(99, 132, 23),
|
||||
Color::Rgb(101, 133, 23),
|
||||
Color::Rgb(102, 135, 23),
|
||||
Color::Rgb(103, 136, 23),
|
||||
Color::Rgb(105, 138, 23),
|
||||
Color::Rgb(106, 140, 24),
|
||||
Color::Rgb(107, 141, 24),
|
||||
Color::Rgb(109, 143, 24),
|
||||
Color::Rgb(110, 144, 24),
|
||||
Color::Rgb(111, 146, 24),
|
||||
Color::Rgb(113, 147, 24),
|
||||
Color::Rgb(114, 149, 24),
|
||||
Color::Rgb(115, 150, 24),
|
||||
Color::Rgb(117, 152, 24),
|
||||
Color::Rgb(118, 153, 24),
|
||||
Color::Rgb(119, 154, 24),
|
||||
Color::Rgb(121, 156, 24),
|
||||
Color::Rgb(122, 157, 24),
|
||||
Color::Rgb(123, 159, 24),
|
||||
Color::Rgb(125, 160, 24),
|
||||
Color::Rgb(126, 162, 25),
|
||||
Color::Rgb(128, 163, 25),
|
||||
Color::Rgb(129, 164, 25),
|
||||
Color::Rgb(130, 166, 25),
|
||||
Color::Rgb(132, 167, 25),
|
||||
Color::Rgb(133, 168, 25),
|
||||
Color::Rgb(134, 170, 25),
|
||||
Color::Rgb(136, 171, 25),
|
||||
Color::Rgb(137, 172, 25),
|
||||
Color::Rgb(139, 174, 25),
|
||||
Color::Rgb(140, 175, 25),
|
||||
Color::Rgb(141, 176, 25),
|
||||
Color::Rgb(143, 177, 25),
|
||||
Color::Rgb(144, 178, 25),
|
||||
Color::Rgb(146, 180, 25),
|
||||
Color::Rgb(147, 181, 25),
|
||||
Color::Rgb(148, 182, 25),
|
||||
Color::Rgb(150, 183, 25),
|
||||
Color::Rgb(151, 184, 25),
|
||||
Color::Rgb(153, 186, 25),
|
||||
Color::Rgb(154, 187, 25),
|
||||
Color::Rgb(155, 188, 25),
|
||||
Color::Rgb(157, 189, 25),
|
||||
Color::Rgb(158, 190, 25),
|
||||
Color::Rgb(159, 191, 25),
|
||||
Color::Rgb(161, 192, 25),
|
||||
Color::Rgb(162, 193, 25),
|
||||
Color::Rgb(163, 194, 25),
|
||||
Color::Rgb(165, 195, 25),
|
||||
Color::Rgb(166, 196, 25),
|
||||
Color::Rgb(168, 197, 25),
|
||||
Color::Rgb(169, 198, 25),
|
||||
Color::Rgb(170, 199, 25),
|
||||
Color::Rgb(172, 200, 25),
|
||||
Color::Rgb(173, 201, 25),
|
||||
Color::Rgb(174, 201, 25),
|
||||
Color::Rgb(176, 202, 25),
|
||||
Color::Rgb(177, 203, 25),
|
||||
Color::Rgb(178, 204, 25),
|
||||
Color::Rgb(180, 205, 25),
|
||||
Color::Rgb(181, 206, 25),
|
||||
Color::Rgb(182, 206, 25),
|
||||
Color::Rgb(183, 207, 24),
|
||||
Color::Rgb(185, 208, 24),
|
||||
Color::Rgb(186, 209, 24),
|
||||
Color::Rgb(187, 209, 24),
|
||||
Color::Rgb(189, 210, 24),
|
||||
Color::Rgb(190, 211, 24),
|
||||
Color::Rgb(191, 211, 24),
|
||||
Color::Rgb(192, 212, 24),
|
||||
Color::Rgb(193, 212, 24),
|
||||
Color::Rgb(195, 213, 24),
|
||||
Color::Rgb(196, 214, 24),
|
||||
Color::Rgb(197, 214, 24),
|
||||
Color::Rgb(198, 215, 24),
|
||||
Color::Rgb(200, 215, 24),
|
||||
Color::Rgb(201, 216, 24),
|
||||
Color::Rgb(202, 216, 23),
|
||||
Color::Rgb(203, 216, 23),
|
||||
Color::Rgb(204, 217, 23),
|
||||
Color::Rgb(205, 217, 23),
|
||||
Color::Rgb(206, 218, 23),
|
||||
Color::Rgb(208, 218, 23),
|
||||
Color::Rgb(209, 218, 23),
|
||||
Color::Rgb(210, 219, 23),
|
||||
Color::Rgb(211, 219, 23),
|
||||
Color::Rgb(212, 219, 23),
|
||||
Color::Rgb(213, 219, 22),
|
||||
Color::Rgb(214, 220, 22),
|
||||
Color::Rgb(215, 220, 22),
|
||||
Color::Rgb(216, 220, 22),
|
||||
Color::Rgb(217, 220, 22),
|
||||
Color::Rgb(218, 220, 22),
|
||||
Color::Rgb(219, 221, 22),
|
||||
Color::Rgb(220, 221, 22),
|
||||
Color::Rgb(221, 220, 22),
|
||||
Color::Rgb(222, 220, 21),
|
||||
Color::Rgb(223, 220, 21),
|
||||
Color::Rgb(225, 219, 21),
|
||||
Color::Rgb(226, 218, 21),
|
||||
Color::Rgb(227, 218, 21),
|
||||
Color::Rgb(228, 217, 21),
|
||||
Color::Rgb(229, 217, 21),
|
||||
Color::Rgb(229, 216, 20),
|
||||
Color::Rgb(230, 216, 20),
|
||||
Color::Rgb(231, 215, 20),
|
||||
Color::Rgb(232, 214, 20),
|
||||
Color::Rgb(233, 214, 20),
|
||||
Color::Rgb(234, 213, 20),
|
||||
Color::Rgb(235, 212, 20),
|
||||
Color::Rgb(235, 211, 19),
|
||||
Color::Rgb(236, 211, 19),
|
||||
Color::Rgb(237, 210, 19),
|
||||
Color::Rgb(238, 209, 19),
|
||||
Color::Rgb(238, 208, 19),
|
||||
Color::Rgb(239, 207, 19),
|
||||
Color::Rgb(239, 206, 18),
|
||||
Color::Rgb(240, 206, 18),
|
||||
Color::Rgb(241, 205, 18),
|
||||
Color::Rgb(241, 204, 18),
|
||||
Color::Rgb(242, 203, 18),
|
||||
Color::Rgb(242, 202, 18),
|
||||
Color::Rgb(243, 201, 18),
|
||||
Color::Rgb(243, 200, 17),
|
||||
Color::Rgb(244, 199, 17),
|
||||
Color::Rgb(244, 198, 17),
|
||||
Color::Rgb(244, 197, 17),
|
||||
Color::Rgb(245, 196, 17),
|
||||
Color::Rgb(245, 195, 17),
|
||||
Color::Rgb(245, 193, 16),
|
||||
Color::Rgb(246, 192, 16),
|
||||
Color::Rgb(246, 191, 16),
|
||||
Color::Rgb(246, 190, 16),
|
||||
Color::Rgb(246, 189, 16),
|
||||
Color::Rgb(247, 188, 16),
|
||||
Color::Rgb(247, 186, 15),
|
||||
Color::Rgb(247, 185, 15),
|
||||
Color::Rgb(247, 184, 15),
|
||||
Color::Rgb(247, 183, 15),
|
||||
Color::Rgb(247, 181, 15),
|
||||
Color::Rgb(247, 180, 15),
|
||||
Color::Rgb(247, 179, 15),
|
||||
Color::Rgb(247, 177, 14),
|
||||
Color::Rgb(247, 176, 14),
|
||||
Color::Rgb(247, 175, 14),
|
||||
Color::Rgb(247, 173, 14),
|
||||
Color::Rgb(247, 172, 14),
|
||||
Color::Rgb(247, 171, 14),
|
||||
Color::Rgb(247, 169, 13),
|
||||
Color::Rgb(247, 168, 13),
|
||||
Color::Rgb(247, 166, 13),
|
||||
Color::Rgb(246, 165, 13),
|
||||
Color::Rgb(246, 163, 13),
|
||||
Color::Rgb(246, 162, 13),
|
||||
Color::Rgb(246, 160, 12),
|
||||
Color::Rgb(245, 159, 12),
|
||||
Color::Rgb(245, 157, 12),
|
||||
Color::Rgb(245, 156, 12),
|
||||
Color::Rgb(244, 154, 12),
|
||||
Color::Rgb(244, 153, 12),
|
||||
Color::Rgb(244, 151, 12),
|
||||
Color::Rgb(243, 149, 11),
|
||||
Color::Rgb(243, 148, 11),
|
||||
Color::Rgb(242, 146, 11),
|
||||
Color::Rgb(242, 144, 11),
|
||||
Color::Rgb(241, 143, 11),
|
||||
Color::Rgb(241, 141, 11),
|
||||
Color::Rgb(240, 139, 11),
|
||||
Color::Rgb(240, 138, 10),
|
||||
Color::Rgb(239, 136, 10),
|
||||
Color::Rgb(238, 134, 10),
|
||||
Color::Rgb(238, 133, 10),
|
||||
Color::Rgb(237, 131, 10),
|
||||
Color::Rgb(237, 129, 10),
|
||||
Color::Rgb(236, 127, 99),
|
||||
Color::Rgb(235, 125, 98),
|
||||
Color::Rgb(234, 124, 96),
|
||||
Color::Rgb(234, 122, 95),
|
||||
Color::Rgb(233, 120, 93),
|
||||
Color::Rgb(232, 118, 92),
|
||||
Color::Rgb(231, 116, 91),
|
||||
Color::Rgb(230, 114, 89),
|
||||
Color::Rgb(229, 112, 88),
|
||||
Color::Rgb(229, 111, 86),
|
||||
Color::Rgb(228, 109, 85),
|
||||
Color::Rgb(227, 107, 84),
|
||||
Color::Rgb(226, 105, 82),
|
||||
Color::Rgb(225, 103, 81),
|
||||
Color::Rgb(224, 101, 79),
|
||||
Color::Rgb(223, 99, 78),
|
||||
Color::Rgb(222, 97, 77),
|
||||
Color::Rgb(221, 95, 75),
|
||||
Color::Rgb(220, 93, 74),
|
||||
Color::Rgb(219, 91, 73),
|
||||
Color::Rgb(218, 89, 71),
|
||||
Color::Rgb(216, 86, 70),
|
||||
Color::Rgb(215, 84, 69),
|
||||
Color::Rgb(214, 82, 68),
|
||||
Color::Rgb(213, 80, 66),
|
||||
Color::Rgb(212, 78, 65),
|
||||
Color::Rgb(211, 76, 64),
|
||||
Color::Rgb(209, 73, 62),
|
||||
Color::Rgb(208, 71, 61),
|
||||
Color::Rgb(207, 69, 60),
|
||||
Color::Rgb(206, 67, 59),
|
||||
Color::Rgb(204, 64, 57),
|
||||
Color::Rgb(203, 62, 56),
|
||||
Color::Rgb(202, 59, 55),
|
||||
Color::Rgb(200, 57, 54),
|
||||
Color::Rgb(199, 54, 53),
|
||||
Color::Rgb(198, 52, 52),
|
||||
Color::Rgb(196, 49, 50),
|
||||
Color::Rgb(195, 46, 49),
|
||||
Color::Rgb(193, 43, 48),
|
||||
Color::Rgb(192, 40, 47),
|
||||
Color::Rgb(191, 37, 46),
|
||||
Color::Rgb(189, 34, 45),
|
||||
Color::Rgb(188, 30, 44),
|
||||
Color::Rgb(186, 26, 43),
|
||||
Color::Rgb(185, 22, 41),
|
||||
Color::Rgb(183, 17, 40),
|
||||
Color::Rgb(182, 11, 39),
|
||||
Color::Rgb(180, 4, 38),
|
||||
]);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const COLORMAP_INFERNO: ColorMap = ColorMap(&[
|
||||
Color::Rgb(0, 0, 4),
|
||||
Color::Rgb(1, 0, 5),
|
||||
Color::Rgb(1, 1, 6),
|
||||
Color::Rgb(1, 1, 8),
|
||||
Color::Rgb(2, 1, 10),
|
||||
Color::Rgb(2, 2, 12),
|
||||
Color::Rgb(2, 2, 14),
|
||||
Color::Rgb(3, 2, 16),
|
||||
Color::Rgb(4, 3, 18),
|
||||
Color::Rgb(4, 3, 20),
|
||||
Color::Rgb(5, 4, 23),
|
||||
Color::Rgb(6, 4, 25),
|
||||
Color::Rgb(7, 5, 27),
|
||||
Color::Rgb(8, 5, 29),
|
||||
Color::Rgb(9, 6, 31),
|
||||
Color::Rgb(10, 7, 34),
|
||||
Color::Rgb(11, 7, 36),
|
||||
Color::Rgb(12, 8, 38),
|
||||
Color::Rgb(13, 8, 41),
|
||||
Color::Rgb(14, 9, 43),
|
||||
Color::Rgb(16, 9, 45),
|
||||
Color::Rgb(17, 10, 48),
|
||||
Color::Rgb(18, 10, 50),
|
||||
Color::Rgb(20, 11, 52),
|
||||
Color::Rgb(21, 11, 55),
|
||||
Color::Rgb(22, 11, 57),
|
||||
Color::Rgb(24, 12, 60),
|
||||
Color::Rgb(25, 12, 62),
|
||||
Color::Rgb(27, 12, 65),
|
||||
Color::Rgb(28, 12, 67),
|
||||
Color::Rgb(30, 12, 69),
|
||||
Color::Rgb(31, 12, 72),
|
||||
Color::Rgb(33, 12, 74),
|
||||
Color::Rgb(35, 12, 76),
|
||||
Color::Rgb(36, 12, 79),
|
||||
Color::Rgb(38, 12, 81),
|
||||
Color::Rgb(40, 11, 83),
|
||||
Color::Rgb(41, 11, 85),
|
||||
Color::Rgb(43, 11, 87),
|
||||
Color::Rgb(45, 11, 89),
|
||||
Color::Rgb(47, 10, 91),
|
||||
Color::Rgb(49, 10, 92),
|
||||
Color::Rgb(50, 10, 94),
|
||||
Color::Rgb(52, 10, 95),
|
||||
Color::Rgb(54, 9, 97),
|
||||
Color::Rgb(56, 9, 98),
|
||||
Color::Rgb(57, 9, 99),
|
||||
Color::Rgb(59, 9, 100),
|
||||
Color::Rgb(61, 9, 101),
|
||||
Color::Rgb(62, 9, 102),
|
||||
Color::Rgb(64, 10, 103),
|
||||
Color::Rgb(66, 10, 104),
|
||||
Color::Rgb(68, 10, 104),
|
||||
Color::Rgb(69, 10, 105),
|
||||
Color::Rgb(71, 11, 106),
|
||||
Color::Rgb(73, 11, 106),
|
||||
Color::Rgb(74, 12, 107),
|
||||
Color::Rgb(76, 12, 107),
|
||||
Color::Rgb(77, 13, 108),
|
||||
Color::Rgb(79, 13, 108),
|
||||
Color::Rgb(81, 14, 108),
|
||||
Color::Rgb(82, 14, 109),
|
||||
Color::Rgb(84, 15, 109),
|
||||
Color::Rgb(85, 15, 109),
|
||||
Color::Rgb(87, 16, 110),
|
||||
Color::Rgb(89, 16, 110),
|
||||
Color::Rgb(90, 17, 110),
|
||||
Color::Rgb(92, 18, 110),
|
||||
Color::Rgb(93, 18, 110),
|
||||
Color::Rgb(95, 19, 110),
|
||||
Color::Rgb(97, 19, 110),
|
||||
Color::Rgb(98, 20, 110),
|
||||
Color::Rgb(100, 21, 110),
|
||||
Color::Rgb(101, 21, 110),
|
||||
Color::Rgb(103, 22, 110),
|
||||
Color::Rgb(105, 22, 110),
|
||||
Color::Rgb(106, 23, 110),
|
||||
Color::Rgb(108, 24, 110),
|
||||
Color::Rgb(109, 24, 110),
|
||||
Color::Rgb(111, 25, 110),
|
||||
Color::Rgb(113, 25, 110),
|
||||
Color::Rgb(114, 26, 110),
|
||||
Color::Rgb(116, 26, 110),
|
||||
Color::Rgb(117, 27, 110),
|
||||
Color::Rgb(119, 28, 109),
|
||||
Color::Rgb(120, 28, 109),
|
||||
Color::Rgb(122, 29, 109),
|
||||
Color::Rgb(124, 29, 109),
|
||||
Color::Rgb(125, 30, 109),
|
||||
Color::Rgb(127, 30, 108),
|
||||
Color::Rgb(128, 31, 108),
|
||||
Color::Rgb(130, 32, 108),
|
||||
Color::Rgb(132, 32, 107),
|
||||
Color::Rgb(133, 33, 107),
|
||||
Color::Rgb(135, 33, 107),
|
||||
Color::Rgb(136, 34, 106),
|
||||
Color::Rgb(138, 34, 106),
|
||||
Color::Rgb(140, 35, 105),
|
||||
Color::Rgb(141, 35, 105),
|
||||
Color::Rgb(143, 36, 105),
|
||||
Color::Rgb(144, 37, 104),
|
||||
Color::Rgb(146, 37, 104),
|
||||
Color::Rgb(147, 38, 103),
|
||||
Color::Rgb(149, 38, 103),
|
||||
Color::Rgb(151, 39, 102),
|
||||
Color::Rgb(152, 39, 102),
|
||||
Color::Rgb(154, 40, 101),
|
||||
Color::Rgb(155, 41, 100),
|
||||
Color::Rgb(157, 41, 100),
|
||||
Color::Rgb(159, 42, 99),
|
||||
Color::Rgb(160, 42, 99),
|
||||
Color::Rgb(162, 43, 98),
|
||||
Color::Rgb(163, 44, 97),
|
||||
Color::Rgb(165, 44, 96),
|
||||
Color::Rgb(166, 45, 96),
|
||||
Color::Rgb(168, 46, 95),
|
||||
Color::Rgb(169, 46, 94),
|
||||
Color::Rgb(171, 47, 94),
|
||||
Color::Rgb(173, 48, 93),
|
||||
Color::Rgb(174, 48, 92),
|
||||
Color::Rgb(176, 49, 91),
|
||||
Color::Rgb(177, 50, 90),
|
||||
Color::Rgb(179, 50, 90),
|
||||
Color::Rgb(180, 51, 89),
|
||||
Color::Rgb(182, 52, 88),
|
||||
Color::Rgb(183, 53, 87),
|
||||
Color::Rgb(185, 53, 86),
|
||||
Color::Rgb(186, 54, 85),
|
||||
Color::Rgb(188, 55, 84),
|
||||
Color::Rgb(189, 56, 83),
|
||||
Color::Rgb(191, 57, 82),
|
||||
Color::Rgb(192, 58, 81),
|
||||
Color::Rgb(193, 58, 80),
|
||||
Color::Rgb(195, 59, 79),
|
||||
Color::Rgb(196, 60, 78),
|
||||
Color::Rgb(198, 61, 77),
|
||||
Color::Rgb(199, 62, 76),
|
||||
Color::Rgb(200, 63, 75),
|
||||
Color::Rgb(202, 64, 74),
|
||||
Color::Rgb(203, 65, 73),
|
||||
Color::Rgb(204, 66, 72),
|
||||
Color::Rgb(206, 67, 71),
|
||||
Color::Rgb(207, 68, 70),
|
||||
Color::Rgb(208, 69, 69),
|
||||
Color::Rgb(210, 70, 68),
|
||||
Color::Rgb(211, 71, 67),
|
||||
Color::Rgb(212, 72, 66),
|
||||
Color::Rgb(213, 74, 65),
|
||||
Color::Rgb(215, 75, 63),
|
||||
Color::Rgb(216, 76, 62),
|
||||
Color::Rgb(217, 77, 61),
|
||||
Color::Rgb(218, 78, 60),
|
||||
Color::Rgb(219, 80, 59),
|
||||
Color::Rgb(221, 81, 58),
|
||||
Color::Rgb(222, 82, 56),
|
||||
Color::Rgb(223, 83, 55),
|
||||
Color::Rgb(224, 85, 54),
|
||||
Color::Rgb(225, 86, 53),
|
||||
Color::Rgb(226, 87, 52),
|
||||
Color::Rgb(227, 89, 51),
|
||||
Color::Rgb(228, 90, 49),
|
||||
Color::Rgb(229, 92, 48),
|
||||
Color::Rgb(230, 93, 47),
|
||||
Color::Rgb(231, 94, 46),
|
||||
Color::Rgb(232, 96, 45),
|
||||
Color::Rgb(233, 97, 43),
|
||||
Color::Rgb(234, 99, 42),
|
||||
Color::Rgb(235, 100, 41),
|
||||
Color::Rgb(235, 102, 40),
|
||||
Color::Rgb(236, 103, 38),
|
||||
Color::Rgb(237, 105, 37),
|
||||
Color::Rgb(238, 106, 36),
|
||||
Color::Rgb(239, 108, 35),
|
||||
Color::Rgb(239, 110, 33),
|
||||
Color::Rgb(240, 111, 32),
|
||||
Color::Rgb(241, 113, 31),
|
||||
Color::Rgb(241, 115, 29),
|
||||
Color::Rgb(242, 116, 28),
|
||||
Color::Rgb(243, 118, 27),
|
||||
Color::Rgb(243, 120, 25),
|
||||
Color::Rgb(244, 121, 24),
|
||||
Color::Rgb(245, 123, 23),
|
||||
Color::Rgb(245, 125, 21),
|
||||
Color::Rgb(246, 126, 20),
|
||||
Color::Rgb(246, 128, 19),
|
||||
Color::Rgb(247, 130, 18),
|
||||
Color::Rgb(247, 132, 16),
|
||||
Color::Rgb(248, 133, 15),
|
||||
Color::Rgb(248, 135, 14),
|
||||
Color::Rgb(248, 137, 12),
|
||||
Color::Rgb(249, 139, 11),
|
||||
Color::Rgb(249, 140, 10),
|
||||
Color::Rgb(249, 142, 9),
|
||||
Color::Rgb(250, 144, 8),
|
||||
Color::Rgb(250, 146, 7),
|
||||
Color::Rgb(250, 148, 7),
|
||||
Color::Rgb(251, 150, 6),
|
||||
Color::Rgb(251, 151, 6),
|
||||
Color::Rgb(251, 153, 6),
|
||||
Color::Rgb(251, 155, 6),
|
||||
Color::Rgb(251, 157, 7),
|
||||
Color::Rgb(252, 159, 7),
|
||||
Color::Rgb(252, 161, 8),
|
||||
Color::Rgb(252, 163, 9),
|
||||
Color::Rgb(252, 165, 10),
|
||||
Color::Rgb(252, 166, 12),
|
||||
Color::Rgb(252, 168, 13),
|
||||
Color::Rgb(252, 170, 15),
|
||||
Color::Rgb(252, 172, 17),
|
||||
Color::Rgb(252, 174, 18),
|
||||
Color::Rgb(252, 176, 20),
|
||||
Color::Rgb(252, 178, 22),
|
||||
Color::Rgb(252, 180, 24),
|
||||
Color::Rgb(251, 182, 26),
|
||||
Color::Rgb(251, 184, 29),
|
||||
Color::Rgb(251, 186, 31),
|
||||
Color::Rgb(251, 188, 33),
|
||||
Color::Rgb(251, 190, 35),
|
||||
Color::Rgb(250, 192, 38),
|
||||
Color::Rgb(250, 194, 40),
|
||||
Color::Rgb(250, 196, 42),
|
||||
Color::Rgb(250, 198, 45),
|
||||
Color::Rgb(249, 199, 47),
|
||||
Color::Rgb(249, 201, 50),
|
||||
Color::Rgb(249, 203, 53),
|
||||
Color::Rgb(248, 205, 55),
|
||||
Color::Rgb(248, 207, 58),
|
||||
Color::Rgb(247, 209, 61),
|
||||
Color::Rgb(247, 211, 64),
|
||||
Color::Rgb(246, 213, 67),
|
||||
Color::Rgb(246, 215, 70),
|
||||
Color::Rgb(245, 217, 73),
|
||||
Color::Rgb(245, 219, 76),
|
||||
Color::Rgb(244, 221, 79),
|
||||
Color::Rgb(244, 223, 83),
|
||||
Color::Rgb(244, 225, 86),
|
||||
Color::Rgb(243, 227, 90),
|
||||
Color::Rgb(243, 229, 93),
|
||||
Color::Rgb(242, 230, 97),
|
||||
Color::Rgb(242, 232, 101),
|
||||
Color::Rgb(242, 234, 105),
|
||||
Color::Rgb(241, 236, 109),
|
||||
Color::Rgb(241, 237, 113),
|
||||
Color::Rgb(241, 239, 117),
|
||||
Color::Rgb(241, 241, 121),
|
||||
Color::Rgb(242, 242, 125),
|
||||
Color::Rgb(242, 244, 130),
|
||||
Color::Rgb(243, 245, 134),
|
||||
Color::Rgb(243, 246, 138),
|
||||
Color::Rgb(244, 248, 142),
|
||||
Color::Rgb(245, 249, 146),
|
||||
Color::Rgb(246, 250, 150),
|
||||
Color::Rgb(248, 251, 154),
|
||||
Color::Rgb(249, 252, 157),
|
||||
Color::Rgb(250, 253, 161),
|
||||
Color::Rgb(252, 255, 164),
|
||||
]);
|
||||
|
||||
impl ColorMap {
|
||||
pub fn apply(&self, val: f64) -> Color {
|
||||
assert!(val >= 0.0 && val <= 1.0);
|
||||
let position = (val * 255.0).ceil() as usize;
|
||||
self.0[position]
|
||||
}
|
||||
}
|
481
17/src/main.rs
Normal file
481
17/src/main.rs
Normal file
@ -0,0 +1,481 @@
|
||||
use colormap::ColorMap;
|
||||
use std::collections::hash_map::RandomState;
|
||||
use std::collections::{BinaryHeap, HashMap};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines, Write};
|
||||
use std::iter::repeat;
|
||||
use std::time::Instant;
|
||||
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
|
||||
|
||||
mod colormap;
|
||||
|
||||
const COLORMAP: &ColorMap = &colormap::COLORMAP_INFERNO;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// DATA
|
||||
|
||||
const UNPATH_CHAR: char = '█';
|
||||
const UNVISITED_CHAR: char = ' ';
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
const fn all() -> &'static [Self; 4] {
|
||||
&[
|
||||
Direction::Left,
|
||||
Direction::Right,
|
||||
Direction::Up,
|
||||
Direction::Down,
|
||||
]
|
||||
}
|
||||
const fn opposite(&self) -> Self {
|
||||
match self {
|
||||
Direction::Left => Direction::Right,
|
||||
Direction::Right => Direction::Left,
|
||||
Direction::Up => Direction::Down,
|
||||
Direction::Down => Direction::Up,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Direction> for char {
|
||||
fn from(dir: &Direction) -> Self {
|
||||
match dir {
|
||||
Direction::Left => '←',
|
||||
Direction::Right => '→',
|
||||
Direction::Up => '↑',
|
||||
Direction::Down => '↓',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CityMap {
|
||||
map: Vec<Vec<u64>>,
|
||||
}
|
||||
|
||||
impl CityMap {
|
||||
fn offset_pos(&self, pos: (usize, usize), dir: &Direction) -> Option<(usize, usize)> {
|
||||
match dir {
|
||||
Direction::Left if pos.0 > 0 => Some((pos.0 - 1, pos.1)),
|
||||
Direction::Right if pos.0 < self.map[0].len() - 1 => Some((pos.0 + 1, pos.1)),
|
||||
Direction::Up if pos.1 > 0 => Some((pos.0, pos.1 - 1)),
|
||||
Direction::Down if pos.1 < self.map.len() - 1 => Some((pos.0, pos.1 + 1)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
fn print(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let cost_max = *self.map.iter().flat_map(|row| row.iter()).max().unwrap() as f64;
|
||||
|
||||
let mut so_lock = StandardStream::stdout(ColorChoice::Always);
|
||||
for y in 0..self.map.len() {
|
||||
for val in &self.map[y] {
|
||||
so_lock.set_color(
|
||||
ColorSpec::new()
|
||||
.set_bg(Some(COLORMAP.apply(*val as f64 / cost_max)))
|
||||
.set_fg(Some(Color::Black)),
|
||||
)?;
|
||||
so_lock.write_fmt(format_args!("{}", val))?;
|
||||
}
|
||||
so_lock.reset()?;
|
||||
writeln!(so_lock)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
type Position = (usize, usize);
|
||||
|
||||
struct WalkCost<'a> {
|
||||
start: Position,
|
||||
cost_from: Vec<Vec<HashMap<(Direction, usize), u64>>>,
|
||||
map: &'a CityMap,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Move {
|
||||
new_pos: Position,
|
||||
dir: &'static Direction,
|
||||
consecutive: usize,
|
||||
weight: u64,
|
||||
}
|
||||
|
||||
impl PartialEq for Move {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.weight == other.weight
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Move {}
|
||||
|
||||
impl PartialOrd for Move {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Move {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
std::cmp::Reverse(self.weight).cmp(&std::cmp::Reverse(other.weight))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> WalkCost<'a> {
|
||||
fn from_map(map: &'a CityMap, start: Position) -> Self {
|
||||
Self {
|
||||
map,
|
||||
start,
|
||||
cost_from: map
|
||||
.map
|
||||
.iter()
|
||||
.map(|row| repeat(HashMap::new()).take(row.len()).collect())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
fn compute(&mut self) {
|
||||
let mut unvisited_next_moves: BinaryHeap<Move> = BinaryHeap::new();
|
||||
let valid_start_moves: Vec<Move> = Direction::all()
|
||||
.iter()
|
||||
.filter_map(|dir| {
|
||||
self.map.offset_pos(self.start, dir).and_then(|pos| {
|
||||
Some(Move {
|
||||
new_pos: pos,
|
||||
dir,
|
||||
consecutive: 1,
|
||||
weight: self.map.map[pos.1][pos.0],
|
||||
})
|
||||
})
|
||||
}) // valid positions
|
||||
.collect();
|
||||
|
||||
for m in valid_start_moves {
|
||||
unvisited_next_moves.push(m);
|
||||
}
|
||||
|
||||
while let Some(cur_move) = unvisited_next_moves.pop() {
|
||||
// we've been here already at a lower cost
|
||||
// if cur_move.weight >= self.cost_to[cur_move.new_pos.1][cur_move.new_pos.0] {
|
||||
// continue;
|
||||
// }
|
||||
if let Some(last_weight) = self.cost_from[cur_move.new_pos.1][cur_move.new_pos.0]
|
||||
.get(&(*cur_move.dir, cur_move.consecutive))
|
||||
{
|
||||
if cur_move.weight < *last_weight {
|
||||
self.cost_from[cur_move.new_pos.1][cur_move.new_pos.0]
|
||||
.insert((*cur_move.dir, cur_move.consecutive), cur_move.weight);
|
||||
} else {
|
||||
continue;
|
||||
} // visited before at lower cost }
|
||||
} else {
|
||||
self.cost_from[cur_move.new_pos.1][cur_move.new_pos.0]
|
||||
.insert((*cur_move.dir, cur_move.consecutive), cur_move.weight);
|
||||
}
|
||||
// println!("state at {:?}: {:?}", cur_move, self.cost_from[cur_move.new_pos.1][cur_move.new_pos.0]);
|
||||
|
||||
let valid_moves = Direction::all().iter().filter_map(|dir| {
|
||||
self.map
|
||||
.offset_pos(cur_move.new_pos, dir)
|
||||
.and_then(|new_pos| {
|
||||
Some(Move {
|
||||
new_pos,
|
||||
dir,
|
||||
consecutive: if cur_move.dir == dir {
|
||||
cur_move.consecutive + 1
|
||||
} else {
|
||||
1
|
||||
},
|
||||
weight: cur_move.weight + self.map.map[new_pos.1][new_pos.0],
|
||||
})
|
||||
})
|
||||
.filter(|m| m.consecutive != 4 && *m.dir != cur_move.dir.opposite())
|
||||
.filter(|m| {
|
||||
m.weight
|
||||
< *self.cost_from[m.new_pos.1][m.new_pos.0]
|
||||
.get(&(*m.dir, m.consecutive))
|
||||
.unwrap_or(&u64::MAX)
|
||||
})
|
||||
}); // valid positions
|
||||
// println!("valid moves with {:?}", cur_move);
|
||||
for next_move in valid_moves {
|
||||
// println!(" {:?}", next_move);
|
||||
unvisited_next_moves.push(next_move);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WalkCost2<'a> {
|
||||
start: Position,
|
||||
cost_from: Vec<Vec<HashMap<(Direction, usize), u64>>>,
|
||||
map: &'a CityMap,
|
||||
}
|
||||
|
||||
impl<'a> WalkCost2<'a> {
|
||||
fn from_map(map: &'a CityMap, start: Position) -> Self {
|
||||
Self {
|
||||
map,
|
||||
start,
|
||||
cost_from: map
|
||||
.map
|
||||
.iter()
|
||||
.map(|row| repeat(HashMap::new()).take(row.len()).collect())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
fn min_cost_at(&self, pos: Position) -> Option<&u64> {
|
||||
self.cost_from[pos.1][pos.0].values().min()
|
||||
}
|
||||
fn compute(&mut self, to: Position) {
|
||||
let mut unvisited_next_moves: BinaryHeap<Move> = BinaryHeap::new();
|
||||
let valid_start_moves: Vec<Move> = Direction::all()
|
||||
.iter()
|
||||
.filter_map(|dir| {
|
||||
self.map.offset_pos(self.start, dir).and_then(|pos| {
|
||||
Some(Move {
|
||||
new_pos: pos,
|
||||
dir,
|
||||
consecutive: 1,
|
||||
weight: self.map.map[pos.1][pos.0],
|
||||
})
|
||||
})
|
||||
}) // valid positions
|
||||
.collect();
|
||||
|
||||
for m in valid_start_moves {
|
||||
unvisited_next_moves.push(m);
|
||||
}
|
||||
|
||||
while let Some(cur_move) = unvisited_next_moves.pop() {
|
||||
// we've been here already at a lower cost
|
||||
// if cur_move.weight >= self.cost_to[cur_move.new_pos.1][cur_move.new_pos.0] {
|
||||
// continue;
|
||||
// }
|
||||
if let Some(last_weight) = self.cost_from[cur_move.new_pos.1][cur_move.new_pos.0]
|
||||
.get(&(*cur_move.dir, cur_move.consecutive))
|
||||
{
|
||||
if cur_move.weight < *last_weight {
|
||||
self.cost_from[cur_move.new_pos.1][cur_move.new_pos.0]
|
||||
.insert((*cur_move.dir, cur_move.consecutive), cur_move.weight);
|
||||
// println!("move {:?} inserted {:?}", cur_move, (*cur_move.dir, cur_move.consecutive));
|
||||
} else {
|
||||
continue;
|
||||
} // visited before at lower cost }
|
||||
} else {
|
||||
// println!("move {:?} inserted {:?}", cur_move, (*cur_move.dir, cur_move.consecutive));
|
||||
self.cost_from[cur_move.new_pos.1][cur_move.new_pos.0]
|
||||
.insert((*cur_move.dir, cur_move.consecutive), cur_move.weight);
|
||||
}
|
||||
|
||||
if cur_move.new_pos == to {
|
||||
// println!("reached end pos {:?} via {:?}", to, cur_move);
|
||||
continue;
|
||||
}
|
||||
let valid_moves = Direction::all().iter().filter_map(|dir| {
|
||||
self.map
|
||||
.offset_pos(cur_move.new_pos, dir)
|
||||
.and_then(|new_pos| {
|
||||
Some(Move {
|
||||
new_pos,
|
||||
dir,
|
||||
consecutive: if cur_move.dir == dir {
|
||||
cur_move.consecutive + 1
|
||||
} else {
|
||||
1
|
||||
},
|
||||
weight: cur_move.weight + self.map.map[new_pos.1][new_pos.0],
|
||||
})
|
||||
})
|
||||
.filter(|m| m.new_pos != self.start)
|
||||
.filter(|m| *m.dir != cur_move.dir.opposite())
|
||||
.filter(|m| {
|
||||
if m.dir == cur_move.dir {
|
||||
m.consecutive < 11
|
||||
} else {
|
||||
cur_move.consecutive >= 4
|
||||
}
|
||||
})
|
||||
.filter(|m| m.new_pos != to || m.consecutive >= 4)
|
||||
.filter(|m| {
|
||||
m.weight
|
||||
< *self.cost_from[m.new_pos.1][m.new_pos.0]
|
||||
.get(&(*m.dir, m.consecutive))
|
||||
.unwrap_or(&u64::MAX)
|
||||
})
|
||||
}); // valid positions
|
||||
// println!("valid moves with {:?}", cur_move);
|
||||
for next_move in valid_moves {
|
||||
// println!(" {:?}", next_move);
|
||||
unvisited_next_moves.push(next_move);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn shortest_path_to(&self, to: Position) -> Vec<(Position, Direction)> {
|
||||
let mut path = Vec::new();
|
||||
let mut cur_pos = to;
|
||||
// start at the end, walk backwards
|
||||
while cur_pos != self.start {
|
||||
let (m, _val) = self.cost_from[cur_pos.1][cur_pos.0]
|
||||
.iter()
|
||||
.min_by(|a, b| a.1.cmp(b.1))
|
||||
.unwrap();
|
||||
path.push((cur_pos, m.0));
|
||||
cur_pos = self.map.offset_pos(cur_pos, &m.0.opposite()).unwrap();
|
||||
}
|
||||
path
|
||||
}
|
||||
fn print_path(&self, to: Position) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let path = self.shortest_path_to(to);
|
||||
let map: HashMap<_, _, RandomState> = HashMap::from_iter(path.into_iter());
|
||||
let cost_max_of_min = *self
|
||||
.cost_from
|
||||
.iter()
|
||||
.flat_map(|row| row.iter().filter_map(|cell| cell.values().min()))
|
||||
.max()
|
||||
.unwrap() as f64;
|
||||
let mut so_lock = StandardStream::stdout(ColorChoice::Always);
|
||||
|
||||
for y in 0..self.cost_from.len() {
|
||||
for x in 0..self.map.map[y].len() {
|
||||
let mut color = ColorSpec::new();
|
||||
let c = if let Some(to_dir) = map.get(&(x, y)) {
|
||||
let normalized_cost =
|
||||
*self.min_cost_at((x, y)).unwrap() as f64 / cost_max_of_min;
|
||||
let bg_color = COLORMAP.apply(normalized_cost);
|
||||
let fg_color = if let Color::Rgb(r, g, b) = bg_color {
|
||||
Color::Rgb(255 - r, 255 - g, 255 - b)
|
||||
} else {
|
||||
Color::Black
|
||||
};
|
||||
color.set_fg(Some(fg_color)).set_bg(Some(bg_color)).bold();
|
||||
to_dir.into()
|
||||
} else {
|
||||
if let Some(cost) = &self.min_cost_at((x, y)) {
|
||||
color.set_fg(Some(COLORMAP.apply(**cost as f64 / cost_max_of_min)));
|
||||
UNPATH_CHAR
|
||||
} else {
|
||||
color.set_fg(Some(Color::Black));
|
||||
UNVISITED_CHAR
|
||||
}
|
||||
};
|
||||
so_lock.set_color(&color)?;
|
||||
let mut char_buf = [0u8; 4];
|
||||
c.encode_utf8(&mut char_buf);
|
||||
so_lock.write_all(&char_buf)?;
|
||||
}
|
||||
so_lock.reset()?;
|
||||
writeln!(so_lock)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for CityMap {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
Self {
|
||||
map: lines
|
||||
.map(|l| l.unwrap().chars().map(|c| c as u64 - '0' as u64).collect())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let map = CityMap::from(input);
|
||||
let mut costs = WalkCost::from_map(&map, (0, 0));
|
||||
costs.compute();
|
||||
|
||||
// println!("{}", costs);
|
||||
// costs.print_shortest_path((costs.cost_to[0].len() - 1, costs.cost_to.len() - 1));
|
||||
|
||||
*costs.cost_from[costs.cost_from.len() - 1][costs.cost_from[0].len() - 1]
|
||||
.values()
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let map = CityMap::from(input);
|
||||
// map.print().unwrap();
|
||||
let mut costs = WalkCost2::from_map(&map, (0, 0));
|
||||
costs.compute((map.map[0].len() - 1, map.map.len() - 1));
|
||||
|
||||
// println!("{}", costs);
|
||||
costs
|
||||
.print_path((costs.cost_from[0].len() - 1, costs.cost_from.len() - 1))
|
||||
.unwrap();
|
||||
|
||||
*costs.cost_from[costs.cost_from.len() - 1][costs.cost_from[0].len() - 1]
|
||||
.values()
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
use test_case::test_case;
|
||||
|
||||
const EXAMPLE: &str = &"2413432311323
|
||||
3215453535623
|
||||
3255245654254
|
||||
3446585845452
|
||||
4546657867536
|
||||
1438598798454
|
||||
4457876987766
|
||||
3637877979653
|
||||
4654967986887
|
||||
4564679986453
|
||||
1224686865563
|
||||
2546548887735
|
||||
4322674655533";
|
||||
|
||||
const EXAMPLE2: &str = &"111111111111
|
||||
999999999991
|
||||
999999999991
|
||||
999999999991
|
||||
999999999991";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 102);
|
||||
}
|
||||
|
||||
#[test_case(EXAMPLE, 94)]
|
||||
#[test_case(EXAMPLE2, 71)]
|
||||
fn problem2_example(example: &str, expect: u64) {
|
||||
let c = Cursor::new(example);
|
||||
assert_eq!(problem2(c.lines()), expect);
|
||||
}
|
||||
}
|
25
18/Cargo.lock
generated
Normal file
25
18/Cargo.lock
generated
Normal file
@ -0,0 +1,25 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day18"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
9
18/Cargo.toml
Normal file
9
18/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "day18"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.12.0"
|
640
18/input
Normal file
640
18/input
Normal file
@ -0,0 +1,640 @@
|
||||
L 4 (#248a72)
|
||||
U 3 (#295c13)
|
||||
L 4 (#49e802)
|
||||
U 5 (#5ff8b3)
|
||||
R 3 (#0df642)
|
||||
U 2 (#15b973)
|
||||
R 5 (#6cfb92)
|
||||
U 11 (#4e3cd3)
|
||||
L 4 (#422dd0)
|
||||
D 5 (#303fe3)
|
||||
L 7 (#6225e0)
|
||||
D 2 (#58bd63)
|
||||
L 9 (#6225e2)
|
||||
D 8 (#2b1703)
|
||||
L 6 (#422dd2)
|
||||
D 9 (#2eb9b3)
|
||||
L 2 (#10f270)
|
||||
D 10 (#0677b3)
|
||||
L 4 (#190450)
|
||||
U 11 (#55b4e3)
|
||||
L 4 (#361732)
|
||||
U 3 (#034663)
|
||||
L 4 (#37f902)
|
||||
U 6 (#19bb73)
|
||||
R 8 (#6e1030)
|
||||
U 8 (#4cad93)
|
||||
L 4 (#2509d0)
|
||||
U 6 (#1e1e61)
|
||||
L 5 (#3d3b90)
|
||||
U 8 (#28ec81)
|
||||
L 2 (#3f9200)
|
||||
U 5 (#437871)
|
||||
L 6 (#174bc0)
|
||||
D 5 (#3b58a1)
|
||||
L 11 (#064a60)
|
||||
U 5 (#539da3)
|
||||
L 4 (#1ea0d0)
|
||||
D 7 (#1909b3)
|
||||
L 2 (#296a52)
|
||||
D 9 (#6780c3)
|
||||
L 3 (#296a50)
|
||||
U 11 (#356893)
|
||||
L 2 (#0eb430)
|
||||
U 5 (#019203)
|
||||
L 5 (#4eea10)
|
||||
U 4 (#436533)
|
||||
L 4 (#20aeb0)
|
||||
U 4 (#2fb883)
|
||||
L 6 (#5046c0)
|
||||
U 11 (#392293)
|
||||
R 8 (#2567a0)
|
||||
U 3 (#57ee03)
|
||||
R 12 (#270540)
|
||||
U 2 (#358173)
|
||||
R 6 (#289e40)
|
||||
U 2 (#77b991)
|
||||
R 4 (#016c10)
|
||||
U 11 (#351091)
|
||||
R 2 (#714f90)
|
||||
U 6 (#4add71)
|
||||
L 11 (#00eab0)
|
||||
D 5 (#2f8361)
|
||||
L 8 (#192200)
|
||||
U 5 (#1416c1)
|
||||
L 13 (#775d30)
|
||||
U 3 (#3d3d63)
|
||||
L 8 (#6e4710)
|
||||
U 3 (#28cfd3)
|
||||
L 8 (#389880)
|
||||
U 5 (#28cfd1)
|
||||
L 7 (#4cd750)
|
||||
D 5 (#1d56e3)
|
||||
L 3 (#2789e2)
|
||||
D 5 (#5d7573)
|
||||
R 9 (#1b1372)
|
||||
D 5 (#1965a3)
|
||||
R 4 (#111052)
|
||||
D 2 (#5a2861)
|
||||
R 10 (#37f1c2)
|
||||
D 3 (#0b7ad1)
|
||||
R 5 (#012162)
|
||||
U 5 (#226f43)
|
||||
R 4 (#583cd2)
|
||||
D 5 (#4333f3)
|
||||
R 5 (#0eb952)
|
||||
D 3 (#22a273)
|
||||
L 2 (#34c5d0)
|
||||
D 3 (#355f11)
|
||||
L 5 (#13a460)
|
||||
D 4 (#355f13)
|
||||
L 6 (#3e2900)
|
||||
U 4 (#28d423)
|
||||
L 8 (#042432)
|
||||
D 3 (#4378f3)
|
||||
L 6 (#18a200)
|
||||
D 5 (#16a843)
|
||||
L 5 (#18a202)
|
||||
D 7 (#46fdd3)
|
||||
L 5 (#2a4802)
|
||||
D 5 (#2a4d23)
|
||||
L 5 (#6049d2)
|
||||
D 4 (#0a4023)
|
||||
L 4 (#09afb2)
|
||||
U 4 (#687713)
|
||||
L 5 (#4b85f2)
|
||||
D 4 (#0e1a53)
|
||||
L 8 (#331b60)
|
||||
U 6 (#270d83)
|
||||
L 6 (#331b62)
|
||||
U 6 (#25dba3)
|
||||
L 6 (#412e82)
|
||||
D 6 (#5e2e73)
|
||||
L 8 (#1de802)
|
||||
U 6 (#1e7143)
|
||||
L 4 (#4e7e82)
|
||||
U 3 (#160d63)
|
||||
L 5 (#19d230)
|
||||
U 3 (#36a4a3)
|
||||
R 3 (#19d232)
|
||||
U 6 (#4c63b3)
|
||||
R 10 (#0d2862)
|
||||
U 5 (#0ec351)
|
||||
R 11 (#593c62)
|
||||
U 6 (#12de21)
|
||||
R 2 (#08d482)
|
||||
U 4 (#277081)
|
||||
R 3 (#10eee0)
|
||||
U 4 (#382b91)
|
||||
L 4 (#512200)
|
||||
U 7 (#1279f1)
|
||||
L 3 (#229312)
|
||||
U 6 (#422721)
|
||||
R 6 (#71ddd2)
|
||||
U 6 (#093871)
|
||||
R 13 (#0d5622)
|
||||
D 5 (#093873)
|
||||
R 7 (#4c34e2)
|
||||
U 6 (#5b1743)
|
||||
R 2 (#4779a2)
|
||||
D 6 (#1cc6e3)
|
||||
R 7 (#3c13a0)
|
||||
U 5 (#3b60f3)
|
||||
R 4 (#3c13a2)
|
||||
U 9 (#229f83)
|
||||
R 3 (#0a6ff2)
|
||||
D 2 (#06d231)
|
||||
R 8 (#0298b2)
|
||||
D 11 (#4eb6a1)
|
||||
R 7 (#0298b0)
|
||||
U 8 (#438ce1)
|
||||
R 7 (#0e69e2)
|
||||
U 5 (#2d3e73)
|
||||
R 8 (#40b2c2)
|
||||
U 6 (#64cb53)
|
||||
L 2 (#40b2c0)
|
||||
U 3 (#0215c3)
|
||||
L 3 (#2cbf42)
|
||||
U 4 (#00c523)
|
||||
L 7 (#1fc3d2)
|
||||
D 4 (#68a633)
|
||||
L 5 (#1fc3d0)
|
||||
U 5 (#149853)
|
||||
L 5 (#2cbf40)
|
||||
U 9 (#0b9613)
|
||||
L 3 (#1e7f00)
|
||||
U 8 (#2fc533)
|
||||
L 7 (#3d7180)
|
||||
U 3 (#33f3a3)
|
||||
R 9 (#66d340)
|
||||
U 2 (#0fa1f1)
|
||||
R 4 (#0546c0)
|
||||
D 6 (#4c00b3)
|
||||
R 8 (#483b50)
|
||||
U 6 (#4c00b1)
|
||||
R 4 (#2fc7c0)
|
||||
U 2 (#0fa1f3)
|
||||
R 7 (#377280)
|
||||
U 6 (#200c43)
|
||||
R 5 (#429ef0)
|
||||
U 3 (#3a90f1)
|
||||
R 5 (#226142)
|
||||
U 4 (#2740c1)
|
||||
R 5 (#41ac62)
|
||||
U 3 (#275423)
|
||||
R 2 (#3ba072)
|
||||
U 11 (#275421)
|
||||
R 4 (#27ea92)
|
||||
D 8 (#402001)
|
||||
R 2 (#3456c0)
|
||||
D 6 (#5a4541)
|
||||
R 3 (#4d1400)
|
||||
U 4 (#5a4543)
|
||||
R 6 (#462de0)
|
||||
U 8 (#3fcdb1)
|
||||
R 6 (#1f2d90)
|
||||
U 6 (#4e7851)
|
||||
R 3 (#41eb30)
|
||||
D 6 (#4e7853)
|
||||
R 4 (#1aa1c0)
|
||||
D 10 (#0a4073)
|
||||
R 6 (#2134b2)
|
||||
D 7 (#164e43)
|
||||
R 4 (#200c72)
|
||||
D 5 (#3beca3)
|
||||
R 6 (#7445e0)
|
||||
U 3 (#2cda83)
|
||||
R 4 (#7445e2)
|
||||
U 3 (#475553)
|
||||
L 5 (#200c70)
|
||||
U 10 (#23fb33)
|
||||
R 5 (#2134b0)
|
||||
U 7 (#3c98d3)
|
||||
L 4 (#4cfc80)
|
||||
U 5 (#0f0e71)
|
||||
R 8 (#3c1d22)
|
||||
U 10 (#23a311)
|
||||
R 6 (#05da32)
|
||||
D 5 (#6229c1)
|
||||
R 5 (#41f750)
|
||||
D 8 (#1f4191)
|
||||
R 3 (#3530f0)
|
||||
D 13 (#4d3941)
|
||||
R 3 (#6215e0)
|
||||
D 9 (#2fe911)
|
||||
R 6 (#05cf90)
|
||||
U 4 (#25c901)
|
||||
R 2 (#335232)
|
||||
U 12 (#271371)
|
||||
R 2 (#335230)
|
||||
U 5 (#2bd1d1)
|
||||
L 9 (#1ffad0)
|
||||
U 6 (#6f6bc1)
|
||||
R 9 (#099600)
|
||||
U 5 (#13bee1)
|
||||
R 3 (#5aa820)
|
||||
U 3 (#3546c1)
|
||||
R 6 (#4dd5f0)
|
||||
D 11 (#495be1)
|
||||
R 6 (#60c8e0)
|
||||
U 11 (#4bd201)
|
||||
R 4 (#367f30)
|
||||
D 4 (#43dbc1)
|
||||
R 6 (#4bb740)
|
||||
U 12 (#07ce11)
|
||||
R 6 (#4b4d70)
|
||||
D 12 (#3e29e1)
|
||||
R 5 (#313fc0)
|
||||
U 4 (#293d51)
|
||||
R 4 (#1b4860)
|
||||
U 11 (#514571)
|
||||
R 4 (#5c11a2)
|
||||
U 4 (#444841)
|
||||
R 8 (#5c11a0)
|
||||
U 2 (#3e6c51)
|
||||
R 11 (#16dab0)
|
||||
U 7 (#26baf1)
|
||||
R 2 (#32e240)
|
||||
U 5 (#26baf3)
|
||||
R 6 (#2f0a70)
|
||||
U 6 (#11a821)
|
||||
R 3 (#527fc0)
|
||||
U 7 (#468b31)
|
||||
R 6 (#0641a0)
|
||||
U 10 (#20f351)
|
||||
R 7 (#547a90)
|
||||
U 12 (#1dbf11)
|
||||
R 2 (#17d0d2)
|
||||
U 10 (#159981)
|
||||
R 6 (#634e12)
|
||||
U 5 (#4ff021)
|
||||
R 10 (#006122)
|
||||
D 6 (#6589a3)
|
||||
R 3 (#1a74f2)
|
||||
D 2 (#19b911)
|
||||
R 12 (#3ed5f2)
|
||||
D 5 (#28ab31)
|
||||
R 3 (#09dd82)
|
||||
D 5 (#614c01)
|
||||
R 6 (#284d32)
|
||||
D 9 (#06b521)
|
||||
R 8 (#4dfad2)
|
||||
D 7 (#5b0f61)
|
||||
R 2 (#0fff22)
|
||||
D 5 (#1e6ff1)
|
||||
R 2 (#47b352)
|
||||
D 9 (#29c291)
|
||||
R 5 (#352ef2)
|
||||
D 3 (#042d11)
|
||||
R 4 (#262542)
|
||||
D 7 (#042d13)
|
||||
R 4 (#21e8f2)
|
||||
D 3 (#18cc21)
|
||||
R 3 (#16ed70)
|
||||
U 9 (#270ea1)
|
||||
R 7 (#4391e0)
|
||||
U 9 (#270ea3)
|
||||
R 4 (#22bdd0)
|
||||
D 3 (#3b72b1)
|
||||
R 7 (#1fd4b2)
|
||||
D 8 (#01bfe1)
|
||||
L 7 (#3d18a2)
|
||||
D 7 (#20dac1)
|
||||
R 4 (#67d990)
|
||||
D 4 (#1acd93)
|
||||
L 7 (#017410)
|
||||
D 2 (#6e4923)
|
||||
L 7 (#10bdd0)
|
||||
D 13 (#0650b3)
|
||||
L 2 (#072660)
|
||||
U 13 (#221151)
|
||||
L 6 (#41d720)
|
||||
D 3 (#5bc831)
|
||||
L 4 (#252450)
|
||||
D 9 (#118de1)
|
||||
R 6 (#05b1d0)
|
||||
D 4 (#247721)
|
||||
R 9 (#2b6b10)
|
||||
U 4 (#60da41)
|
||||
R 10 (#470c42)
|
||||
D 3 (#4fdc91)
|
||||
R 2 (#470c40)
|
||||
D 8 (#189db1)
|
||||
L 5 (#4a1f70)
|
||||
D 7 (#07e141)
|
||||
L 3 (#2524b0)
|
||||
D 5 (#2a6ce1)
|
||||
L 11 (#1a2e50)
|
||||
D 2 (#4f08c1)
|
||||
L 3 (#3b7ec0)
|
||||
D 9 (#65e011)
|
||||
L 8 (#24b9a0)
|
||||
D 6 (#196c61)
|
||||
L 5 (#540b20)
|
||||
D 6 (#243801)
|
||||
L 2 (#397ce0)
|
||||
D 3 (#411a41)
|
||||
L 12 (#397ce2)
|
||||
D 2 (#526d51)
|
||||
L 2 (#5b5810)
|
||||
D 5 (#2e96d3)
|
||||
L 8 (#6c4f80)
|
||||
U 6 (#274453)
|
||||
L 3 (#077010)
|
||||
U 5 (#37f603)
|
||||
R 5 (#73bf92)
|
||||
U 4 (#29ee73)
|
||||
R 11 (#5ffd40)
|
||||
U 5 (#3e12d3)
|
||||
L 4 (#4b4e32)
|
||||
U 12 (#114e01)
|
||||
L 2 (#45d0b2)
|
||||
U 4 (#114e03)
|
||||
L 6 (#4b8b02)
|
||||
U 9 (#3eff03)
|
||||
L 4 (#6968d0)
|
||||
U 4 (#3d4d33)
|
||||
L 6 (#1dd0e0)
|
||||
D 2 (#436023)
|
||||
L 9 (#58b812)
|
||||
D 6 (#423003)
|
||||
L 7 (#2e81a2)
|
||||
D 3 (#3d9e13)
|
||||
L 11 (#305450)
|
||||
D 6 (#2667f3)
|
||||
L 7 (#3a8470)
|
||||
D 8 (#293191)
|
||||
R 3 (#207ee0)
|
||||
D 4 (#293193)
|
||||
R 3 (#2c4360)
|
||||
D 4 (#2667f1)
|
||||
R 7 (#250ee0)
|
||||
U 4 (#70e1c3)
|
||||
R 4 (#2907d0)
|
||||
D 6 (#0b69a1)
|
||||
R 6 (#3babc0)
|
||||
D 6 (#7698c3)
|
||||
R 2 (#2752c0)
|
||||
D 3 (#7698c1)
|
||||
L 4 (#2dc550)
|
||||
D 11 (#4ec121)
|
||||
L 8 (#199d00)
|
||||
U 11 (#33f261)
|
||||
L 7 (#3b4e30)
|
||||
D 5 (#24e991)
|
||||
L 6 (#0aaeb2)
|
||||
U 9 (#15a993)
|
||||
L 5 (#59ed02)
|
||||
U 2 (#15a991)
|
||||
L 5 (#2c0432)
|
||||
U 10 (#337e81)
|
||||
L 7 (#248670)
|
||||
D 2 (#511d31)
|
||||
L 3 (#52ebc0)
|
||||
D 13 (#511d33)
|
||||
L 4 (#192db0)
|
||||
D 7 (#3dcf11)
|
||||
L 2 (#285030)
|
||||
D 3 (#15acc1)
|
||||
L 6 (#3a6c70)
|
||||
D 5 (#36f281)
|
||||
L 4 (#44fd02)
|
||||
U 5 (#4e8821)
|
||||
L 4 (#473972)
|
||||
U 5 (#2ab9f1)
|
||||
L 8 (#60aaa0)
|
||||
U 5 (#35c651)
|
||||
L 3 (#4736b2)
|
||||
U 10 (#4741d1)
|
||||
L 3 (#1973f2)
|
||||
U 5 (#1b5031)
|
||||
L 3 (#3c6532)
|
||||
D 5 (#49bd31)
|
||||
L 4 (#5e3f60)
|
||||
D 3 (#4a2011)
|
||||
L 4 (#2ba190)
|
||||
D 6 (#4a2013)
|
||||
L 3 (#653430)
|
||||
D 7 (#10dda1)
|
||||
L 11 (#2532d2)
|
||||
D 3 (#675311)
|
||||
L 4 (#27d642)
|
||||
D 6 (#02cae1)
|
||||
L 10 (#466652)
|
||||
D 7 (#34cef3)
|
||||
R 3 (#263692)
|
||||
D 7 (#34cef1)
|
||||
R 8 (#2c59d2)
|
||||
D 5 (#31afe1)
|
||||
L 8 (#091562)
|
||||
D 5 (#12c861)
|
||||
R 4 (#47a772)
|
||||
D 5 (#68a5b1)
|
||||
L 7 (#1f79a2)
|
||||
D 4 (#3b3c13)
|
||||
R 10 (#0e7122)
|
||||
D 4 (#087363)
|
||||
R 4 (#3e26c2)
|
||||
U 13 (#4953f3)
|
||||
R 3 (#5ac862)
|
||||
U 3 (#4953f1)
|
||||
R 3 (#13cfe2)
|
||||
D 5 (#087361)
|
||||
R 11 (#57f7a2)
|
||||
D 4 (#3b3c11)
|
||||
L 11 (#6dcb32)
|
||||
D 7 (#35e653)
|
||||
R 6 (#525282)
|
||||
D 5 (#3dac93)
|
||||
R 9 (#377082)
|
||||
D 6 (#2afda1)
|
||||
R 10 (#3e6422)
|
||||
D 10 (#220471)
|
||||
R 10 (#37ebf2)
|
||||
D 2 (#4d0213)
|
||||
R 5 (#2fa2f2)
|
||||
D 4 (#30df53)
|
||||
R 5 (#617e00)
|
||||
U 6 (#536393)
|
||||
R 5 (#496510)
|
||||
D 6 (#5f6733)
|
||||
R 4 (#3bf9b0)
|
||||
D 3 (#5f6731)
|
||||
R 4 (#48d940)
|
||||
D 3 (#35a5d3)
|
||||
R 4 (#284a82)
|
||||
D 9 (#445b23)
|
||||
L 4 (#2535c2)
|
||||
D 4 (#3f8b43)
|
||||
R 2 (#41a002)
|
||||
D 7 (#20b143)
|
||||
R 3 (#63ae42)
|
||||
U 8 (#328b03)
|
||||
R 9 (#383210)
|
||||
U 3 (#1ce143)
|
||||
R 7 (#383212)
|
||||
U 6 (#2ed603)
|
||||
R 5 (#00c512)
|
||||
U 6 (#6dea43)
|
||||
R 6 (#00c510)
|
||||
U 7 (#0f0643)
|
||||
R 3 (#4292a2)
|
||||
U 7 (#684961)
|
||||
R 3 (#03de80)
|
||||
U 5 (#46e0b1)
|
||||
R 6 (#3d4ae2)
|
||||
D 5 (#1d5fc1)
|
||||
R 7 (#3d4ae0)
|
||||
U 13 (#470ab1)
|
||||
R 5 (#03de82)
|
||||
U 4 (#282c71)
|
||||
R 6 (#5520f2)
|
||||
D 5 (#2f0981)
|
||||
R 2 (#5520f0)
|
||||
D 12 (#4081a1)
|
||||
R 6 (#22a272)
|
||||
U 5 (#284c53)
|
||||
R 8 (#081202)
|
||||
D 5 (#0b7831)
|
||||
R 4 (#3e4552)
|
||||
D 13 (#0b7833)
|
||||
R 5 (#38e092)
|
||||
U 11 (#284c51)
|
||||
R 2 (#550082)
|
||||
U 2 (#175033)
|
||||
R 6 (#036dc2)
|
||||
D 3 (#068791)
|
||||
R 9 (#3ff6f2)
|
||||
D 5 (#4a5783)
|
||||
R 13 (#4d5f92)
|
||||
D 6 (#3e3423)
|
||||
L 12 (#4f62d2)
|
||||
D 7 (#5e4363)
|
||||
L 3 (#0f7032)
|
||||
U 7 (#285261)
|
||||
L 12 (#4ea392)
|
||||
D 5 (#4c2dc1)
|
||||
L 4 (#0d2822)
|
||||
D 5 (#4c2dc3)
|
||||
R 9 (#518da2)
|
||||
D 2 (#41b3b1)
|
||||
R 7 (#023270)
|
||||
D 3 (#13d6e1)
|
||||
R 11 (#0874c0)
|
||||
D 3 (#2026c1)
|
||||
R 4 (#68f3a0)
|
||||
D 7 (#2026c3)
|
||||
L 8 (#208470)
|
||||
D 4 (#09bd81)
|
||||
L 3 (#193a10)
|
||||
D 7 (#5f3491)
|
||||
L 4 (#08cad2)
|
||||
D 10 (#068793)
|
||||
L 10 (#48acb2)
|
||||
D 4 (#20e341)
|
||||
L 7 (#6137a2)
|
||||
D 8 (#20e343)
|
||||
L 7 (#0bf292)
|
||||
D 7 (#5b5f13)
|
||||
L 8 (#2b2532)
|
||||
D 3 (#034073)
|
||||
L 5 (#3c7bb2)
|
||||
D 11 (#09c643)
|
||||
L 3 (#0d6e52)
|
||||
U 3 (#569d23)
|
||||
L 5 (#63fed0)
|
||||
U 4 (#162193)
|
||||
L 4 (#2eb310)
|
||||
U 3 (#655e23)
|
||||
L 10 (#42f8e0)
|
||||
U 4 (#341983)
|
||||
R 14 (#3dbbc0)
|
||||
U 5 (#551b13)
|
||||
L 5 (#2a94f0)
|
||||
U 6 (#05ae53)
|
||||
L 2 (#09db90)
|
||||
U 5 (#2c9e13)
|
||||
L 8 (#4c6d10)
|
||||
D 10 (#40ffb3)
|
||||
L 3 (#306c30)
|
||||
D 2 (#338911)
|
||||
L 6 (#4bed00)
|
||||
D 7 (#338913)
|
||||
R 7 (#12aae0)
|
||||
D 4 (#459613)
|
||||
L 7 (#75d3a2)
|
||||
D 7 (#37ad61)
|
||||
L 6 (#6dcf92)
|
||||
D 4 (#3b7703)
|
||||
R 9 (#0ee2b2)
|
||||
D 4 (#514c13)
|
||||
R 6 (#0ee2b0)
|
||||
D 3 (#2863b3)
|
||||
L 8 (#52eee2)
|
||||
D 8 (#2fc771)
|
||||
L 7 (#5be782)
|
||||
D 4 (#2f39a1)
|
||||
L 6 (#5be780)
|
||||
U 4 (#5625b1)
|
||||
L 2 (#5588c2)
|
||||
U 14 (#37ad63)
|
||||
L 3 (#0681e2)
|
||||
U 4 (#085481)
|
||||
L 3 (#037432)
|
||||
U 12 (#31ed51)
|
||||
L 4 (#6791e2)
|
||||
D 5 (#3546d3)
|
||||
L 6 (#4419e2)
|
||||
D 10 (#3546d1)
|
||||
L 4 (#2c1a72)
|
||||
D 10 (#5bead1)
|
||||
L 3 (#3b3252)
|
||||
D 9 (#3390c1)
|
||||
L 3 (#1d78c2)
|
||||
D 5 (#488d71)
|
||||
R 10 (#244042)
|
||||
D 2 (#10d1e1)
|
||||
R 5 (#3fd582)
|
||||
D 5 (#5025a1)
|
||||
L 3 (#381b70)
|
||||
D 11 (#771831)
|
||||
L 7 (#2abf50)
|
||||
U 11 (#17be81)
|
||||
L 5 (#1eb3c0)
|
||||
D 5 (#3d9c61)
|
||||
L 5 (#5f4de2)
|
||||
D 8 (#278361)
|
||||
L 2 (#2b95b2)
|
||||
D 9 (#2cb0b1)
|
||||
L 4 (#4a0182)
|
||||
D 6 (#2c6bb3)
|
||||
L 2 (#499642)
|
||||
D 5 (#4c76d3)
|
||||
L 8 (#2fe412)
|
||||
U 9 (#07b893)
|
||||
L 2 (#236d52)
|
||||
U 8 (#3956a3)
|
||||
L 7 (#34f252)
|
||||
U 3 (#52bbf1)
|
||||
L 7 (#189470)
|
||||
U 4 (#54b661)
|
||||
L 9 (#189472)
|
||||
U 7 (#0110f1)
|
||||
L 3 (#409bf2)
|
||||
U 3 (#46d3e3)
|
||||
L 5 (#4c0f82)
|
||||
U 11 (#215e73)
|
||||
L 4 (#4c0f80)
|
||||
U 7 (#4050f3)
|
||||
L 9 (#39b192)
|
||||
U 7 (#28b043)
|
||||
L 3 (#011270)
|
||||
U 7 (#1f6693)
|
||||
R 7 (#73c390)
|
||||
U 2 (#2c4113)
|
||||
R 5 (#0321c0)
|
||||
U 8 (#2f2903)
|
||||
L 12 (#5ab560)
|
||||
U 3 (#4dd983)
|
||||
L 6 (#38b7d2)
|
||||
U 12 (#03c8c3)
|
304
18/src/main.rs
Normal file
304
18/src/main.rs
Normal file
@ -0,0 +1,304 @@
|
||||
use itertools::Itertools;
|
||||
use std::collections::LinkedList;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// DATA
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
enum Turn {
|
||||
LeftNinety,
|
||||
RightNinety,
|
||||
OneEighty,
|
||||
None,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
const fn all() -> &'static [Self; 4] {
|
||||
&[Direction::Left, Direction::Right, Direction::Up, Direction::Down]
|
||||
}
|
||||
const fn opposite(&self) -> Self {
|
||||
match self {
|
||||
Direction::Left => Direction::Right,
|
||||
Direction::Right => Direction::Left,
|
||||
Direction::Up => Direction::Down,
|
||||
Direction::Down => Direction::Up,
|
||||
}
|
||||
}
|
||||
const fn offset(&self) -> (isize, isize) {
|
||||
match self {
|
||||
Direction::Left => (-1, 0),
|
||||
Direction::Right => (1, 0),
|
||||
Direction::Up => (0, -1),
|
||||
Direction::Down => (0, 1),
|
||||
}
|
||||
}
|
||||
fn turn_kind(&self, next_dir: Direction) -> Turn {
|
||||
if *self == next_dir {
|
||||
Turn::None
|
||||
} else if self.opposite() == next_dir {
|
||||
Turn::OneEighty
|
||||
} else {
|
||||
match self {
|
||||
Direction::Left if next_dir == Direction::Up => Turn::RightNinety,
|
||||
Direction::Left if next_dir == Direction::Down => Turn::LeftNinety,
|
||||
Direction::Right if next_dir == Direction::Up => Turn::LeftNinety,
|
||||
Direction::Right if next_dir == Direction::Down => Turn::RightNinety,
|
||||
Direction::Up if next_dir == Direction::Left => Turn::LeftNinety,
|
||||
Direction::Up if next_dir == Direction::Right => Turn::RightNinety,
|
||||
Direction::Down if next_dir == Direction::Right => Turn::LeftNinety,
|
||||
Direction::Down if next_dir == Direction::Left => Turn::RightNinety,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Direction {
|
||||
fn from(s: &str) -> Self {
|
||||
match s {
|
||||
"L" => Direction::Left,
|
||||
"R" => Direction::Right,
|
||||
"U" => Direction::Up,
|
||||
"D" => Direction::Down,
|
||||
s => panic!("{} is not a valid direction", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Direction> for char {
|
||||
fn from(dir: &Direction) -> Self {
|
||||
match dir {
|
||||
Direction::Left => '←',
|
||||
Direction::Right => '→',
|
||||
Direction::Up => '↑',
|
||||
Direction::Down => '↓',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct DigInstruction {
|
||||
dir: Direction,
|
||||
count: usize,
|
||||
color: String,
|
||||
}
|
||||
|
||||
impl From<&str> for DigInstruction {
|
||||
fn from(s: &str) -> Self {
|
||||
let mut parts = s.split_ascii_whitespace();
|
||||
let (dir, count, color) = (
|
||||
parts.next().unwrap(),
|
||||
parts.next().unwrap(),
|
||||
parts.next().unwrap().chars().skip(2).take(6).collect::<String>(),
|
||||
);
|
||||
Self {
|
||||
dir: dir.into(),
|
||||
count: count.parse().unwrap(),
|
||||
color: color.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DigInstruction {
|
||||
fn part2_transform(&mut self) {
|
||||
let (distance_s, direction_s) = self.color.split_at(5);
|
||||
self.count = usize::from_str_radix(distance_s, 16).unwrap();
|
||||
self.dir = match direction_s {
|
||||
"0" => Direction::Right,
|
||||
"1" => Direction::Down,
|
||||
"2" => Direction::Left,
|
||||
"3" => Direction::Up,
|
||||
s => panic!("`{}` is not a valid direction code", s),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DigPlan {
|
||||
instructions: Vec<DigInstruction>,
|
||||
}
|
||||
|
||||
impl DigPlan {
|
||||
fn part2_transform(&mut self) {
|
||||
for i in &mut self.instructions {
|
||||
i.part2_transform();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct DigTile {
|
||||
position: Position,
|
||||
}
|
||||
|
||||
impl Default for DigTile {
|
||||
fn default() -> Self {
|
||||
Self { position: (0, 0) }
|
||||
}
|
||||
}
|
||||
|
||||
type Position = (isize, isize);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DigHole {
|
||||
tiles_loop: LinkedList<DigTile>,
|
||||
area: u64,
|
||||
}
|
||||
|
||||
// determinant of positions p1 and p2
|
||||
fn det(p1: Position, p2: Position) -> i64 {
|
||||
((p1.0 * p2.1) - (p1.1 * p2.0)) as i64
|
||||
}
|
||||
|
||||
impl DigHole {
|
||||
fn new() -> Self {
|
||||
DigHole {
|
||||
tiles_loop: LinkedList::new(),
|
||||
area: 0,
|
||||
}
|
||||
}
|
||||
fn pos_offset_n(&self, pos: Position, offset: (isize, isize), n: usize) -> Position {
|
||||
(pos.0 + offset.0 * n as isize, pos.1 + offset.1 * n as isize)
|
||||
}
|
||||
fn run_plan(&mut self, plan: &DigPlan) {
|
||||
let mut cur_pos = (0, 0);
|
||||
|
||||
self.tiles_loop.push_back(DigTile { position: cur_pos });
|
||||
let mut move_offset;
|
||||
for (idx, i) in plan.instructions.iter().enumerate() {
|
||||
let prev_instruction = if idx > 0 {
|
||||
&plan.instructions[idx - 1]
|
||||
} else {
|
||||
&plan.instructions[plan.instructions.len() - 1]
|
||||
};
|
||||
let Some(next_instruction) = plan.instructions.get(idx + 1).or(Some(&plan.instructions[0])) else {
|
||||
panic!()
|
||||
};
|
||||
let cur_turn = prev_instruction.dir.turn_kind(i.dir);
|
||||
let next_turn = i.dir.turn_kind(next_instruction.dir);
|
||||
|
||||
// Point needs to live on the 'outside' corner of the character. to achieve this we need to offset the move
|
||||
// by the following. Found this empirically but there's probably some mathematical principle behind it...
|
||||
move_offset = match (cur_turn, next_turn) {
|
||||
(Turn::RightNinety, Turn::RightNinety) => 1,
|
||||
(Turn::RightNinety, Turn::LeftNinety) => 0,
|
||||
(Turn::LeftNinety, Turn::LeftNinety) => -1,
|
||||
(Turn::LeftNinety, Turn::RightNinety) => 0,
|
||||
t => panic!("turn {:?} not allowed here", t),
|
||||
};
|
||||
|
||||
cur_pos = self.pos_offset_n(cur_pos, i.dir.offset(), (i.count as isize + move_offset) as usize);
|
||||
self.tiles_loop.push_back(DigTile { position: cur_pos });
|
||||
}
|
||||
|
||||
// Shoelace formula
|
||||
// https://en.wikipedia.org/wiki/Shoelace_formula
|
||||
let double_area: i64 = self
|
||||
.tiles_loop
|
||||
.iter()
|
||||
.tuple_windows()
|
||||
.map(|(a, b)| det(a.position, b.position))
|
||||
.sum();
|
||||
self.area = (double_area / 2).abs() as u64;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for DigPlan {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
Self {
|
||||
instructions: lines.map(|line| DigInstruction::from(line.unwrap().as_str())).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let plan = DigPlan::from(input);
|
||||
let mut dig = DigHole::new();
|
||||
dig.run_plan(&plan);
|
||||
dig.area
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut plan = DigPlan::from(input);
|
||||
let mut dig = DigHole::new();
|
||||
plan.part2_transform();
|
||||
dig.run_plan(&plan);
|
||||
dig.area
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"R 6 (#70c710)
|
||||
D 5 (#0dc571)
|
||||
L 2 (#5713f0)
|
||||
D 2 (#d2c081)
|
||||
R 2 (#59c680)
|
||||
D 2 (#411b91)
|
||||
L 5 (#8ceee2)
|
||||
U 2 (#caa173)
|
||||
L 1 (#1b58a2)
|
||||
U 2 (#caa171)
|
||||
R 2 (#7807d2)
|
||||
U 3 (#a77fa3)
|
||||
L 2 (#015232)
|
||||
U 2 (#7a21e3)";
|
||||
|
||||
const AREA16_SQUARE: &str = &"R 3 (#000000)
|
||||
D 3 (#000000)
|
||||
L 3 (#000000)
|
||||
U 4 (#000000";
|
||||
|
||||
#[test]
|
||||
fn area16_square() {
|
||||
let c = Cursor::new(AREA16_SQUARE);
|
||||
assert_eq!(problem1(c.lines()), 16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 62);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 952408144115);
|
||||
}
|
||||
}
|
25
19/Cargo.lock
generated
Normal file
25
19/Cargo.lock
generated
Normal file
@ -0,0 +1,25 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "day19"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
7
19/Cargo.toml
Normal file
7
19/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "day19"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
num-traits = "0.2.17"
|
775
19/input
Normal file
775
19/input
Normal file
@ -0,0 +1,775 @@
|
||||
kzq{m<596:R,x<1149:R,A}
|
||||
in{s<2440:cd,tgz}
|
||||
rs{m<2118:zx,s>3630:A,m<2297:cx,vfc}
|
||||
hzz{m<2478:A,R}
|
||||
ss{a<692:R,A}
|
||||
sv{x<877:A,m<2320:R,A}
|
||||
ph{x<2510:mf,x>3150:R,m>624:xtc,fr}
|
||||
rg{s>440:hj,a>434:lg,ljm}
|
||||
hdr{m<1158:R,m>1494:vfl,a<1353:A,R}
|
||||
zhp{x>633:A,x<248:R,A}
|
||||
fd{s<1838:A,m<3087:A,a>3495:R,jsg}
|
||||
qvh{x<3002:crs,m<2331:A,s<3294:dh,R}
|
||||
qbr{m>3556:R,m<3200:R,R}
|
||||
sql{m<3219:A,zf}
|
||||
zf{a<633:A,s<1348:A,A}
|
||||
rr{x<3035:A,s<3096:A,a<2451:R,A}
|
||||
bng{s>3079:R,a<724:jd,R}
|
||||
lv{a<3333:tqj,hth}
|
||||
bcp{a>1296:dtp,m>2875:dnq,x>1453:xjl,gp}
|
||||
tz{m>3020:R,R}
|
||||
gnz{m<692:R,m>1130:R,m>877:R,R}
|
||||
xqg{x>3462:A,s<3298:A,s>3449:R,R}
|
||||
pxd{s>1539:jvr,m<2976:frj,x>1748:mr,fts}
|
||||
tj{m>3165:R,m<3044:R,a>1557:R,A}
|
||||
jqm{x<2410:xf,m>3048:zm,zbl}
|
||||
pv{a>2330:R,a>2259:A,x>3069:A,A}
|
||||
qnz{m>1947:bz,x<2553:jr,x<3256:prq,bx}
|
||||
cn{x>2438:nl,s<193:A,R}
|
||||
kkb{s>3372:A,a>295:A,R}
|
||||
rgr{a>707:R,a>400:hrd,npv}
|
||||
klp{s<2137:jzp,x>1502:qnz,xj}
|
||||
fm{m>3258:db,qd}
|
||||
scf{a>490:A,m>3260:R,R}
|
||||
btz{a>3068:dr,a>2668:hfb,m<2408:cs,fgr}
|
||||
xqr{m>2286:A,a<2390:tf,x>3254:R,fkk}
|
||||
tp{x<1044:A,a>2510:A,s<1735:A,A}
|
||||
frj{x>2659:vhd,s>1415:lfl,sll}
|
||||
kcn{s<1967:R,R}
|
||||
vrm{a>1620:R,x>1345:A,s>3219:A,A}
|
||||
vm{x<2777:gnz,m<614:hrg,a>903:shm,R}
|
||||
bqq{a<994:A,m<2065:vrm,s<3419:bnv,zqt}
|
||||
dtp{a>2018:cp,tbq}
|
||||
qk{m>3174:slm,m>2948:jqm,gz}
|
||||
gzq{m>1755:R,A}
|
||||
nl{s>174:A,a<3022:A,m>2165:R,A}
|
||||
mkk{a>2954:A,R}
|
||||
gp{x>808:bng,nmr}
|
||||
khf{m<1278:R,a>264:A,x>3812:A,A}
|
||||
xxf{m>1340:A,s>2282:R,R}
|
||||
bbk{a>1074:gqc,a>616:mdv,pgv}
|
||||
nrp{x<2414:R,mjc}
|
||||
kpt{m<3158:bcp,clt}
|
||||
snl{m<868:km,m<1182:A,x<715:R,A}
|
||||
cfm{s<3832:R,A}
|
||||
pt{m>3354:rkx,A}
|
||||
bz{a>3073:jz,s>2285:A,a>2653:tt,sgd}
|
||||
zp{s>3328:R,m<981:R,A}
|
||||
zkg{a<910:kjc,a<1539:hzz,s<2149:xdc,R}
|
||||
jxm{x>2135:R,m>1114:R,a<668:A,ghm}
|
||||
szq{s<450:cn,s>694:sdd,s>567:cm,lk}
|
||||
vlz{s>584:R,s<287:R,A}
|
||||
fr{s>1707:A,m<281:A,a<1488:R,R}
|
||||
cdh{x>1427:R,x>1191:R,A}
|
||||
brs{s>2803:A,a<821:A,s>2565:R,R}
|
||||
ghm{s<3298:R,m>738:A,x>868:R,R}
|
||||
cdn{s<745:R,a<1738:R,R}
|
||||
vgc{s>3045:A,s>2796:R,A}
|
||||
mjc{m<1443:R,a<1751:R,a<2183:A,R}
|
||||
rhs{a<1453:A,m>933:kg,A}
|
||||
vgh{m>3481:zmk,x>2384:ng,s<3473:pt,xvj}
|
||||
lfb{x>1099:A,A}
|
||||
cb{a<2973:qkv,x>2753:knq,R}
|
||||
vd{a<1578:zbh,x>2560:A,s<1772:R,A}
|
||||
dh{m<2492:R,m>2532:A,A}
|
||||
tqj{m>1459:R,m>649:R,m>261:A,A}
|
||||
sch{m<1650:R,A}
|
||||
brm{x<2245:rm,vsm}
|
||||
xqc{x>1906:R,s<2586:R,m>1404:R,A}
|
||||
vmx{m<2123:qsd,s<2169:R,s<2335:R,A}
|
||||
nrj{s>2051:ml,a<3354:A,x<772:tjm,czr}
|
||||
zpq{a<805:R,s<2733:A,x<2371:R,R}
|
||||
lq{m<2008:nxh,m<2296:vmx,zkg}
|
||||
lfn{m>2015:R,A}
|
||||
vhv{s>2798:A,m<2650:R,hsz}
|
||||
rxq{a>2045:A,a>2002:A,R}
|
||||
gv{x>3571:R,m>3216:A,R}
|
||||
kjg{x>2443:R,s>3563:A,A}
|
||||
qv{a>903:A,a<755:A,m<2822:R,A}
|
||||
dqb{s<1310:A,s<1331:R,s<1351:R,A}
|
||||
pll{s<1875:R,s<1928:A,a>3979:A,R}
|
||||
cct{x>2015:cb,m<1524:vqc,a>3121:sdz,rs}
|
||||
dq{a>3084:R,a>2989:A,x<1241:A,R}
|
||||
xzx{a>2077:A,a<2023:A,a>2046:A,R}
|
||||
nmr{s>3420:R,A}
|
||||
klr{m<1060:A,m>1274:A,ms}
|
||||
dr{s>1739:qvk,m<2207:R,a>3629:R,gk}
|
||||
qvk{s<1772:A,a>3599:R,R}
|
||||
gbj{a>855:R,m>2778:R,A}
|
||||
drj{s<2725:R,A}
|
||||
th{s<219:R,s>361:R,R}
|
||||
dd{x<1745:zgq,a<2006:R,s<3396:tlq,vn}
|
||||
cpr{x<2287:R,a>3768:R,A}
|
||||
ntn{a<1603:R,x<3513:A,x<3736:R,A}
|
||||
zlg{a<2254:xbz,m>1915:xqr,qhg}
|
||||
mv{m<1685:A,s<2921:A,s<3099:nrm,A}
|
||||
tnz{m>1738:R,R}
|
||||
hql{m<1446:rj,qn}
|
||||
bxk{x>1683:A,m<3826:R,x>1019:A,R}
|
||||
pg{x>2110:A,A}
|
||||
vsm{m<1847:R,x<2870:A,R}
|
||||
qcs{m>3409:xh,x<948:A,x>1273:R,R}
|
||||
zxz{a<961:gzj,x>900:bg,m<796:nn,A}
|
||||
mp{a>2922:R,x<1561:A,A}
|
||||
nb{m>1334:lq,a<942:kjq,s<2216:vcc,zd}
|
||||
kjc{x>2597:R,m<2416:R,s<2114:R,R}
|
||||
nz{a>349:A,x<1677:R,A}
|
||||
cj{x<2805:kjg,x<3336:A,R}
|
||||
kq{m<1306:R,s<3407:gmg,A}
|
||||
jp{x<2530:hd,pmn}
|
||||
vhj{s<2857:A,s<3029:A,x<3204:A,A}
|
||||
zcr{s>3421:R,A}
|
||||
kgq{m<2273:bqq,m>2432:mmf,x>1209:zxp,dzs}
|
||||
crs{a<302:R,A}
|
||||
fq{m>2037:vgj,m<1874:kfg,m>1968:jx,dtq}
|
||||
rjx{x<2876:sf,xlc}
|
||||
qsg{x>2668:A,s<2509:R,R}
|
||||
gz{a<1575:tvn,a<1927:ljt,a>2208:vmj,nqk}
|
||||
fzj{s>2118:A,R}
|
||||
jtn{s<3102:A,m<2129:R,s>3609:A,R}
|
||||
htb{x<1752:lf,s<2690:zb,a>3052:ntg,chm}
|
||||
nqk{m>2784:A,x>2006:rxq,xzx}
|
||||
ktz{a>1145:lnr,zz}
|
||||
cl{s>2245:R,A}
|
||||
pp{x>3144:R,a>1054:A,A}
|
||||
km{s<3596:R,a<217:R,a<378:A,A}
|
||||
btd{a>328:R,x>3186:R,s<2776:R,R}
|
||||
nv{a<3170:A,x<1822:A,R}
|
||||
zqt{a<1992:R,s>3757:A,R}
|
||||
zvh{x<3431:A,x<3695:R,a<181:A,khf}
|
||||
rjc{s>3558:rxs,ngt}
|
||||
fvr{s<1819:A,a>3820:R,A}
|
||||
gdh{a<1044:A,m>3889:R,a<1313:A,R}
|
||||
xjl{m>2748:zfc,x>2350:hkv,qdk}
|
||||
dzs{a<1516:tbs,m<2379:zcr,x>802:A,lvn}
|
||||
hnk{m<1382:cqm,x<618:R,m>2969:A,ck}
|
||||
sl{s<2067:R,rq}
|
||||
bn{m>2044:R,x>1947:R,s>2494:A,A}
|
||||
klj{m>595:zs,a>1587:A,A}
|
||||
hd{m<814:rt,hdr}
|
||||
pm{x>1330:rjf,s>3318:snl,m<757:lgm,jhh}
|
||||
xn{m>894:R,s<486:R,A}
|
||||
zxp{s>3057:mnb,A}
|
||||
bt{x>2338:R,s<2515:R,A}
|
||||
qdh{x<1435:dfm,m>3320:sn,m<2950:knb,xcq}
|
||||
zsf{x>3119:R,s<3965:A,R}
|
||||
lxs{x<1891:R,R}
|
||||
fp{a>839:A,a<370:A,x>3697:R,A}
|
||||
fb{x>1576:A,x>1383:R,R}
|
||||
ssq{x>1389:R,x<683:A,R}
|
||||
psl{s>1912:nb,mdx}
|
||||
gzd{a<286:R,m>2048:R,A}
|
||||
cm{x<2249:R,R}
|
||||
ps{m<3057:A,a<192:A,R}
|
||||
ql{x<1455:R,s<2316:A,dz}
|
||||
tl{s>2746:R,a<2925:jth,s<2631:R,dq}
|
||||
fl{m<871:R,R}
|
||||
dnd{s<3340:R,a<1631:A,R}
|
||||
hpk{x<2148:nbd,kq}
|
||||
hrd{m>2977:A,R}
|
||||
cqm{a<3300:A,s<2326:R,R}
|
||||
vhx{a>264:sx,czq}
|
||||
hpb{m<1744:bkc,x<1249:cf,vkm}
|
||||
ms{x>3633:R,a>279:A,x>3536:A,A}
|
||||
qkk{a<2687:A,s<2740:R,A}
|
||||
vfc{a<2771:R,A}
|
||||
rjf{s<3472:br,x<1970:A,a>216:R,A}
|
||||
xbz{x<3190:lkc,gvr}
|
||||
mx{s>1027:R,A}
|
||||
fxr{a<3952:R,R}
|
||||
sz{m>3436:R,a>3677:R,a<3578:A,R}
|
||||
qsd{s>2211:A,s>2062:A,x<1916:R,R}
|
||||
jxd{a>3568:A,x>2134:R,hr}
|
||||
xlc{m<3646:ntn,m>3749:vb,a<829:hmk,gc}
|
||||
zmb{x<854:A,tv}
|
||||
dxx{a>796:brs,m<1206:gq,R}
|
||||
jj{m<1020:xhs,a<758:ghs,dxx}
|
||||
jd{s>2702:A,a>437:A,x<1198:A,A}
|
||||
vb{a<1183:A,x>3584:R,R}
|
||||
zg{a<1774:R,rp}
|
||||
fjl{m<1926:A,A}
|
||||
sx{m>412:rlx,m<224:hsm,ts}
|
||||
clt{m>3707:kbk,vgh}
|
||||
sdd{x>1333:A,s>792:ffv,qc}
|
||||
ltl{s<2747:A,A}
|
||||
qd{a<1088:A,a>1543:R,R}
|
||||
lnr{s>1491:A,tgm}
|
||||
hr{s<2837:A,R}
|
||||
tbn{m>1412:A,x<1334:ltl,bbq}
|
||||
db{x<1961:R,R}
|
||||
dfm{m>3324:R,A}
|
||||
mdx{s>1504:cc,sb}
|
||||
xvj{x<1523:R,R}
|
||||
zm{x>3061:txs,x<2826:R,R}
|
||||
bkc{s<3439:R,s<3712:R,R}
|
||||
sp{a>996:A,R}
|
||||
ftd{x>2631:R,m>2447:R,x>2241:R,R}
|
||||
qxl{m>591:R,x>508:A,R}
|
||||
ngs{x<1410:R,A}
|
||||
nvl{m>836:R,A}
|
||||
kbd{m>2655:jxd,shz}
|
||||
bzz{m>2969:R,A}
|
||||
hth{x>532:R,x<263:A,A}
|
||||
dtq{x<1785:fjl,qpt}
|
||||
qbz{m<1913:kkb,m<2018:R,x<2884:tvj,gzd}
|
||||
tr{x<1816:zxz,s<3159:gj,a>942:vtz,vm}
|
||||
pdr{a>3495:R,x<960:A,A}
|
||||
sfd{m<1983:R,a>3730:A,A}
|
||||
qm{a<3400:A,R}
|
||||
vlx{x<1628:R,x>2516:A,R}
|
||||
ztb{s<1848:A,s<1862:R,A}
|
||||
tlq{m<3961:A,A}
|
||||
mtx{x<628:R,s<2839:A,R}
|
||||
dp{m<631:R,x>3424:R,A}
|
||||
bch{x>544:R,s<1473:A,A}
|
||||
qkv{s>3614:A,a<2756:R,A}
|
||||
tlz{s<1526:R,A}
|
||||
nr{a<1406:R,s>1965:ls,a<1804:R,kmj}
|
||||
rn{m<3158:R,x>1428:R,A}
|
||||
fn{s>2334:R,R}
|
||||
fv{s>496:R,m>2847:A,R}
|
||||
kdt{x<1651:qx,mn}
|
||||
dt{s<1907:R,A}
|
||||
fxp{s>1444:R,x<1151:R,s<1432:R,A}
|
||||
skp{s<2684:ff,a>3661:grc,kbd}
|
||||
sf{a<1342:R,R}
|
||||
vn{x<2642:A,m>3964:A,x>3188:R,R}
|
||||
cc{m<1326:ph,vd}
|
||||
st{m>2033:kv,x>2199:mh,qs}
|
||||
tt{s<2228:R,m>2870:A,x<2943:R,A}
|
||||
zxc{x<2549:A,a<790:fl,a>821:hs,rv}
|
||||
nzg{a>721:R,a<709:R,m<1312:R,R}
|
||||
dpm{x<2029:dvz,tkb}
|
||||
xzp{x<1033:zhp,m<3650:vk,s>1404:cdh,R}
|
||||
kmt{x>1508:A,m>3316:sdt,ngs}
|
||||
jr{x<2063:zvg,x<2340:A,m>945:cl,R}
|
||||
slv{m<658:A,m>699:R,x<1549:R,R}
|
||||
txs{x>3387:R,x>3223:A,A}
|
||||
jbj{x<1080:R,R}
|
||||
slm{s>2107:qgv,x>1425:pbp,nr}
|
||||
xj{s<2246:lv,hnk}
|
||||
rxs{a>3208:R,s>3711:tz,bvt}
|
||||
sgd{m>2799:R,m<2302:A,s>2226:A,A}
|
||||
gng{m>1061:xqc,m>382:A,s<2565:A,rkh}
|
||||
tq{m>3700:R,m>3578:A,m<3552:R,R}
|
||||
gqc{m<751:vc,m<1228:trs,qln}
|
||||
bzg{a<3173:A,x>2040:A,A}
|
||||
gr{s>1874:A,A}
|
||||
sm{x>1443:fc,m<3252:pqp,lh}
|
||||
vt{x<324:sch,m<2405:zdb,s<2751:A,mtx}
|
||||
rrz{a<2925:A,m<1807:A,A}
|
||||
dvm{s>3793:R,a<714:R,a>723:A,R}
|
||||
ns{a>216:fzj,s<2226:A,pl}
|
||||
tsn{m<1180:R,x<1442:ss,a<693:A,dvm}
|
||||
lgm{m<295:mt,qxl}
|
||||
gq{a>772:R,s>2860:A,A}
|
||||
tv{x<1247:R,m>2373:A,R}
|
||||
shm{a>923:R,R}
|
||||
tc{m>1326:pd,x<2176:A,A}
|
||||
zs{a>956:R,x<1552:A,m<1047:A,A}
|
||||
kbk{a<1245:zr,m>3892:dd,a>1823:hf,rkz}
|
||||
gc{s>1625:A,x<3456:R,A}
|
||||
vv{m<1670:jp,a<1470:tvs,dx}
|
||||
dv{a<3900:dt,x<2401:R,a>3952:pll,A}
|
||||
rh{x>1522:md,zmb}
|
||||
bv{s<813:R,x<1898:A,m<2291:A,A}
|
||||
dfs{a>2165:A,x<2625:A,m<905:A,R}
|
||||
sq{m<1537:A,a>3700:R,s>3518:R,R}
|
||||
zbh{m>1984:R,s>1714:A,s>1589:R,A}
|
||||
pmn{x>3353:mxr,xn}
|
||||
fc{m<3293:A,R}
|
||||
hj{m>2607:nz,bv}
|
||||
cjt{s<3222:R,a>778:A,R}
|
||||
md{a<2755:A,a<2974:bqz,m<1812:A,R}
|
||||
jcn{x<3486:A,A}
|
||||
tm{x<1626:R,x>2473:A,R}
|
||||
rp{s<2043:A,A}
|
||||
dtt{x<2469:A,x>2652:A,R}
|
||||
rkh{a<3899:R,a<3939:A,a>3972:A,R}
|
||||
vtz{x<3222:jnj,A}
|
||||
dz{a>1273:R,x<2592:R,a>1109:R,A}
|
||||
zbl{x<3369:A,a<1301:A,A}
|
||||
xcc{x<1386:R,x>2717:A,A}
|
||||
snz{x>1513:R,A}
|
||||
pnp{m>2870:R,s<1615:R,A}
|
||||
nzs{x<2228:svh,a>3290:drm,qck}
|
||||
dx{m<2704:st,bnq}
|
||||
ml{m>2093:A,m<723:R,x>705:A,A}
|
||||
nrm{x<2693:R,x>3329:R,a<1508:A,R}
|
||||
ls{a>2023:R,x<645:A,x<1062:R,R}
|
||||
zbk{s<3432:A,R}
|
||||
pcx{a>133:A,R}
|
||||
xc{a<2881:A,m>2239:R,R}
|
||||
bvt{x>2521:R,m>3250:A,A}
|
||||
vfl{a>1549:A,A}
|
||||
gb{s>2827:fxr,a<3925:vp,tk}
|
||||
nt{a<3562:R,s>1880:R,A}
|
||||
qh{s<2766:R,m>1823:R,m<1032:R,R}
|
||||
vkb{m>3657:R,a<1604:A,R}
|
||||
qdk{a>446:vrt,a>237:R,A}
|
||||
nx{s<3053:A,x>2661:A,s<3652:A,A}
|
||||
ffv{m>2118:A,x<591:A,R}
|
||||
gnx{m>3550:A,s>340:R,A}
|
||||
xdc{s<2011:R,a<1886:A,m<2525:R,R}
|
||||
rnx{x>1741:A,R}
|
||||
vgj{a<1194:R,a>1316:A,mjf}
|
||||
rz{m<245:A,R}
|
||||
jzp{x<1378:nrj,qm}
|
||||
dhz{m<2327:dnd,x<3029:ftd,m<2461:R,A}
|
||||
mmf{x>1349:R,m>2512:A,R}
|
||||
chm{m<1360:sh,a>2753:dmf,x<2850:zdz,rd}
|
||||
bb{a<1712:R,s<1716:A,fgd}
|
||||
lfl{s>1480:R,fxp}
|
||||
vkm{a<944:fb,cdz}
|
||||
shz{x>2518:R,s>2824:pdr,x<1098:A,R}
|
||||
lvn{a<1975:A,A}
|
||||
ng{m<3372:pjq,R}
|
||||
ntg{x<2896:bvx,hql}
|
||||
qck{a>2892:R,x>2827:gx,m<1542:njr,R}
|
||||
xg{m<274:R,R}
|
||||
qs{a<1914:cdn,R}
|
||||
bd{m>3657:jbj,m<3576:R,x>715:hk,R}
|
||||
mnb{m>2328:A,s<3622:A,a<1275:A,A}
|
||||
lkc{s>3247:R,A}
|
||||
jz{a<3649:A,a<3878:R,R}
|
||||
pgv{x<2543:pm,m<747:vhx,s<3269:kb,hx}
|
||||
vfk{s>2335:sd,R}
|
||||
mxr{s<525:pz,fp}
|
||||
qln{s<3057:tbn,m>1379:nrp,tc}
|
||||
hsm{a<391:A,R}
|
||||
mdv{a>842:tr,s<3143:jj,mfx}
|
||||
tgm{x<1435:R,A}
|
||||
bj{x>2353:R,A}
|
||||
frk{s>1770:A,lfb}
|
||||
tnt{a>228:R,x<307:A,A}
|
||||
bx{s<2240:R,m>928:gf,x<3724:gm,fn}
|
||||
vr{s<3307:R,m>3549:R,A}
|
||||
zd{a<1856:ql,vfk}
|
||||
jth{s<2601:A,A}
|
||||
tbq{s>3089:A,s<2692:bzz,A}
|
||||
zz{x>1544:tlz,bch}
|
||||
mq{m>1048:R,s<3046:dfs,m<905:nvl,R}
|
||||
xsb{a>968:A,s>3282:R,R}
|
||||
ctf{m>2182:dhz,s>3326:cj,m<1769:mv,xxb}
|
||||
cd{a>2405:qjl,s<1247:vv,m<2651:psl,cz}
|
||||
sdt{m<3413:A,s<1386:A,R}
|
||||
nm{m>1061:A,m<861:R,a<1430:R,zp}
|
||||
kbp{a>257:R,R}
|
||||
czq{s>3301:A,pcx}
|
||||
rv{x<3177:R,x<3631:R,m>605:R,R}
|
||||
lg{x<2664:A,fqp}
|
||||
rq{s<2141:R,x<1452:A,x<2322:A,A}
|
||||
rkx{m>3406:R,s>2856:R,a>1356:R,R}
|
||||
rxz{a>3491:ft,m>1104:R,s<1879:A,A}
|
||||
tqc{s>2638:A,R}
|
||||
kb{m<1115:btd,a<356:zvh,nh}
|
||||
svh{m>2131:A,s>1205:A,sdj}
|
||||
gzj{s>3413:R,m<563:R,R}
|
||||
tgz{a>2498:nc,m<1536:bbk,m>2606:kpt,dpm}
|
||||
nc{s>2973:mml,a>3390:skp,htb}
|
||||
zr{m>3877:A,a<786:zbk,sp}
|
||||
hf{m<3830:A,R}
|
||||
rj{s>2812:A,R}
|
||||
lvf{s<2217:ghz,m<352:fg,s<2328:R,R}
|
||||
tvn{x<1573:A,ct}
|
||||
pqp{a<1606:A,s>1424:R,x>1211:A,A}
|
||||
fpm{a<3321:A,a>3380:A,R}
|
||||
lpq{a<2688:A,m>550:A,R}
|
||||
skb{a>496:R,a>370:A,m>3052:A,R}
|
||||
vqc{a>2824:A,mdj}
|
||||
sk{s>3032:R,a>1895:kzq,A}
|
||||
fqp{x<3283:R,x>3734:R,m>2573:A,A}
|
||||
kv{x<1403:R,A}
|
||||
jhh{a<365:zv,s>2937:R,a<532:A,A}
|
||||
qx{m<216:A,m<345:A,R}
|
||||
tvj{m>2055:R,x>2595:R,R}
|
||||
fkk{s<3440:A,R}
|
||||
nh{s>2904:R,x>3474:A,R}
|
||||
bnq{x<1726:qcs,x>2609:xjj,pg}
|
||||
bhv{s<1815:btz,a<3302:rh,m<1426:xs,dfq}
|
||||
grc{a>3883:gb,a>3753:brm,a<3710:vhv,xr}
|
||||
pl{x<1731:R,a<138:R,m<1085:R,R}
|
||||
ngt{x>2573:xqg,a>3461:sz,m>3259:vr,vmf}
|
||||
jnq{m<2176:R,m>2968:R,x>3137:A,R}
|
||||
sb{m>1679:lfn,s>1408:snz,klj}
|
||||
jvr{a>1008:bb,s<1695:np,ln}
|
||||
kjq{m<593:lvf,m<873:bcs,a>378:djc,ns}
|
||||
hh{s>2869:R,A}
|
||||
kj{x>1634:rrz,s<2750:A,m>2365:mp,R}
|
||||
xf{m<3098:A,m<3128:cr,a<995:rn,vj}
|
||||
zv{x<860:A,a>221:R,x>1038:A,R}
|
||||
rm{a>3836:A,A}
|
||||
tbs{a>927:A,R}
|
||||
gm{m<317:A,A}
|
||||
sdz{s>3569:R,m<1986:tnz,fpm}
|
||||
lf{x<960:vt,x<1466:tl,kj}
|
||||
qhg{m<1782:vgc,a<2401:A,rr}
|
||||
nxh{a<1275:R,gzq}
|
||||
tk{x<2449:A,R}
|
||||
cp{s<3395:R,s>3741:cfm,tm}
|
||||
zdb{x>591:A,s<2781:A,R}
|
||||
mhm{x<3419:R,x<3710:A,m>2686:A,A}
|
||||
pz{m>885:R,a<1395:A,R}
|
||||
jxl{a<1824:rz,A}
|
||||
vmr{a>570:jqd,m>2081:qvh,m>1814:qbz,dkx}
|
||||
kmj{s<1935:R,A}
|
||||
prq{m>920:xxf,R}
|
||||
cf{s>3313:A,x>700:A,m>1872:A,R}
|
||||
qgv{a>1042:vlx,a>596:rqd,R}
|
||||
mr{x>3011:gv,x>2379:mjx,fm}
|
||||
cx{a>2892:A,A}
|
||||
xz{m>2929:R,s<2814:R,s>2986:A,A}
|
||||
ck{x<994:A,s>2364:A,m>2064:A,R}
|
||||
zdd{s>911:nzs,szq}
|
||||
vj{s>2138:A,m>3156:A,R}
|
||||
jnj{a<996:A,s<3488:R,R}
|
||||
kfg{s<786:qtq,A}
|
||||
tjm{s<2018:R,s<2038:R,R}
|
||||
dkx{x>2834:R,x<2537:R,nx}
|
||||
zfc{m<2823:gbj,crk}
|
||||
ff{m>1893:dc,a>3780:gng,xjz}
|
||||
vmf{x<1019:A,A}
|
||||
ghs{a<703:A,a>738:R,nzg}
|
||||
gs{a<393:R,a<477:R,s<3909:R,zsf}
|
||||
zvg{s>2319:A,x>1801:A,A}
|
||||
gk{x<2559:R,A}
|
||||
xjz{s<2581:R,x>2364:R,a<3606:A,tqc}
|
||||
sd{x<2625:R,A}
|
||||
mdj{s>3552:A,x>946:A,R}
|
||||
nbd{x<1042:sq,m<915:A,tmj}
|
||||
tmj{m>1880:A,x>1503:R,A}
|
||||
drm{x>3299:R,s<1171:mx,R}
|
||||
cs{m>1405:A,x>2157:A,tp}
|
||||
xtc{x<2884:R,A}
|
||||
gj{a>929:vhj,a<885:R,A}
|
||||
mml{m>2426:rjc,a>3449:hpk,cct}
|
||||
hfb{x<1738:xc,R}
|
||||
vk{m<3572:A,m>3601:A,s>1380:R,R}
|
||||
dmf{a<2866:A,R}
|
||||
jx{m<1993:R,R}
|
||||
vz{m<408:R,A}
|
||||
cr{m>3114:R,x<927:A,R}
|
||||
rqd{a>827:R,m<3616:A,R}
|
||||
hxm{a<2012:A,a<2147:R,s>1974:R,R}
|
||||
fgr{m>3145:A,R}
|
||||
ljm{a>175:th,x>2267:R,s>203:A,R}
|
||||
sh{x<2556:A,s<2802:qkk,x>3244:R,lpq}
|
||||
mh{x<3136:R,jcn}
|
||||
jcv{x>3293:A,A}
|
||||
xh{m<3719:A,x<825:A,R}
|
||||
nn{s>3158:R,a>1035:A,m>397:A,A}
|
||||
np{m<3051:pnp,scf}
|
||||
xd{m<3074:A,s<2935:A,a>2618:A,R}
|
||||
njr{m>623:R,x<2518:A,R}
|
||||
vmj{x>1396:pv,a<2288:bfk,R}
|
||||
rt{a>991:xg,a>395:R,a>238:A,vz}
|
||||
lmf{a<941:tq,s<1601:R,R}
|
||||
zdz{s>2837:R,m<2501:cvx,a<2586:R,A}
|
||||
gmg{a>3638:A,a>3540:R,A}
|
||||
zmk{m>3609:vkb,jc}
|
||||
skj{a>908:R,a>564:R,x<489:tnt,R}
|
||||
mb{m>3811:ktz,x<1811:gl,rjx}
|
||||
rl{x<2034:R,m>1003:A,a<3236:A,R}
|
||||
dvz{m>1954:kgq,hpb}
|
||||
hmk{x>3265:R,s>1639:A,s>1393:R,R}
|
||||
dfq{s>1884:hjr,a>3606:bq,m<2391:hvz,fd}
|
||||
jqd{x<2830:cjt,jtn}
|
||||
vhd{m>2806:pp,a<962:dsd,A}
|
||||
knb{a>1140:R,qv}
|
||||
br{x<1778:R,R}
|
||||
zkt{s>3133:R,m<3860:R,A}
|
||||
zgq{a>1715:R,m<3933:R,A}
|
||||
xjj{a<1879:R,x>3421:qbr,x<3014:R,R}
|
||||
bg{m<731:A,m<1261:R,a<1026:A,A}
|
||||
ct{x<2963:A,s<2119:R,x>3312:A,A}
|
||||
bvx{x>2177:R,m<1910:rl,x>1943:bzg,nv}
|
||||
hg{x>2696:jnq,x>2077:bt,bn}
|
||||
hs{x<3271:R,A}
|
||||
tvs{a<654:rg,m<2741:fq,qdh}
|
||||
qtq{a<982:R,a<1234:A,R}
|
||||
gcg{m>3101:R,a<480:R,A}
|
||||
vp{a>3910:R,s>2776:A,a>3898:A,A}
|
||||
pd{x>1921:A,A}
|
||||
xt{a>967:R,m>3516:A,a>776:R,A}
|
||||
qc{a>3321:R,A}
|
||||
tkb{a<1063:vmr,a>1959:zlg,ctf}
|
||||
bcs{s>2230:lxs,s>2030:R,m<743:slv,A}
|
||||
qn{a<3266:A,a>3348:R,m<2667:R,A}
|
||||
cvx{x>2282:A,m<2005:R,a<2628:A,R}
|
||||
hrg{m>356:R,s>3696:R,A}
|
||||
hvz{s<1848:A,a<3490:A,s<1870:A,xcc}
|
||||
lh{s>1362:R,x>1231:R,a>1747:R,R}
|
||||
vc{m<422:jxl,x>2315:zdg,sk}
|
||||
fts{x<952:skj,a>1143:sm,x<1335:sql,kmt}
|
||||
jsg{x>2596:R,x>1393:A,m>3518:R,A}
|
||||
hk{x>1083:R,m>3604:R,A}
|
||||
mt{s>2812:R,x<595:R,s>2688:R,A}
|
||||
cdz{x>1644:R,m>1862:R,A}
|
||||
pxv{a<3725:nt,a<3830:A,A}
|
||||
njd{m<2225:R,mkk}
|
||||
mjx{s<1366:dqb,tj}
|
||||
bfk{a>2248:R,R}
|
||||
xs{m<518:pxv,a<3589:rxz,a>3783:dv,gr}
|
||||
djc{s>2174:A,js}
|
||||
zx{x<1016:A,x<1528:R,R}
|
||||
mzd{a>2015:R,R}
|
||||
knq{a>3143:R,x>3377:R,R}
|
||||
bq{s>1846:A,s>1827:cpr,fvr}
|
||||
zdg{s>3443:A,a>1681:mzd,s<2909:dp,A}
|
||||
sll{m<2763:R,s<1342:ssq,R}
|
||||
ft{m<1121:A,s>1882:A,s>1847:R,R}
|
||||
dnq{x>1487:bl,s<3256:tpk,m<3063:rgr,gmd}
|
||||
bqz{a>2865:R,A}
|
||||
sdj{m>1268:A,s<1037:R,a<3341:A,R}
|
||||
dc{s>2554:A,m<2684:R,qsg}
|
||||
bbq{s>2709:A,s>2586:A,R}
|
||||
js{m<1039:A,A}
|
||||
hjr{x<1882:R,s>1927:R,jcv}
|
||||
lk{a>3257:bj,a>2920:A,m>1832:fv,R}
|
||||
ts{a>401:R,a<339:A,s<3429:A,R}
|
||||
xr{x<1991:sv,s<2852:qh,s<2893:hh,sfd}
|
||||
bl{m<2988:A,a>784:xsb,a>295:skb,ps}
|
||||
kg{x<1065:R,x>1534:A,R}
|
||||
gf{x<3539:A,a<3041:R,R}
|
||||
ckj{s<2886:A,s>2893:A,A}
|
||||
fg{s<2314:A,m<139:R,x>1421:A,R}
|
||||
mn{x<3000:A,m>315:R,m<177:A,R}
|
||||
vrt{s>3263:A,a<878:R,x>2044:A,R}
|
||||
npv{x<687:R,A}
|
||||
ljt{x<2374:R,A}
|
||||
pbp{a>1398:hxm,a>588:xt,a<333:kcn,R}
|
||||
fgd{s>1796:R,x>2219:R,m<3069:A,R}
|
||||
xhs{a<752:R,zpq}
|
||||
tf{m<2132:A,m>2187:A,A}
|
||||
qjl{s<1624:zdd,s>1981:klp,bhv}
|
||||
gx{s<1192:A,s>1376:R,R}
|
||||
hsz{m>3435:R,s<2747:A,A}
|
||||
rkz{a>1486:bxk,m<3808:R,a>1388:A,zkt}
|
||||
mjf{x>2320:A,x<1139:A,R}
|
||||
gl{a>1425:bd,s>1660:frk,s>1500:lmf,xzp}
|
||||
gvr{m<2241:R,R}
|
||||
bnv{s<3071:R,R}
|
||||
vcc{m<618:sl,x>2269:zg,rhs}
|
||||
ghz{x>1927:A,a<394:A,m<231:A,R}
|
||||
crk{m<2842:R,x>2970:A,x<2213:R,R}
|
||||
mfx{a>731:zxc,m<547:kdt,s>3502:tsn,jxm}
|
||||
pjq{m<3273:A,a<945:A,A}
|
||||
tpk{m>2975:drj,xz}
|
||||
qpt{x>2909:A,a>991:A,a<810:R,R}
|
||||
jc{m>3552:R,R}
|
||||
rd{s<2850:R,x>3613:A,s>2904:xd,ckj}
|
||||
rlx{x>3373:R,A}
|
||||
hkv{a>502:mhm,s>3324:R,A}
|
||||
dsd{s<1357:R,x<3340:R,R}
|
||||
ln{s>1813:ztb,m>3116:rnx,A}
|
||||
czr{m>2538:R,A}
|
||||
xxb{s>2993:R,x>2787:R,dtt}
|
||||
mf{s<1679:A,m<538:A,R}
|
||||
zb{s>2579:njd,hg}
|
||||
sn{m>3668:gdh,x>2740:A,s>624:R,gnx}
|
||||
trs{a<1933:nm,mq}
|
||||
xcq{m>3184:vlz,x<2483:R,R}
|
||||
hx{s>3738:gs,x<3448:kbp,klr}
|
||||
cz{s>1882:qk,m<3508:pxd,mb}
|
||||
gmd{x>924:A,x<437:A,gcg}
|
||||
|
||||
{x=363,m=218,a=594,s=411}
|
||||
{x=973,m=37,a=2533,s=132}
|
||||
{x=2768,m=1537,a=645,s=580}
|
||||
{x=2079,m=168,a=502,s=656}
|
||||
{x=38,m=145,a=3452,s=1162}
|
||||
{x=70,m=1238,a=99,s=560}
|
||||
{x=1261,m=1540,a=283,s=28}
|
||||
{x=1194,m=780,a=1538,s=2681}
|
||||
{x=1236,m=1847,a=1403,s=1086}
|
||||
{x=2227,m=163,a=716,s=410}
|
||||
{x=9,m=369,a=572,s=1418}
|
||||
{x=201,m=1472,a=943,s=3541}
|
||||
{x=2730,m=1777,a=127,s=3031}
|
||||
{x=329,m=139,a=1310,s=2983}
|
||||
{x=54,m=981,a=1378,s=783}
|
||||
{x=658,m=410,a=482,s=490}
|
||||
{x=1555,m=1246,a=365,s=2769}
|
||||
{x=1075,m=95,a=806,s=750}
|
||||
{x=408,m=125,a=2296,s=1599}
|
||||
{x=715,m=1257,a=1287,s=1638}
|
||||
{x=63,m=1295,a=169,s=1802}
|
||||
{x=2068,m=4,a=768,s=365}
|
||||
{x=1390,m=3366,a=1730,s=1631}
|
||||
{x=1900,m=622,a=761,s=1108}
|
||||
{x=1857,m=678,a=136,s=965}
|
||||
{x=3295,m=47,a=303,s=63}
|
||||
{x=2853,m=700,a=315,s=647}
|
||||
{x=379,m=304,a=914,s=59}
|
||||
{x=2591,m=385,a=1410,s=1473}
|
||||
{x=140,m=1237,a=769,s=2670}
|
||||
{x=747,m=395,a=1988,s=633}
|
||||
{x=30,m=381,a=1966,s=2597}
|
||||
{x=1969,m=1191,a=501,s=328}
|
||||
{x=127,m=1200,a=47,s=2408}
|
||||
{x=1409,m=2136,a=205,s=3122}
|
||||
{x=150,m=88,a=1082,s=3059}
|
||||
{x=320,m=2917,a=1371,s=22}
|
||||
{x=2237,m=1186,a=466,s=2252}
|
||||
{x=2460,m=7,a=1758,s=874}
|
||||
{x=421,m=126,a=1338,s=1479}
|
||||
{x=150,m=675,a=2555,s=267}
|
||||
{x=1007,m=1178,a=2927,s=2435}
|
||||
{x=902,m=190,a=77,s=1279}
|
||||
{x=1393,m=716,a=686,s=569}
|
||||
{x=339,m=1199,a=275,s=338}
|
||||
{x=116,m=1997,a=739,s=142}
|
||||
{x=1332,m=69,a=74,s=1953}
|
||||
{x=2324,m=2089,a=101,s=1595}
|
||||
{x=2966,m=696,a=305,s=1221}
|
||||
{x=810,m=1860,a=141,s=49}
|
||||
{x=995,m=382,a=1020,s=756}
|
||||
{x=899,m=133,a=746,s=952}
|
||||
{x=325,m=1880,a=554,s=1749}
|
||||
{x=506,m=1478,a=897,s=597}
|
||||
{x=659,m=424,a=20,s=1447}
|
||||
{x=4,m=310,a=1121,s=286}
|
||||
{x=3357,m=396,a=1204,s=2886}
|
||||
{x=1209,m=614,a=2397,s=408}
|
||||
{x=505,m=339,a=72,s=709}
|
||||
{x=3478,m=1412,a=1777,s=1}
|
||||
{x=2271,m=136,a=83,s=477}
|
||||
{x=3008,m=280,a=2167,s=1522}
|
||||
{x=543,m=772,a=433,s=3560}
|
||||
{x=227,m=2037,a=1444,s=272}
|
||||
{x=869,m=80,a=2585,s=1212}
|
||||
{x=893,m=1207,a=124,s=126}
|
||||
{x=2178,m=2030,a=3000,s=1438}
|
||||
{x=450,m=1798,a=1307,s=2147}
|
||||
{x=469,m=1554,a=1080,s=393}
|
||||
{x=49,m=389,a=813,s=39}
|
||||
{x=3041,m=607,a=379,s=1435}
|
||||
{x=62,m=121,a=47,s=2394}
|
||||
{x=1589,m=2474,a=1599,s=3}
|
||||
{x=439,m=1493,a=284,s=3}
|
||||
{x=619,m=1377,a=1107,s=3452}
|
||||
{x=1802,m=1132,a=851,s=111}
|
||||
{x=2154,m=464,a=2611,s=2147}
|
||||
{x=843,m=423,a=355,s=838}
|
||||
{x=3,m=423,a=139,s=857}
|
||||
{x=42,m=843,a=2219,s=3695}
|
||||
{x=1068,m=575,a=88,s=222}
|
||||
{x=3097,m=238,a=913,s=2452}
|
||||
{x=109,m=206,a=291,s=728}
|
||||
{x=3635,m=1815,a=26,s=19}
|
||||
{x=49,m=115,a=2998,s=26}
|
||||
{x=2093,m=391,a=267,s=2896}
|
||||
{x=282,m=2364,a=62,s=62}
|
||||
{x=361,m=719,a=1679,s=137}
|
||||
{x=631,m=1131,a=203,s=2281}
|
||||
{x=794,m=1004,a=868,s=636}
|
||||
{x=1702,m=415,a=35,s=236}
|
||||
{x=63,m=1690,a=682,s=2009}
|
||||
{x=1815,m=3459,a=144,s=374}
|
||||
{x=91,m=590,a=1651,s=1681}
|
||||
{x=1561,m=2303,a=307,s=1463}
|
||||
{x=842,m=927,a=868,s=455}
|
||||
{x=51,m=23,a=427,s=247}
|
||||
{x=2431,m=187,a=267,s=184}
|
||||
{x=1596,m=1904,a=668,s=1553}
|
||||
{x=922,m=1435,a=336,s=1301}
|
||||
{x=1038,m=1632,a=220,s=117}
|
||||
{x=1935,m=1433,a=2988,s=316}
|
||||
{x=21,m=1158,a=1988,s=1242}
|
||||
{x=840,m=1272,a=418,s=1198}
|
||||
{x=1227,m=1811,a=158,s=10}
|
||||
{x=1836,m=56,a=19,s=1573}
|
||||
{x=461,m=621,a=532,s=92}
|
||||
{x=2082,m=1292,a=1032,s=322}
|
||||
{x=2094,m=249,a=865,s=2030}
|
||||
{x=1092,m=265,a=1745,s=1720}
|
||||
{x=2361,m=1087,a=209,s=1934}
|
||||
{x=92,m=111,a=3188,s=2172}
|
||||
{x=248,m=2163,a=1351,s=1194}
|
||||
{x=1675,m=2194,a=324,s=1764}
|
||||
{x=2148,m=3124,a=854,s=1823}
|
||||
{x=520,m=617,a=649,s=49}
|
||||
{x=2497,m=12,a=270,s=161}
|
||||
{x=248,m=2,a=1026,s=1196}
|
||||
{x=367,m=860,a=1141,s=61}
|
||||
{x=411,m=90,a=3401,s=2156}
|
||||
{x=284,m=265,a=421,s=866}
|
||||
{x=2152,m=2245,a=1206,s=1056}
|
||||
{x=1578,m=74,a=93,s=1494}
|
||||
{x=225,m=50,a=2223,s=1888}
|
||||
{x=2448,m=372,a=587,s=820}
|
||||
{x=1222,m=215,a=31,s=1753}
|
||||
{x=2906,m=1170,a=1120,s=291}
|
||||
{x=1253,m=329,a=478,s=2489}
|
||||
{x=563,m=150,a=103,s=1051}
|
||||
{x=212,m=980,a=1325,s=882}
|
||||
{x=580,m=754,a=555,s=1470}
|
||||
{x=522,m=397,a=1018,s=763}
|
||||
{x=2327,m=1100,a=975,s=511}
|
||||
{x=324,m=1719,a=48,s=569}
|
||||
{x=1872,m=3353,a=54,s=1330}
|
||||
{x=2082,m=1209,a=2390,s=747}
|
||||
{x=1510,m=2290,a=591,s=45}
|
||||
{x=60,m=1482,a=924,s=598}
|
||||
{x=775,m=675,a=1635,s=1560}
|
||||
{x=316,m=170,a=168,s=1335}
|
||||
{x=1821,m=79,a=2073,s=92}
|
||||
{x=612,m=1814,a=1651,s=3496}
|
||||
{x=116,m=2643,a=1073,s=301}
|
||||
{x=313,m=92,a=2892,s=109}
|
||||
{x=1109,m=279,a=701,s=763}
|
||||
{x=86,m=214,a=1910,s=99}
|
||||
{x=1049,m=320,a=530,s=216}
|
||||
{x=192,m=366,a=887,s=1516}
|
||||
{x=353,m=107,a=257,s=225}
|
||||
{x=117,m=72,a=810,s=147}
|
||||
{x=341,m=17,a=190,s=2748}
|
||||
{x=1397,m=572,a=2275,s=1494}
|
||||
{x=386,m=1691,a=346,s=985}
|
||||
{x=603,m=584,a=1464,s=291}
|
||||
{x=49,m=46,a=2277,s=1200}
|
||||
{x=3116,m=1,a=500,s=166}
|
||||
{x=310,m=1054,a=1271,s=1423}
|
||||
{x=1690,m=721,a=1555,s=232}
|
||||
{x=1713,m=2002,a=1132,s=611}
|
||||
{x=229,m=1721,a=1590,s=42}
|
||||
{x=16,m=1444,a=2296,s=144}
|
||||
{x=371,m=339,a=1073,s=1585}
|
||||
{x=1025,m=10,a=491,s=196}
|
||||
{x=58,m=1161,a=492,s=1401}
|
||||
{x=305,m=1366,a=919,s=236}
|
||||
{x=1427,m=654,a=2052,s=2399}
|
||||
{x=1312,m=723,a=408,s=173}
|
||||
{x=589,m=703,a=29,s=126}
|
||||
{x=2609,m=1461,a=266,s=129}
|
||||
{x=299,m=253,a=857,s=2220}
|
||||
{x=259,m=600,a=494,s=546}
|
||||
{x=2978,m=988,a=1660,s=2661}
|
||||
{x=193,m=478,a=213,s=1631}
|
||||
{x=3378,m=2275,a=534,s=2317}
|
||||
{x=654,m=2641,a=284,s=1768}
|
||||
{x=50,m=76,a=672,s=120}
|
||||
{x=85,m=630,a=1446,s=1321}
|
||||
{x=306,m=986,a=808,s=1724}
|
||||
{x=782,m=1554,a=741,s=2220}
|
||||
{x=1115,m=48,a=3283,s=958}
|
||||
{x=214,m=2498,a=996,s=981}
|
||||
{x=1437,m=53,a=2052,s=914}
|
||||
{x=3256,m=441,a=47,s=108}
|
||||
{x=689,m=1954,a=60,s=133}
|
||||
{x=1,m=2270,a=903,s=13}
|
||||
{x=2373,m=956,a=2739,s=860}
|
||||
{x=1270,m=357,a=2115,s=1868}
|
||||
{x=114,m=587,a=349,s=62}
|
||||
{x=186,m=491,a=464,s=46}
|
||||
{x=2001,m=99,a=649,s=1854}
|
||||
{x=408,m=386,a=681,s=774}
|
||||
{x=697,m=775,a=2740,s=1582}
|
||||
{x=525,m=2075,a=11,s=822}
|
||||
{x=621,m=1069,a=233,s=255}
|
||||
{x=979,m=2750,a=241,s=199}
|
||||
{x=2006,m=665,a=2211,s=1776}
|
||||
{x=483,m=213,a=2042,s=67}
|
||||
{x=1181,m=1199,a=1513,s=919}
|
||||
{x=1378,m=274,a=438,s=546}
|
||||
{x=59,m=224,a=3034,s=254}
|
392
19/src/main.rs
Normal file
392
19/src/main.rs
Normal file
@ -0,0 +1,392 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::ops::{Range, IndexMut, Index};
|
||||
use std::time::Instant;
|
||||
use num_traits::Num;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// DATA
|
||||
|
||||
const INPUT_RANGE: Range<u64> = 1..4001;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RulePredicate {
|
||||
op: PredicateOperator,
|
||||
var: char,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum RuleAction {
|
||||
Terminate(bool),
|
||||
Jump(String),
|
||||
}
|
||||
|
||||
impl From<&str> for RuleAction {
|
||||
fn from(s: &str) -> Self {
|
||||
match s {
|
||||
"A" => Self::Terminate(true),
|
||||
"R" => Self::Terminate(false),
|
||||
s => Self::Jump(s.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Rule {
|
||||
pred: RulePredicate,
|
||||
action: RuleAction,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum PredicateOperator {
|
||||
Always,
|
||||
Lt(u64),
|
||||
Gt(u64),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct XmasRanges {
|
||||
ranges: [Vec<Range<u64>>; 4],
|
||||
}
|
||||
|
||||
impl XmasRanges {
|
||||
fn none() -> XmasRanges {
|
||||
Self {
|
||||
ranges: [vec![0..0], vec![0..0], vec![0..0], vec![0..0]],
|
||||
}
|
||||
}
|
||||
fn all() -> XmasRanges {
|
||||
Self {
|
||||
ranges: [
|
||||
vec![INPUT_RANGE],
|
||||
vec![INPUT_RANGE],
|
||||
vec![INPUT_RANGE],
|
||||
vec![INPUT_RANGE],
|
||||
],
|
||||
}
|
||||
}
|
||||
fn idx(c: char) -> usize {
|
||||
match c {
|
||||
'x' => 0,
|
||||
'm' => 1,
|
||||
'a' => 2,
|
||||
's' => 3,
|
||||
c => panic!("`{}` is not a valid xmas char", c),
|
||||
}
|
||||
}
|
||||
fn insert(&mut self, c: char, v: Vec<Range<u64>>) {
|
||||
self.ranges[Self::idx(c)] = v;
|
||||
}
|
||||
fn count_states(&self) -> u64 {
|
||||
self.ranges
|
||||
.iter()
|
||||
.map(|ranges| ranges.iter().map(|range| range.end - range.start).sum::<u64>())
|
||||
.product()
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<char> for XmasRanges {
|
||||
type Output = Vec<Range<u64>>;
|
||||
fn index(&self, index: char) -> &Self::Output {
|
||||
&self.ranges[Self::idx(index)]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<char> for XmasRanges {
|
||||
fn index_mut(&mut self, index: char) -> &mut Self::Output {
|
||||
&mut self.ranges[Self::idx(index)]
|
||||
}
|
||||
}
|
||||
|
||||
fn range_overlap<T: Num + Ord + Copy>(r1: &Range<T>, r2: &Range<T>) -> Option<Range<T>> {
|
||||
let new_start = std::cmp::max(r1.start, r2.start);
|
||||
let new_end = std::cmp::min(r1.end - T::one(), r2.end - T::one());
|
||||
|
||||
if new_start <= std::cmp::min(r1.end - T::one(), r2.end - T::one()) && new_end >= std::cmp::max(r1.start, r2.start)
|
||||
{
|
||||
Some(new_start..new_end + T::one())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn range_exclude<T: Num + Ord + Copy>(keep: &Range<T>, exclude: &Range<T>) -> Vec<Range<T>> {
|
||||
let mut residual = Vec::new();
|
||||
if let Some(overlap) = range_overlap(keep, exclude) {
|
||||
if keep.start < overlap.start {
|
||||
residual.push(keep.start..overlap.start);
|
||||
}
|
||||
if keep.end > overlap.end {
|
||||
residual.push(overlap.end..keep.end);
|
||||
}
|
||||
} else {
|
||||
residual.push(keep.clone());
|
||||
}
|
||||
residual
|
||||
}
|
||||
|
||||
impl From<&str> for PredicateOperator {
|
||||
fn from(s: &str) -> Self {
|
||||
let (op_s, val_s) = s.split_at(1);
|
||||
match op_s {
|
||||
"<" => PredicateOperator::Lt(val_s.parse().unwrap()),
|
||||
">" => PredicateOperator::Gt(val_s.parse().unwrap()),
|
||||
s => panic!("unknown operator {}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for RulePredicate {
|
||||
fn from(s: &str) -> Self {
|
||||
let (var_s, pred_s) = s.split_at(1);
|
||||
Self {
|
||||
op: pred_s.into(),
|
||||
var: var_s.chars().next().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RulePredicate {
|
||||
fn check(&self, part: &Part) -> bool {
|
||||
match self.op {
|
||||
PredicateOperator::Always => true,
|
||||
PredicateOperator::Gt(val) => part.0[&self.var] > val,
|
||||
PredicateOperator::Lt(val) => part.0[&self.var] < val,
|
||||
}
|
||||
}
|
||||
fn matching_range(&self) -> Range<u64> {
|
||||
match self.op {
|
||||
PredicateOperator::Always => INPUT_RANGE,
|
||||
PredicateOperator::Gt(val) => val + 1..INPUT_RANGE.end,
|
||||
PredicateOperator::Lt(val) => INPUT_RANGE.start..val,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Rule {
|
||||
fn from(s: &str) -> Self {
|
||||
if let Some((predicate_s, action_s)) = s.split_once(':') {
|
||||
Self {
|
||||
pred: predicate_s.into(),
|
||||
action: action_s.into(),
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
pred: RulePredicate {
|
||||
op: PredicateOperator::Always,
|
||||
var: '\0',
|
||||
},
|
||||
action: s.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rule {
|
||||
fn predicate_result(&self, ranges: XmasRanges) -> (XmasRanges, XmasRanges) {
|
||||
if let PredicateOperator::Always = self.pred.op {
|
||||
(ranges, XmasRanges::none())
|
||||
} else {
|
||||
let (mut matching, mut unmatching) = (ranges.clone(), ranges.clone());
|
||||
let relevant_ranges = &ranges[self.pred.var];
|
||||
matching.insert(
|
||||
self.pred.var,
|
||||
relevant_ranges
|
||||
.iter()
|
||||
.filter_map(|range| range_overlap(range, &self.pred.matching_range()))
|
||||
.collect(),
|
||||
);
|
||||
unmatching.insert(
|
||||
self.pred.var,
|
||||
relevant_ranges
|
||||
.iter()
|
||||
.flat_map(|range| range_exclude(range, &self.pred.matching_range()))
|
||||
.collect(),
|
||||
);
|
||||
(matching, unmatching)
|
||||
}
|
||||
}
|
||||
fn possible_ranges(&self, wfs: &Workflows, ranges: XmasRanges) -> (u64, XmasRanges) {
|
||||
let (matching, unmatching) = self.predicate_result(ranges);
|
||||
match &self.action {
|
||||
RuleAction::Terminate(true) => (matching.count_states(), unmatching),
|
||||
RuleAction::Terminate(false) => (0, unmatching),
|
||||
RuleAction::Jump(wf) => (wfs.0[wf].possible_ranges(wfs, matching), unmatching),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Workflow {
|
||||
name: String,
|
||||
rules: Vec<Rule>,
|
||||
}
|
||||
|
||||
impl From<&str> for Workflow {
|
||||
fn from(s: &str) -> Self {
|
||||
let (name_s, rest_s) = s.split_once('{').unwrap();
|
||||
let rules = rest_s.split_once('}').unwrap().0.split(',').map(|r| r.into()).collect();
|
||||
Self {
|
||||
name: name_s.into(),
|
||||
rules,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Workflow {
|
||||
fn execute(&self, part: &Part) -> RuleAction {
|
||||
for r in &self.rules {
|
||||
if r.pred.check(part) {
|
||||
return r.action.clone();
|
||||
}
|
||||
}
|
||||
panic!("unhandled part {:?}", part);
|
||||
}
|
||||
fn possible_ranges(&self, wfs: &Workflows, mut ranges: XmasRanges) -> u64 {
|
||||
let mut accum = 0u64;
|
||||
for r in &self.rules {
|
||||
let count;
|
||||
(count, ranges) = r.possible_ranges(wfs, ranges);
|
||||
accum += count
|
||||
}
|
||||
accum
|
||||
}
|
||||
}
|
||||
|
||||
impl Workflows {
|
||||
fn execute(&self, part: &Part) -> bool {
|
||||
let mut action = RuleAction::Jump("in".into());
|
||||
loop {
|
||||
match &action {
|
||||
RuleAction::Terminate(b) => return *b,
|
||||
RuleAction::Jump(j) => {
|
||||
let next_workflow = &self.0[j];
|
||||
action = next_workflow.execute(part)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn count_possible_states(&self) -> u64 {
|
||||
self.0["in".into()].possible_ranges(self, XmasRanges::all())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Workflows(HashMap<String, Workflow>);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Part(HashMap<char, u64>);
|
||||
|
||||
impl From<&str> for Part {
|
||||
fn from(s: &str) -> Self {
|
||||
let (_, vars_s) = s.split_once('{').unwrap();
|
||||
let vars = vars_s.split_once('}').unwrap().0.split(',');
|
||||
let mut part = HashMap::new();
|
||||
for var in vars {
|
||||
let (name, val) = var.split_once('=').unwrap();
|
||||
part.insert(name.chars().next().unwrap(), val.parse().unwrap());
|
||||
}
|
||||
Self(part)
|
||||
}
|
||||
}
|
||||
|
||||
type Parts = Vec<Part>;
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(mut input: Lines<T>) -> u64 {
|
||||
let mut wfs = Workflows(HashMap::new());
|
||||
let mut parts: Parts = Vec::new();
|
||||
while let Some(Ok(line)) = input.next() {
|
||||
if line != "" {
|
||||
let wf: Workflow = line.as_str().into();
|
||||
wfs.0.insert(wf.name.clone(), wf);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while let Some(Ok(line)) = input.next() {
|
||||
parts.push(line.as_str().into());
|
||||
}
|
||||
|
||||
parts
|
||||
.iter()
|
||||
.filter(|part| wfs.execute(part))
|
||||
.map(|part| part.0.values().sum::<u64>())
|
||||
.sum::<u64>()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(mut input: Lines<T>) -> u64 {
|
||||
let mut wfs = Workflows(HashMap::new());
|
||||
let mut parts: Parts = Vec::new();
|
||||
while let Some(Ok(line)) = input.next() {
|
||||
if line != "" {
|
||||
let wf: Workflow = line.as_str().into();
|
||||
wfs.0.insert(wf.name.clone(), wf);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while let Some(Ok(line)) = input.next() {
|
||||
parts.push(line.as_str().into());
|
||||
}
|
||||
|
||||
wfs.count_possible_states()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
const EXAMPLE: &str = &"px{a<2006:qkq,m>2090:A,rfg}
|
||||
pv{a>1716:R,A}
|
||||
lnx{m>1548:A,A}
|
||||
rfg{s<537:gd,x>2440:R,A}
|
||||
qs{s>3448:A,lnx}
|
||||
qkq{x<1416:A,crn}
|
||||
crn{x>2662:A,R}
|
||||
in{s<1351:px,qqz}
|
||||
qqz{s>2770:qs,m<1801:hdj,R}
|
||||
gd{a>3333:R,R}
|
||||
hdj{m>838:A,pv}
|
||||
|
||||
{x=787,m=2655,a=1222,s=2876}
|
||||
{x=1679,m=44,a=2067,s=496}
|
||||
{x=2036,m=264,a=79,s=2244}
|
||||
{x=2461,m=1339,a=466,s=291}
|
||||
{x=2127,m=1623,a=2188,s=1013}";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 19114);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 167409079868000);
|
||||
}
|
||||
}
|
201
20/Cargo.lock
generated
Normal file
201
20/Cargo.lock
generated
Normal file
@ -0,0 +1,201 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "day20"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy-regex",
|
||||
"num",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d12be4595afdf58bd19e4a9f4e24187da2a66700786ff660a418e9059937a4c"
|
||||
dependencies = [
|
||||
"lazy-regex-proc_macros",
|
||||
"once_cell",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex-proc_macros"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44bcd58e6c97a7fcbaffcdc95728b393b8d98933bfadad49ed4097845b57ef0b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
10
20/Cargo.toml
Normal file
10
20/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "day20"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lazy-regex = "3.1.0"
|
||||
num = "0.4.1"
|
58
20/input
Normal file
58
20/input
Normal file
@ -0,0 +1,58 @@
|
||||
%hm -> cr
|
||||
%qc -> nd
|
||||
&dh -> rm
|
||||
%ph -> zz
|
||||
%ps -> kc, dt
|
||||
%qb -> dt
|
||||
%jl -> vt, tb
|
||||
%fh -> dm, gr
|
||||
broadcaster -> np, mg, vd, xr
|
||||
%zz -> sq
|
||||
&rm -> rx
|
||||
%nd -> br
|
||||
%nx -> vr, vt
|
||||
%qf -> dt, dv
|
||||
%np -> xm, ph
|
||||
%dm -> nf, gr
|
||||
%sq -> kj
|
||||
%bv -> fp, xm
|
||||
%br -> kt
|
||||
%mg -> dz, gr
|
||||
&dt -> vd, dv, dh, hm, ks, hd, kq
|
||||
%ks -> qf
|
||||
&qd -> rm
|
||||
%xr -> vt, rn
|
||||
%vr -> tg, vt
|
||||
%lc -> xm
|
||||
%tq -> gr, fh
|
||||
%cr -> kq, dt
|
||||
%vd -> dt, ks
|
||||
%tb -> nx
|
||||
%dz -> gr, fd
|
||||
&gr -> dp, mg, fd, qn
|
||||
%nf -> gr
|
||||
%dv -> hm
|
||||
%qj -> lc, xm
|
||||
%kc -> dt, gf
|
||||
%gf -> dt, qb
|
||||
%vh -> xm, sv
|
||||
%sr -> vt
|
||||
%fp -> qg, xm
|
||||
%kj -> vh
|
||||
%pc -> tq, gr
|
||||
%kq -> hd
|
||||
%xd -> xg, gr
|
||||
%tg -> sr, vt
|
||||
&bb -> rm
|
||||
%rn -> vt, qc
|
||||
%hd -> ps
|
||||
%qg -> xm, qj
|
||||
&dp -> rm
|
||||
%qn -> pc
|
||||
%kt -> jl
|
||||
%sv -> bv
|
||||
&vt -> bb, nd, qc, xr, br, tb, kt
|
||||
%fd -> mx
|
||||
&xm -> zz, sv, sq, ph, kj, np, qd
|
||||
%xg -> gr, qn
|
||||
%mx -> gr, xd
|
362
20/src/main.rs
Normal file
362
20/src/main.rs
Normal file
@ -0,0 +1,362 @@
|
||||
use std::collections::{BinaryHeap, HashMap, VecDeque};
|
||||
use std::fmt::Display;
|
||||
use std::fs::File;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::Instant;
|
||||
|
||||
use lazy_regex::lazy_regex;
|
||||
use num::integer::lcm;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
const MODULE_PATTERN: lazy_regex::Lazy<lazy_regex::Regex> = lazy_regex!("^([%&]?)([a-z]+) -> ([a-z, ]+)$");
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
enum PulseType {
|
||||
Low,
|
||||
High,
|
||||
}
|
||||
|
||||
impl From<bool> for PulseType {
|
||||
fn from(value: bool) -> Self {
|
||||
match value {
|
||||
true => PulseType::High,
|
||||
false => PulseType::Low,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PulseType> for bool {
|
||||
fn from(value: PulseType) -> Self {
|
||||
match value {
|
||||
PulseType::High => true,
|
||||
PulseType::Low => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PulseType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
PulseType::Low => f.write_str("low"),
|
||||
PulseType::High => f.write_str("high"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum ModuleKind {
|
||||
FlipFlop,
|
||||
Conjunction,
|
||||
Broadcast,
|
||||
Button,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Module {
|
||||
name: String,
|
||||
kind: Option<ModuleKind>,
|
||||
inputs: Vec<String>,
|
||||
outputs: Vec<String>,
|
||||
on: bool,
|
||||
last_input_states: Vec<PulseType>,
|
||||
}
|
||||
|
||||
impl Hash for Module {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
// the only states that change are 'on' and 'last_input_states', the rest are constant once created
|
||||
self.on.hash(state);
|
||||
self.last_input_states.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Module {
|
||||
fn new(name: String) -> Self {
|
||||
Self {
|
||||
name,
|
||||
kind: None,
|
||||
inputs: Vec::new(),
|
||||
outputs: Vec::new(),
|
||||
on: false,
|
||||
last_input_states: Vec::new(),
|
||||
}
|
||||
}
|
||||
fn source_idx(&self, name: &str) -> usize {
|
||||
self.inputs.iter().position(|in_name| in_name == name).unwrap()
|
||||
}
|
||||
fn with_kind(name: String, kind: ModuleKind) -> Self {
|
||||
let mut m = Self::new(name);
|
||||
m.kind = Some(kind);
|
||||
m
|
||||
}
|
||||
fn and_destinations(mut self, destinations: &str) -> Self {
|
||||
for dest in destinations.split(", ") {
|
||||
self.outputs.push(dest.into());
|
||||
}
|
||||
self
|
||||
}
|
||||
fn and_source(mut self, source: String) -> Self {
|
||||
self.add_source(source);
|
||||
self
|
||||
}
|
||||
fn add_source(&mut self, source: String) {
|
||||
self.inputs.push(source);
|
||||
self.last_input_states.push(PulseType::Low);
|
||||
}
|
||||
fn reset(&mut self) {
|
||||
// relevant state is on and last_input_states
|
||||
self.on = false;
|
||||
for input in &mut self.last_input_states {
|
||||
*input = PulseType::Low;
|
||||
}
|
||||
}
|
||||
fn state_space(&self) -> u128 {
|
||||
match self.kind {
|
||||
Some(ModuleKind::Broadcast) | Some(ModuleKind::Button) => 1,
|
||||
Some(ModuleKind::FlipFlop) => 2,
|
||||
Some(ModuleKind::Conjunction) => 1 << self.last_input_states.len(), // 2^n
|
||||
None => 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Module {
|
||||
fn from(s: &str) -> Self {
|
||||
let Some(re_result) = MODULE_PATTERN.captures(s) else {
|
||||
panic!("unparseable module: {}", s);
|
||||
};
|
||||
let (_, [kind, name, destinations]) = re_result.extract();
|
||||
if name == "broadcaster" {
|
||||
return Module::with_kind(name.into(), ModuleKind::Broadcast).and_destinations(destinations);
|
||||
};
|
||||
match kind {
|
||||
"%" => Module::with_kind(name.into(), ModuleKind::FlipFlop).and_destinations(destinations),
|
||||
"&" => Module::with_kind(name.into(), ModuleKind::Conjunction).and_destinations(destinations),
|
||||
_ => panic!("invalid module kind {}", kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Job {
|
||||
signal: PulseType,
|
||||
targets: Vec<String>,
|
||||
from: String,
|
||||
priority: usize,
|
||||
}
|
||||
|
||||
impl PartialEq for Job {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.priority == other.priority
|
||||
}
|
||||
}
|
||||
impl Eq for Job {}
|
||||
|
||||
impl PartialOrd for Job {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
other.priority.partial_cmp(&self.priority)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Job {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Machine {
|
||||
modules: HashMap<String, Module>,
|
||||
work_queue: BinaryHeap<Job>,
|
||||
count_low: u64,
|
||||
count_high: u64,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Machine {
|
||||
fn from(mut lines: Lines<T>) -> Self {
|
||||
let mut modules = HashMap::from([(
|
||||
"button".into(),
|
||||
Module::with_kind("button".into(), ModuleKind::Button).and_destinations("broadcaster"),
|
||||
)]);
|
||||
while let Some(Ok(line)) = lines.next() {
|
||||
let mut module = Module::from(line.as_str());
|
||||
for output in &module.outputs {
|
||||
if let Some(output_mod) = modules.get_mut(output) {
|
||||
// already exists, push to input list
|
||||
output_mod.add_source(module.name.to_owned());
|
||||
} else {
|
||||
// forward declaration of 'unknown' modules
|
||||
modules.insert(
|
||||
output.clone(),
|
||||
Module::new(output.clone()).and_source(module.name.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(existing_mod) = modules.get(&module.name) {
|
||||
module.inputs = existing_mod.inputs.clone(); // might have been pre-prepared, the rest we take ours
|
||||
module.last_input_states = existing_mod.last_input_states.clone();
|
||||
}
|
||||
modules.insert(module.name.clone(), module);
|
||||
}
|
||||
|
||||
Machine {
|
||||
modules,
|
||||
work_queue: BinaryHeap::new(),
|
||||
count_low: 0,
|
||||
count_high: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
fn press_button(&mut self) {
|
||||
self.send_pulse(PulseType::Low, "broadcaster", "button", 1);
|
||||
}
|
||||
fn send_pulse(&mut self, signal: PulseType, target: &str, from: &str, priority: usize) {
|
||||
// count pulse when it is received
|
||||
match signal {
|
||||
PulseType::Low => self.count_low += 1,
|
||||
PulseType::High => self.count_high += 1,
|
||||
};
|
||||
match self.modules[target].kind {
|
||||
Some(ModuleKind::Button) | Some(ModuleKind::Broadcast) => {
|
||||
self.send_all_outputs(PulseType::Low, target, priority)
|
||||
}
|
||||
Some(ModuleKind::FlipFlop) => match signal {
|
||||
PulseType::High => (),
|
||||
PulseType::Low => {
|
||||
let new_state = !self.modules.get_mut(target).unwrap().on;
|
||||
self.modules.get_mut(target).unwrap().on = new_state;
|
||||
self.send_all_outputs(new_state.into(), target, priority)
|
||||
}
|
||||
},
|
||||
Some(ModuleKind::Conjunction) => {
|
||||
let target_m = self.modules.get_mut(target).unwrap();
|
||||
let source_idx = target_m.source_idx(from);
|
||||
target_m.last_input_states[source_idx] = signal;
|
||||
if target_m.last_input_states.iter().all(|state| *state == PulseType::High) {
|
||||
self.send_all_outputs(PulseType::Low, target, priority)
|
||||
} else {
|
||||
self.send_all_outputs(PulseType::High, target, priority)
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
fn send_all_outputs(&mut self, signal: PulseType, from: &str, priority: usize) {
|
||||
self.work_queue.push(Job {
|
||||
signal,
|
||||
targets: self.modules[from].outputs.iter().map(|op| op.to_owned()).collect(),
|
||||
from: from.to_owned(),
|
||||
priority: priority + 1,
|
||||
})
|
||||
}
|
||||
fn run(&mut self) {
|
||||
while let Some(job) = self.work_queue.pop() {
|
||||
for target in job.targets {
|
||||
self.send_pulse(job.signal, &target, &job.from, job.priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
// the number of cycles it took until the target sends a low pulse, or None if the target node sent no low pulses but the job finished
|
||||
fn time_to_state(&mut self, goal:&str, state: PulseType) -> Option<u64> {
|
||||
while let Some(job) = self.work_queue.pop() {
|
||||
if job.from == goal && job.signal == state {
|
||||
return Some(self.count_high + self.count_low);
|
||||
}
|
||||
for target in job.targets {
|
||||
self.send_pulse(job.signal, &target, &job.from, job.priority);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
fn reset(&mut self) {
|
||||
for (_name, m) in &mut self.modules {
|
||||
m.reset();
|
||||
}
|
||||
self.count_low = 0;
|
||||
self.count_high = 0;
|
||||
}
|
||||
fn state_space(&self) -> u128 {
|
||||
self.modules.values().map(|m| m.state_space()).product()
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
const PROBLEM1_ITERATIONS: usize = 1000;
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut machine = Machine::from(input);
|
||||
for _ in 0..PROBLEM1_ITERATIONS {
|
||||
machine.press_button();
|
||||
machine.run();
|
||||
}
|
||||
machine.count_low * machine.count_high
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u128 {
|
||||
let mut machine = Machine::from(input);
|
||||
println!("STATES: {}", machine.state_space());
|
||||
// Find the rx module and look at its parent(s)
|
||||
let rx = &machine.modules["rx"];
|
||||
// my input has a single conjunction as parent, todo implement other possibilities
|
||||
let con = &machine.modules[&rx.inputs[0]];
|
||||
|
||||
// for each input, find how long it takes for it to be High, so the conjunction sends a low to rx
|
||||
let mut cycles: Vec<_> = Vec::new();
|
||||
for input in con.inputs.clone() {
|
||||
print!("searching distance to {}...", input);
|
||||
machine.reset();
|
||||
let mut button_count = 0;
|
||||
loop {
|
||||
machine.press_button();
|
||||
button_count += 1;
|
||||
if let Some(distance) = machine.time_to_state(&input, PulseType::High) {
|
||||
println!("got {} pulses, {} button presses", distance, button_count);
|
||||
cycles.push(button_count as u128);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cycles.iter().fold(1, |accum, cycle| lcm(accum, *cycle))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"broadcaster -> a
|
||||
%a -> inv, con
|
||||
&inv -> b
|
||||
%b -> con
|
||||
&con -> output";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 11687500);
|
||||
}
|
||||
}
|
465
21/Cargo.lock
generated
Normal file
465
21/Cargo.lock
generated
Normal file
@ -0,0 +1,465 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"unicode-width",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day21"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"indicatif",
|
||||
"polyfit-rs",
|
||||
"primes",
|
||||
"rayon",
|
||||
"test-case",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"
|
||||
dependencies = [
|
||||
"console",
|
||||
"instant",
|
||||
"number_prefix",
|
||||
"portable-atomic",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra"
|
||||
version = "0.31.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20bd243ab3dbb395b39ee730402d2e5405e448c75133ec49cc977762c4cba3d1"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"matrixmultiply",
|
||||
"nalgebra-macros",
|
||||
"num-complex",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"simba",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "number_prefix"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
|
||||
[[package]]
|
||||
name = "polyfit-rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab98d9704c7300e37472a6790a447eaf501d664a1889737faa53c26790d2b697"
|
||||
dependencies = [
|
||||
"nalgebra",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||
|
||||
[[package]]
|
||||
name = "primes"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68a61082d8bceecd71a3870e9162002bb75f7ba9c7aa8b76227e887782fef9c8"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "safe_arch"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simba"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f3fd720c48c53cace224ae62bef1bbff363a70c68c4802a78b5cc6159618176"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"num-complex",
|
||||
"num-traits",
|
||||
"paste",
|
||||
"wide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8"
|
||||
dependencies = [
|
||||
"test-case-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-core"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-macros"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"test-case-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||
|
||||
[[package]]
|
||||
name = "wide"
|
||||
version = "0.7.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c68938b57b33da363195412cfc5fc37c9ed49aa9cfe2156fde64b8d2c9498242"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"safe_arch",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
13
21/Cargo.toml
Normal file
13
21/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "day21"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
indicatif = "0.17.7"
|
||||
polyfit-rs = "0.2.1"
|
||||
primes = "0.3.0"
|
||||
rayon = "1.8.0"
|
||||
test-case = "3.3.1"
|
131
21/input
Normal file
131
21/input
Normal file
@ -0,0 +1,131 @@
|
||||
...................................................................................................................................
|
||||
..............#...#........#...............#.#.......#....##...........#.#..#......#.....#.........#..##...........................
|
||||
.#..##..##..#......#.#.#...##......###...##......#.#..#...................#.....#..........#..#................#...#..........#....
|
||||
.....................#..#.......#.....##.........#.......................................#........#....#.#..........#.#......#.#...
|
||||
......##...#.....#.......#...#..###..........#..........#......................#........#.............#.....#........#....#........
|
||||
.................##.................#...#.........#................................#........#...........#............#........#....
|
||||
..............#.#....#........##.....##..........#.............##.............#...#......#..##..........#.........#.....#...#..#...
|
||||
..#....#.......#...##..#......#.........#.#..#....#.#..............#........#...#...#...............#.#.....#..#..##......#...#....
|
||||
...#......##...##..#...#..........#...#..........#..............#...#..........#..#..#..#........#.#.#.#.#...........###...........
|
||||
.#.#.#...#.#...##............................................#......................#...#......#......##.#.........................
|
||||
.##.#.........#...#..................##...........#............#..................###...#...........#.................#....#.......
|
||||
.....................#...#.#................#................#.#........................#...#...##....##....#.#...#.........#...#..
|
||||
...#.......#...#.........................#.#..................#........##..........................#......##....##............#....
|
||||
......................#.....................#...............#.......#.#...................#...............#...#........#.##......#.
|
||||
............................#..........................#........#....#.##..#.......#.##..#...#.#..#...............#.#..#....#......
|
||||
.......................................................#.#..#.#....#......................#............#....#..#.......#.........#.
|
||||
.....##........#...............#.......#...............#.#..........##..#...................#................#..#...#.#....#...###.
|
||||
....#.....................##................#.......#.......#...#.#...#...............#................#...............##..........
|
||||
....#........#..#.......#.#.#........................#.#...........#.......#..#.........#....#.......#........#.#.#................
|
||||
......###.....#..#...........#.....#..#..#........#......#.#........###.....##............#..#...........#.........................
|
||||
.....#...........#...................#..#..........#..#...###.#.........#.##...............#..##..........#.........#..............
|
||||
.#.........#....#............#.##..........................##.....#........#....#.............#.......#...#..............##.#......
|
||||
.#..#...#.......#...#.......##.......#.#.............................#...#...#.#...........#...#.................#.........#.#.#...
|
||||
...#....................#.....##..............#.................#.................#............#......#....#.......#.........#.....
|
||||
.......#...#.............#.##...#.#...................#.....#..#........#................................#.............#..#...##...
|
||||
...#.###..............#....#........................#......#...#.........#......#.#....................#........#...#...#.......#..
|
||||
............#.#...#...........................#....###.###...#........#..#........#...................##.....###......#........#...
|
||||
.....#...#................#.##..##..................#....#.........#............##...................##................#.....#.....
|
||||
.#....#..............##...#..................#......#..........##.#....#......##.#...............#....##..............#....#.......
|
||||
....#.#.##...........##.....#...........#.........#...#........#..#.......#......#................#.#...#....#...#.................
|
||||
.......#...#...#...#..#.......#..........#..................#..#........#..#.#.....#.#.....................##......................
|
||||
.....##.........#.......##...#.............#.##.#.#...#.##.#...#......#...#....#.......#..#.........#...........#.##.###.#.....#...
|
||||
...................#.#.......................#.....#.#......#.....##...#.#....#..#..........#...........#..##....#...#.......#.#...
|
||||
.....#..#..#.........#...#.#.........#...#.#...##...#......##........#...............#.......#................#.....#...#.#........
|
||||
........#.....###.....................#.........#.........#.........#....##............#..##.............#.........#..#.......#....
|
||||
.#.........#....##..##.................#...#................................#...#.....#.........#.......#............#....#......#.
|
||||
..#.........#.......#..................#..#.#...#........#.#.......#...##.#........#..........#.#..........#..#.....#.........#....
|
||||
..#...............#...................##.#.......#...#..........#....................##.........#.................#..#......##..#..
|
||||
.#........#.......#............##...........##........#.......................#................#....................#...###......#.
|
||||
........###..........#..............#.............#..#.#.#............##...............#........#...#........#...................#.
|
||||
...#............................#...##.##........#......#..#...................#.#.....#...#.##...............#........#...#.......
|
||||
..#...##....................#.....##......#.......#..........#......#.........#...#..............#..............#..................
|
||||
.....#..#....................#....###.....#..#.............#...#....#................#.....#.....................#........#........
|
||||
.....#.#...#.....#..............##............#....##.#....#.#........##...........#....#.........................#....#......##...
|
||||
....#..#.....##...........#.#.#.#............#....#.....#.........#........................##.......#.#..............##...#........
|
||||
...............#..............#................................#....#........#.......#.......##......#.#............#......#....#..
|
||||
.#......#....##........#.............#..#.#.............#...#..#.........#.........#................#..................#...........
|
||||
.........#..............#....#......#.....##......#............#....#.........#....#...................#....#.........#......#..#..
|
||||
..............................#....#.#........#.#.....#..#.................#....#...#..........#............##.......#.#.#....#....
|
||||
.#..................#....#..#.......#.##..............#...#.......#................#...............................................
|
||||
.#..##.........................#.....###......#....#......#.....#............#.#......##......##......##....#..........##.....#....
|
||||
..........................##.#.....#..........................................#.#..#....#..#..................#...........#........
|
||||
..##.....#.......#....#.........#..........#....................#.........#........###........................#..........#.........
|
||||
.#.#...............#..........#.......#.....#....##.#..#.##...............#...#...#.#......#.......#.......#.#.............#....##.
|
||||
..................#...............##.........##..#........#..#..........#.....................#............................#.......
|
||||
.....#................#...##.......##.........#.....#.#....#.#........#...#..#....#..............#..#....#....#....#...............
|
||||
..##.#........#...............#.#..#...................##...#......#.#...#..#.....##.................##...#.#...................#..
|
||||
...#...............#......#.....#.......#......#.........#...#......#...#..#....#..#......#.......#.......#...#.##.#...........##..
|
||||
..............##..........##..........#..##...............#...........##..#..#..#.#.......#...#.............#......................
|
||||
..........#.#........................#...#.#..#.#...##..#.#.#.#.......#....#.#.#..............#...#...#........###..##...........#.
|
||||
......................#...#.#..##.....#....#.....###.#..#.....#..........#........#...........##...#..#...........##..#............
|
||||
..................................####.#..............#.................#........#.#............##......#.#..........#.............
|
||||
..................#..........#.............................#...........#..#..#......#................#.......##...##..#............
|
||||
....................#...#....#.#.#.##......#................#.................#...........#....#..........#....#...##.###..........
|
||||
.................#.......#...#............###.###..#.......#......#.......#..##......#.#.....#.....................#...............
|
||||
.................................................................S.................................................................
|
||||
.......##...........#.........###.......#....###.#.#....#.#....#....#........#.......#...#...#.#.........#...................#.....
|
||||
.......#...............#............#...#..#.......##...#...#.#............#.............#......##..........#..............#.......
|
||||
.......##.........#.....................##...#...#.................#...#.......#..####......#.....#..............#..##.............
|
||||
........#..#.............#.#..##..............#...#.............#.....#......#...#.#.......#...............##...##.................
|
||||
.........#..#...#..#.#..#..#...................##......#.....#..#...##..............#......#..........#.##...#.#.##.#..............
|
||||
..............#..........#....................................#.........#.......#..#............##................#................
|
||||
...........#...#.....#.........#....#..###....#...#.......#....#...............##.....#.......#.#.....#.#....#.#..#................
|
||||
..#...................#........###..............#.#................#...###...##.............#.###......#...#...#.....#..........#..
|
||||
.#.#............#.....#....###......................................#..........................#..................#................
|
||||
................#..#...#................#.................##.................##..........#.......#...#.............#...............
|
||||
.....##...........#....#.......#......#.#.....#.....#................#.....#.........#..#.................#........#........#......
|
||||
.#.#.............#..#.#..............#.....#..#.#.....#..#......#.........#.....#.#......#..#.......#.#......##............#..#....
|
||||
...................#............#....#...........#........#...................#.....##..............#........###...............#...
|
||||
......###..........###.#.......#.................................................#..#.........#.#...#.........#.#..........#.#.....
|
||||
..#.................#..#..#...#............#...#...#..##.#....##..#..................##.....#......#.........................#...#.
|
||||
......................#.#.....#.#...#.......##...........#...#....#.............#.......#.............#.#.#.#......................
|
||||
......#..#.#..........#....#.........#......#................#.........##.#....#.......#........#.#....................#......#....
|
||||
..#....#....#...............#..........#...#.#......#...................#.........#..#.#......#..#.........................##....#.
|
||||
..............#..........##......#.##...#...#.#................#...#..#.......#.#.....#........#...###..##.........#..##.........#.
|
||||
........##...........................##.......#.#..................#........#.......#.#........#.........................##....#...
|
||||
..#.#...........#.......................#.#.....#....#.....#...............####...#..............#...#....................#.#......
|
||||
.......#...#....#.#.......#####...##.....#.#.......#....#.#........#................................#.##..........##....#..#.......
|
||||
.........#.....#................##.#..................#.....................#...#................#.###.#.......###....#............
|
||||
............#.#....#........#....#..................#...##.............#............#.......#.....#..#............##...............
|
||||
....#.....#..........#..............#...#...#........##.....#.#....#....#........##.............................#.#.......#........
|
||||
..#..#.#.......#.................#................................#......##.#..#..............#.#................#...#.#...........
|
||||
.....#.....#........................#..#................#......#.......#.........###.#.#.........#.........#.....#.......#.........
|
||||
.......#.......................................#.......#...............#.#..###...#.#.##.......#...........#.#.....#.##........#...
|
||||
......##.........#.................................#.........#........##.#................#.#...#.............#...#..#........#....
|
||||
......#.....#.#.......#...........#..#...........#.........#..#.#.......#.........##.....#....#.#...............#...#...#....#...#.
|
||||
..#...#.#....#....#..............................#..#...#.......#.#.#..##..................#...............#......#..###..#.#......
|
||||
.....#...#..#......#.....##...............#..........#..#.#####.......#...........#...................#.....#...#.........#..#.#...
|
||||
.................#.......#..................#........#.......##...##.#....#.#.............#.............#....#....#................
|
||||
...........####..#.....#....#.............#.......#...#..#.....#.............#...#....#.............#.#....#.#.............#.......
|
||||
...#..#..#...#...#.#.....#.......................#....#..###.###.....#.........#....................#....#..#............#.....#...
|
||||
.#.##....##...#......#.#.....#......................#.##..................#........#..#................#.#.......#.............#...
|
||||
....##........#.......#..#..#............#..#..#..#...#......###..#..#..#...##...............................#.#........#......#.#.
|
||||
..#..#..........#..........#..#.#.............#.....#...........#.##.......#............................#...........#...#..........
|
||||
..#.#..#...#....#.....#.....#...#................#.....#.....#....#..#...#..#....#....#.....................#....#.................
|
||||
.......#........#...#.............#.................#...#.#.....#.#....#..........#......................#..#............#.........
|
||||
....#........#........#..............#.........................#...................#..........#.........#..#.........#.............
|
||||
................#........#.........#............................#.#.............#..##.......#......#..#.................#......#.#.
|
||||
..#.....#.........#...#..#.#.........................#...#...#...........#.....#...........#........#.............#.....#........#.
|
||||
....#...#....#......#....#...#..#.................#...##.....#.#............................##...#...#..##.#.....................#.
|
||||
...#..##...............#............................#...........#......#.#.....#............#........#.##................#.........
|
||||
................#..#.............#..#..............#.#....#...#.#...#...#.#.##.............................#..#...........#........
|
||||
.......#.......#....###............#.#.#.....................#.#..#....#.................##.....#.#..........##..#......#..........
|
||||
.......#..........##.#.......#.##...#...............##.....#..........#................#............#...#........#........#........
|
||||
...###.#.............................#.....#.#............##..#...#.....###..........#...............................#.....#....#..
|
||||
....###.#...#.......#.##........#......#..##.#..........#.#...#.#....#.#..............##....#..#...#...........#...#.#..#..........
|
||||
.....#....#.#..##.....#..........#..#...##..............#.......#.......#.............#..#.....#.......#.....#...##...###.......#..
|
||||
........##...#...##..#.#.....#..........................#.#.#..#..#...................#....#....#..#....#..........#....##.........
|
||||
...........##.....#...#........##..#........#....#..........#..#...............................................#......#.#.......#..
|
||||
...#..##.........##....#...........##...#.......##.........#........#...........#........#.#.##...........#....#.....###...#.......
|
||||
...#...#........................#..#...#..#........................................#......#..#...#.#....#...........#..............
|
||||
...#..#.......#..#......##...................#...............#.....#.#.............#.....#.........#.#..##.....#..........#..#.....
|
||||
....###....#..#.....#.#........#.##.......##...#...............#...............###.###.#...#............##.....#.................#.
|
||||
....#...#.........#.##............#.....#........#............................................##.#......#..##.........#....###..#..
|
||||
............#...##..#..........#........#.......#.#..........................#..#.#.......#......#.......................##.#..#...
|
||||
....#......#....#....#..#.....#........#......#....#..#.#..............................#..#....#............#....#.................
|
||||
..#.............#...#......#...#.....................#.##...............................##...#.......#........................#.##.
|
||||
....#....##........#..............#....#.......#.....................................#........#........#...##..........#...........
|
||||
....#.#.##..#..#....................#.................#.##.............#....#....#.............###...#...#..##....#.....##.........
|
||||
.............#.......#...............#........#.#.....#..#.#................#.....#..##.....#....#...............#....#......#...#.
|
||||
...................................................................................................................................
|
230
21/src/main.rs
Normal file
230
21/src/main.rs
Normal file
@ -0,0 +1,230 @@
|
||||
use core::panic;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use rayon::prelude::*;
|
||||
use std::collections::HashSet;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
type Position = (isize, isize);
|
||||
type WrappedPosition = (usize, usize);
|
||||
type Offset = (isize, isize);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct MapTile {
|
||||
c: char,
|
||||
}
|
||||
|
||||
impl MapTile {
|
||||
fn new(c: char) -> Self {
|
||||
Self { c }
|
||||
}
|
||||
}
|
||||
|
||||
struct GardenMap {
|
||||
map: Vec<Vec<MapTile>>,
|
||||
start: Position,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for GardenMap {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
let map = lines
|
||||
.map(|line| line.unwrap().chars().map(|c| MapTile::new(c)).collect())
|
||||
.collect();
|
||||
let mut new = Self { map, start: (0, 0) };
|
||||
new.find_start();
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
const ADJACENCIES: [Offset; 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
|
||||
|
||||
impl GardenMap {
|
||||
fn wrap_pos(&self, pos: &Position) -> WrappedPosition {
|
||||
let (width, height) = (self.width() as isize, self.height() as isize);
|
||||
(
|
||||
if pos.0 < 0 {
|
||||
(pos.0 + (-pos.0 / width + 1) * width) as usize % self.width()
|
||||
} else {
|
||||
pos.0 as usize % self.width()
|
||||
},
|
||||
if pos.1 < 0 {
|
||||
(pos.1 + (-pos.1 / height + 1) * height) as usize % self.height()
|
||||
} else {
|
||||
pos.1 as usize % self.height()
|
||||
},
|
||||
)
|
||||
}
|
||||
fn width(&self) -> usize {
|
||||
self.map[0].len()
|
||||
}
|
||||
fn height(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
fn at(&self, pos: &Position) -> &MapTile {
|
||||
let pos = self.wrap_pos(pos);
|
||||
&self.map[pos.1][pos.0]
|
||||
}
|
||||
// return the valid 'moves' from pos
|
||||
fn adjacent_to(&self, pos: &Position) -> Vec<Position> {
|
||||
ADJACENCIES
|
||||
.iter()
|
||||
.filter_map(|ofs| self.offset_pos(pos, ofs))
|
||||
.filter(|pos| self.at(pos).c != '#')
|
||||
.collect()
|
||||
}
|
||||
fn offset_pos(&self, pos: &Position, ofs: &Offset) -> Option<Position> {
|
||||
let new_pos = (pos.0 as isize + ofs.0, pos.1 as isize + ofs.1);
|
||||
return Some((new_pos.0, new_pos.1));
|
||||
}
|
||||
fn find_start(&mut self) {
|
||||
for (y, row) in self.map.iter().enumerate() {
|
||||
for (x, tile) in row.iter().enumerate() {
|
||||
if tile.c == 'S' {
|
||||
self.start = (x as isize, y as isize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("didn't find the start square!");
|
||||
}
|
||||
fn reachable_after(&self, from: &Position, n: usize) -> u64 {
|
||||
let bar = ProgressBar::new(n as u64).with_style(
|
||||
ProgressStyle::with_template(
|
||||
"[{elapsed_precise}/{eta_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {per_sec}",
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
let mut visited_after: Vec<HashSet<Position>> = Vec::new();
|
||||
visited_after.push(HashSet::from([*from]));
|
||||
for i in 1..n+1 {
|
||||
visited_after.push(
|
||||
visited_after[i - 1]
|
||||
.iter()
|
||||
.flat_map(|last| self.adjacent_to(last))
|
||||
.collect(),
|
||||
);
|
||||
bar.inc(1);
|
||||
// if primes::is_prime(i as u64) {
|
||||
// println!("count after {} steps: {}", i, visited_after[i].len());
|
||||
// }
|
||||
}
|
||||
|
||||
visited_after[n].len() as u64
|
||||
}
|
||||
fn reachable_count_after(&self, from: &Position, n: usize) -> u64 {
|
||||
let dim = self.width() as f64;
|
||||
let target_mod = (n % self.width()) as f64;
|
||||
let x_values:Vec<f64> = vec![target_mod, target_mod + dim, target_mod + 2.*dim];
|
||||
let y_values:Vec<f64> = x_values.iter().map(|n| self.reachable_after(from, *n as usize) as f64).collect();
|
||||
|
||||
let coeffs = polyfit_rs::polyfit_rs::polyfit(
|
||||
&x_values,
|
||||
&y_values,
|
||||
2,
|
||||
).unwrap();
|
||||
println!("values: x: {:?} y: {:?}", x_values, y_values);
|
||||
println!("coefficients: {:?}", coeffs);
|
||||
|
||||
let f_n= n as f64;
|
||||
let result = coeffs[0] + coeffs[1] * f_n + coeffs[2] * f_n.powf(2.0);
|
||||
|
||||
result.round() as u64
|
||||
}
|
||||
fn draw_with_bounds(&self, from: &Position, to: &Position) {
|
||||
for row in from.1..to.1 + 1 {
|
||||
for col in from.0..to.0 + 1 {
|
||||
print!("{}", self.at(&(col, row)).c);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fn print_visited(map: &GardenMap, visited: &Vec<Vec<bool>>) {
|
||||
// for (y, row) in visited.iter().enumerate() {
|
||||
// for (x, cell) in row.iter().enumerate() {
|
||||
// print!("{}", if *cell { 'O' } else { map.at(&(x, y)).c });
|
||||
// }
|
||||
// println!();
|
||||
// }
|
||||
// }
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1_impl<T: BufRead>(input: Lines<T>, n: usize) -> u64 {
|
||||
let map = GardenMap::from(input);
|
||||
// println!("map: {:?} start: {:?}", map.map, &map.start);
|
||||
// map.draw_with_bounds(
|
||||
// &(-(map.width() as isize), -(map.height() as isize)),
|
||||
// &(map.width() as isize * 2 + 1, map.height() as isize * 2 + 1),
|
||||
// );
|
||||
map.reachable_count_after(&map.start, n)
|
||||
}
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
problem1_impl(input, 64)
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
problem1_impl(input, 26501365)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
use test_case::test_case;
|
||||
|
||||
const EXAMPLE: &str = &"...........
|
||||
.....###.#.
|
||||
.###.##..#.
|
||||
..#.#...#..
|
||||
....#.#....
|
||||
.##..S####.
|
||||
.##..#...#.
|
||||
.......##..
|
||||
.##.#.####.
|
||||
.##..##.##.
|
||||
...........";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1_impl(c.lines(), 6), 16);
|
||||
}
|
||||
|
||||
#[test_case(6, 16)]
|
||||
#[test_case(10, 50)]
|
||||
#[test_case(50, 1594)]
|
||||
#[test_case(100, 6536)]
|
||||
#[test_case(500, 167004)]
|
||||
fn problem2_example(n: usize, expect: u64) {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1_impl(c.lines(), n), expect);
|
||||
}
|
||||
}
|
128
22/Cargo.lock
generated
Normal file
128
22/Cargo.lock
generated
Normal file
@ -0,0 +1,128 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "day22"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"ndarray",
|
||||
"petgraph",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||
dependencies = [
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
11
22/Cargo.toml
Normal file
11
22/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "day22"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.12.0"
|
||||
ndarray = "0.15.6"
|
||||
petgraph = "0.6.4"
|
385
22/src/main.rs
Normal file
385
22/src/main.rs
Normal file
@ -0,0 +1,385 @@
|
||||
use itertools::Itertools;
|
||||
use ndarray::prelude::*;
|
||||
use petgraph::prelude::*;
|
||||
use petgraph::visit::{IntoNodeReferences, Walker};
|
||||
use std::collections::BinaryHeap;
|
||||
use std::fmt::{Display, Write};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::str::FromStr;
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Clone, Debug)]
|
||||
struct Coord {
|
||||
x: usize,
|
||||
y: usize,
|
||||
z: usize,
|
||||
}
|
||||
|
||||
impl FromStr for Coord {
|
||||
type Err = Box<dyn std::error::Error>;
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
let (x, y, z) = value.split(',').next_tuple().unwrap();
|
||||
Ok(Self {
|
||||
x: x.parse()?,
|
||||
y: y.parse()?,
|
||||
z: z.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
||||
struct BrickBlock {
|
||||
c1: Coord,
|
||||
c2: Coord,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for BrickBlock {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(
|
||||
f,
|
||||
"[{},{},{} - {},{},{}]",
|
||||
self.c1.x, self.c1.y, self.c1.z, self.c2.x, self.c2.y, self.c2.z
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl BrickBlock {
|
||||
fn bottom_z_plane(&self) -> usize {
|
||||
std::cmp::min(self.c1.z, self.c2.z)
|
||||
}
|
||||
fn top_z_plane(&self) -> usize {
|
||||
std::cmp::max(self.c1.z, self.c2.z)
|
||||
}
|
||||
fn bottom_x_plane(&self) -> usize {
|
||||
std::cmp::min(self.c1.x, self.c2.x)
|
||||
}
|
||||
fn top_x_plane(&self) -> usize {
|
||||
std::cmp::max(self.c1.x, self.c2.x)
|
||||
}
|
||||
fn bottom_y_plane(&self) -> usize {
|
||||
std::cmp::min(self.c1.y, self.c2.y)
|
||||
}
|
||||
fn top_y_plane(&self) -> usize {
|
||||
std::cmp::max(self.c1.y, self.c2.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for BrickBlock {
|
||||
fn from(value: &str) -> Self {
|
||||
let (c1, c2) = value.split_once('~').unwrap();
|
||||
Self {
|
||||
c1: c1.parse().unwrap(),
|
||||
c2: c2.parse().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for BrickBlock {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(other.bottom_z_plane().cmp(&self.bottom_z_plane()))
|
||||
}
|
||||
}
|
||||
|
||||
// Note this is a reversed ordering
|
||||
impl Ord for BrickBlock {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.bottom_z_plane().cmp(&other.bottom_z_plane())
|
||||
}
|
||||
}
|
||||
|
||||
type BlockMap = Array3<MapTile>;
|
||||
type MapTile = Option<BrickBlock>;
|
||||
|
||||
struct BlockPile {
|
||||
blocks: Vec<BrickBlock>,
|
||||
block_map: Array3<MapTile>,
|
||||
bounds: (usize, usize, usize),
|
||||
graph: Graph<BrickBlock, (), Directed, usize>,
|
||||
}
|
||||
|
||||
impl BlockPile {
|
||||
fn remove_block(&mut self, block: &BrickBlock) {
|
||||
// loop over the (inclusive) bounding coordinates and remove them all from the map
|
||||
self.block_map
|
||||
.slice_mut(s![
|
||||
block.bottom_x_plane()..block.top_x_plane() + 1,
|
||||
block.bottom_y_plane()..block.top_y_plane() + 1,
|
||||
block.bottom_z_plane()..block.top_z_plane() + 1,
|
||||
])
|
||||
.fill(None);
|
||||
self.blocks.remove(self.blocks.iter().position(|b| b == block).unwrap());
|
||||
}
|
||||
fn add_block(&mut self, block: &BrickBlock) {
|
||||
// loop over the (inclusive) bounding coordinates and remove them all from the map
|
||||
self.block_map
|
||||
.slice_mut(s![
|
||||
block.bottom_x_plane()..block.top_x_plane() + 1,
|
||||
block.bottom_y_plane()..block.top_y_plane() + 1,
|
||||
block.bottom_z_plane()..block.top_z_plane() + 1,
|
||||
])
|
||||
.fill(Some(block.to_owned()));
|
||||
self.blocks.push(block.clone());
|
||||
}
|
||||
fn blocks_directly_above(&self, block: &BrickBlock) -> Vec<BrickBlock> {
|
||||
// find the top plane of the block
|
||||
// get the array range of all squares at z_plane + 1 within the bounds of x & y
|
||||
// i think there is a built in way in ndarray to do this...
|
||||
let directly_above = self.block_map.slice(s![
|
||||
block.bottom_x_plane()..block.top_x_plane() + 1,
|
||||
block.bottom_y_plane()..block.top_y_plane() + 1,
|
||||
block.top_z_plane() + 1..std::cmp::min(block.top_z_plane() + 2, self.bounds.2)
|
||||
]);
|
||||
|
||||
directly_above.iter().filter_map(|v| v.clone()).unique().collect()
|
||||
}
|
||||
fn supported_by(&self, block: &BrickBlock) -> usize {
|
||||
let z_plane = std::cmp::min(block.c1.z, block.c2.z);
|
||||
// get the slice of tiles below us
|
||||
let directly_below = self.block_map.slice(s![
|
||||
block.bottom_x_plane()..block.top_x_plane() + 1,
|
||||
block.bottom_y_plane()..block.top_y_plane() + 1,
|
||||
z_plane - 1..z_plane // the layer below
|
||||
]);
|
||||
directly_below.iter().filter_map(|v| v.clone()).unique().count()
|
||||
}
|
||||
fn blocks_above_will_move_if_we_are_gone(&mut self, block: &BrickBlock) -> bool {
|
||||
self.blocks_directly_above(&block)
|
||||
.iter()
|
||||
.map(|b| self.supported_by(b))
|
||||
.any(|b| b == 1) // block we support will move if we are their only support
|
||||
}
|
||||
fn blocks_supported_by_at_all(&self, block: &BrickBlock) -> Vec<BrickBlock> {
|
||||
self.blocks_directly_above(&block).iter().map(|b| b.clone()).collect()
|
||||
}
|
||||
/// Find the plane of the first block directly below us
|
||||
fn supporting_plane(&self, block: &BrickBlock) -> Option<usize> {
|
||||
// find the bottom plane of ourselves
|
||||
let z_plane = std::cmp::min(block.c1.z, block.c2.z);
|
||||
// get the slice of tiles below us
|
||||
let directly_below = self.block_map.slice(s![
|
||||
block.bottom_x_plane()..block.top_x_plane() + 1,
|
||||
block.bottom_y_plane()..block.top_y_plane() + 1,
|
||||
1..z_plane // don't include our own plane
|
||||
]);
|
||||
// find the highest top z value of those
|
||||
let block_below = directly_below
|
||||
.indexed_iter()
|
||||
.filter_map(|(idx, v)| if let Some(val) = v { Some((idx, val)) } else { None })
|
||||
.max_by_key(|(_idx, v)| v.top_z_plane());
|
||||
|
||||
if let Some(block) = block_below {
|
||||
Some(block.1.top_z_plane())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn drop_blocks(&mut self) {
|
||||
// VecDeque doesn't sort and Vec isn't convenient for pushback and popfront, so eh... use a heap.
|
||||
let mut blocks_to_move = BinaryHeap::from(self.blocks.clone());
|
||||
while let Some(mut block) = blocks_to_move.pop() {
|
||||
let z_move = match self.supporting_plane(&block) {
|
||||
Some(z) if z + 1 != block.bottom_z_plane() => block.bottom_z_plane() - (z + 1),
|
||||
None if block.bottom_z_plane() != 1 => block.bottom_z_plane() - 1,
|
||||
_ => {
|
||||
continue;
|
||||
} // we are in position already with nothing below us
|
||||
};
|
||||
self.remove_block(&block);
|
||||
block.c1.z -= z_move;
|
||||
block.c2.z -= z_move;
|
||||
self.add_block(&block);
|
||||
blocks_to_move.push(block);
|
||||
}
|
||||
}
|
||||
fn build_graph(&mut self) {
|
||||
self.blocks.sort_by_key(|b| b.bottom_z_plane());
|
||||
for b in 0..self.blocks.len() {
|
||||
self.graph.add_node(self.blocks[b].clone());
|
||||
}
|
||||
for b in 0..self.blocks.len() {
|
||||
let block = &self.blocks[b];
|
||||
let depends_on_us = self.blocks_supported_by_at_all(block);
|
||||
for dependent in depends_on_us {
|
||||
self.graph.add_edge(
|
||||
b.into(),
|
||||
self.blocks.iter().position(|b| b == &dependent).unwrap().into(),
|
||||
(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for BlockPile {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
let blocks = lines.map(|line| BrickBlock::from(line.unwrap().as_str())).collect_vec();
|
||||
let mut bounds = (0, 0, 0);
|
||||
for block in &blocks {
|
||||
bounds.0 = std::cmp::max(block.top_x_plane() + 1, bounds.0);
|
||||
bounds.1 = std::cmp::max(block.top_y_plane() + 1, bounds.1);
|
||||
bounds.2 = std::cmp::max(block.top_z_plane() + 1, bounds.2);
|
||||
}
|
||||
let mut new = BlockPile {
|
||||
blocks: Vec::new(),
|
||||
bounds,
|
||||
block_map: BlockMap::from_elem(bounds, None),
|
||||
graph: Graph::default(),
|
||||
};
|
||||
for block in blocks {
|
||||
new.add_block(&block);
|
||||
}
|
||||
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BlockPile {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for z in (0..self.bounds.2).rev() {
|
||||
let z_plane = self.block_map.slice(s![.., .., z..z+1]);
|
||||
if z_plane.iter().all(|b| b.is_none()) { continue };
|
||||
for i in 0..self.bounds.0 {
|
||||
// XZ view
|
||||
let y = z_plane.slice(s![i..i + 1, .., ..]);
|
||||
f.write_char(
|
||||
match y.iter().enumerate().find_map(|(idx, val)| val.is_some().then(|| idx)) {
|
||||
None => ' ',
|
||||
Some(0) | Some(1) => '█',
|
||||
Some(2) | Some(3) => '▓',
|
||||
Some(4) | Some(5) => '▒',
|
||||
Some(6) | Some(7) => '░',
|
||||
_ => '░',
|
||||
},
|
||||
)?;
|
||||
}
|
||||
write!(f, " {} ", z)?;
|
||||
for y in 0..self.bounds.1 {
|
||||
let x = z_plane.slice(s![.., y..y + 1, ..]);
|
||||
f.write_char(
|
||||
match x.iter().enumerate().find_map(|(idx, val)| val.is_some().then(|| idx)) {
|
||||
None => ' ',
|
||||
Some(0) | Some(1) => '█',
|
||||
Some(2) | Some(3) => '▓',
|
||||
Some(4) | Some(5) => '▒',
|
||||
Some(6) | Some(7) => '░',
|
||||
_ => '░',
|
||||
},
|
||||
)?;
|
||||
}
|
||||
writeln!(f, " {}", z)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut pile = BlockPile::from(input);
|
||||
println!("{}", pile);
|
||||
println!("dropping blocks!");
|
||||
pile.drop_blocks();
|
||||
println!("{}", pile);
|
||||
|
||||
let blocks = pile.blocks.clone();
|
||||
let removable: Vec<_> = blocks
|
||||
.iter()
|
||||
.filter(|b| !pile.blocks_above_will_move_if_we_are_gone(*b))
|
||||
.collect();
|
||||
|
||||
removable.len() as u64
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut pile = BlockPile::from(input);
|
||||
pile.drop_blocks();
|
||||
pile.build_graph();
|
||||
|
||||
println!("{}", pile);
|
||||
|
||||
let mut accum = 0;
|
||||
let fixed_nodes = pile
|
||||
.graph
|
||||
.node_references()
|
||||
.filter(|(_idx, b)| b.bottom_z_plane() == 1)
|
||||
.map(|(idx, _b)| idx)
|
||||
.collect_vec();
|
||||
for node in pile.graph.node_indices() {
|
||||
// remove links to node's neighbors
|
||||
let dependents = pile.graph.neighbors(node).collect_vec();
|
||||
let edges = pile.graph.edges(node).map(|v| v.id()).collect_vec();
|
||||
for edge in edges {
|
||||
pile.graph.remove_edge(edge);
|
||||
}
|
||||
|
||||
// find how many nodes are reachable from z = 1 - these won't move
|
||||
let safe_blocks = fixed_nodes
|
||||
.iter()
|
||||
.flat_map(|origin| {
|
||||
Bfs::new(&pile.graph, *origin)
|
||||
.iter(&pile.graph)
|
||||
.map(|n| pile.graph[n].clone())
|
||||
})
|
||||
.unique()
|
||||
.count();
|
||||
// we are looking for the nodes that *will* disintegrate
|
||||
accum += pile.graph.node_count() - safe_blocks;
|
||||
// put the graph back how it was
|
||||
for neigh in dependents {
|
||||
pile.graph.add_edge(node, neigh, ());
|
||||
}
|
||||
}
|
||||
accum as u64
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"1,0,1~1,2,1
|
||||
0,0,2~2,0,2
|
||||
0,2,3~2,2,3
|
||||
0,0,4~0,2,4
|
||||
2,0,5~2,2,5
|
||||
0,1,6~2,1,6
|
||||
1,1,8~1,1,9";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 7);
|
||||
}
|
||||
}
|
128
23/Cargo.lock
generated
Normal file
128
23/Cargo.lock
generated
Normal file
@ -0,0 +1,128 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "day23"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"ndarray",
|
||||
"petgraph",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||
dependencies = [
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
11
23/Cargo.toml
Normal file
11
23/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "day23"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.12.0"
|
||||
ndarray = "0.15.6"
|
||||
petgraph = "0.6.4"
|
326
23/src/main.rs
Normal file
326
23/src/main.rs
Normal file
@ -0,0 +1,326 @@
|
||||
use itertools::Itertools;
|
||||
use ndarray::prelude::*;
|
||||
use petgraph::algo::all_simple_paths;
|
||||
use petgraph::prelude::*;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::{Debug, Display, Write};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Node {
|
||||
c: char,
|
||||
pos: Position,
|
||||
}
|
||||
|
||||
impl Display for Node {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "({},{})", self.pos.0, self.pos.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Node {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "({},{})", self.pos.0, self.pos.1)
|
||||
}
|
||||
}
|
||||
|
||||
type Position = (usize, usize);
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ForestMap {
|
||||
map: Array2<char>,
|
||||
indexes: HashMap<Position, NodeIndex>,
|
||||
graph: StableDiGraph<Node, u64>,
|
||||
start: Position,
|
||||
end: Position,
|
||||
}
|
||||
|
||||
const ADJACENCIES: [(isize, isize); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
|
||||
|
||||
fn offset_pos(map: &Array2<char>, pos: Position, ofs: (isize, isize)) -> Option<Position> {
|
||||
let new_pos = (pos.0 as isize + ofs.0, pos.1 as isize + ofs.1);
|
||||
if new_pos.0 >= 0
|
||||
&& new_pos.0 < map.len_of(Axis(0)) as isize
|
||||
&& new_pos.1 >= 0
|
||||
&& new_pos.1 < map.len_of(Axis(1)) as isize
|
||||
{
|
||||
Some((new_pos.0 as usize, new_pos.1 as usize))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn adjacent_to(map: &Array2<char>, pos: Position) -> Vec<Position> {
|
||||
ADJACENCIES
|
||||
.iter()
|
||||
.filter_map(|ofs| offset_pos(map, pos, *ofs))
|
||||
.collect()
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for ForestMap {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
let rows = lines.map(|line| line.unwrap().chars().collect_vec()).collect_vec();
|
||||
let map = Array::from_shape_vec([rows[0].len(), rows.len()], rows.into_iter().flatten().collect_vec())
|
||||
.unwrap()
|
||||
.reversed_axes();
|
||||
let start = (map.slice(s![.., 0]).iter().position(|c| *c == '.').unwrap(), 0);
|
||||
let end = (
|
||||
map.slice(s![.., map.len_of(Axis(1)) - 1])
|
||||
.iter()
|
||||
.position(|c| *c == '.')
|
||||
.unwrap(),
|
||||
map.len_of(Axis(1)) - 1,
|
||||
);
|
||||
|
||||
let mut graph = StableGraph::default();
|
||||
let mut indexes = HashMap::new();
|
||||
for (pos, c) in map.indexed_iter() {
|
||||
if *c != '#' {
|
||||
indexes.insert(pos, graph.add_node(Node { c: *c, pos }));
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
map,
|
||||
start,
|
||||
end,
|
||||
graph,
|
||||
indexes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ForestMap {
|
||||
fn build_graph(&mut self) {
|
||||
for (pos, c) in self.map.indexed_iter() {
|
||||
match c {
|
||||
'#' => continue,
|
||||
'.' => {
|
||||
adjacent_to(&self.map, pos).iter().for_each(|adj| {
|
||||
if self.indexes.contains_key(&adj) {
|
||||
self.graph.add_edge(self.indexes[&pos], self.indexes[adj], 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
'^' => {
|
||||
if let Some(adj) = offset_pos(&self.map, pos, (0, -1)) {
|
||||
if self.indexes.contains_key(&adj) {
|
||||
self.graph.add_edge(self.indexes[&pos], self.indexes[&adj], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
'>' => {
|
||||
if let Some(adj) = offset_pos(&self.map, pos, (1, 0)) {
|
||||
if self.indexes.contains_key(&adj) {
|
||||
self.graph.add_edge(self.indexes[&pos], self.indexes[&adj], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
'v' => {
|
||||
if let Some(adj) = offset_pos(&self.map, pos, (0, 1)) {
|
||||
if self.indexes.contains_key(&adj) {
|
||||
self.graph.add_edge(self.indexes[&pos], self.indexes[&adj], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
'<' => {
|
||||
if let Some(adj) = offset_pos(&self.map, pos, (-1, 0)) {
|
||||
if self.indexes.contains_key(&adj) {
|
||||
self.graph.add_edge(self.indexes[&pos], self.indexes[&adj], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
c => panic!("invalid map character {}", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_graph2(&mut self) {
|
||||
for (pos, c) in self.map.indexed_iter() {
|
||||
match c {
|
||||
'#' => continue,
|
||||
'.' | '^' | '>' | 'v' | '<' => {
|
||||
adjacent_to(&self.map, pos).iter().for_each(|adj| {
|
||||
if self.indexes.contains_key(&adj) {
|
||||
self.graph.add_edge(self.indexes[&pos], self.indexes[adj], 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
c => panic!("invalid map character {}", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cull nodes that don't change the topology of the graph and combine their cost
|
||||
fn simplify_graph(&mut self) {
|
||||
let mut idxs: Vec<_> = self
|
||||
.graph
|
||||
.neighbors(self.indexes[&self.start])
|
||||
.map(|idx| (self.indexes[&self.start], idx))
|
||||
.collect();
|
||||
let mut visited = HashSet::from([self.indexes[&self.start]]);
|
||||
while let Some((last_idx, cur_idx)) = idxs.pop() {
|
||||
if !visited.insert(cur_idx) {
|
||||
continue;
|
||||
}
|
||||
let our_neighbors = self.graph.neighbors(cur_idx).collect_vec();
|
||||
|
||||
// if we have exactly 2 neighbours, then one is where we came from, and we can shortcut this node with a
|
||||
// pair of new edges A <-> C and break the existing 4 edges between them
|
||||
if our_neighbors.len() == 2 {
|
||||
let next_idx = our_neighbors.iter().find(|n| **n != last_idx).unwrap();
|
||||
|
||||
// remove the 4 existing edges
|
||||
// careful of order of operations, as removing edges invalidates edge indexes
|
||||
let forward_cost = self
|
||||
.graph
|
||||
.remove_edge(self.graph.find_edge(cur_idx, *next_idx).unwrap())
|
||||
.unwrap();
|
||||
let last_forward_cost = self
|
||||
.graph
|
||||
.remove_edge(self.graph.find_edge(last_idx, cur_idx).unwrap())
|
||||
.unwrap();
|
||||
let backward_cost = self
|
||||
.graph
|
||||
.remove_edge(self.graph.find_edge(cur_idx, last_idx).unwrap())
|
||||
.unwrap();
|
||||
let next_backward_cost = self
|
||||
.graph
|
||||
.remove_edge(self.graph.find_edge(*next_idx, cur_idx).unwrap())
|
||||
.unwrap();
|
||||
let new_forward_cost = forward_cost + last_forward_cost;
|
||||
let new_backward_cost = backward_cost + next_backward_cost;
|
||||
|
||||
// add edge from last to next
|
||||
self.graph.add_edge(last_idx, *next_idx, new_forward_cost);
|
||||
self.graph.add_edge(*next_idx, last_idx, new_backward_cost);
|
||||
|
||||
self.graph.remove_node(cur_idx);
|
||||
// push the next node
|
||||
idxs.push((last_idx, *next_idx));
|
||||
} else {
|
||||
// don't do anything about nodes with > 2 edges, just push them onto the stack, if there are some
|
||||
idxs.append(
|
||||
&mut self
|
||||
.graph
|
||||
.neighbors(cur_idx)
|
||||
.into_iter()
|
||||
.map(|next_idx| (cur_idx, next_idx))
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for ForestMap {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for y in 0..self.map.len_of(Axis(1)) {
|
||||
for c in self.map.index_axis(Axis(1), y) {
|
||||
f.write_char(*c)?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut map = ForestMap::from(input);
|
||||
map.build_graph();
|
||||
// println!("{:?}", map);
|
||||
let paths = all_simple_paths::<Vec<_>, _>(&map.graph, map.indexes[&map.start], map.indexes[&map.end], 0, None)
|
||||
.collect_vec();
|
||||
let longest = paths.iter().max_by_key(|path| path.len()).unwrap();
|
||||
|
||||
longest.len() as u64 - 1
|
||||
}
|
||||
|
||||
fn calc_path_length(map: &ForestMap, path: &Vec<NodeIndex>) -> u64 {
|
||||
path.iter().tuple_windows().fold(0, |accum, (prev, next)| {
|
||||
accum + map.graph[map.graph.find_edge(*prev, *next).unwrap()]
|
||||
})
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut map = ForestMap::from(input);
|
||||
map.build_graph2();
|
||||
map.simplify_graph();
|
||||
|
||||
let paths = all_simple_paths::<Vec<_>, _>(&map.graph, map.indexes[&map.start], map.indexes[&map.end], 0, None)
|
||||
.collect_vec();
|
||||
let longest = paths.iter().max_by_key(|path| calc_path_length(&map, &path)).unwrap();
|
||||
longest.iter().tuple_windows().fold(0, |accum, (prev, next)| {
|
||||
accum + map.graph[map.graph.find_edge(*prev, *next).unwrap()]
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"#.#####################
|
||||
#.......#########...###
|
||||
#######.#########.#.###
|
||||
###.....#.>.>.###.#.###
|
||||
###v#####.#v#.###.#.###
|
||||
###.>...#.#.#.....#...#
|
||||
###v###.#.#.#########.#
|
||||
###...#.#.#.......#...#
|
||||
#####.#.#.#######.#.###
|
||||
#.....#.#.#.......#...#
|
||||
#.#####.#.#.#########v#
|
||||
#.#...#...#...###...>.#
|
||||
#.#.#v#######v###.###v#
|
||||
#...#.>.#...>.>.#.###.#
|
||||
#####v#.#.###v#.#.###.#
|
||||
#.....#...#...#.#.#...#
|
||||
#.#########.###.#.#.###
|
||||
#...###...#...#...#.###
|
||||
###.###.#.###v#####v###
|
||||
#...#...#.#.>.>.#.>.###
|
||||
#.###.###.#.###.#.#v###
|
||||
#.....###...###...#...#
|
||||
#####################.#";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 94);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 154);
|
||||
}
|
||||
}
|
134
24/Cargo.lock
generated
Normal file
134
24/Cargo.lock
generated
Normal file
@ -0,0 +1,134 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day24"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"lazy-regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d12be4595afdf58bd19e4a9f4e24187da2a66700786ff660a418e9059937a4c"
|
||||
dependencies = [
|
||||
"lazy-regex-proc_macros",
|
||||
"once_cell",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex-proc_macros"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44bcd58e6c97a7fcbaffcdc95728b393b8d98933bfadad49ed4097845b57ef0b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
10
24/Cargo.toml
Normal file
10
24/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "day24"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.12.0"
|
||||
lazy-regex = "3.1.0"
|
24
24/cheat.py
Normal file
24
24/cheat.py
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from z3 import *
|
||||
|
||||
rx, ry, rz = Ints('rx ry rz')
|
||||
rvx, rvy, rvz = Ints('rvx rvy rvz')
|
||||
t0, t1, t2 = Ints('t0 t1 t2')
|
||||
answer = Int('answer')
|
||||
|
||||
solve(
|
||||
rx + t0 * rvx == 225415405941969 + t0 * 23,
|
||||
ry + t0 * rvy == 400648127977931 + t0 * -204,
|
||||
rz + t0 * rvz == 79201130433258 + t0 * 617,
|
||||
|
||||
rx + t1 * rvx == 353783687623292 + t1 * -80,
|
||||
ry + t1 * rvy == 138575899489956 + t1 * 156,
|
||||
rz + t1 * rvz == 318416438572569 + t1 * 21,
|
||||
|
||||
rx + t2 * rvx == 215751176267772 + t2 * -120,
|
||||
ry + t2 * rvy == 376619563956940 + t2 * 126,
|
||||
rz + t2 * rvz == 230133299986253 + t2 * -352,
|
||||
|
||||
answer == rx + ry + rz,
|
||||
)
|
205
24/src/main.rs
Normal file
205
24/src/main.rs
Normal file
@ -0,0 +1,205 @@
|
||||
use itertools::Itertools;
|
||||
use std::fmt::Debug;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::ops::Index;
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// Parse
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Vec3 {
|
||||
x: f64,
|
||||
y: f64,
|
||||
z: f64,
|
||||
}
|
||||
impl Debug for Vec3 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}, {}, {}", self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Vec2 {
|
||||
x: f64,
|
||||
y: f64,
|
||||
}
|
||||
impl Debug for Vec2 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}, {}", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
|
||||
struct Hailstone {
|
||||
pos: Vec3,
|
||||
vel: Vec3,
|
||||
}
|
||||
|
||||
impl Hailstone {
|
||||
fn xy_vel_angle(&self) -> f64 {
|
||||
(self.vel.y / self.vel.x).atan()
|
||||
}
|
||||
fn xy_vel_abs(&self) -> f64 {
|
||||
(self.vel.x.powi(2) + self.vel.y.powi(2)).sqrt()
|
||||
}
|
||||
fn xy_slope(&self) -> f64 {
|
||||
self.vel.y / self.vel.x
|
||||
}
|
||||
fn y_crossing(&self) -> f64 {
|
||||
self.pos.y - self.xy_slope() * self.pos.x
|
||||
}
|
||||
fn xy_poi(&self, other: &Hailstone) -> Option<Vec2> {
|
||||
let our_slope = self.xy_slope();
|
||||
let other_slope = other.xy_slope();
|
||||
if our_slope == other_slope || our_slope * other_slope == -1. {
|
||||
None
|
||||
} else {
|
||||
let our_yint = self.y_crossing();
|
||||
let other_yint = other.y_crossing();
|
||||
let ratio = (other_yint - our_yint) / (our_slope - other_slope);
|
||||
Some(Vec2 {
|
||||
x: ratio,
|
||||
y: our_slope * ratio + our_yint,
|
||||
})
|
||||
}
|
||||
}
|
||||
fn xy_point_future(&self, point: &Vec2) -> bool {
|
||||
// a point will be in the past if the difference between its 'new' position and its 'start' position has a
|
||||
// different sign than the velocity for any component
|
||||
let diffs = [point.x - self.pos.x, point.y - self.pos.y];
|
||||
// for (diff, vel) in diffs.iter().zip([self.vel.x, self.vel.y].iter()) {
|
||||
// println!(" diff: {:?} vel: {:?} mul: {:?}", diff, vel, diff * vel > 0.);
|
||||
// }
|
||||
diffs.iter().zip([self.vel.x, self.vel.y].iter()).any(|(diff, vel)| diff * vel > 0.)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Hailstone {
|
||||
fn from(value: &str) -> Self {
|
||||
let (pos, vel) = value.split_once("@").unwrap();
|
||||
let [px, py, pz] = pos.split(",").map(|s| s.trim().parse::<f64>().unwrap()).collect_vec()[..] else {
|
||||
panic!()
|
||||
};
|
||||
let [vx, vy, vz] = vel.split(",").map(|s| s.trim().parse::<f64>().unwrap()).collect_vec()[..] else {
|
||||
panic!()
|
||||
};
|
||||
|
||||
Self {
|
||||
pos: Vec3 { x: px, y: py, z: pz },
|
||||
vel: Vec3 { x: vx, y: vy, z: vz },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Hailstone {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?} @ {:?}", self.pos, self.vel)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Hailstones {
|
||||
stones: Vec<Hailstone>,
|
||||
}
|
||||
|
||||
impl Hailstones {
|
||||
fn count_xy_pois(&self, bounds: (f64, f64)) -> u64 {
|
||||
assert!(bounds.0 < bounds.1);
|
||||
let mut stones = self.stones.clone();
|
||||
|
||||
let mut count = 0;
|
||||
while let Some(stone) = &stones.pop() {
|
||||
for other in &stones {
|
||||
let Some(poi) = stone.xy_poi(other) else { continue };
|
||||
// println!("intersection: {:?} / {:?} @ {:?}", stone, other, poi);
|
||||
if poi.x >= bounds.0 && poi.x <= bounds.1 && poi.y >= bounds.0 && poi.y <= bounds.1 && stone.xy_point_future(&poi) && other.xy_point_future(&poi) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Hailstones {
|
||||
type Output = Hailstone;
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self.stones[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Hailstones {
|
||||
fn from(value: Lines<T>) -> Self {
|
||||
let mut stones = Vec::new();
|
||||
for line in value {
|
||||
stones.push(Hailstone::from(line.unwrap().as_str()));
|
||||
}
|
||||
Hailstones { stones }
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
problem1_impl(input, (200000000000000., 400000000000000.))
|
||||
}
|
||||
|
||||
fn problem1_impl<T: BufRead>(input: Lines<T>, bounds: (f64, f64)) -> u64 {
|
||||
let stones = Hailstones::from(input);
|
||||
|
||||
stones.count_xy_pois(bounds)
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"19, 13, 30 @ -2, 1, -2
|
||||
18, 19, 22 @ -1, -1, -2
|
||||
20, 25, 34 @ -2, -2, -4
|
||||
12, 31, 28 @ -1, -2, -1
|
||||
20, 19, 15 @ 1, -5, -3";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1_impl(c.lines(), (7., 27.)), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 0);
|
||||
}
|
||||
}
|
266
25/Cargo.lock
generated
Normal file
266
25/Cargo.lock
generated
Normal file
@ -0,0 +1,266 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"unicode-width",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day25"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"indicatif",
|
||||
"itertools",
|
||||
"petgraph",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"
|
||||
dependencies = [
|
||||
"console",
|
||||
"instant",
|
||||
"number_prefix",
|
||||
"portable-atomic",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
|
||||
[[package]]
|
||||
name = "number_prefix"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
12
25/Cargo.toml
Normal file
12
25/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "day25"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
indicatif = "0.17.7"
|
||||
itertools = "0.12.0"
|
||||
petgraph = "0.6.4"
|
||||
rayon = "1.8.0"
|
171
25/src/main.rs
Normal file
171
25/src/main.rs
Normal file
@ -0,0 +1,171 @@
|
||||
use indicatif::{ProgressBar, ProgressIterator, ProgressStyle};
|
||||
use itertools::Itertools;
|
||||
use petgraph::algo::connected_components;
|
||||
use petgraph::dot::Dot;
|
||||
use petgraph::prelude::*;
|
||||
use petgraph::visit::{depth_first_search, DfsEvent, IntoEdgeReferences, IntoNodeIdentifiers, IntoNodeReferences};
|
||||
use rayon::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
struct Circuit {
|
||||
graph: UnGraph<String, String>,
|
||||
nodes: HashMap<String, Node>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Node {
|
||||
targets: Vec<String>,
|
||||
index: Option<NodeIndex>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
fn with_index(mut self, index: NodeIndex) -> Self {
|
||||
self.index = Some(index);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Circuit {
|
||||
fn from(lines: Lines<T>) -> Self {
|
||||
let mut graph = UnGraph::default();
|
||||
let mut nodes = HashMap::new();
|
||||
for line in lines.map(|v| v.unwrap()) {
|
||||
let (source, targets_s) = line.split_once(": ").unwrap();
|
||||
let targets = targets_s.split_whitespace().map(|s| s.to_string()).collect_vec();
|
||||
nodes.insert(
|
||||
source.to_string(),
|
||||
Node {
|
||||
targets,
|
||||
index: Some(graph.add_node(source.to_string())),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for (name, node) in nodes.iter_mut() {
|
||||
for target in &node.targets {
|
||||
let target_idx = match graph.node_references().find(|n| n.1 == target).map(|n| n.0) {
|
||||
Some(target) => target,
|
||||
None => graph.add_node(target.to_string()),
|
||||
};
|
||||
graph.add_edge(node.index.unwrap(), target_idx, format!("{}-{}", name, target));
|
||||
}
|
||||
}
|
||||
|
||||
Self { graph, nodes }
|
||||
}
|
||||
}
|
||||
|
||||
impl Circuit {
|
||||
// returns the set of nodes on each side
|
||||
fn find_critical_edges(&self, removals: usize) -> (Vec<String>, Vec<String>) {
|
||||
let bar = ProgressBar::new(self.graph.edge_references().combinations(removals).try_len().unwrap() as u64)
|
||||
.with_style(
|
||||
ProgressStyle::with_template(
|
||||
"[{elapsed_precise}/{eta_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {per_sec}",
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
// for set in self.graph.edge_references().combinations(removals).progress_with(bar) {
|
||||
|
||||
let set = [("zcp", "zjm"), ("rsg", "nsk"), ("jks", "rfg")]
|
||||
.iter()
|
||||
.flat_map(|(src, dst)| {
|
||||
self.graph.edge_references().filter(|e| self.graph[e.source()] == *src && self.graph[e.target()] == *dst || self.graph[e.target()] == *src && self.graph[e.source()] == *dst)
|
||||
}).collect_vec();
|
||||
let mut local_graph: StableUnGraph<_, _> = self.graph.clone().into();
|
||||
for wire in &set {
|
||||
local_graph.remove_edge(wire.id());
|
||||
}
|
||||
let local_graph = UnGraph::from(local_graph);
|
||||
if connected_components(&local_graph) == 2 {
|
||||
// each edge will have one leg in each component, so return the set of connected nodes
|
||||
let mut left = Vec::new();
|
||||
depth_first_search(&local_graph, Some(set[0].source()), |event| {
|
||||
if let DfsEvent::Discover(n, t) = event {
|
||||
left.push(local_graph[n].to_string());
|
||||
}
|
||||
});
|
||||
let mut right = Vec::new();
|
||||
depth_first_search(&local_graph, Some(set[0].target()), |event| {
|
||||
if let DfsEvent::Discover(n, t) = event {
|
||||
right.push(local_graph[n].to_string());
|
||||
}
|
||||
});
|
||||
return (left, right);
|
||||
}
|
||||
// }
|
||||
panic!("no cutline found");
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let circuit = Circuit::from(input);
|
||||
println!("{:?}", Dot::new(&circuit.graph));
|
||||
let (left, right) = circuit.find_critical_edges(3);
|
||||
(left.len() * right.len()) as u64
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"jqt: rhn xhk nvd
|
||||
rsh: frs pzl lsr
|
||||
xhk: hfx
|
||||
cmg: qnr nvd lhk bvb
|
||||
rhn: xhk bvb hfx
|
||||
bvb: xhk hfx
|
||||
pzl: lsr hfx nvd
|
||||
qnr: nvd
|
||||
ntq: jqt hfx bvb xhk
|
||||
nvd: lhk
|
||||
lsr: lhk
|
||||
rzs: qnr cmg lsr rsh
|
||||
frs: qnr lhk lsr";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 54);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 0);
|
||||
}
|
||||
}
|
@ -129,7 +129,7 @@ impl From<&str> for Card {
|
||||
// Take a seat in the large pile of colorful cards. How many points are they worth in
|
||||
// total?
|
||||
|
||||
fn problem1(input: InputIter) -> u64 {
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let cards: Vec<Card> = input
|
||||
.map(|line| Card::from(line.unwrap().as_str()))
|
||||
.collect();
|
||||
@ -199,7 +199,7 @@ fn problem2_award_copies<'a>(orig_cards: &'a Vec<Card>, card: &Card) -> Vec<&'a
|
||||
new_cards
|
||||
}
|
||||
|
||||
fn problem2(input: InputIter) -> u64 {
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let orig_cards: Vec<Card> = input
|
||||
.map(|line| Card::from(line.unwrap().as_str()))
|
||||
.collect();
|
||||
@ -218,3 +218,29 @@ fn problem2(input: InputIter) -> u64 {
|
||||
|
||||
(won_cards.len() + orig_cards.len()) as u64
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{problem1, problem2};
|
||||
use std::io::{BufRead, Cursor};
|
||||
|
||||
const example_input: &str = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
|
||||
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
|
||||
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
|
||||
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
|
||||
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
|
||||
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11";
|
||||
|
||||
#[test]
|
||||
fn problem1_example_test() {
|
||||
let input = Cursor::new(example_input).lines();
|
||||
|
||||
assert_eq!(problem1(input), 13);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example_test() {
|
||||
let input = Cursor::new(example_input).lines();
|
||||
assert_eq!(problem2(input), 30);
|
||||
}
|
||||
}
|
||||
|
183
5/Cargo.lock
generated
Normal file
183
5/Cargo.lock
generated
Normal file
@ -0,0 +1,183 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "day5"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"num",
|
||||
"test-case",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8"
|
||||
dependencies = [
|
||||
"test-case-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-core"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-macros"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"test-case-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
11
5/Cargo.toml
Normal file
11
5/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "day5"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.12.0"
|
||||
num = "0.4.1"
|
||||
test-case = "3.3.1"
|
188
5/input
Normal file
188
5/input
Normal file
@ -0,0 +1,188 @@
|
||||
seeds: 2494933545 159314859 4045092792 172620202 928898138 554061882 2740120981 81327018 2031777983 63513119 2871914181 270575980 2200250633 216481794 3289604059 25147787 3472625834 10030240 260990830 232636388
|
||||
|
||||
seed-to-soil map:
|
||||
3272284283 2724782980 1022683013
|
||||
138187491 4195038636 99928660
|
||||
2359623759 797621236 127984779
|
||||
662451929 2224466386 266466256
|
||||
928918185 714355413 83265823
|
||||
1012184008 3891516474 303522162
|
||||
3063776460 1098322140 208507823
|
||||
2194238166 1306829963 50525692
|
||||
357106588 2091837170 132629216
|
||||
2244763858 2490932642 114859901
|
||||
2050187685 3747465993 144050481
|
||||
489735804 925606015 172716125
|
||||
2487608538 138187491 576167922
|
||||
238116151 2605792543 118990437
|
||||
1315706170 1357355655 734481515
|
||||
|
||||
soil-to-fertilizer map:
|
||||
4265669768 2142212766 29297528
|
||||
2030756625 2171510294 69737894
|
||||
3038084234 3411621093 262803613
|
||||
2410534622 3266307064 145314029
|
||||
2667304792 2241248188 370779442
|
||||
2100494519 3921619167 310040103
|
||||
3611390334 2612027630 654279434
|
||||
2555848651 2030756625 111456141
|
||||
733063720 869238953 195075492
|
||||
3300887847 4231659270 63308026
|
||||
3364195873 3674424706 247194461
|
||||
928139212 733063720 136175233
|
||||
|
||||
fertilizer-to-water map:
|
||||
0 772139976 154052576
|
||||
909628165 428370542 51644443
|
||||
3172969725 4109584032 185383264
|
||||
1116931128 1046566515 14194115
|
||||
223777814 10055892 255169216
|
||||
2512535520 1229983026 60386000
|
||||
3109777744 3899207072 16374329
|
||||
4030761870 3829858282 12540292
|
||||
828135093 718323602 53816374
|
||||
2358450176 2554590817 154085344
|
||||
3126152073 3152512175 46817652
|
||||
4043302162 3842398574 56808498
|
||||
3694349069 3493296400 336412801
|
||||
770911368 661099877 57223725
|
||||
3574254366 3032417472 120094703
|
||||
2689829955 2124052738 139986329
|
||||
3358352989 1925653441 3542661
|
||||
154052576 1060760630 69725238
|
||||
3460616091 3829709201 149081
|
||||
881951467 480014985 9494517
|
||||
1777535488 3915581401 135358522
|
||||
2829816284 1290369026 84715328
|
||||
478947030 489509502 171590375
|
||||
2686813330 1226966401 3016625
|
||||
3361895650 3199329827 98720441
|
||||
1226966401 1375084354 550569087
|
||||
3515610257 4050939923 58644109
|
||||
650537405 926192552 120373963
|
||||
4100110660 1929196102 194856636
|
||||
1912894010 2708676161 323741311
|
||||
3460765172 2264039067 54845085
|
||||
898932898 0 10055892
|
||||
891445984 265225108 7486914
|
||||
2914531612 3298050268 195246132
|
||||
2572921520 2318884152 113891810
|
||||
961272608 272712022 155658520
|
||||
908988790 1130485868 639375
|
||||
2236635321 2432775962 121814855
|
||||
|
||||
water-to-light map:
|
||||
2821176146 2286693663 106119314
|
||||
3822234587 2463633329 180779736
|
||||
1725724347 2842879211 104224606
|
||||
3308097155 4172728180 122239116
|
||||
3299768179 2834550235 8328976
|
||||
525232540 357109336 38255672
|
||||
751267412 803626289 867213460
|
||||
2181067610 2392812977 70820352
|
||||
2251887962 2644413065 134698828
|
||||
3430336271 3994876090 163182805
|
||||
357109336 395365008 62712446
|
||||
3646455511 2158365540 128328123
|
||||
3084834769 2947103817 214933410
|
||||
1618480872 3954660777 40215313
|
||||
1673365470 751267412 52358877
|
||||
2927295460 3797121468 157539309
|
||||
2386586790 1723776184 434589356
|
||||
3774783634 2779111893 47450953
|
||||
4003014323 3162037227 291952973
|
||||
419821782 458077454 105410758
|
||||
3593519076 1670839749 52936435
|
||||
1658696185 4158058895 14669285
|
||||
2173080221 2826562846 7987389
|
||||
1829948953 3453990200 343131268
|
||||
|
||||
light-to-temperature map:
|
||||
457330729 4090205185 204762111
|
||||
2982196520 3401667644 30193953
|
||||
2238727594 3778270640 263367024
|
||||
2540710222 1921368253 380651678
|
||||
2224576409 4041637664 14151185
|
||||
1803946096 1170025919 125923944
|
||||
947791690 3069412788 65888847
|
||||
3354708582 3597834895 180435745
|
||||
1173448701 516297801 630497395
|
||||
4079424710 2899828022 88028778
|
||||
1929870040 1295949863 294706369
|
||||
928458849 495946333 19332841
|
||||
3145865299 515279174 1018627
|
||||
3071616223 2825578946 74249076
|
||||
3012390473 3431861597 52676537
|
||||
0 156654134 174053721
|
||||
1013680537 1590656232 159768164
|
||||
2502094618 457330729 38615604
|
||||
4167453488 3484538134 113296761
|
||||
4058703342 3048691420 20721368
|
||||
3146883926 1750424396 164394644
|
||||
662092840 3135301635 266366009
|
||||
174053721 0 156654134
|
||||
4280750249 4055788849 14217047
|
||||
3311278570 1146795196 23230723
|
||||
3334509293 4070005896 20199289
|
||||
3535144327 2302019931 523559015
|
||||
3065067010 1914819040 6549213
|
||||
2921361900 2987856800 60834620
|
||||
|
||||
temperature-to-humidity map:
|
||||
19014508 1616728169 261978440
|
||||
479364011 879054632 183139707
|
||||
3422279791 4197415651 97551645
|
||||
2947838505 2859883311 474441286
|
||||
3922771609 3441941550 130194267
|
||||
1538347549 1285663854 77335299
|
||||
4074125861 3334324597 17231539
|
||||
2692139672 3923798143 165313419
|
||||
3867887507 3572135817 45827004
|
||||
4091357400 2695950683 148956394
|
||||
280992948 874337342 4717290
|
||||
3585981058 4137845928 59569723
|
||||
1194193608 267159640 344153941
|
||||
3645550781 2226309992 39998882
|
||||
2606341883 3617962821 85797789
|
||||
2452453972 3769910232 153887911
|
||||
4279991062 2844907077 14976234
|
||||
4240313794 4089111562 39677268
|
||||
285710238 0 193653773
|
||||
662503718 1585706204 31021965
|
||||
4052965876 2266308874 21159985
|
||||
2226309992 2287468859 226143980
|
||||
0 248145132 19014508
|
||||
3685549663 2513612839 182337844
|
||||
2857453091 3351556136 90385414
|
||||
1139702249 193653773 54491359
|
||||
3913714511 4128788830 9057098
|
||||
916232734 1062194339 223469515
|
||||
1615682848 611313581 263023761
|
||||
693525683 1362999153 222707051
|
||||
3519831436 3703760610 66149622
|
||||
|
||||
humidity-to-location map:
|
||||
3722067319 3568864729 46052123
|
||||
761939125 1263883488 182519766
|
||||
3952597071 3400791743 168072986
|
||||
1928058 204065059 218803536
|
||||
1797120632 863951513 248903371
|
||||
3409129274 3614916852 109595510
|
||||
0 1261955430 1928058
|
||||
3854871689 2940386871 97725382
|
||||
3518724784 3898809601 159455982
|
||||
220731594 1446403254 100124613
|
||||
944458891 1813379640 207908225
|
||||
3194065032 4058265583 117770911
|
||||
3059317673 3222157831 134747359
|
||||
3678180766 3356905190 43886553
|
||||
3375153977 3124864500 33975297
|
||||
2940386871 4176036494 118930802
|
||||
1152367116 2021287865 24736138
|
||||
3311835943 3158839797 63318034
|
||||
320856207 422868595 441082918
|
||||
1593055573 0 204065059
|
||||
4120670057 3724512362 174297239
|
||||
1177103254 1112854884 149100546
|
||||
1326203800 1546527867 266851773
|
||||
3768119442 3038112253 86752247
|
523
5/src/main.rs
Normal file
523
5/src/main.rs
Normal file
@ -0,0 +1,523 @@
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::ops::Range;
|
||||
use std::time::Instant;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
// --- Day 5: If You Give A Seed A Fertilizer ---
|
||||
|
||||
// You take the boat and find the gardener right where you were told he would be:
|
||||
// managing a giant "garden" that looks more to you like a farm.
|
||||
|
||||
// "A water source? Island Island is the water source!" You point out that Snow Island
|
||||
// isn't receiving any water.
|
||||
|
||||
// "Oh, we had to stop the water because we ran out of sand to filter it with! Can't
|
||||
// make snow with dirty water. Don't worry, I'm sure we'll get more sand soon; we only
|
||||
// turned off the water a few days... weeks... oh no." His face sinks into a look of
|
||||
// horrified realization.
|
||||
|
||||
// "I've been so busy making sure everyone here has food that I completely forgot to
|
||||
// check why we stopped getting more sand! There's a ferry leaving soon that is headed
|
||||
// over in that direction - it's much faster than your boat. Could you please go check
|
||||
// it out?"
|
||||
|
||||
// You barely have time to agree to this request when he brings up another. "While you
|
||||
// wait for the ferry, maybe you can help us with our food production problem. The
|
||||
// latest Island Island Almanac just arrived and we're having trouble making sense of
|
||||
// it."
|
||||
|
||||
// The almanac (your puzzle input) lists all of the seeds that need to be planted. It
|
||||
// also lists what type of soil to use with each kind of seed, what type of fertilizer
|
||||
// to use with each kind of soil, what type of water to use with each kind of
|
||||
// fertilizer, and so on. Every type of seed, soil, fertilizer and so on is identified
|
||||
// with a number, but numbers are reused by each category - that is, soil 123 and
|
||||
// fertilizer 123 aren't necessarily related to each other.
|
||||
|
||||
// For example:
|
||||
|
||||
// seeds: 79 14 55 13
|
||||
//
|
||||
// seed-to-soil map:
|
||||
// 50 98 2
|
||||
// 52 50 48
|
||||
//
|
||||
// soil-to-fertilizer map:
|
||||
// 0 15 37
|
||||
// 37 52 2
|
||||
// 39 0 15
|
||||
//
|
||||
// fertilizer-to-water map:
|
||||
// 49 53 8
|
||||
// 0 11 42
|
||||
// 42 0 7
|
||||
// 57 7 4
|
||||
//
|
||||
// water-to-light map:
|
||||
// 88 18 7
|
||||
// 18 25 70
|
||||
//
|
||||
// light-to-temperature map:
|
||||
// 45 77 23
|
||||
// 81 45 19
|
||||
// 68 64 13
|
||||
//
|
||||
// temperature-to-humidity map:
|
||||
// 0 69 1
|
||||
// 1 0 69
|
||||
//
|
||||
// humidity-to-location map:
|
||||
// 60 56 37
|
||||
// 56 93 4
|
||||
|
||||
// The almanac starts by listing which seeds need to be planted: seeds 79, 14, 55, and 13.
|
||||
|
||||
// The rest of the almanac contains a list of maps which describe how to convert numbers
|
||||
// from a source category into numbers in a destination category. That is, the section
|
||||
// that starts with seed-to-soil map: describes how to convert a seed number (the
|
||||
// source) to a soil number (the destination). This lets the gardener and his team know
|
||||
// which soil to use with which seeds, which water to use with which fertilizer, and so
|
||||
// on.
|
||||
|
||||
// Rather than list every source number and its corresponding destination number one by
|
||||
// one, the maps describe entire ranges of numbers that can be converted. Each line
|
||||
// within a map contains three numbers: the destination range start, the source range
|
||||
// start, and the range length.
|
||||
|
||||
// Consider again the example seed-to-soil map:
|
||||
|
||||
// 50 98 2
|
||||
// 52 50 48
|
||||
|
||||
// The first line has a destination range start of 50, a source range start of 98, and a
|
||||
// range length of 2. This line means that the source range starts at 98 and contains
|
||||
// two values: 98 and 99. The destination range is the same length, but it starts at 50,
|
||||
// so its two values are 50 and 51. With this information, you know that seed number 98
|
||||
// corresponds to soil number 50 and that seed number 99 corresponds to soil number 51.
|
||||
|
||||
// The second line means that the source range starts at 50 and contains 48 values: 50,
|
||||
// 51, ..., 96, 97. This corresponds to a destination range starting at 52 and also
|
||||
// containing 48 values: 52, 53, ..., 98, 99. So, seed number 53 corresponds to soil
|
||||
// number 55.
|
||||
|
||||
// Any source numbers that aren't mapped correspond to the same destination number. So,
|
||||
// seed number 10 corresponds to soil number 10.
|
||||
|
||||
// So, the entire list of seed numbers and their corresponding soil numbers looks like
|
||||
// this:
|
||||
|
||||
// seed soil
|
||||
// 0 0
|
||||
// 1 1
|
||||
// ... ...
|
||||
// 48 48
|
||||
// 49 49
|
||||
// 50 52
|
||||
// 51 53
|
||||
// ... ...
|
||||
// 96 98
|
||||
// 97 99
|
||||
// 98 50
|
||||
// 99 51
|
||||
|
||||
// With this map, you can look up the soil number required for each initial seed number:
|
||||
|
||||
// Seed number 79 corresponds to soil number 81.
|
||||
// Seed number 14 corresponds to soil number 14.
|
||||
// Seed number 55 corresponds to soil number 57.
|
||||
// Seed number 13 corresponds to soil number 13.
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PARSING
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AlmanacMapping {
|
||||
source_range: Range<i64>,
|
||||
dest_range: Range<i64>,
|
||||
}
|
||||
|
||||
impl From<&str> for AlmanacMapping {
|
||||
fn from(s: &str) -> Self {
|
||||
let s_nums: Vec<_> = s.split_whitespace().take(3).collect();
|
||||
let length: i64 = s_nums[2].parse().unwrap();
|
||||
let source_start: i64 = s_nums[1].parse().unwrap();
|
||||
let dest_start: i64 = s_nums[0].parse().unwrap();
|
||||
AlmanacMapping {
|
||||
source_range: source_start..source_start + length,
|
||||
dest_range: dest_start..dest_start + length,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AlmanacMapping {
|
||||
fn lookup(&self, key: i64) -> Option<i64> {
|
||||
if self.source_range.contains(&key) {
|
||||
Some(self.dest_range.start + (key - self.source_range.start))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AlmanacMappingTable {
|
||||
name: String,
|
||||
mappings: Vec<AlmanacMapping>,
|
||||
}
|
||||
|
||||
fn range_overlap<T: num::Num + Ord + Copy>(r1: &Range<T>, r2: &Range<T>) -> Option<Range<T>> {
|
||||
let new_start = std::cmp::max(r1.start, r2.start);
|
||||
let new_end = std::cmp::min(r1.end - T::one(), r2.end - T::one());
|
||||
|
||||
if new_start <= std::cmp::min(r1.end - T::one(), r2.end - T::one())
|
||||
&& new_end >= std::cmp::max(r1.start, r2.start)
|
||||
{
|
||||
Some(new_start..new_end + T::one())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn range_exclude<T: num::Num + Ord + Copy>(keep: &Range<T>, exclude: &Range<T>) -> Vec<Range<T>> {
|
||||
let mut residual = Vec::new();
|
||||
if let Some(overlap) = range_overlap(keep, exclude) {
|
||||
if keep.start < overlap.start {
|
||||
residual.push(keep.start..overlap.start);
|
||||
}
|
||||
if keep.end > overlap.end {
|
||||
residual.push(overlap.end..keep.end);
|
||||
}
|
||||
} else {
|
||||
residual.push(keep.clone());
|
||||
}
|
||||
residual
|
||||
}
|
||||
|
||||
impl AlmanacMappingTable {
|
||||
fn lookup(&self, key: i64) -> i64 {
|
||||
self.mappings
|
||||
.iter()
|
||||
.find_map(|map| map.lookup(key))
|
||||
.unwrap_or(key)
|
||||
}
|
||||
fn lookup_ranges(&self, ranges: Vec<Range<i64>>) -> Vec<Range<i64>> {
|
||||
ranges
|
||||
.iter()
|
||||
.flat_map(|range| self.lookup_range(range))
|
||||
.collect()
|
||||
}
|
||||
fn lookup_range(&self, range: &Range<i64>) -> Vec<Range<i64>> {
|
||||
let mut residual = vec![range.clone()];
|
||||
let mut resolved_mappings = Vec::new();
|
||||
|
||||
for map in &self.mappings {
|
||||
let mut local_residual = Vec::new();
|
||||
for range in residual.into_iter() {
|
||||
if let Some(overlap) = range_overlap(&range, &map.source_range) {
|
||||
let dest_start_idx = overlap.start - map.source_range.start;
|
||||
let length = overlap.end.saturating_sub(overlap.start);
|
||||
resolved_mappings.push(
|
||||
(map.dest_range.start + dest_start_idx)
|
||||
..(map.dest_range.start + dest_start_idx + length),
|
||||
);
|
||||
local_residual.extend_from_slice(&range_exclude(&range, &overlap));
|
||||
} else {
|
||||
local_residual.push(range);
|
||||
}
|
||||
}
|
||||
residual = local_residual;
|
||||
}
|
||||
|
||||
// unresolved maps map 1:1
|
||||
resolved_mappings.extend_from_slice(&residual);
|
||||
|
||||
resolved_mappings
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<&mut Lines<T>> for AlmanacMappingTable {
|
||||
fn from(lines: &mut Lines<T>) -> Self {
|
||||
let name = lines
|
||||
.next()
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.split_once(':')
|
||||
.unwrap()
|
||||
.0
|
||||
.into();
|
||||
let mut mappings = Vec::new();
|
||||
for line in lines.map(|l| l.unwrap()) {
|
||||
if line == "" {
|
||||
break;
|
||||
}
|
||||
mappings.push(AlmanacMapping::from(line.as_str()));
|
||||
}
|
||||
AlmanacMappingTable { name, mappings }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Almanac {
|
||||
seeds: Vec<i64>,
|
||||
seed_to_soil: AlmanacMappingTable,
|
||||
soil_to_fertilizer: AlmanacMappingTable,
|
||||
fertilizer_to_water: AlmanacMappingTable,
|
||||
water_to_light: AlmanacMappingTable,
|
||||
light_to_temperature: AlmanacMappingTable,
|
||||
temperature_to_humidity: AlmanacMappingTable,
|
||||
humidity_to_location: AlmanacMappingTable,
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Almanac {
|
||||
fn from(mut lines: Lines<T>) -> Self {
|
||||
let seeds_s = lines.next().unwrap().unwrap();
|
||||
let seeds: Vec<i64> = seeds_s
|
||||
.split_once(": ")
|
||||
.unwrap()
|
||||
.1
|
||||
.split_whitespace()
|
||||
.map(|s| s.parse().unwrap())
|
||||
.collect();
|
||||
lines.next();
|
||||
|
||||
Almanac {
|
||||
seeds,
|
||||
seed_to_soil: AlmanacMappingTable::from(&mut lines),
|
||||
soil_to_fertilizer: AlmanacMappingTable::from(&mut lines),
|
||||
fertilizer_to_water: AlmanacMappingTable::from(&mut lines),
|
||||
water_to_light: AlmanacMappingTable::from(&mut lines),
|
||||
light_to_temperature: AlmanacMappingTable::from(&mut lines),
|
||||
temperature_to_humidity: AlmanacMappingTable::from(&mut lines),
|
||||
humidity_to_location: AlmanacMappingTable::from(&mut lines),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Almanac {
|
||||
fn lookup(&self, seed_id: i64) -> i64 {
|
||||
self.humidity_to_location.lookup(
|
||||
self.temperature_to_humidity.lookup(
|
||||
self.light_to_temperature.lookup(
|
||||
self.water_to_light.lookup(
|
||||
self.fertilizer_to_water.lookup(
|
||||
self.soil_to_fertilizer
|
||||
.lookup(self.seed_to_soil.lookup(seed_id)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
fn lookup_range(&self, range: Range<i64>) -> Vec<Range<i64>> {
|
||||
self.humidity_to_location.lookup_ranges(
|
||||
self.temperature_to_humidity.lookup_ranges(
|
||||
self.light_to_temperature.lookup_ranges(
|
||||
self.water_to_light.lookup_ranges(
|
||||
self.fertilizer_to_water.lookup_ranges(
|
||||
self.soil_to_fertilizer
|
||||
.lookup_ranges(self.seed_to_soil.lookup_ranges(vec![range])),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
// The gardener and his team want to get started as soon as possible, so they'd like to
|
||||
// know the closest location that needs a seed. Using these maps, find the lowest
|
||||
// location number that corresponds to any of the initial seeds. To do this, you'll need
|
||||
// to convert each seed number through other categories until you can find its
|
||||
// corresponding location number. In this example, the corresponding types are:
|
||||
|
||||
// Seed 79, soil 81, fertilizer 81, water 81, light 74, temperature 78, humidity 78, location 82.
|
||||
// Seed 14, soil 14, fertilizer 53, water 49, light 42, temperature 42, humidity 43, location 43.
|
||||
// Seed 55, soil 57, fertilizer 57, water 53, light 46, temperature 82, humidity 82, location 86.
|
||||
// Seed 13, soil 13, fertilizer 52, water 41, light 34, temperature 34, humidity 35, location 35.
|
||||
|
||||
// So, the lowest location number in this example is 35.
|
||||
|
||||
// What is the lowest location number that corresponds to any of the initial seed numbers?
|
||||
|
||||
fn problem1_lowest_location(almanac: &Almanac) -> i64 {
|
||||
almanac
|
||||
.seeds
|
||||
.iter()
|
||||
.map(|seed| almanac.lookup(*seed))
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> i64 {
|
||||
let almanac = Almanac::from(input);
|
||||
problem1_lowest_location(&almanac)
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
|
||||
// Everyone will starve if you only plant such a small number of seeds. Re-reading the
|
||||
// almanac, it looks like the seeds: line actually describes ranges of seed numbers.
|
||||
|
||||
// The values on the initial seeds: line come in pairs. Within each pair, the first
|
||||
// value is the start of the range and the second value is the length of the range. So,
|
||||
// in the first line of the example above:
|
||||
|
||||
// seeds: 79 14 55 13
|
||||
|
||||
// This line describes two ranges of seed numbers to be planted in the garden. The first
|
||||
// range starts with seed number 79 and contains 14 values: 79, 80, ..., 91, 92. The
|
||||
// second range starts with seed number 55 and contains 13 values: 55, 56, ..., 66, 67.
|
||||
|
||||
// Now, rather than considering four seed numbers, you need to consider a total of 27
|
||||
// seed numbers.
|
||||
|
||||
// In the above example, the lowest location number can be obtained from seed number 82,
|
||||
// which corresponds to soil 84, fertilizer 84, water 84, light 77, temperature 45,
|
||||
// humidity 46, and location 46. So, the lowest location number is 46.
|
||||
|
||||
// Consider all of the initial seed numbers listed in the ranges on the first line of
|
||||
// the almanac. What is the lowest location number that corresponds to any of the
|
||||
// initial seed numbers?
|
||||
|
||||
fn problem2_lowest_location(almanac: &Almanac) -> i64 {
|
||||
let seed_ranges = almanac
|
||||
.seeds
|
||||
.iter()
|
||||
.tuples()
|
||||
.map(|(range_start, length)| *range_start..*range_start + *length);
|
||||
|
||||
// seed_ranges
|
||||
// .map(|range| {
|
||||
// range
|
||||
// .into_par_iter()
|
||||
// .map(|x| almanac.lookup(x))
|
||||
// .min()
|
||||
// .unwrap()
|
||||
// })
|
||||
// .min()
|
||||
// .unwrap()
|
||||
let ranges = seed_ranges
|
||||
.flat_map(|range| almanac.lookup_range(range))
|
||||
.collect_vec();
|
||||
|
||||
ranges.iter().map(|range| range.start).min().unwrap()
|
||||
}
|
||||
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> i64 {
|
||||
let almanac = Almanac::from(input);
|
||||
problem2_lowest_location(&almanac)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use num::Num;
|
||||
use std::io::{BufRead, Cursor};
|
||||
use test_case::test_case;
|
||||
|
||||
use crate::*;
|
||||
|
||||
const EXAMPLE_ALMANAC: &str = &"seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4";
|
||||
|
||||
#[test]
|
||||
fn test_almanac_mapping_parse() {
|
||||
let s = "50 98 2";
|
||||
let a = AlmanacMapping::from(s);
|
||||
assert_eq!(a.source_range, 98..100);
|
||||
assert_eq!(a.dest_range, 50..52);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_almanac_mapping_lookup() {
|
||||
let s = "50 98 2";
|
||||
let a = AlmanacMapping::from(s);
|
||||
assert_eq!(a.lookup(99), Some(51));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_almanac_parsing() {
|
||||
let c = Cursor::new(EXAMPLE_ALMANAC);
|
||||
let a = Almanac::from(c.lines());
|
||||
assert_eq!(a.lookup(79), 82);
|
||||
}
|
||||
|
||||
#[test_case(0..5, 2..4, Some(2..4) ; "one range overlaps completely")]
|
||||
#[test_case(0..5, 2..10, Some(2..5) ; "one range overlaps from below")]
|
||||
#[test_case(0..5, 5..10, None ; "no overlap, touching")]
|
||||
#[test_case(0..5, 6..10, None ; "no overlap, disjoint")]
|
||||
fn test_range_overlap<T: Num + Copy + Ord + std::fmt::Debug>(
|
||||
r1: Range<T>,
|
||||
r2: Range<T>,
|
||||
expected: Option<Range<T>>,
|
||||
) {
|
||||
assert_eq!(range_overlap(&r1, &r2), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE_ALMANAC);
|
||||
let a = Almanac::from(c.lines());
|
||||
assert_eq!(problem1_lowest_location(&a), 35);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE_ALMANAC);
|
||||
let a = Almanac::from(c.lines());
|
||||
assert_eq!(problem2_lowest_location(&a), 46);
|
||||
}
|
||||
}
|
7
6/Cargo.lock
generated
Normal file
7
6/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day6"
|
||||
version = "0.1.0"
|
8
6/Cargo.toml
Normal file
8
6/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day6"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
242
6/src/main.rs
Normal file
242
6/src/main.rs
Normal file
@ -0,0 +1,242 @@
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
|
||||
// --- Day 6: Wait For It ---
|
||||
|
||||
// The ferry quickly brings you across Island Island. After asking around, you discover
|
||||
// that there is indeed normally a large pile of sand somewhere near here, but you don't
|
||||
// see anything besides lots of water and the small island where the ferry has docked.
|
||||
|
||||
// As you try to figure out what to do next, you notice a poster on a wall near the
|
||||
// ferry dock. "Boat races! Open to the public! Grand prize is an all-expenses-paid trip
|
||||
// to Desert Island!" That must be where the sand comes from! Best of all, the boat
|
||||
// races are starting in just a few minutes.
|
||||
|
||||
// You manage to sign up as a competitor in the boat races just in time. The organizer
|
||||
// explains that it's not really a traditional race - instead, you will get a fixed
|
||||
// amount of time during which your boat has to travel as far as it can, and you win if
|
||||
// your boat goes the farthest.
|
||||
|
||||
// As part of signing up, you get a sheet of paper (your puzzle input) that lists the
|
||||
// time allowed for each race and also the best distance ever recorded in that race. To
|
||||
// guarantee you win the grand prize, you need to make sure you go farther in each race
|
||||
// than the current record holder.
|
||||
|
||||
// The organizer brings you over to the area where the boat races are held. The boats
|
||||
// are much smaller than you expected - they're actually toy boats, each with a big
|
||||
// button on top. Holding down the button charges the boat, and releasing the button
|
||||
// allows the boat to move. Boats move faster if their button was held longer, but time
|
||||
// spent holding the button counts against the total race time. You can only hold the
|
||||
// button at the start of the race, and boats don't move until the button is released.
|
||||
|
||||
// For example:
|
||||
|
||||
// Time: 7 15 30
|
||||
// Distance: 9 40 200
|
||||
|
||||
// This document describes three races:
|
||||
|
||||
// The first race lasts 7 milliseconds. The record distance in this race is 9 millimeters.
|
||||
// The second race lasts 15 milliseconds. The record distance in this race is 40 millimeters.
|
||||
// The third race lasts 30 milliseconds. The record distance in this race is 200 millimeters.
|
||||
|
||||
// Your toy boat has a starting speed of zero millimeters per millisecond. For each
|
||||
// whole millisecond you spend at the beginning of the race holding down the button, the
|
||||
// boat's speed increases by one millimeter per millisecond.
|
||||
|
||||
// So, because the first race lasts 7 milliseconds, you only have a few options:
|
||||
|
||||
// Don't hold the button at all (that is, hold it for 0 milliseconds) at the start
|
||||
// of the race. The boat won't move; it will have traveled 0 millimeters by the end
|
||||
// of the race.
|
||||
|
||||
// Hold the button for 1 millisecond at the start of the race. Then, the boat will
|
||||
// travel at a speed of 1 millimeter per millisecond for 6 milliseconds, reaching a
|
||||
// total distance traveled of 6 millimeters.
|
||||
|
||||
// Hold the button for 2 milliseconds, giving the boat a speed of 2 millimeters per
|
||||
// millisecond. It will then get 5 milliseconds to move, reaching a total distance
|
||||
// of 10 millimeters.
|
||||
|
||||
// Hold the button for 3 milliseconds. After its remaining 4 milliseconds of travel
|
||||
// time, the boat will have gone 12 millimeters.
|
||||
|
||||
// Hold the button for 4 milliseconds. After its remaining 3 milliseconds of travel
|
||||
// time, the boat will have gone 12 millimeters.
|
||||
|
||||
// Hold the button for 5 milliseconds, causing the boat to travel a total of 10
|
||||
// millimeters.
|
||||
|
||||
// Hold the button for 6 milliseconds, causing the boat to travel a total of 6
|
||||
// millimeters.
|
||||
|
||||
// Hold the button for 7 milliseconds. That's the entire duration of the race. You
|
||||
// never let go of the button. The boat can't move until you let go of the button.
|
||||
// Please make sure you let go of the button so the boat gets to move. 0
|
||||
// millimeters.
|
||||
|
||||
// Since the current record for this race is 9 millimeters, there are actually 4
|
||||
// different ways you could win: you could hold the button for 2, 3, 4, or 5
|
||||
// milliseconds at the start of the race.
|
||||
|
||||
// In the second race, you could hold the button for at least 4 milliseconds and at most
|
||||
// 11 milliseconds and beat the record, a total of 8 different ways to win.
|
||||
|
||||
// In the third race, you could hold the button for at least 11 milliseconds and no more
|
||||
// than 19 milliseconds and still beat the record, a total of 9 ways you could win.
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Problem 1 solution: {}", problem1(get_input()));
|
||||
println!("Problem 2 solution: {}", problem2(get_input()));
|
||||
}
|
||||
|
||||
// PARSER
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
// Appropriate for Problem 1 only
|
||||
struct Races(Vec<(u64, u64)>);
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Races {
|
||||
fn from(mut input: Lines<T>) -> Self {
|
||||
let timeline = input.next().unwrap().unwrap();
|
||||
let distline = input.next().unwrap().unwrap();
|
||||
|
||||
let times = timeline
|
||||
.split_whitespace()
|
||||
.skip(1)
|
||||
.map(|s| s.parse().unwrap());
|
||||
let distances = distline
|
||||
.split_whitespace()
|
||||
.skip(1)
|
||||
.map(|s| s.parse().unwrap());
|
||||
|
||||
Races(times.zip(distances).collect())
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
// To see how much margin of error you have, determine the number of ways you can beat
|
||||
// the record in each race; in this example, if you multiply these values together, you
|
||||
// get 288 (4 * 8 * 9).
|
||||
|
||||
// Determine the number of ways you could beat the record in each race. What do you get
|
||||
// if you multiply these numbers together?
|
||||
|
||||
/// Calculate the 'score' of a race. Speed will equal button duration, and runtime
|
||||
/// equals the remaining time
|
||||
fn race_distance(button_duration: u64, race_duration: u64) -> u64 {
|
||||
assert!(button_duration <= race_duration);
|
||||
|
||||
let running_time = race_duration - button_duration;
|
||||
|
||||
running_time * button_duration
|
||||
}
|
||||
|
||||
fn problem1_possible_wins(race: (u64, u64)) -> u64 {
|
||||
let (duration, record) = race;
|
||||
|
||||
(1..duration)
|
||||
.map(|button_duration| race_distance(button_duration, duration))
|
||||
.filter(|achieved_distance| *achieved_distance > record)
|
||||
.count() as u64
|
||||
}
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let races = Races::from(input);
|
||||
races
|
||||
.0
|
||||
.iter()
|
||||
.map(|race| problem1_possible_wins(*race))
|
||||
.fold(1, |accum, elem| accum * elem)
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
|
||||
// As the race is about to start, you realize the piece of paper with race times and
|
||||
// record distances you got earlier actually just has very bad kerning. There's really
|
||||
// only one race - ignore the spaces between the numbers on each line.
|
||||
|
||||
// So, the example from before:
|
||||
|
||||
// Time: 7 15 30
|
||||
// Distance: 9 40 200
|
||||
|
||||
// ...now instead means this:
|
||||
|
||||
// Time: 71530
|
||||
// Distance: 940200
|
||||
|
||||
// Now, you have to figure out how many ways there are to win this single race. In this
|
||||
// example, the race lasts for 71530 milliseconds and the record distance you need to
|
||||
// beat is 940200 millimeters. You could hold the button anywhere from 14 to 71516
|
||||
// milliseconds and beat the record, a total of 71503 ways!
|
||||
|
||||
// How many ways can you beat the record in this one much longer race?
|
||||
|
||||
fn problem2_parse_all_digits_to_number(s: &str) -> u64 {
|
||||
s.chars().filter(|c| c.is_digit(10)).fold(0, |accum, elem| {
|
||||
accum * 10 + elem.to_digit(10).unwrap() as u64
|
||||
})
|
||||
}
|
||||
|
||||
fn problem2<T: BufRead>(mut input: Lines<T>) -> u64 {
|
||||
let time = problem2_parse_all_digits_to_number(input.next().unwrap().unwrap().as_str());
|
||||
let distance = problem2_parse_all_digits_to_number(input.next().unwrap().unwrap().as_str());
|
||||
|
||||
problem1_possible_wins((time, distance))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"Time: 7 15 30
|
||||
Distance: 9 40 200";
|
||||
|
||||
#[test]
|
||||
fn test_races_parser() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
let races = Races::from(c.lines());
|
||||
assert_eq!(races.0, vec![(7, 9), (15, 40), (30, 200)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_race_distance() {
|
||||
assert_eq!(race_distance(0, 7), 0);
|
||||
assert_eq!(race_distance(1, 7), 6);
|
||||
assert_eq!(race_distance(2, 7), 10);
|
||||
assert_eq!(race_distance(3, 7), 12);
|
||||
assert_eq!(race_distance(7, 7), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_possible_wins() {
|
||||
assert_eq!(problem1_possible_wins((7, 9)), 4);
|
||||
assert_eq!(problem1_possible_wins((15, 40)), 8);
|
||||
assert_eq!(problem1_possible_wins((30, 200)), 9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 288);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 71503);
|
||||
}
|
||||
}
|
7
7/Cargo.lock
generated
Normal file
7
7/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day7"
|
||||
version = "0.1.0"
|
8
7/Cargo.toml
Normal file
8
7/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day7"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
267
7/src/main.rs
Normal file
267
7/src/main.rs
Normal file
@ -0,0 +1,267 @@
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Problem 1 solution: {}", problem1(get_input()));
|
||||
println!("Problem 2 solution: {}", problem2(get_input()));
|
||||
}
|
||||
|
||||
// PARSING
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
||||
enum Card {
|
||||
TWO,
|
||||
THREE,
|
||||
FOUR,
|
||||
FIVE,
|
||||
SIX,
|
||||
SEVEN,
|
||||
EIGHT,
|
||||
NINE,
|
||||
T,
|
||||
J,
|
||||
Q,
|
||||
K,
|
||||
A,
|
||||
}
|
||||
|
||||
impl Card {
|
||||
const fn count() -> usize {
|
||||
Card::A as usize + 1
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq)]
|
||||
enum HandType {
|
||||
HighCard,
|
||||
OnePair,
|
||||
TwoPair,
|
||||
ThreeOfAKind,
|
||||
FullHouse,
|
||||
FourOfAKind,
|
||||
FiveOfAKind,
|
||||
}
|
||||
|
||||
impl From<char> for Card {
|
||||
fn from(c: char) -> Self {
|
||||
match c {
|
||||
'A' => Self::A,
|
||||
'K' => Self::K,
|
||||
'Q' => Self::Q,
|
||||
'J' => Self::J,
|
||||
'T' => Self::T,
|
||||
'9' => Self::NINE,
|
||||
'8' => Self::EIGHT,
|
||||
'7' => Self::SEVEN,
|
||||
'6' => Self::SIX,
|
||||
'5' => Self::FIVE,
|
||||
'4' => Self::FOUR,
|
||||
'3' => Self::THREE,
|
||||
'2' => Self::TWO,
|
||||
_ => panic!("Invalid card {}", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Hand<const WILD: bool> {
|
||||
cards: Vec<Card>,
|
||||
bid: u64,
|
||||
}
|
||||
|
||||
impl<const WILD: bool> Hand<WILD> {
|
||||
fn card_counts(&self) -> [u64; Card::count()] {
|
||||
let mut counts = [0u64; Card::count()];
|
||||
for card in &self.cards {
|
||||
counts[*card as usize] += 1;
|
||||
}
|
||||
|
||||
counts
|
||||
}
|
||||
fn hand_type(&self) -> HandType {
|
||||
if !WILD {
|
||||
let card_counts = self.card_counts();
|
||||
if card_counts.contains(&5) {
|
||||
HandType::FiveOfAKind
|
||||
} else if card_counts.contains(&4) {
|
||||
HandType::FourOfAKind
|
||||
} else if card_counts.contains(&3) && card_counts.contains(&2) {
|
||||
HandType::FullHouse
|
||||
} else if card_counts.contains(&3) {
|
||||
HandType::ThreeOfAKind
|
||||
} else if card_counts.iter().filter(|count| **count == 2).count() == 2 {
|
||||
HandType::TwoPair
|
||||
} else if card_counts.contains(&2) {
|
||||
HandType::OnePair
|
||||
} else {
|
||||
HandType::HighCard
|
||||
}
|
||||
} else {
|
||||
let mut card_counts = self.card_counts();
|
||||
let wild_count = card_counts[Card::J as usize];
|
||||
card_counts[Card::J as usize] = 0;
|
||||
|
||||
let same_count = card_counts.iter().max().unwrap() + wild_count;
|
||||
|
||||
if same_count == 5 {
|
||||
HandType::FiveOfAKind
|
||||
} else if same_count == 4 {
|
||||
HandType::FourOfAKind
|
||||
} else if card_counts.contains(&3) && card_counts.contains(&2) {
|
||||
HandType::FullHouse
|
||||
} else
|
||||
// Full House with WILDs
|
||||
if wild_count == 1
|
||||
&& (card_counts.contains(&3)
|
||||
|| (card_counts.iter().filter(|count| **count == 2).count() == 2))
|
||||
{
|
||||
HandType::FullHouse
|
||||
} else if wild_count == 2 && card_counts.contains(&2) {
|
||||
HandType::FullHouse
|
||||
} else if wild_count == 3 {
|
||||
HandType::FullHouse
|
||||
} else if same_count == 3 {
|
||||
HandType::ThreeOfAKind
|
||||
} else if card_counts.iter().filter(|count| **count == 2).count() == 2
|
||||
|| (card_counts.contains(&2) && wild_count > 0)
|
||||
{
|
||||
HandType::TwoPair
|
||||
} else if same_count == 2 {
|
||||
HandType::OnePair
|
||||
} else {
|
||||
HandType::HighCard
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const WILD: bool> From<&str> for Hand<WILD> {
|
||||
fn from(s: &str) -> Self {
|
||||
let (cards_s, bid_s) = s.split_once(' ').unwrap();
|
||||
let bid = bid_s.parse().unwrap();
|
||||
let cards = cards_s.chars().map(|c| Card::from(c)).collect();
|
||||
|
||||
Hand { cards, bid }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const WILD: bool> PartialOrd for Hand<WILD> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<const WILD: bool> Ord for Hand<WILD> {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
let our_type = self.hand_type();
|
||||
let other_type = other.hand_type();
|
||||
if our_type != other_type {
|
||||
our_type.cmp(&other_type)
|
||||
} else {
|
||||
let (ours, theirs) = self
|
||||
.cards
|
||||
.iter()
|
||||
.zip(other.cards.iter())
|
||||
.find(|(ours, theirs)| *ours != *theirs)
|
||||
.unwrap();
|
||||
if !WILD {
|
||||
ours.cmp(theirs)
|
||||
} else {
|
||||
if *ours == Card::J {
|
||||
std::cmp::Ordering::Less
|
||||
} else if *theirs == Card::J {
|
||||
std::cmp::Ordering::Greater
|
||||
} else {
|
||||
ours.cmp(theirs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut hands: Vec<_> = input
|
||||
.map(|line| Hand::<false>::from(line.unwrap().as_str()))
|
||||
.collect();
|
||||
hands.sort();
|
||||
hands
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, hand)| (idx + 1) as u64 * hand.bid)
|
||||
.sum()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let mut hands: Vec<_> = input
|
||||
.map(|line| Hand::<true>::from(line.unwrap().as_str()))
|
||||
.collect();
|
||||
hands.sort();
|
||||
hands
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, hand)| (idx + 1) as u64 * hand.bid)
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::*;
|
||||
|
||||
const EXAMPLE: &str = &"32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483";
|
||||
|
||||
#[test]
|
||||
fn test_hand_parser() {
|
||||
let hand = Hand::<false>::from(EXAMPLE.lines().next().unwrap());
|
||||
assert_eq!(
|
||||
hand,
|
||||
Hand {
|
||||
bid: 765,
|
||||
cards: vec![Card::THREE, Card::TWO, Card::T, Card::THREE, Card::K]
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem1_test_hand_compare() {
|
||||
let hand1 = Hand::<false>::from("T55J5 123");
|
||||
let hand2 = Hand::<false>::from("QQQJA 123");
|
||||
let hand3 = Hand::<false>::from("KK677 123");
|
||||
|
||||
assert!(hand2 > hand1);
|
||||
assert!(hand3 < hand1);
|
||||
assert!(hand3 < hand2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_test_hand_compare() {}
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 6440);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 5905);
|
||||
}
|
||||
}
|
201
8/Cargo.lock
generated
Normal file
201
8/Cargo.lock
generated
Normal file
@ -0,0 +1,201 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "day8"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy-regex",
|
||||
"num",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d12be4595afdf58bd19e4a9f4e24187da2a66700786ff660a418e9059937a4c"
|
||||
dependencies = [
|
||||
"lazy-regex-proc_macros",
|
||||
"once_cell",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-regex-proc_macros"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44bcd58e6c97a7fcbaffcdc95728b393b8d98933bfadad49ed4097845b57ef0b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
8
8/Cargo.toml
Normal file
8
8/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day8"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
lazy-regex = "3.1.0"
|
||||
num = "0.4.1"
|
740
8/input
Normal file
740
8/input
Normal file
@ -0,0 +1,740 @@
|
||||
LLRLLRRLRLRRRLRRLLRRRLRLRLRRLRRRLRRLRLRLLRLLLRRRLRRLRRRLRRRLRRRLRLRRLLRRLRRLRRLRRRLRLRRRLLRLRRLRRRLRLRRRLRRRLRLRRRLLRRRLRRRLRLRRLRLRRRLLRRLRRLRRLRRLRLRLRRRLLRRRLRRLRRRLRLRLRRRLLRLRRLLRLRRLRLRRRLRLRRLLRRRLLRRLRLRLLRLLRRLRRLLRRLRLRRLRLRLRRRLRRLRLLLLRRLRLRLRRRLLLRRRLRRLRRLRLLRLRRRLLLRRRLRRRLRRRR
|
||||
|
||||
NQT = (TXC, RVJ)
|
||||
FPT = (PNS, KJL)
|
||||
BNQ = (THG, LCV)
|
||||
SPL = (VBH, NNV)
|
||||
TLM = (LVQ, PGT)
|
||||
GHC = (XKN, SPR)
|
||||
PHT = (HMF, DST)
|
||||
FSF = (JCM, SMT)
|
||||
GDD = (FHJ, RBS)
|
||||
GVR = (FVD, FVD)
|
||||
SST = (PMF, MGC)
|
||||
ZZZ = (VLV, SQV)
|
||||
SDV = (DBL, GTL)
|
||||
XSP = (GRV, RFM)
|
||||
SKG = (NGH, VDX)
|
||||
BPK = (RMK, LCQ)
|
||||
VSC = (DRN, SFR)
|
||||
BFR = (BJR, GMD)
|
||||
HTM = (PFM, LVD)
|
||||
XVP = (LDP, LDP)
|
||||
DRD = (SCH, LKD)
|
||||
DSJ = (GSQ, JTN)
|
||||
VTS = (BNQ, VFX)
|
||||
KVF = (HTP, MQK)
|
||||
GPS = (FXQ, TPF)
|
||||
VRC = (RTK, RTK)
|
||||
HRD = (PMQ, JCR)
|
||||
DJK = (FTC, KXH)
|
||||
VGJ = (PCJ, TVH)
|
||||
QMN = (TLC, HNG)
|
||||
DMH = (QSD, PDP)
|
||||
CRL = (VFR, MDR)
|
||||
XGV = (CMV, FTV)
|
||||
XJX = (HTM, HHG)
|
||||
SQP = (XKK, KJF)
|
||||
PXZ = (JCK, PTH)
|
||||
BDV = (JMH, CND)
|
||||
FBD = (CQS, QCN)
|
||||
TRS = (FGM, NKF)
|
||||
TLC = (HBC, FRC)
|
||||
DKR = (LCP, VLD)
|
||||
GTF = (QHD, PBB)
|
||||
NCC = (HJF, LNR)
|
||||
KGS = (KPF, GTB)
|
||||
CPQ = (SLR, DRD)
|
||||
RJQ = (KXK, BFR)
|
||||
XSQ = (PNN, NMG)
|
||||
DVP = (MBH, QLV)
|
||||
CQL = (DVP, VHQ)
|
||||
CPV = (MDL, VFB)
|
||||
VHV = (CQS, QCN)
|
||||
NRD = (KSC, HKX)
|
||||
STX = (CGJ, PGK)
|
||||
CNP = (FVB, MCN)
|
||||
JXT = (DXT, LHK)
|
||||
GHG = (MCL, MPB)
|
||||
PGK = (RMS, SBC)
|
||||
DNH = (FSV, RNS)
|
||||
TFZ = (NQT, PBD)
|
||||
MBQ = (DPH, FDK)
|
||||
SJQ = (JLB, LJJ)
|
||||
MBN = (FTD, CDB)
|
||||
TDJ = (FJB, PQX)
|
||||
DXT = (FJP, HGQ)
|
||||
MSG = (MSM, CXN)
|
||||
RTK = (GVR, GVR)
|
||||
SDX = (VTS, MRG)
|
||||
VCX = (QTL, NVV)
|
||||
XCS = (KLR, THD)
|
||||
RDD = (QDS, JST)
|
||||
FVB = (BLD, NPF)
|
||||
LVD = (JXC, FQR)
|
||||
TMR = (SNJ, DML)
|
||||
RCH = (JST, QDS)
|
||||
RVJ = (XMN, SDT)
|
||||
SQV = (MVP, MKC)
|
||||
HDB = (LTL, JJP)
|
||||
LVC = (CLL, CLL)
|
||||
FGM = (TPG, PHK)
|
||||
SCS = (MLK, TKF)
|
||||
PRF = (TLB, KTT)
|
||||
MPM = (NMN, KGS)
|
||||
MGC = (NLT, MGS)
|
||||
CNK = (BFR, KXK)
|
||||
FXQ = (JMX, LLL)
|
||||
GTB = (MFM, PMV)
|
||||
VXS = (DPN, FPN)
|
||||
NRB = (SCS, SGH)
|
||||
QLJ = (NLL, VMM)
|
||||
PNN = (SFJ, HSR)
|
||||
BRJ = (RMQ, XLJ)
|
||||
SNF = (FMH, MNR)
|
||||
VLD = (SHN, FBG)
|
||||
FSM = (GKF, DBC)
|
||||
MHP = (LBX, KQH)
|
||||
NSQ = (QKK, KND)
|
||||
RRT = (RMK, LCQ)
|
||||
BCX = (GTM, MVV)
|
||||
XSX = (XFK, XNF)
|
||||
TKF = (MFF, VCV)
|
||||
HPD = (GHC, RKN)
|
||||
MRG = (BNQ, VFX)
|
||||
QTK = (QRT, RRB)
|
||||
HFF = (NKD, SXP)
|
||||
MFM = (BRB, DDN)
|
||||
VVL = (GPC, BRJ)
|
||||
CST = (GQT, NLG)
|
||||
THD = (MVK, DRJ)
|
||||
XFN = (JNC, MNF)
|
||||
NKH = (PMD, BDV)
|
||||
NLT = (HKK, KCD)
|
||||
VXR = (XCS, GRX)
|
||||
SDS = (JBV, JFM)
|
||||
BFM = (XXG, CHQ)
|
||||
PMD = (JMH, CND)
|
||||
VVF = (GQT, NLG)
|
||||
FGG = (NRD, SNP)
|
||||
LKD = (NGK, SQP)
|
||||
RSV = (TXL, GPD)
|
||||
LNR = (RDB, NTD)
|
||||
RPL = (SNB, MHK)
|
||||
CCG = (JDT, PJD)
|
||||
TKR = (TMD, VCL)
|
||||
DRJ = (CQL, XFH)
|
||||
JFM = (MMV, GPS)
|
||||
FJP = (BDM, QXN)
|
||||
QJS = (BFM, RHM)
|
||||
KTT = (PXV, VJV)
|
||||
XXB = (VKG, HXL)
|
||||
RMK = (DBR, HFQ)
|
||||
NGK = (KJF, XKK)
|
||||
NPF = (SMK, BTJ)
|
||||
RBS = (PGN, GNH)
|
||||
PNS = (VTJ, KSM)
|
||||
BCK = (SDX, NRF)
|
||||
RNS = (XVS, KFX)
|
||||
PDB = (BHH, BHH)
|
||||
GMQ = (MRD, JRG)
|
||||
DGM = (HDV, GSD)
|
||||
TLB = (PXV, VJV)
|
||||
QRT = (FRS, FFT)
|
||||
VSX = (NLL, VMM)
|
||||
GSQ = (JRJ, LGV)
|
||||
TXC = (XMN, SDT)
|
||||
HGQ = (QXN, BDM)
|
||||
PMQ = (KBB, NRH)
|
||||
KRC = (DGM, XCR)
|
||||
QLZ = (TKM, HTF)
|
||||
NJM = (GPC, BRJ)
|
||||
FRG = (QLS, GXP)
|
||||
NMG = (SFJ, HSR)
|
||||
JDT = (TDF, QHT)
|
||||
LFC = (RFM, GRV)
|
||||
TXL = (XSX, FTP)
|
||||
DKG = (JNL, XBR)
|
||||
VKF = (GTM, MVV)
|
||||
VQV = (RHT, SDS)
|
||||
SJH = (LPV, TRQ)
|
||||
KSM = (LHX, CPQ)
|
||||
QMH = (MMD, GPB)
|
||||
VNP = (TRQ, LPV)
|
||||
NBM = (JPF, KRM)
|
||||
RGQ = (TMH, KQR)
|
||||
RSM = (SMP, KSG)
|
||||
HDV = (VXS, VQG)
|
||||
TTD = (CDB, FTD)
|
||||
GXF = (SLN, SCF)
|
||||
QHT = (TMR, QTH)
|
||||
MNR = (VXR, GDS)
|
||||
GSA = (THS, NKH)
|
||||
XKN = (GNB, VLQ)
|
||||
HHQ = (RRB, QRT)
|
||||
CLC = (THS, NKH)
|
||||
BSN = (QKN, QKN)
|
||||
QRB = (KDT, JSL)
|
||||
JCX = (VCX, DXP)
|
||||
BDM = (SQN, TBH)
|
||||
GQT = (DNB, NTS)
|
||||
QSF = (KXH, FTC)
|
||||
HFQ = (NNQ, LLM)
|
||||
VFB = (NGF, NXB)
|
||||
JMX = (HFB, DNR)
|
||||
VKS = (NBM, NQF)
|
||||
PGN = (FBD, VHV)
|
||||
PNQ = (KQR, TMH)
|
||||
QLM = (VVL, NJM)
|
||||
PRB = (KQD, QRB)
|
||||
GTL = (VQJ, DJR)
|
||||
KNL = (JRN, KVF)
|
||||
VMT = (LTL, JJP)
|
||||
QKN = (PHM, VQS)
|
||||
QBL = (LXK, PRF)
|
||||
PCT = (VNP, SJH)
|
||||
QLV = (HXF, DXH)
|
||||
HNN = (DSJ, XDN)
|
||||
LGV = (VVD, XXB)
|
||||
XCB = (XXQ, CHX)
|
||||
GXC = (FGG, MSX)
|
||||
SLN = (VLP, SST)
|
||||
NQQ = (SXP, NKD)
|
||||
DRN = (DPC, TCV)
|
||||
JHF = (QTK, HHQ)
|
||||
GPM = (GTF, NCX)
|
||||
PFM = (JXC, JXC)
|
||||
KBT = (KQH, LBX)
|
||||
XFH = (VHQ, DVP)
|
||||
CPT = (VSD, TKR)
|
||||
GSX = (CTF, XXX)
|
||||
SPR = (GNB, VLQ)
|
||||
XBP = (MXH, TBJ)
|
||||
VKG = (PKS, CPT)
|
||||
THG = (FRP, FRP)
|
||||
SHN = (FRG, TCF)
|
||||
BFS = (RPL, JRV)
|
||||
PHK = (BQG, BMH)
|
||||
SMK = (VRV, FDG)
|
||||
PBF = (MSG, XGT)
|
||||
NKF = (TPG, PHK)
|
||||
VDQ = (MHP, KBT)
|
||||
JRG = (DXJ, JCX)
|
||||
MHK = (QTS, CRL)
|
||||
CXN = (FBR, FCT)
|
||||
DHT = (XXQ, CHX)
|
||||
DML = (SPL, TBX)
|
||||
BTJ = (FDG, VRV)
|
||||
KVG = (TJJ, TRS)
|
||||
JPH = (CLC, DXZ)
|
||||
HXL = (PKS, CPT)
|
||||
RDB = (PKM, FLG)
|
||||
CTF = (NLX, SJQ)
|
||||
BMH = (GVP, NSQ)
|
||||
GTP = (NMG, PNN)
|
||||
KJL = (KSM, VTJ)
|
||||
SLR = (LKD, SCH)
|
||||
TJJ = (NKF, FGM)
|
||||
DPH = (HHT, NRB)
|
||||
PBN = (CLC, CLC)
|
||||
FFT = (DJK, QSF)
|
||||
RTL = (TBJ, MXH)
|
||||
PJD = (TDF, QHT)
|
||||
HTP = (BGK, NCC)
|
||||
MDL = (NXB, NGF)
|
||||
CGJ = (SBC, RMS)
|
||||
RTR = (LHK, DXT)
|
||||
MLR = (JNC, MNF)
|
||||
DXL = (RKN, GHC)
|
||||
QTS = (VFR, MDR)
|
||||
LLM = (KSK, BHN)
|
||||
FFJ = (HGD, HGD)
|
||||
PQX = (VRC, KXG)
|
||||
XFK = (QNM, TMC)
|
||||
FVD = (HTF, TKM)
|
||||
CSR = (XDN, DSJ)
|
||||
VPN = (DPH, FDK)
|
||||
TJN = (HGC, HJH)
|
||||
KSC = (SVX, SVX)
|
||||
TLH = (FSV, RNS)
|
||||
QTH = (DML, SNJ)
|
||||
VQJ = (SMR, KCL)
|
||||
GNP = (JRQ, GBR)
|
||||
TKB = (TLC, HNG)
|
||||
FBV = (BFM, RHM)
|
||||
DMS = (BTG, NXV)
|
||||
VDX = (BCM, RNG)
|
||||
MSN = (QTK, HHQ)
|
||||
TKM = (LSM, PBF)
|
||||
FSS = (MCN, FVB)
|
||||
DLA = (PHM, VQS)
|
||||
LXK = (KTT, TLB)
|
||||
JBV = (MMV, GPS)
|
||||
FFQ = (QJS, FBV)
|
||||
MXH = (RPP, LKF)
|
||||
RKN = (SPR, XKN)
|
||||
FDG = (RSC, QMH)
|
||||
NLL = (VKS, FPF)
|
||||
XDN = (JTN, GSQ)
|
||||
FLS = (JNL, XBR)
|
||||
MLA = (PTH, JCK)
|
||||
GTM = (FSS, CNP)
|
||||
NVV = (LLR, NLV)
|
||||
TBX = (VBH, NNV)
|
||||
HTG = (VDQ, GFH)
|
||||
VLQ = (HXR, QNQ)
|
||||
JSL = (MVC, DJM)
|
||||
BPX = (VVL, NJM)
|
||||
FBG = (FRG, TCF)
|
||||
PFS = (HMH, KFF)
|
||||
GPB = (DDH, RSM)
|
||||
JFB = (FXX, GXC)
|
||||
XJZ = (VQS, PHM)
|
||||
FRS = (QSF, DJK)
|
||||
NKP = (PDB, SGT)
|
||||
KSB = (CTF, XXX)
|
||||
DTL = (FMH, MNR)
|
||||
HSN = (PBN, JPH)
|
||||
JCQ = (XCB, DHT)
|
||||
GBR = (NKP, GHV)
|
||||
BKL = (CKM, XJX)
|
||||
JLH = (XGV, MXR)
|
||||
TBJ = (LKF, RPP)
|
||||
RSJ = (HVN, KKH)
|
||||
SVX = (BSN, BSN)
|
||||
GRV = (CHT, NMV)
|
||||
TKX = (RHT, SDS)
|
||||
MQK = (BGK, NCC)
|
||||
KLR = (DRJ, MVK)
|
||||
NCH = (BCX, VKF)
|
||||
NLX = (JLB, LJJ)
|
||||
VHQ = (MBH, QLV)
|
||||
QXR = (NCH, FRT)
|
||||
FQS = (VGJ, HFG)
|
||||
LCP = (SHN, FBG)
|
||||
NCX = (QHD, PBB)
|
||||
SXK = (HGD, ZZZ)
|
||||
RNR = (RTR, JXT)
|
||||
VQG = (FPN, DPN)
|
||||
RMJ = (HNN, CSR)
|
||||
KSL = (BCK, QQJ)
|
||||
HCK = (QMN, TKB)
|
||||
LBX = (HFD, XQH)
|
||||
MTL = (NCH, FRT)
|
||||
XHR = (KFL, TLM)
|
||||
LLH = (LFC, XSP)
|
||||
JRJ = (XXB, VVD)
|
||||
KGM = (FQS, KGC)
|
||||
SDT = (MNQ, GTN)
|
||||
GJQ = (KLG, DMS)
|
||||
RNG = (RNR, GHB)
|
||||
DCK = (TXL, GPD)
|
||||
DXJ = (DXP, VCX)
|
||||
SNP = (KSC, HKX)
|
||||
KRS = (BMQ, GBP)
|
||||
GPC = (RMQ, XLJ)
|
||||
CDB = (MXQ, XLM)
|
||||
NLV = (FGS, KNL)
|
||||
GNB = (HXR, QNQ)
|
||||
KFL = (PGT, LVQ)
|
||||
HQL = (QXR, MTL)
|
||||
BJR = (PBH, PHT)
|
||||
QTL = (LLR, NLV)
|
||||
SNB = (CRL, QTS)
|
||||
LDP = (PBN, PBN)
|
||||
DFJ = (FHJ, RBS)
|
||||
JJP = (XMJ, VVQ)
|
||||
GQC = (QRB, KQD)
|
||||
SFR = (DPC, TCV)
|
||||
MPB = (FSM, GGL)
|
||||
SXP = (QFP, GFQ)
|
||||
MNF = (DKG, FLS)
|
||||
KLG = (NXV, BTG)
|
||||
TVH = (JFB, PJJ)
|
||||
SHJ = (SFX, TMT)
|
||||
RHF = (SRD, KBV)
|
||||
XBR = (NQQ, HFF)
|
||||
PBD = (RVJ, TXC)
|
||||
XXQ = (KSL, DDL)
|
||||
FTP = (XNF, XFK)
|
||||
HBC = (JTF, LLH)
|
||||
BTG = (HDB, VMT)
|
||||
KFX = (DMH, GBM)
|
||||
SGH = (MLK, TKF)
|
||||
CVS = (GBP, BMQ)
|
||||
DDL = (BCK, QQJ)
|
||||
PKM = (QNV, DPJ)
|
||||
QSR = (KJL, PNS)
|
||||
KPD = (PCT, MCP)
|
||||
BHH = (LVC, LVC)
|
||||
MDR = (HTG, SFD)
|
||||
HKK = (DXL, HPD)
|
||||
SMD = (RCQ, NJD)
|
||||
XMJ = (MKM, NTN)
|
||||
CQS = (DNH, TLH)
|
||||
PBH = (HMF, DST)
|
||||
MKC = (CJH, JDQ)
|
||||
KLL = (FJB, PQX)
|
||||
CXP = (VGS, HFX)
|
||||
JPF = (STX, BXV)
|
||||
CRV = (RCQ, NJD)
|
||||
FDK = (NRB, HHT)
|
||||
BTT = (CRV, SMD)
|
||||
RHT = (JBV, JFM)
|
||||
MXR = (FTV, CMV)
|
||||
DBL = (DJR, VQJ)
|
||||
CHX = (DDL, KSL)
|
||||
JKX = (VDX, NGH)
|
||||
MQA = (HTF, TKM)
|
||||
DJQ = (DLT, SBS)
|
||||
VFR = (SFD, HTG)
|
||||
NMN = (KPF, GTB)
|
||||
JNK = (VNQ, TPT)
|
||||
KJH = (GTF, NCX)
|
||||
QLS = (GXF, SCK)
|
||||
NHR = (PNQ, RGQ)
|
||||
FPF = (NBM, NQF)
|
||||
BKP = (KLL, TDJ)
|
||||
SBC = (TTF, SSS)
|
||||
XMN = (GTN, MNQ)
|
||||
PBB = (RRT, BPK)
|
||||
XVS = (GBM, DMH)
|
||||
HFX = (MPN, JLH)
|
||||
KDS = (TXG, DBT)
|
||||
DDN = (GDD, DFJ)
|
||||
SSS = (CST, VVF)
|
||||
NGH = (RNG, BCM)
|
||||
HNG = (HBC, FRC)
|
||||
CND = (RCH, RDD)
|
||||
HFD = (NHR, RDV)
|
||||
FRC = (JTF, LLH)
|
||||
TBH = (KDS, CNQ)
|
||||
QNQ = (TFB, KGM)
|
||||
SMT = (MBK, TJN)
|
||||
NGF = (BPV, JNR)
|
||||
XLM = (XVP, QCK)
|
||||
JLB = (SNF, DTL)
|
||||
NXV = (HDB, VMT)
|
||||
VSD = (TMD, VCL)
|
||||
TMT = (GHG, PVG)
|
||||
NNV = (JKX, SKG)
|
||||
HFB = (QQK, BKP)
|
||||
BLD = (SMK, BTJ)
|
||||
JGH = (TKB, QMN)
|
||||
XXX = (NLX, SJQ)
|
||||
LQH = (VLD, LCP)
|
||||
KRM = (BXV, STX)
|
||||
HVN = (FTH, QBL)
|
||||
QXM = (KLG, DMS)
|
||||
DBR = (LLM, NNQ)
|
||||
MVP = (CJH, JDQ)
|
||||
FBR = (MBQ, VPN)
|
||||
SFP = (HRD, SGC)
|
||||
HGD = (SQV, VLV)
|
||||
CJH = (JNK, DXR)
|
||||
DJM = (XSQ, GTP)
|
||||
KXG = (RTK, RKV)
|
||||
HTF = (LSM, PBF)
|
||||
FXX = (MSX, FGG)
|
||||
MFF = (VSC, QCP)
|
||||
TMH = (HQL, GSJ)
|
||||
KBB = (CHN, FSF)
|
||||
XTV = (SBH, SGR)
|
||||
MFH = (JGH, HCK)
|
||||
SGC = (JCR, PMQ)
|
||||
TRQ = (LVM, FFQ)
|
||||
VCL = (DXK, RBD)
|
||||
QSD = (VQF, JCQ)
|
||||
FQR = (FFJ, SXK)
|
||||
KQD = (KDT, JSL)
|
||||
XLJ = (DCG, MPM)
|
||||
FXL = (TFF, SSP)
|
||||
RRN = (DBL, GTL)
|
||||
CKM = (HTM, HHG)
|
||||
VLP = (MGC, PMF)
|
||||
KPQ = (MDL, VFB)
|
||||
XQH = (RDV, NHR)
|
||||
JRN = (MQK, HTP)
|
||||
JMH = (RCH, RDD)
|
||||
JRV = (SNB, MHK)
|
||||
QCP = (DRN, SFR)
|
||||
LLR = (KNL, FGS)
|
||||
NMV = (DLJ, DJQ)
|
||||
KBV = (GQC, PRB)
|
||||
JXC = (FFJ, FFJ)
|
||||
LFS = (MHB, VXT)
|
||||
DST = (XHR, PCS)
|
||||
SNJ = (TBX, SPL)
|
||||
KND = (FDH, CCG)
|
||||
CMT = (KPK, RMJ)
|
||||
HHG = (PFM, LVD)
|
||||
RPP = (MBN, TTD)
|
||||
MBK = (HJH, HGC)
|
||||
NQF = (JPF, KRM)
|
||||
FPN = (BFS, RVB)
|
||||
GFQ = (RTL, XBP)
|
||||
SCH = (NGK, SQP)
|
||||
VFX = (THG, LCV)
|
||||
CTG = (TMT, SFX)
|
||||
PGT = (CMT, RFB)
|
||||
RLB = (TFF, SSP)
|
||||
STD = (SJT, TFZ)
|
||||
VMM = (FPF, VKS)
|
||||
SFX = (GHG, PVG)
|
||||
BXV = (CGJ, PGK)
|
||||
FBT = (TBM, RHF)
|
||||
LJJ = (SNF, DTL)
|
||||
LKF = (MBN, TTD)
|
||||
QNV = (KRC, VMF)
|
||||
VGS = (MPN, JLH)
|
||||
MKM = (JJD, BKL)
|
||||
HKX = (SVX, RKF)
|
||||
MSL = (CRV, SMD)
|
||||
RHM = (CHQ, XXG)
|
||||
FRP = (MSF, MSF)
|
||||
VCV = (VSC, QCP)
|
||||
FMH = (VXR, GDS)
|
||||
FLR = (VGS, HFX)
|
||||
GHV = (PDB, SGT)
|
||||
FHQ = (MRD, JRG)
|
||||
HJF = (RDB, NTD)
|
||||
MSM = (FBR, FCT)
|
||||
GHB = (JXT, RTR)
|
||||
BMQ = (MFH, GTR)
|
||||
MCP = (VNP, SJH)
|
||||
SRD = (PRB, GQC)
|
||||
DXR = (TPT, VNQ)
|
||||
RFB = (KPK, RMJ)
|
||||
GSJ = (MTL, QXR)
|
||||
FHJ = (PGN, GNH)
|
||||
LCQ = (DBR, HFQ)
|
||||
GBM = (PDP, QSD)
|
||||
TPT = (JHF, MSN)
|
||||
MVV = (CNP, FSS)
|
||||
KXD = (LQH, DKR)
|
||||
PXV = (QXM, GJQ)
|
||||
BHN = (KPQ, CPV)
|
||||
SBS = (RRN, SDV)
|
||||
LHX = (SLR, DRD)
|
||||
TBM = (KBV, SRD)
|
||||
DXK = (PLP, FGX)
|
||||
NKD = (QFP, GFQ)
|
||||
PVG = (MCL, MPB)
|
||||
TTF = (VVF, CST)
|
||||
PDP = (VQF, JCQ)
|
||||
MSX = (NRD, SNP)
|
||||
CMV = (RSV, DCK)
|
||||
PMF = (NLT, MGS)
|
||||
MSF = (SJT, SJT)
|
||||
NTC = (DKR, LQH)
|
||||
GNH = (VHV, FBD)
|
||||
GSD = (VQG, VXS)
|
||||
VBH = (JKX, SKG)
|
||||
GTR = (JGH, HCK)
|
||||
SSL = (MHB, VXT)
|
||||
NLG = (NTS, DNB)
|
||||
JRQ = (NKP, GHV)
|
||||
MLK = (MFF, VCV)
|
||||
BLF = (HRD, SGC)
|
||||
BGK = (HJF, LNR)
|
||||
VQF = (XCB, DHT)
|
||||
GVP = (QKK, KND)
|
||||
FTD = (MXQ, XLM)
|
||||
JST = (JFC, KVG)
|
||||
JFC = (TJJ, TRS)
|
||||
MMD = (DDH, RSM)
|
||||
SBH = (TKX, VQV)
|
||||
PDH = (CVS, KRS)
|
||||
NRH = (CHN, FSF)
|
||||
MRD = (JCX, DXJ)
|
||||
KGC = (VGJ, HFG)
|
||||
RRB = (FFT, FRS)
|
||||
KQR = (GSJ, HQL)
|
||||
FSV = (XVS, KFX)
|
||||
DBC = (PSR, QXX)
|
||||
GMR = (KKH, HVN)
|
||||
CLG = (CLL, PXZ)
|
||||
JNL = (HFF, NQQ)
|
||||
JCR = (KBB, NRH)
|
||||
FTV = (DCK, RSV)
|
||||
DPC = (FHQ, GMQ)
|
||||
MVC = (XSQ, GTP)
|
||||
KXK = (GMD, BJR)
|
||||
DPJ = (KRC, VMF)
|
||||
FTC = (GSX, KSB)
|
||||
TBK = (QKN, XJZ)
|
||||
VFG = (SHJ, CTG)
|
||||
VXT = (QLJ, VSX)
|
||||
MHB = (VSX, QLJ)
|
||||
MMV = (TPF, FXQ)
|
||||
QCN = (DNH, TLH)
|
||||
KPK = (CSR, HNN)
|
||||
RDV = (PNQ, RGQ)
|
||||
DCG = (KGS, NMN)
|
||||
FJB = (VRC, KXG)
|
||||
NTD = (PKM, FLG)
|
||||
DBT = (GPM, KJH)
|
||||
LLL = (HFB, DNR)
|
||||
SMR = (BPX, QLM)
|
||||
MGS = (HKK, KCD)
|
||||
HHT = (SCS, SGH)
|
||||
MVK = (CQL, XFH)
|
||||
GFH = (KBT, MHP)
|
||||
JNC = (FLS, DKG)
|
||||
QHD = (RRT, BPK)
|
||||
NTN = (BKL, JJD)
|
||||
VQS = (CNK, RJQ)
|
||||
KQH = (XQH, HFD)
|
||||
GGL = (DBC, GKF)
|
||||
QQK = (KLL, TDJ)
|
||||
LHK = (HGQ, FJP)
|
||||
RKV = (GVR, PLT)
|
||||
VKV = (TBM, RHF)
|
||||
MPN = (XGV, MXR)
|
||||
PHM = (RJQ, CNK)
|
||||
TPG = (BQG, BMH)
|
||||
CLL = (PTH, JCK)
|
||||
MXQ = (XVP, QCK)
|
||||
NXB = (BPV, JNR)
|
||||
GTN = (PFS, HGV)
|
||||
FRT = (VKF, BCX)
|
||||
GRX = (THD, KLR)
|
||||
VLV = (MVP, MKC)
|
||||
NJD = (QBX, XTV)
|
||||
VJV = (QXM, GJQ)
|
||||
KPF = (MFM, PMV)
|
||||
JCM = (TJN, MBK)
|
||||
HFG = (TVH, PCJ)
|
||||
HJH = (QNB, PDH)
|
||||
JTN = (JRJ, LGV)
|
||||
CHQ = (XFN, MLR)
|
||||
JNR = (TXN, KPD)
|
||||
BCM = (RNR, GHB)
|
||||
PCS = (TLM, KFL)
|
||||
DXP = (QTL, NVV)
|
||||
KJF = (NTC, KXD)
|
||||
DLT = (RRN, SDV)
|
||||
QXN = (TBH, SQN)
|
||||
TMC = (FBT, VKV)
|
||||
PJJ = (GXC, FXX)
|
||||
KXH = (KSB, GSX)
|
||||
GDS = (XCS, GRX)
|
||||
BQG = (GVP, NSQ)
|
||||
XNF = (TMC, QNM)
|
||||
RFM = (CHT, NMV)
|
||||
JDQ = (JNK, DXR)
|
||||
LKP = (MSF, STD)
|
||||
TFB = (FQS, KGC)
|
||||
DNR = (BKP, QQK)
|
||||
FGX = (FPT, QSR)
|
||||
HXR = (KGM, TFB)
|
||||
XKK = (NTC, KXD)
|
||||
FDH = (JDT, PJD)
|
||||
FTH = (PRF, LXK)
|
||||
TCF = (GXP, QLS)
|
||||
TXN = (PCT, MCP)
|
||||
TPF = (LLL, JMX)
|
||||
LPV = (LVM, FFQ)
|
||||
HXF = (FXL, RLB)
|
||||
HGV = (KFF, HMH)
|
||||
MCN = (BLD, NPF)
|
||||
SMP = (BTT, MSL)
|
||||
LVM = (FBV, QJS)
|
||||
TCV = (GMQ, FHQ)
|
||||
FLG = (DPJ, QNV)
|
||||
PTH = (LFS, SSL)
|
||||
SQS = (SHJ, CTG)
|
||||
GBP = (MFH, GTR)
|
||||
QCK = (LDP, HSN)
|
||||
JCK = (LFS, SSL)
|
||||
TNL = (LVC, CLG)
|
||||
GKF = (QXX, PSR)
|
||||
PCJ = (PJJ, JFB)
|
||||
MBH = (DXH, HXF)
|
||||
PLP = (FPT, QSR)
|
||||
VXQ = (JRQ, GBR)
|
||||
DDH = (KSG, SMP)
|
||||
PKS = (TKR, VSD)
|
||||
JRT = (CXP, FLR)
|
||||
HMH = (SQS, VFG)
|
||||
DNB = (JRT, BRM)
|
||||
BRB = (DFJ, GDD)
|
||||
PSR = (SFP, BLF)
|
||||
KSK = (KPQ, CPV)
|
||||
QXX = (BLF, SFP)
|
||||
SSP = (GMR, RSJ)
|
||||
VMF = (DGM, XCR)
|
||||
MNQ = (PFS, HGV)
|
||||
HSR = (VXQ, GNP)
|
||||
KSG = (MSL, BTT)
|
||||
VRV = (RSC, QMH)
|
||||
XXG = (MLR, XFN)
|
||||
RVB = (JRV, RPL)
|
||||
KDT = (MVC, DJM)
|
||||
SQN = (CNQ, KDS)
|
||||
BPV = (TXN, KPD)
|
||||
SJT = (PBD, NQT)
|
||||
LCV = (FRP, LKP)
|
||||
CNQ = (TXG, DBT)
|
||||
GPD = (FTP, XSX)
|
||||
CHN = (SMT, JCM)
|
||||
XGT = (MSM, CXN)
|
||||
TFF = (GMR, RSJ)
|
||||
QKK = (FDH, CCG)
|
||||
CHT = (DLJ, DJQ)
|
||||
BRM = (CXP, FLR)
|
||||
KFF = (VFG, SQS)
|
||||
FGS = (KVF, JRN)
|
||||
SFD = (GFH, VDQ)
|
||||
RMQ = (MPM, DCG)
|
||||
AAA = (SQV, VLV)
|
||||
JJD = (XJX, CKM)
|
||||
VVD = (HXL, VKG)
|
||||
SCF = (VLP, SST)
|
||||
RKF = (BSN, TBK)
|
||||
LVQ = (CMT, RFB)
|
||||
SCK = (SCF, SLN)
|
||||
TXG = (GPM, KJH)
|
||||
DXZ = (NKH, THS)
|
||||
HMF = (PCS, XHR)
|
||||
KKH = (QBL, FTH)
|
||||
THS = (PMD, BDV)
|
||||
FCT = (MBQ, VPN)
|
||||
VVQ = (MKM, NTN)
|
||||
QNM = (VKV, FBT)
|
||||
LTL = (XMJ, VVQ)
|
||||
TDF = (QTH, TMR)
|
||||
VNQ = (JHF, MSN)
|
||||
KCL = (QLM, BPX)
|
||||
RMS = (TTF, SSS)
|
||||
HGC = (QNB, PDH)
|
||||
JTF = (LFC, XSP)
|
||||
PMV = (DDN, BRB)
|
||||
VTJ = (CPQ, LHX)
|
||||
NNQ = (BHN, KSK)
|
||||
NRF = (VTS, MRG)
|
||||
QNB = (KRS, CVS)
|
||||
RCQ = (QBX, XTV)
|
||||
MCL = (FSM, GGL)
|
||||
NTS = (JRT, BRM)
|
||||
QQJ = (NRF, SDX)
|
||||
QFP = (XBP, RTL)
|
||||
DPN = (BFS, RVB)
|
||||
XCR = (HDV, GSD)
|
||||
SGT = (BHH, TNL)
|
||||
JGA = (PBD, NQT)
|
||||
LSM = (XGT, MSG)
|
||||
PLT = (FVD, QLZ)
|
||||
RSC = (MMD, GPB)
|
||||
DXH = (RLB, FXL)
|
||||
TMD = (DXK, RBD)
|
||||
QDS = (JFC, KVG)
|
||||
KCD = (DXL, HPD)
|
||||
GMD = (PHT, PBH)
|
||||
DLJ = (DLT, SBS)
|
||||
DJR = (SMR, KCL)
|
||||
SGR = (VQV, TKX)
|
||||
RBD = (FGX, PLP)
|
||||
SFJ = (GNP, VXQ)
|
||||
GXP = (SCK, GXF)
|
||||
QBX = (SBH, SGR)
|
171
8/src/main.rs
Normal file
171
8/src/main.rs
Normal file
@ -0,0 +1,171 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
|
||||
use lazy_regex::{lazy_regex, Lazy, Regex};
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Problem 1 solution: {}", problem1(get_input()));
|
||||
println!("Problem 2 solution: {}", problem2(get_input()));
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
const LINE_REGEX: Lazy<Regex> = lazy_regex!(r"([A-Z0-9]{3}) = \(([A-Z0-9]{3}), ([A-Z0-9]{3})\)");
|
||||
|
||||
enum Instruction {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
}
|
||||
|
||||
impl From<char> for Instruction {
|
||||
fn from(c: char) -> Self {
|
||||
match c {
|
||||
'L' => Self::LEFT,
|
||||
'R' => Self::RIGHT,
|
||||
_ => panic!("Invalid instruction"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Element {
|
||||
left: String,
|
||||
right: String,
|
||||
}
|
||||
|
||||
type Nodes = HashMap<String, Element>;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Map {
|
||||
instructions: Vec<char>,
|
||||
nodes: Nodes,
|
||||
}
|
||||
|
||||
fn parse_node(nodes: &mut Nodes, node: &str) {
|
||||
let matches = LINE_REGEX.captures(node).unwrap();
|
||||
|
||||
let node_id = matches.get(1).unwrap().as_str();
|
||||
let left = matches.get(2).unwrap().as_str();
|
||||
let right = matches.get(3).unwrap().as_str();
|
||||
|
||||
nodes.insert(
|
||||
node_id.to_string(),
|
||||
Element {
|
||||
left: left.to_string(),
|
||||
right: right.to_string(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
impl<T: BufRead> From<Lines<T>> for Map {
|
||||
fn from(mut lines: Lines<T>) -> Self {
|
||||
let instructions = lines.next().unwrap().unwrap().chars().collect();
|
||||
let mut nodes = HashMap::new();
|
||||
lines.next();
|
||||
for line in lines {
|
||||
parse_node(&mut nodes, line.unwrap().as_str());
|
||||
}
|
||||
|
||||
Self {
|
||||
instructions,
|
||||
nodes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let map = Map::from(input);
|
||||
|
||||
let mut count = 0;
|
||||
let mut cur_node = "AAA";
|
||||
for side in map.instructions.iter().cycle() {
|
||||
count += 1;
|
||||
cur_node = match side {
|
||||
'L' => &map.nodes[cur_node].left,
|
||||
'R' => &map.nodes[cur_node].right,
|
||||
_ => panic!("invalid instruction"),
|
||||
};
|
||||
if cur_node == "ZZZ" {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
fn node_cycle_length(map: &Map, node: &str) -> u64 {
|
||||
let mut count = 0;
|
||||
let mut cur_node = node;
|
||||
for side in map.instructions.iter().cycle() {
|
||||
count += 1;
|
||||
cur_node = match side {
|
||||
'L' => &map.nodes[cur_node].left,
|
||||
'R' => &map.nodes[cur_node].right,
|
||||
_ => panic!("invalid instruction"),
|
||||
};
|
||||
if cur_node.ends_with('Z') {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
let map = Map::from(input);
|
||||
|
||||
let starting_nodes: Vec<_> = map.nodes.keys().filter(|s| s.ends_with('A')).collect();
|
||||
|
||||
starting_nodes.iter().map(|n| node_cycle_length(&map, *n)).fold(1, |accum, elem| num::integer::lcm(accum, elem))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"RL
|
||||
|
||||
AAA = (BBB, CCC)
|
||||
BBB = (DDD, EEE)
|
||||
CCC = (ZZZ, GGG)
|
||||
DDD = (DDD, DDD)
|
||||
EEE = (EEE, EEE)
|
||||
GGG = (GGG, GGG)
|
||||
ZZZ = (ZZZ, ZZZ)";
|
||||
|
||||
const EXAMPLE2: &str = &"LR
|
||||
|
||||
11A = (11B, XXX)
|
||||
11B = (XXX, 11Z)
|
||||
11Z = (11B, XXX)
|
||||
22A = (22B, XXX)
|
||||
22B = (22C, 22C)
|
||||
22C = (22Z, 22Z)
|
||||
22Z = (22B, 22B)
|
||||
XXX = (XXX, XXX)";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE2);
|
||||
assert_eq!(problem2(c.lines()), 6);
|
||||
}
|
||||
}
|
25
9/Cargo.lock
generated
Normal file
25
9/Cargo.lock
generated
Normal file
@ -0,0 +1,25 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day9"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
9
9/Cargo.toml
Normal file
9
9/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "day9"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.12.0"
|
200
9/input
Normal file
200
9/input
Normal file
@ -0,0 +1,200 @@
|
||||
27 49 92 176 327 586 1039 1879 3511 6711 12850 24194 44291 78456 134365 222769 358339 560653 855336 1275364 1862543
|
||||
15 25 36 57 117 286 706 1643 3584 7420 14791 28745 55012 104457 197703 373565 703877 1318603 2446886 4482001 8081143
|
||||
2 -1 -1 5 35 140 429 1101 2482 5067 9586 17171 29829 51664 91688 169675 327410 648943 1295161 2560233 4960367
|
||||
17 40 75 124 195 314 553 1083 2269 4852 10332 21799 45683 95258 197352 404834 819561 1634448 3210609 6218318 11892083
|
||||
12 28 47 77 148 320 690 1410 2740 5170 9648 17942 33138 60228 106667 182671 300884 474856 715541 1024739 1384064
|
||||
23 34 56 98 179 335 630 1192 2323 4773 10330 22981 51089 111404 236460 488303 984007 1942732 3771076 7214380 13617999
|
||||
-3 9 34 76 147 268 465 760 1157 1623 2064 2296 2011 738 -2201 -7740 -17123 -31963 -54306 -86700 -132269
|
||||
2 5 10 28 85 240 617 1451 3148 6359 12068 21694 37207 61258 97323 149861 224486 328153 469358 658352 907369
|
||||
2 8 19 26 30 54 164 525 1536 4108 10175 23584 51670 108250 219765 438340 869318 1727304 3445143 6876026 13651774
|
||||
-7 -3 9 42 129 327 726 1476 2850 5366 9996 18495 33888 61158 108183 186975 315279 518595 832691 1306680 2006739
|
||||
14 15 24 47 93 174 306 517 868 1493 2664 4887 9035 16524 29538 51309 86458 141403 224840 348303 526809
|
||||
-4 10 50 125 241 410 669 1105 1873 3186 5269 8334 12802 20376 37376 83418 211850 554706 1416484 3461131 8070127
|
||||
15 39 76 141 268 519 996 1856 3329 5739 9528 15283 23766 35947 53040 76542 108275 150431 205620 276921 367936
|
||||
24 38 52 61 53 10 -73 -138 42 1075 4356 12809 32195 73394 156469 318214 626801 1211053 2319569 4439602 8532786
|
||||
4 10 36 100 243 556 1233 2668 5629 11577 23262 45830 88824 169667 319485 592472 1080426 1934604 3397664 5849192 9869161
|
||||
-4 7 35 84 170 335 665 1316 2552 4799 8719 15308 26022 42935 68933 107948 165236 247703 364283 526372 748322
|
||||
-7 4 31 85 196 437 976 2172 4734 9973 20207 39455 74747 138831 256043 475047 895657 1722829 3370197 6649632 13104456
|
||||
16 32 58 111 217 410 745 1344 2499 4865 9805 20028 40853 82880 167863 341774 703534 1466538 3085872 6511449 13672565
|
||||
-5 -11 -19 -29 -41 -55 -71 -89 -109 -131 -155 -181 -209 -239 -271 -305 -341 -379 -419 -461 -505
|
||||
5 8 27 84 220 507 1078 2190 4332 8382 15798 28785 50293 83555 130708 190077 252623 301509 328232 401228 871348
|
||||
22 31 48 86 172 357 726 1417 2671 4960 9297 17952 36037 74887 159044 340266 724833 1525270 3155647 6402851 12728283
|
||||
13 26 37 45 58 113 311 867 2175 4888 10013 19021 33972 57655 93743 146963 223281 330102 476485 673373 933838
|
||||
12 37 78 151 286 522 901 1478 2383 3991 7275 14433 29888 61749 123771 237731 435898 762853 1275224 2036831 3105150
|
||||
8 21 55 123 237 408 646 960 1358 1847 2433 3121 3915 4818 5832 6958 8196 9545 11003 12567 14233
|
||||
3 19 44 71 100 149 259 491 916 1602 2605 3974 5783 8206 11654 16996 25889 41245 67866 113281 188822
|
||||
8 19 57 138 279 498 814 1247 1818 2549 3463 4584 5937 7548 9444 11653 14204 17127 20453 24214 28443
|
||||
9 4 5 23 80 223 554 1285 2829 5953 12058 23725 45786 87356 165507 311589 581617 1072658 1947779 3472867 6069516
|
||||
4 5 15 44 100 191 336 594 1120 2264 4761 10142 21660 46317 99077 211200 446093 928628 1898502 3807091 7495429
|
||||
15 29 52 91 168 327 635 1168 1976 3031 4181 5172 5894 7252 13693 39949 128019 387751 1089032 2861339 7106618
|
||||
4 27 76 163 300 499 772 1131 1588 2155 2844 3667 4636 5763 7060 8539 10212 12091 14188 16515 19084
|
||||
0 14 49 126 288 620 1290 2632 5308 10611 21004 41028 78750 147953 271285 484572 842448 1425348 2347731 3767130 5893244
|
||||
3 5 19 56 140 317 663 1291 2357 4065 6671 10486 15878 23273 33155 46065 62599 83405 109179 140660 178624
|
||||
15 24 50 100 174 275 432 735 1381 2730 5370 10190 18460 31917 52856 84225 129723 193900 282258 401352 558890
|
||||
3 10 28 67 151 337 751 1653 3540 7288 14321 26777 47618 80603 130010 199955 293113 408598 538706 664167 747489
|
||||
20 41 74 126 209 345 579 1013 1892 3804 8106 17770 38987 84130 177153 363333 726644 1420251 2718970 5107486 9425181
|
||||
15 27 39 51 63 75 87 99 111 123 135 147 159 171 183 195 207 219 231 243 255
|
||||
8 21 58 139 303 630 1288 2630 5374 10904 21738 42245 79828 147184 267217 484267 889432 1675307 3248534 6450147 12967977
|
||||
12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 102 108 114 120 126 132
|
||||
0 4 25 68 141 272 548 1191 2693 6050 13171 27607 55878 109928 211696 401582 753886 1404336 2597893 4769494 8676715
|
||||
4 -3 -3 13 61 170 394 850 1809 3869 8243 17220 34937 68787 132155 249818 468390 875793 1636077 3049219 5650065
|
||||
-7 -12 -10 18 99 265 551 994 1633 2510 3672 5174 7083 9483 12481 16214 20857 26632 33818 42762 53891
|
||||
10 11 22 61 152 325 616 1067 1726 2647 3890 5521 7612 10241 13492 17455 22226 27907 34606 42437 51520
|
||||
-3 8 30 79 184 392 785 1526 2963 5845 11749 23884 48524 97419 191628 367293 683905 1235574 2165672 3684933 6092624
|
||||
2 3 19 75 213 511 1120 2320 4588 8669 15665 27239 46225 78349 136635 251895 496486 1036135 2239379 4901527 10688757
|
||||
1 16 38 75 146 280 530 1025 2091 4478 9733 20768 42711 84231 159727 293088 524193 920024 1593528 2736001 4674548
|
||||
3 25 64 128 238 443 857 1732 3581 7365 14758 28504 52880 94279 161927 268748 432391 676433 1031772 1538224 2246338
|
||||
15 31 66 135 254 453 816 1572 3270 7080 15271 31926 63963 122540 224931 396969 676161 1115589 1788720 2795257 4268172
|
||||
27 52 87 132 187 252 327 412 507 612 727 852 987 1132 1287 1452 1627 1812 2007 2212 2427
|
||||
6 4 2 0 -2 -4 -6 -8 -10 -12 -14 -16 -18 -20 -22 -24 -26 -28 -30 -32 -34
|
||||
4 11 20 44 117 313 790 1867 4137 8611 16871 31171 54336 89114 136235 189681 226470 186864 -59204 -757963 -2305449
|
||||
4 11 27 57 125 292 679 1491 3030 5674 9787 15514 22407 28825 31055 22114 -9784 -83075 -224933 -473457 -879727
|
||||
13 17 21 35 75 166 351 719 1485 3189 7136 16294 37055 82679 180193 384661 809354 1689777 3517915 7317730 15196654
|
||||
10 17 24 31 38 45 52 59 66 73 80 87 94 101 108 115 122 129 136 143 150
|
||||
27 49 91 159 267 461 851 1657 3290 6505 12672 24205 45163 81989 144294 245595 404241 646129 1014881 1605299 2658415
|
||||
19 34 60 116 232 449 819 1405 2281 3532 5254 7554 10550 14371 19157 25059 32239 40870 51136 63232 77364
|
||||
18 24 42 87 174 318 534 837 1242 1764 2418 3219 4182 5322 6654 8193 9954 11952 14202 16719 19518
|
||||
6 29 59 90 126 189 331 657 1366 2817 5627 10808 19950 35457 60843 101095 163110 256213 392763 588854 865118
|
||||
24 38 63 112 208 396 772 1544 3141 6387 12773 24924 47533 89430 168250 320635 623454 1235720 2477499 4972172 9893262
|
||||
20 31 47 90 193 406 812 1566 2988 5773 11448 23343 48599 102174 214505 445531 909284 1815331 3536133 6713024 12418165
|
||||
2 8 15 29 71 183 441 988 2108 4377 8967 18275 37245 76104 155813 318424 645830 1292206 2537887 4875649 9144499
|
||||
12 27 60 123 244 489 1000 2064 4242 8598 17076 33085 62395 114591 205730 363815 640895 1140372 2078175 3917166 7655393
|
||||
18 41 85 154 264 458 825 1540 2955 5784 11438 22579 43975 83751 155144 278883 486328 823515 1356267 2176544 3410218
|
||||
25 47 94 176 295 447 637 917 1470 2781 5959 13315 29395 62880 130203 262551 519331 1013463 1957376 3743766 7082563
|
||||
12 36 78 153 285 506 857 1391 2178 3312 4920 7173 10299 14598 20459 28379 38984 53052 71538 95601 126633
|
||||
-9 -10 -9 -9 -1 49 226 731 2030 5162 12340 28097 61446 129887 266659 533459 1041993 1989246 3713317 6779115 12106201
|
||||
20 29 35 31 19 21 90 321 862 1925 3797 6851 11557 18493 28356 41973 60312 84493 115799 155687 205799
|
||||
-6 -3 11 42 98 202 434 1017 2457 5737 12550 25536 48463 86262 144791 230163 347428 498349 677957 869510 1037416
|
||||
4 7 5 -2 -13 -16 32 239 835 2267 5358 11580 23540 45868 86847 161361 296086 538343 970707 1734362 3065353
|
||||
23 34 45 56 67 78 89 100 111 122 133 144 155 166 177 188 199 210 221 232 243
|
||||
15 24 53 118 232 398 608 856 1169 1659 2616 4730 9709 21946 52622 128909 313015 739022 1680219 3666426 7680242
|
||||
17 38 88 196 409 802 1506 2779 5162 9791 18983 37288 73326 142974 274971 521020 974399 1804584 3321362 6091664 11147623
|
||||
8 8 10 17 39 104 275 677 1544 3319 6903 14301 30250 66118 148768 339775 775365 1746373 3853149 8297308 17418410
|
||||
-3 2 15 47 120 283 651 1479 3282 7013 14320 27926 52219 94208 165102 282908 476627 792860 1305925 2132937 3455722
|
||||
16 26 41 60 86 138 269 592 1329 2920 6269 13283 28019 59072 124461 261459 545998 1130142 2312689 4668734 9281108
|
||||
-6 6 46 126 262 491 897 1643 3003 5392 9425 16132 27661 49173 93242 189001 399616 853530 1797416 3682042 7296424
|
||||
-4 -1 13 47 127 326 824 2022 4746 10587 22427 45208 87060 161160 289492 511743 907304 1648299 3121165 6190937 12747973
|
||||
17 31 61 134 285 567 1071 1956 3494 6140 10642 18211 30776 51354 84570 137367 219951 347021 539339 825700 1245367
|
||||
4 3 11 37 90 179 313 501 752 1075 1479 1973 2566 3267 4085 5029 6108 7331 8707 10245 11954
|
||||
19 46 84 140 224 358 596 1065 2064 4295 9340 20529 44357 92619 185525 356467 660393 1191126 2121031 3794357 6943216
|
||||
8 16 37 100 246 537 1085 2114 4078 7876 15236 29393 56278 106613 199710 370762 685812 1274056 2398767 4611270 9075822
|
||||
2 -4 -19 -38 -51 -33 87 495 1640 4543 11410 26772 59475 125979 255657 499296 943299 1735447 3136428 5630823 10173850
|
||||
13 27 38 49 83 210 581 1472 3345 6937 13400 24555 43443 75674 132840 240992 460991 935765 1996936 4399387 9824965
|
||||
3 12 35 67 93 81 -25 -310 -889 -1902 -3501 -5827 -8975 -12945 -17577 -22468 -26869 -29560 -28701 -21657 -4795
|
||||
15 27 46 66 87 125 222 456 951 1887 3510 6142 10191 16161 24662 36420 52287 73251 100446 135162 178855
|
||||
14 23 39 75 169 398 911 2007 4290 8934 18087 35434 66925 121655 212859 358956 584542 921193 1407895 2090869 3022505
|
||||
15 36 81 166 312 559 986 1730 2993 5021 8033 12071 16734 20750 21330 13237 -12509 -70382 -182663 -382436 -717404
|
||||
19 32 45 58 71 84 97 110 123 136 149 162 175 188 201 214 227 240 253 266 279
|
||||
-2 5 22 60 151 373 887 1980 4103 7888 14123 23659 37218 55066 76510 99173 117996 123911 102124 29942 -125927
|
||||
9 12 22 34 39 22 -29 -77 87 1096 4442 13136 32617 71938 145339 274569 492877 852644 1440422 2405998 4016403
|
||||
-9 -6 6 35 100 239 526 1098 2199 4271 8176 15743 31038 63112 131591 277503 583471 1210275 2461445 4894923 9512306
|
||||
12 23 55 123 242 427 693 1055 1528 2127 2867 3763 4830 6083 7537 9207 11108 13255 15663 18347 21322
|
||||
11 14 21 26 25 31 109 449 1515 4352 11208 26742 60269 129816 269400 542212 1064843 2052166 3900239 7337374 13693713
|
||||
10 31 73 150 276 476 823 1514 2996 6142 12452 24210 44460 76567 122998 182788 246942 290761 261763 61494 -480916
|
||||
-4 -8 -10 -5 30 161 548 1551 3942 9304 20736 44029 89532 174989 329698 600421 1059560 1816208 3030786 4934087 7851666
|
||||
-4 3 20 47 84 131 188 255 332 419 516 623 740 867 1004 1151 1308 1475 1652 1839 2036
|
||||
8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88
|
||||
21 30 36 46 86 222 598 1499 3452 7392 14956 29058 55103 103623 195940 375980 734087 1453470 2898156 5775242 11427276
|
||||
-6 -9 -4 16 58 129 236 386 586 843 1164 1556 2026 2581 3228 3974 4826 5791 6876 8088 9434
|
||||
8 13 20 29 40 53 68 85 104 125 148 173 200 229 260 293 328 365 404 445 488
|
||||
19 26 32 48 96 211 458 978 2082 4425 9321 19308 39132 77369 148902 278349 504201 882744 1489634 2415052 3745420
|
||||
10 16 24 40 81 183 409 857 1668 3034 5206 8502 13315 20121 29487 42079 58670 80148 107524 141940 184677
|
||||
21 26 30 39 59 99 190 425 1023 2422 5411 11315 22256 41568 74658 131212 231061 418918 798584 1606547 3360157
|
||||
9 8 8 22 86 266 662 1403 2625 4431 6867 10055 14884 25203 53477 133622 347577 876546 2094306 4729204 10134266
|
||||
-1 -2 8 32 73 143 280 580 1265 2834 6384 14244 31139 66195 136212 270772 519915 965310 1736072 3030632 5146357
|
||||
-2 -2 13 54 132 258 443 698 1034 1462 1993 2638 3408 4314 5367 6578 7958 9518 11269 13222 15388
|
||||
-2 6 37 114 269 538 965 1638 2793 5036 9744 19705 40030 79298 150754 273141 470376 768738 1189479 1733748 2355379
|
||||
16 23 24 15 6 48 281 1011 2839 6897 15303 32048 64706 127665 248103 476869 908233 1716234 3223529 6036316 11315929
|
||||
19 32 68 142 265 447 721 1214 2309 4976 11411 26234 58716 126943 265692 541495 1081721 2131187 4163142 8097743 15731633
|
||||
1 -3 -6 -2 22 89 251 650 1660 4159 9982 22608 48171 97033 186547 346470 630043 1136417 2054362 3743666 6880068
|
||||
24 47 92 170 291 461 690 1024 1630 2995 6347 14470 33172 73795 157408 321954 635304 1221423 2316722 4394762 8439429
|
||||
23 48 86 149 276 546 1093 2138 4061 7537 13765 24853 44523 79524 142575 258436 475994 891197 1688199 3208496 6058065
|
||||
3 13 49 128 272 504 852 1373 2208 3676 6407 11496 20625 36039 60164 94507 137265 178775 193541 127056 -125026
|
||||
4 -2 -11 -25 -36 3 218 875 2497 6123 13899 30391 65368 139404 294608 614273 1257478 2518044 4922297 9387695 17475856
|
||||
5 19 49 109 219 403 687 1103 1706 2616 4111 6822 12116 22794 44271 86434 166379 312193 567853 999139 1700177
|
||||
21 50 107 220 438 835 1512 2597 4243 6624 9929 14354 20092 27321 36190 46803 59201 73342 89079 106136 124082
|
||||
27 51 101 202 395 740 1313 2194 3454 5171 7538 11170 17772 31396 60592 121846 244797 479835 908803 1659658 2926089
|
||||
17 37 67 109 166 250 412 817 1900 4669 11281 26120 57765 122464 250040 493560 944611 1756661 3179751 5610679 9663912
|
||||
13 15 16 16 15 13 10 6 1 -5 -12 -20 -29 -39 -50 -62 -75 -89 -104 -120 -137
|
||||
12 13 11 -2 -39 -104 -149 24 963 3946 11669 29464 67455 144426 294890 582251 1123729 2138238 4039298 7616181 14386452
|
||||
7 20 51 104 183 292 435 616 839 1108 1427 1800 2231 2724 3283 3912 4615 5396 6259 7208 8247
|
||||
5 5 8 19 51 134 329 746 1571 3135 6123 12145 25114 54288 120647 269980 599712 1314292 2840161 6063874 12820008
|
||||
12 15 13 7 0 -3 5 33 92 195 357 595 928 1377 1965 2717 3660 4823 6237 7935 9952
|
||||
1 8 16 31 81 244 689 1737 3973 8477 17295 34347 67092 129523 247677 470351 891245 1696557 3268454 6407922 12805039
|
||||
9 33 76 143 237 360 525 789 1317 2487 5046 10327 20537 39126 71247 124317 208689 338445 532320 814767 1217173
|
||||
11 31 64 110 169 241 326 424 535 659 796 946 1109 1285 1474 1676 1891 2119 2360 2614 2881
|
||||
26 42 70 127 236 435 800 1487 2809 5398 10572 21146 43107 88829 182848 371662 739580 1433330 2698962 4935561 8771430
|
||||
2 11 40 93 179 314 517 803 1177 1632 2152 2725 3398 4496 7371 16631 46060 132925 369880 971301 2402941
|
||||
5 15 28 44 63 85 110 138 169 203 240 280 323 369 418 470 525 583 644 708 775
|
||||
12 24 48 106 232 475 909 1662 2974 5293 9422 16753 29700 52649 94250 173043 330936 664202 1391576 2997148 6517328
|
||||
-1 17 59 136 265 479 854 1563 2960 5693 10849 20148 36241 63285 108309 184739 321329 583473 1120691 2265768 4730029
|
||||
2 -3 -5 14 91 282 664 1350 2548 4733 9060 18229 38123 80680 168633 342961 674142 1278589 2341985 4151616 7140235
|
||||
11 32 67 124 226 434 878 1803 3653 7238 14067 27011 51650 99105 192160 378598 759877 1551137 3202487 6635077 13683300
|
||||
22 49 84 133 214 355 588 943 1457 2233 3620 6653 14027 32153 75410 174913 396773 880766 1923511 4158780 8947225
|
||||
15 33 73 148 287 553 1078 2128 4219 8323 16251 31416 60433 116531 226750 446724 890047 1784573 3576629 7117548 13987187
|
||||
8 16 40 102 243 527 1056 2021 3824 7316 14206 27706 53487 101031 185474 330045 569216 952688 1550348 2458342 3806419
|
||||
14 32 56 87 145 286 626 1379 2934 6028 12118 24115 47717 93666 181356 344335 638374 1152920 2026908 3470079 5791137
|
||||
16 30 47 82 166 351 715 1367 2452 4156 6711 10400 15562 22597 31971 44221 59960 79882 104767 135486 173006
|
||||
15 21 33 65 152 369 870 1969 4302 9132 18888 38064 74645 142274 263427 473922 829153 1412511 2346531 3807387 6043446
|
||||
2 11 34 82 177 374 809 1793 3980 8650 18179 36848 72337 138680 262338 494747 937838 1794641 3466872 6738086 13108833
|
||||
8 32 85 189 374 673 1107 1667 2323 3124 4498 7917 17159 40477 94074 207383 430762 846336 1582851 2835549 4892228
|
||||
23 44 84 148 239 358 504 674 863 1064 1268 1464 1639 1778 1864 1878 1799 1604 1268 764 63
|
||||
8 11 30 73 153 292 535 989 1912 3905 8328 18210 40229 88947 195693 426912 921729 1968565 4161259 8717037 18122990
|
||||
19 20 16 7 -7 -26 -50 -79 -113 -152 -196 -245 -299 -358 -422 -491 -565 -644 -728 -817 -911
|
||||
-1 5 18 47 118 279 616 1295 2650 5354 10743 21411 42250 82159 156668 291686 528445 929423 1584524 2615995 4179378
|
||||
1 4 5 4 1 -4 -11 -20 -31 -44 -59 -76 -95 -116 -139 -164 -191 -220 -251 -284 -319
|
||||
10 30 63 115 204 363 637 1086 1835 3268 6569 15003 36649 89801 213009 482818 1043768 2157242 4278403 8173867 15097050
|
||||
25 41 67 117 222 433 820 1480 2579 4477 8040 15359 31320 66885 145720 317282 682310 1442050 2992534 6103186 12250215
|
||||
12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 102 108 114 120 126 132
|
||||
15 22 40 80 159 300 532 890 1415 2154 3160 4492 6215 8400 11124 14470 18527 23390 29160 35944 43855
|
||||
8 7 11 41 134 350 790 1640 3278 6516 13097 26628 54204 109065 214728 411149 763596 1375053 2403127 4082595 6754906
|
||||
19 29 36 40 53 119 342 922 2199 4705 9224 16860 29113 47963 75962 116334 173083 251109 356332 495824 677949
|
||||
0 0 -5 -5 35 192 613 1574 3615 7833 16464 33946 68728 136175 263016 493891 900674 1595382 2747625 4607709 7536673
|
||||
-2 0 7 14 16 6 -27 -83 -90 254 1829 6796 19932 51036 119067 258967 532494 1044852 1969467 3583930 6320920
|
||||
26 35 52 99 221 492 1020 1960 3549 6182 10553 17890 30318 51389 86823 145509 240820 392301 627794 986069 1520035
|
||||
5 21 46 78 125 234 550 1426 3608 8527 18748 38671 75709 142525 261777 476692 874459 1636085 3137694 6146600 12183961
|
||||
-2 -6 -6 18 104 324 825 1919 4252 9083 18697 36969 70134 128019 226586 393988 684961 1212859 2215513 4180473 8066083
|
||||
9 3 0 17 89 288 750 1702 3476 6492 11187 17862 26414 35915 43995 45981 33739 -5839 -92766 -256377 -538305
|
||||
8 14 18 21 28 50 115 309 881 2459 6437 15606 35115 73861 146420 275644 496062 858236 1434236 2324411 3665646
|
||||
-7 -11 -6 15 60 157 387 931 2131 4565 9136 17175 30558 51837 84385 132555 201853 299125 432758 612895 851664
|
||||
10 19 24 25 22 15 4 -11 -30 -53 -80 -111 -146 -185 -228 -275 -326 -381 -440 -503 -570
|
||||
13 19 31 52 101 226 526 1205 2703 5983 13105 28309 60021 124633 253872 509555 1013313 2005639 3960067 7796758 15268381
|
||||
1 8 29 69 132 232 426 877 1954 4375 9398 19064 36495 66249 114733 190674 305647 474658 716779 1055831 1521110
|
||||
16 24 26 23 18 16 24 51 108 208 366 599 926 1368 1948 2691 3624 4776 6178 7863 9866
|
||||
2 9 16 23 30 37 44 51 58 65 72 79 86 93 100 107 114 121 128 135 142
|
||||
-6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26
|
||||
16 35 60 94 145 232 391 684 1223 2231 4173 8002 15578 30332 58262 109364 199618 353667 608346 1017238 1656455
|
||||
-2 3 31 105 258 541 1053 2022 3981 8098 16734 34318 68643 132702 247198 443877 769848 1293069 2109193 3349983 5193520
|
||||
-8 -13 -18 -23 -28 -33 -38 -43 -48 -53 -58 -63 -68 -73 -78 -83 -88 -93 -98 -103 -108
|
||||
10 30 63 126 257 536 1124 2334 4755 9470 18464 35449 67620 129460 250952 495036 993952 2023078 4146993 8500420 17313419
|
||||
-9 -12 -14 -15 -15 -14 -12 -9 -5 0 6 13 21 30 40 51 63 76 90 105 121
|
||||
-5 -8 -10 -4 22 91 247 575 1252 2676 5755 12487 27048 57780 120827 246847 493437 967924 1868360 3555370 6674502
|
||||
1 7 13 19 25 31 37 43 49 55 61 67 73 79 85 91 97 103 109 115 121
|
||||
10 12 19 46 131 355 869 1923 3896 7344 13120 22688 38891 67754 122697 234467 474563 1009589 2223578 4982855 11186148
|
||||
3 -1 7 43 125 273 509 857 1343 1995 2843 3919 5257 6893 8865 11213 13979 17207 20943 25235 30133
|
||||
13 24 36 47 70 147 361 848 1829 3712 7353 14609 29360 59215 118142 230266 435053 794032 1399090 2382195 3926146
|
||||
9 6 11 46 151 398 912 1911 3803 7420 14528 28829 57767 115566 228065 440074 826157 1505954 2665385 4585336 7679711
|
||||
16 39 76 127 192 287 472 902 1936 4380 10002 22541 49545 105547 217409 433311 838156 1580625 2921540 5320719 9591714
|
||||
0 3 21 71 173 355 678 1297 2575 5268 10799 21634 41766 77341 137657 237491 403773 694697 1250635 2419574 5045700
|
||||
6 13 17 26 67 205 584 1500 3516 7629 15499 29750 54353 95101 160186 260888 412386 634701 953781 1402738 2023247
|
||||
13 25 45 80 128 176 209 245 427 1232 3904 11298 29466 70580 158268 337300 691065 1372831 2660967 5054944 9439092
|
||||
12 27 56 109 217 450 952 2016 4237 8811 18102 36684 73186 143428 275536 517963 951618 1707611 2992452 5122887 8572903
|
||||
11 9 18 50 123 268 550 1128 2407 5389 12427 28744 65328 144230 308068 637127 1280826 2517520 4871558 9346510 17891302
|
||||
21 38 67 119 209 358 602 1007 1685 2817 4726 8115 14700 28634 59344 126700 269817 561276 1129161 2190075 4097255
|
||||
20 42 87 173 334 639 1220 2307 4268 7652 13233 22053 35462 55153 83190 122027 174516 243902 333803 448173 591246
|
||||
-8 -17 -31 -55 -87 -106 -57 174 807 2254 5266 11168 22214 42099 76670 134883 230058 381489 616471 972811 1501895
|
||||
0 7 34 95 211 424 819 1555 2919 5449 10239 19663 38964 79482 164782 341635 698754 1397451 2720024 5143775 9451177
|
||||
19 26 34 59 144 369 871 1896 3913 7829 15369 29767 57136 109398 210718 411416 816946 1645551 3337551 6752638 13509007
|
||||
17 28 54 109 207 362 588 899 1309 1832 2482 3273 4219 5334 6632 8127 9833 11764 13934 16357 19047
|
||||
17 24 43 87 168 300 509 860 1528 2974 6339 14232 32144 70737 149186 299524 571463 1036320 1787319 2931489 4565420
|
||||
0 8 33 87 192 392 779 1532 2965 5579 10114 17600 29411 47333 73666 111391 164446 238170 339991 480453 674698
|
||||
-10 -13 -4 36 137 338 676 1159 1720 2174 2272 2106 3430 13019 50131 161667 451022 1130269 2610728 5654808 11623123
|
||||
12 27 59 121 226 387 617 929 1336 1851 2487 3257 4174 5251 6501 7937 9572 11419 13491 15801 18362
|
||||
-6 5 43 135 328 690 1307 2277 3702 5679 8291 11599 15636 20404 25875 31997 38706 45945 53691 61991 71008
|
||||
-4 -10 -24 -54 -111 -209 -365 -599 -934 -1396 -2014 -2820 -3849 -5139 -6731 -8669 -11000 -13774 -17044 -20866 -25299
|
||||
14 13 10 15 48 152 421 1050 2418 5219 10660 20749 38700 69486 120575 202888 332022 529785 826094 1261291 1888936
|
||||
13 32 68 142 287 548 982 1658 2657 4072 6008 8582 11923 16172 21482 28018 35957 45488 56812 70142 85703
|
||||
-5 0 15 47 113 262 609 1386 3024 6296 12579 24342 46049 85805 158353 290736 533880 988511 1866498 3637488 7371468
|
||||
4 4 8 16 28 44 64 88 116 148 184 224 268 316 368 424 484 548 616 688 764
|
||||
3 5 9 15 23 33 45 59 75 93 113 135 159 185 213 243 275 309 345 383 423
|
||||
8 23 45 76 121 182 252 312 334 293 191 96 199 892 2870 7260 15780 30931 56225 96452 157989
|
115
9/src/main.rs
Normal file
115
9/src/main.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use itertools::Itertools;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
|
||||
fn get_input() -> InputIter {
|
||||
let f = File::open("input").unwrap();
|
||||
let br = BufReader::new(f);
|
||||
br.lines()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Problem 1 solution: {}", problem1(get_input()));
|
||||
println!("Problem 2 solution: {}", problem2(get_input()));
|
||||
}
|
||||
|
||||
// PARSE
|
||||
|
||||
#[derive(Debug)]
|
||||
struct History(Vec<Vec<i64>>);
|
||||
|
||||
impl From<&str> for History {
|
||||
fn from(s: &str) -> Self {
|
||||
let hist: Vec<i64> = s
|
||||
.split_whitespace()
|
||||
.map(|num| num.parse().unwrap())
|
||||
.collect();
|
||||
Self(vec![hist])
|
||||
}
|
||||
}
|
||||
|
||||
impl History {
|
||||
fn build_row(&mut self) {
|
||||
let last = self.0.last().unwrap();
|
||||
self.0
|
||||
.push(last.iter().tuple_windows().map(|(a, b)| b - a).collect())
|
||||
}
|
||||
|
||||
fn build(&mut self) {
|
||||
while !self.0.last().unwrap().iter().all(|x| *x == 0) {
|
||||
self.build_row();
|
||||
}
|
||||
}
|
||||
|
||||
fn extrapolate(&mut self) {
|
||||
self.build();
|
||||
self.0.last_mut().unwrap().push(0);
|
||||
for (lower, upper) in (0..self.0.len()).rev().tuple_windows() {
|
||||
let new_value = self.0[upper].last().unwrap() + self.0[lower].last().unwrap();
|
||||
self.0[upper].push(new_value);
|
||||
}
|
||||
}
|
||||
|
||||
fn extrapolate2(&mut self) {
|
||||
self.build();
|
||||
self.0.last_mut().unwrap().insert(0, 0);
|
||||
for (lower, upper) in (0..self.0.len()).rev().tuple_windows() {
|
||||
let new_value = self.0[upper].first().unwrap() - self.0[lower].first().unwrap();
|
||||
self.0[upper].insert(0, new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> i64 {
|
||||
let mut histories: Vec<History> = input.map(|s| History::from(s.unwrap().as_str())).collect();
|
||||
|
||||
for history in &mut histories {
|
||||
history.extrapolate();
|
||||
}
|
||||
|
||||
histories
|
||||
.iter()
|
||||
.map(|history| history.0.first().unwrap().last().unwrap())
|
||||
.sum()
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> i64 {
|
||||
let mut histories: Vec<History> = input.map(|s| History::from(s.unwrap().as_str())).collect();
|
||||
|
||||
for history in &mut histories {
|
||||
history.extrapolate2();
|
||||
}
|
||||
|
||||
histories
|
||||
.iter()
|
||||
.map(|history| history.0.first().unwrap().first().unwrap())
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"0 3 6 9 12 15
|
||||
1 3 6 10 15 21
|
||||
10 13 16 21 30 45";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 114);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 2);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::time::Instant;
|
||||
|
||||
// BOILERPLATE
|
||||
type InputIter = Lines<BufReader<File>>;
|
||||
@ -11,17 +12,44 @@ fn get_input() -> InputIter {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Problem 1 solution: {}", problem1(get_input()));
|
||||
println!("Problem 2 solution: {}", problem2(get_input()));
|
||||
let start = Instant::now();
|
||||
let ans1 = problem1(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||
|
||||
let start = Instant::now();
|
||||
let ans2 = problem2(get_input());
|
||||
let duration = start.elapsed();
|
||||
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||
}
|
||||
|
||||
// PROBLEM 1 solution
|
||||
|
||||
fn problem1(input: InputIter) -> u64 {
|
||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
// PROBLEM 2 solution
|
||||
fn problem2(input: InputIter) -> u64 {
|
||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
const EXAMPLE: &str = &"";
|
||||
|
||||
#[test]
|
||||
fn problem1_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem1(c.lines()), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn problem2_example() {
|
||||
let c = Cursor::new(EXAMPLE);
|
||||
assert_eq!(problem2(c.lines()), 0);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user