Compare commits

...

63 Commits

Author SHA1 Message Date
48c96ce7ea day24: cheat solution used for part 2 submission 2024-12-11 09:54:10 -08:00
342f4c1883 day25: problem 1 solution - cheated with dot 2023-12-24 22:33:20 -08:00
881d0b08ad day24: problem 1 solution 2023-12-23 22:54:21 -08:00
c1eb7761e3 day23: problem 2 solution 2023-12-23 02:54:07 -08:00
98456ed98d day23: problem 1 solution 2023-12-22 22:33:34 -08:00
d6d4c0d056 gitignore 2023-12-22 20:58:14 -08:00
3bb3b3d6b6 day22: cleanup & nice output 2023-12-22 04:19:58 -08:00
dd91259fe2 day22: problem 2 solution.
no help but annoyingly i misread the hint about low/high and didn't submit my *correct* answer for over an hour while I bug hunted!
2023-12-22 03:47:01 -08:00
8495969877 day22: problem 1 solution 2023-12-22 01:32:08 -08:00
190fc92842 day21: problem 2 solution
not proud of this one either, completely cheated and it does not get
exactly the correct error (it was off by one for my input), but the
quadratic solver on Wolfram Alpha was able to do it.
2023-12-21 03:17:11 -08:00
eb6c1f42cd day 21: problem 1 solution
another unsatisfying one where i needed a visual hint to grok what i
should be doing.

a bunch of graph building stuff that wasn't needed for the part 1
solution at all.
2023-12-21 00:34:08 -08:00
512b05f624 day20: problem 2 solution - needed a hint 2023-12-20 01:48:09 -08:00
877101f9a2 day20: problem 1 solution 2023-12-20 00:13:23 -08:00
cdfecf821c day19: refactoring and cleanup 2023-12-19 02:01:47 -08:00
2b921b5fb2 day19: problem 2 solution 2023-12-19 01:01:36 -08:00
a5dea64b32 day19: problem 1 solution 2023-12-18 22:06:03 -08:00
8200c1a8cf root: add .rustfmt.toml 2023-12-18 02:04:22 -08:00
8d178ddfc6 day18: formatting and cleanup 2023-12-18 02:03:48 -08:00
3bc073f9b8 day18: problem 2 solution 2023-12-18 01:54:31 -08:00
0a9fa8e32f day18: problem 1 solution 2023-12-17 23:04:56 -08:00
e65c17c8e6 day17: don't revisit the start position 2023-12-17 20:55:42 -08:00
3ee26cefe5 day17: super obvious code cleanups, more to do 2023-12-17 15:18:22 -08:00
9e37b2ce66 day17: add heatmap visualization of final path 2023-12-17 15:11:43 -08:00
d422c9b84e day17: problem 2 - an ugly mess but finally working 2023-12-17 05:57:30 -08:00
5efa9853ca day17: problem 1 solution - a messy one! 2023-12-17 04:38:35 -08:00
da25b73eca day16: use tail recursion unstead of passing mutable state 2023-12-16 11:07:39 -08:00
842def62dc day16: back to elegant recursion now that we track beams
problem 1 solution was busting the stack, so used an iterative approach,
but now that we track lit beams we can bail out early enough not to bust
the stack. performance is the same but it's much nicer.
2023-12-15 23:54:22 -08:00
427a0c766b day16: much cleaner, nicely factored solution, and much faster 2023-12-15 23:42:43 -08:00
332620db0f day16: problem 2 solution 2023-12-15 22:39:03 -08:00
a8ec929818 day16: problem 1 solution 2023-12-15 22:19:46 -08:00
f04078fbd7 boilerplate: remove unnecessary Duration import 2023-12-15 20:56:13 -08:00
498c96eaeb day5: reimplement in a sane, fast way 2023-12-15 18:10:29 -08:00
84bcbd550b day5: add timing 2023-12-15 18:09:49 -08:00
e12c0134b0 day15: functional hash implementation using fold() 2023-12-14 23:33:48 -08:00
eac460417c day15: problem 1 & 2 solutions 2023-12-14 22:07:49 -08:00
24c534ff88 day14: itertools is not used anymore 2023-12-14 15:43:11 -08:00
4f1f838d62 day14: simple Vec lookup is faster than HashMap since the cycle is short 2023-12-14 15:41:34 -08:00
ca3254e1e1 day14: translation-based minimal copy implementation 2023-12-14 14:19:58 -08:00
78fb884c03 day14: some silly and not super effective performance optimizations 2023-12-14 01:57:06 -08:00
7926475a56 day14: refactor and cleanup duplicate code 2023-12-14 00:06:24 -08:00
e062ef5078 day14 problem 2 solution 2023-12-13 23:29:03 -08:00
11a7837400 day14: problem 1 solution 2023-12-13 22:12:50 -08:00
5666aee5f2 day13: problem 2 solution 2023-12-12 22:20:54 -08:00
f12e99c1f4 day13: problem 1 solution 2023-12-12 22:05:32 -08:00
c797e874d5 boilerplate: add timing 2023-12-12 02:24:24 -08:00
a431c4b75f day12: problem 2 solution
what a doozy. iterative solution from part 1 totally untenable.
recursive solution a bit tricky, but still not fast enough for brute
force. had to implement memoization cache for reasonable runtime.
2023-12-12 02:20:53 -08:00
20e2a9f7be day12: problem 1 solution
Slow and inefficient but fast enough for a solve
2023-12-11 23:12:06 -08:00
96ea3c317d day11: problem 1 & problem 2 solutions 2023-12-10 22:34:39 -08:00
ebd1d0ff94 day10: problem 2 solution
slightly cheated for ideas on part 2. still a pretty ugly solution.
2023-12-10 00:02:29 -08:00
26f990840a day10: problem 1 solution 2023-12-09 23:24:58 -08:00
b84b0b04e2 day9: formatting 2023-12-08 21:41:30 -08:00
37b645c341 day9: problem 2 solution 2023-12-08 21:39:45 -08:00
d2718db633 day9: problem 1 solution 2023-12-08 21:29:19 -08:00
be0ed3e377 day8: problem 1 & 2 solutions 2023-12-07 22:07:07 -08:00
c8eb06a5ec boilerplate: add test boilerplate 2023-12-07 20:56:59 -08:00
9ab450d258 day7: problem 1 & 2 solutions
forgot to commit problem 1 only solution
2023-12-06 22:37:02 -08:00
9718b8ab04 day6: problem 2 solution 2023-12-06 18:15:36 -08:00
de6e826c31 day6: problem 1 solution 2023-12-06 18:07:15 -08:00
077f4ff8ee day5: problem 2 solution. parallelized! 2023-12-06 17:24:24 -08:00
0665e109af day5: performance: don't iterate to position just do arithemtic 2023-12-06 11:07:40 -08:00
6d1174e2db day5: problem 1 solution 2023-12-06 09:06:59 -08:00
25daf558e6 boilerplate: make generic over Lines type 2023-12-05 21:46:11 -08:00
db4a8b0d24 day4: Add tests 2023-12-05 21:45:49 -08:00
86 changed files with 15493 additions and 7 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
**/target **/target
input

1
.rustfmt.toml Normal file
View File

@ -0,0 +1 @@
max_width = 120

7
10/Cargo.lock generated Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,140 @@
............#..................#..........................................................#..........................#......................
.................................................................#...............#..............#...............#......................#....
...................................#.....................#..................#............................#...................#..............
#.....................#.....................#...............................................................................................
........................................................................................#............#......................................
.....#..............................................#.......................................................................................
.......................................#................................#..........#...........#......................................#.....
..................#...........#.............................................................................................................
.............................................#............#.................................................................................
.#............................................................................#..................................#..........................
............#......................#....................................................................#...................#.............#.
.......#............#....................#........#...................................#......................#..............................
...................................................................#................................#.......................................
..............................#.................................................................................................#...........
..#...........................................................................................#.......................#.....................
..............................................................................#.............................................................
.......................................#.........#............#...........................#................#..............................#.
........................................................#.............#.....................................................................
.....#..........................#....................................................................#....................#.................
....................#.......................#...................................#...............#...............#......................#....
...............#..................................................................................................................#.........
..#......................................................................#...................................................#..............
.................................................#............#.........................................#.............#.....................
....................................#.......................................................................................................
...........#..........................................................................#.....................................................
.................#..........................................................................................................................
.............................................#............................#....................................................#............
.........................#.......#..........................#...............................................................................
.......#............#....................................................................................................#..........#.......
...................................................................#................#...........................#...........................
..............#....................................#..........................#..............#..............................................
..#....................#....................................................................................#........#......................
.........................................................................#......................................................#...........
......................................#.........#...........................................................................................
..........#.................................................................................................................................
.....................#......................#...............#.................................................#.............................
...............................#...................................................#....................................#.................#.
.............................................................................................#..............................................
...................................................................#........................................................................
................#..........#.....................#..................................................................................#.......
...................................#............................................#..................#........................................
.....#.....................................................................#...............................#.....#..........................
............#.........................................................................................................#.....................
.....................#.............................#.......................................................................#................
..............................................................#...............................#..........................................#..
.....................................#.......#.................................................................#............................
...............#...................................................................#.....#..............................#...................
...#.....................#.........................................#......#...........................#.....................................
.........#......................................................................................#.............................#.............
..........................................................#.................................................................................
..................................#.......#...........................................#......................#......................#.......
.............................................................................#..............................................................
.....#...........................................#..................................................#....................#..................
............................................................................................................................................
............................................................................................................................................
.................#...................#........................#......#..................................#...................................
..........................#.........................#.....................................#......#.........................#................
..............................................#...........................#.....................................#...........................
#.....................#.................#............................................................................................#......
...............................#..........................#.....................................................................#...........
..........#.........................#.............................#...........#....................................#........................
.....................................................#......................................................................................
.............................................................................................#..............................................
............................................................................................................................................
...............#...........#..........#.....#..................#.......................#......................#.......#..............#......
........#...........#.............................#.....#...................................................................................
............................................................................................................................................
.#................................#.............................................#................................................#..........
............................................................................................................................................
..........................................................................#...............................................................#.
..............................#...............#......................................#........#.............#.........#.....................
...#................................................#.......................................................................................
............................................................................................................................................
.......................#...............#...........................................................#..........................#.............
.................................................#...........#......................................................#.......................
...........#............................................................................#...................................................
.....#..................................................#.....................................#.............#..............................#
..................#..........#..............................................#..........................#..............................#.....
....................................................#.......................................................................................
..#............................................................................................................#................#...........
.............................................................#........#..........#.....#....................................................
...........#..........#............#.......#...............................................................................#................
............................................................................................................................................
......................................................#..............................................#......................................
.........................#.....#...............................................#................................#................#..........
...#.......................................................................................................#...........................#....
........#...........................#....................................#...............#..................................................
..........................................#.......................#.........................................................................
............................................................#.............................................................#.................
...........................#...................................................................#.....................#......................
...............#.................#............#.............................................................................................
...#......#..........................................#..................................#...............#...................................
.................................................................#......................................................................#...
.......................#..................#...............#..................#..............................................................
.................................................#...................................#.............#............................#...........
................#...........................................................................................................................
...................................#.........................................................#........................#.............#.......
.............................................................#..........................#......................#............#..............#
...#..................#.............................#..........................#............................................................
........#......................................#............................................................................................
..............#............#...........#............................................................#.......................................
....................................................................#.......................#...............................................
.#....................................................................................#........................................#.......#....
...........#...................#............................................................................................................
.........................#..........#.......#.........#..................#..................................#...............................
................................................................#....................................................#......................
...#.............................................................................................#.....#....................................
.................................................#....................#.....................................................................
.......................#.........#..................................................#.......#...................#........#..................
........................................................................................................................................#...
...........#................................................#..............................................#................................
.....................................#..........................................................#...........................................
....#.......................................#....................................................................................#..........
...................#..............................................#.........#..........#.............#......................................
............................................................................................................................................
............................................................................................................................................
.............#.......................................#...............#......................#......................#...............#........
...............................................#............................................................................................
....#.................................#.......................................................................................#.............
............................#.................................................#......#.....................................................#
...................#..............#.......#...............#.....................................................#.........#.................
..................................................................#.....................................#...................................
...................................................#..............................#......#.......#..............................#...........
.......................................#.....................#..............#......................................#........................
.................#..........................................................................................................................
..............................................#.......#.................#.................................#.................................
.........#...............#.............................................................#.................................#.............#....
..#..............................#..................................#.......................................................................
...............................................................#...........#.......................................................#........
............................................................................................................................#...............
................#...........#............#.........#........................................................................................
........#.............#........................................................................................#...........................#
..........................................................#...............................#..............#...........................#......
...............................#................................................................#...........................................
..................#.............................................#.........#..........................................#......................
.....#................................................#.........................................................................#...........
............................................#.....................................#.........#...............................................
.......................................................................................................................................#....
#..........#.............#......#.................................#...................................#.....................................
.....................................#.........#.........................#.....#............................................................

211
11/src/main.rs Normal file
View 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
View 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
View File

@ -0,0 +1,8 @@
[package]
name = "day12"
version = "0.1.0"
edition = "2021"
[dependencies]
itertools = "0.12.0"
rayon = "1.8.0"

1000
12/input Normal file

File diff suppressed because it is too large Load Diff

219
12/src/main.rs Normal file
View 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
View 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
View 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]

1349
13/input Normal file

File diff suppressed because it is too large Load Diff

227
13/src/main.rs Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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]

1
15/input Normal file

File diff suppressed because one or more lines are too long

172
15/src/main.rs Normal file
View 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
View 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
View File

@ -0,0 +1,4 @@
[package]
name = "day16"
version = "0.1.0"
edition = "2021"

110
16/input Normal file
View File

@ -0,0 +1,110 @@
\.....................\.......................|..../......-.........../.|.....\.............|..........|..\...
.../...................\..................../...|.......|........||...................../...........\.........
././....|......./................\............|..\...........-....../............../|........-................
....\..\...........-/..|......|......\............|............../.................-........./...-...|.......\
..................................|.\.......|...../.........................-...../......\..|...............\.
.....\.............................................|../.\............../--.......................\............
|.......-.|........\.................\..............|........./....\.........|...................\-.-...|.....
....\........./....-.........................--.....\..../......................|.\......................\...-
\..-..../.....|..........\......................-|......|...................../...../........./...........-...
........................\.\|......../........../......................\.............|./../....................
.....\...................|.............................|......-........|.........-./.../.|....................
..-................./.........................................\..\........-..-........-.......\../............
-................-............................\................./..--................-............../.|.......
..-.....|.............|................./.......-.-........................-............-...........\.........
..........|..........................-...|..\...............................................\-....\...........
/................../..........|....\..-......................../....\...\..........-....../.........../.....\.
................\....-................-|.\...-...........-.....-........\..........................\..........
...................................\../..|.../../...........................\.........../.\-......|.........-.
/....|....|..........................\............./.....|/................./....-......................-.....
....-.............../.....|...........|../......\../.............../........................|............./...
......./..............|./../.................-.\.........../.....................|.........../........\.......
...................-...............\/.......|........|....................../.......................-/......\.
................\...../....-/......-.........-.....\/.\...............\....../...-....|......|.........\......
....-.........-.........................-......................../.......|...............................\....
......../..................|...../......\..\..-|-..../..............|......../............|.-.......-.........
......./............-..........-............................../.........................|\..-..-\.\......-..\.
.\-.....|......................-..\................/.-................|.\..............\..................|...
-..........................-............../.|.-......\......-..-...../......./................................
....|.................................................\....|..........\...................-......|........./..
................../...........-..............\......................................|.-........|..............
...-............|..............-...........-.\.......................|..|..../......................../.|....-
.......-..-......./...../.........-.......\.....-.../............-./......../.../............-.....|...|......
...............|.........../..........|/..........|..........-.-...../...../..|..........\.....-./.|./....|...
.........|......................\.|.....|......................-.-........|.............................-...|.
.-...|..\...-...............\..............\......./........-............/.-..\........../...../....-....\....
...........\.-.......|.......|....-.............|-.|........../..../...\....\............|.|..|\..............
.....................|.\....|......|../...\......|........................\......|.......-./..../.............
......................\--................................\.................|................-.................
-...............\...-.....................................-.\...../....\...........................|..........
.....|.......\.......................-/...\..-.........-..../\|..................\........-...................
..|........./....|..-./..\..\................-|..........\../......\...............\............\............|
......-................../.............|.............\................................-..\...../........-.....
....................../......../..\.-.........................|....\..|...\...../../.....|............../.....
...\................................/..............................\........|.........\.-............\........
/.................../................-...........-.|.............\.................................|.....-....
.|...-..|/./../.........-./.............................................../..........-.........-.|./..........
..../..................|......................|../..........\........-......../.........\...|.................
........./..................|..-..........|\............\......-..-..\...|....|.....................|....-....
.....|/....|........\.........-................../..........|............|...........-.....|......./......//..
..........\.|../...|........................\.........\.|......||....-...............\\.....|.|..............|
............-................|.....-....||......../.../.......................|..\...........\................
...............-..../......-..../.......|-.....-.....\..................................../..|................
/......-...............\/...././..................\..................\..........-......................|......
...................\.....\.................\...|.................-............/........-..............\./.....
.-.\....\........\........-../.-............../...../..-..|...................../.-.....\.....-........../..\.
|...|...............................|............../.............../....................|...../...............
....../....../...|..............-.-........-..|.../....................\|.....\......................|....../.
...\\.......|...|-............|..........-...........................................\/...../..-.-............
.........|.............|..|......\............\...............|......\......\.............\...\-.......\.....\
...........\..-.|.......|\..\..................-........\/...............................-....................
...\.................\..............................................\...............\.......-.../.............
..\.............\....---....................//.......................................|./.............../\.....
.\...........|..................................\........-......|.........\.................-........-........
..............-...............-.../....-........|.....-../......................./..../........../../--..\....
.........-......\......-.........../...\./.|.................\...................--..-........|..\......\....|
....../.........................................|...../........../..............\\...-/.......-......\..\.....
.........../...\.|..................../.\.................|......\.\..|.........../...../.....\.\...........|.
..../\..-...../.............................../..../............................-...-......\...........\......
..-..\.............................\...........|..........|.........|..........................-......./......
-..|.................-\.....\...............\/.....|...........................././...\......\.......\...-....
......\..............|..|..............-............../....................-....\\........\....|..............
|.............\....\./.....-|-....\.....\..............\/........-.|..|...........-..\......-..../.......|....
............................-.......................|........................../................|.............
/................|../............\/.....\/....-.....\......\...../|..\..........|............../..............
.|....../...../....................../..|.....................-................./...../-.........-............
......................\|........../......./..\........\.........-......../.........../.|/.......\.../.........
...............\......-|............\..\....../.........\.....|...|\............/............\.\..|.......\...
......|...........\....../....\./......./-....\../.......\...-...............\./...\.....-.......-..../.......
...|..|.............................\.....-.|........./......../......................-......./............\..
.....|........\.........|...-.-.........\..../....../..-.......-...............\..../.....-..../..............
........./.\/........................-..........\.....................|.......-..............\./.\............
..../................/................................|.....||..............\........-...............|........
....\./.........../\-.....-...\............//.\..............\...../................|.....\..-................
..../|........./............|.....................|......................-..|...............................\.
..................\............................\.......\.........-.............|...../.-.............-......|.
..............|.-...........................\.\./.......\........../...\................/....-................
.......|................/-............\............/...........-..../...........\......../...\.......\........
..............|..../......................-...........-..\.................................................-..
..............................-..-................-.......-.................-..........\.../...............|..
......-.........-........................./.....................\....|........................................
.....\........./.....-.................../................|...................|........................|......
........../.../........................./.|................-...........\...........-....|.....................
.....-.......\././/.......|..............|......../..\...........\.............................-......|../-.-.
........|-....-....................\.....|\...\/.....\........\......./..........|.\-..|......................
../...-...-...|...../............\.......................-..........\...\.....-...\...............|....../...|
............|..\....|..................\/...................../../....|...................|.............../...
.............-................./............|.......|............\....................................\.-.....
-...../|..............-......\..../..................|..\....-............................................\...
........|.........-........\................/....\..................../.|...................................|.
.....|................./.........-|\...-...................|....-................-......../...............|..-
.|.........|...........|...-.............................\............................|................\......
....|.....-......|......./.-.|...........\..-........|.........................-....-..-.....|................
........................................\.....................-.../........................../../..........|..
-................/....\.......//....-........................../.\.........-......./..|\..........\...........
-............................./......................................../-...........................\|........
........................................../-.....//......\......\...........\........|./....../.......--......
../..............-....../......../................../......./....-...........|../.......\.\.......-......./..\
..............-............../......|.........-...............|................................-..........\...
.....................\..........|..\......|...............................................-...................
...../..|.../.........|.../.......-...................................\.....................................|.

265
16/src/main.rs Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,131 @@
...................................................................................................................................
..............#...#........#...............#.#.......#....##...........#.#..#......#.....#.........#..##...........................
.#..##..##..#......#.#.#...##......###...##......#.#..#...................#.....#..........#..#................#...#..........#....
.....................#..#.......#.....##.........#.......................................#........#....#.#..........#.#......#.#...
......##...#.....#.......#...#..###..........#..........#......................#........#.............#.....#........#....#........
.................##.................#...#.........#................................#........#...........#............#........#....
..............#.#....#........##.....##..........#.............##.............#...#......#..##..........#.........#.....#...#..#...
..#....#.......#...##..#......#.........#.#..#....#.#..............#........#...#...#...............#.#.....#..#..##......#...#....
...#......##...##..#...#..........#...#..........#..............#...#..........#..#..#..#........#.#.#.#.#...........###...........
.#.#.#...#.#...##............................................#......................#...#......#......##.#.........................
.##.#.........#...#..................##...........#............#..................###...#...........#.................#....#.......
.....................#...#.#................#................#.#........................#...#...##....##....#.#...#.........#...#..
...#.......#...#.........................#.#..................#........##..........................#......##....##............#....
......................#.....................#...............#.......#.#...................#...............#...#........#.##......#.
............................#..........................#........#....#.##..#.......#.##..#...#.#..#...............#.#..#....#......
.......................................................#.#..#.#....#......................#............#....#..#.......#.........#.
.....##........#...............#.......#...............#.#..........##..#...................#................#..#...#.#....#...###.
....#.....................##................#.......#.......#...#.#...#...............#................#...............##..........
....#........#..#.......#.#.#........................#.#...........#.......#..#.........#....#.......#........#.#.#................
......###.....#..#...........#.....#..#..#........#......#.#........###.....##............#..#...........#.........................
.....#...........#...................#..#..........#..#...###.#.........#.##...............#..##..........#.........#..............
.#.........#....#............#.##..........................##.....#........#....#.............#.......#...#..............##.#......
.#..#...#.......#...#.......##.......#.#.............................#...#...#.#...........#...#.................#.........#.#.#...
...#....................#.....##..............#.................#.................#............#......#....#.......#.........#.....
.......#...#.............#.##...#.#...................#.....#..#........#................................#.............#..#...##...
...#.###..............#....#........................#......#...#.........#......#.#....................#........#...#...#.......#..
............#.#...#...........................#....###.###...#........#..#........#...................##.....###......#........#...
.....#...#................#.##..##..................#....#.........#............##...................##................#.....#.....
.#....#..............##...#..................#......#..........##.#....#......##.#...............#....##..............#....#.......
....#.#.##...........##.....#...........#.........#...#........#..#.......#......#................#.#...#....#...#.................
.......#...#...#...#..#.......#..........#..................#..#........#..#.#.....#.#.....................##......................
.....##.........#.......##...#.............#.##.#.#...#.##.#...#......#...#....#.......#..#.........#...........#.##.###.#.....#...
...................#.#.......................#.....#.#......#.....##...#.#....#..#..........#...........#..##....#...#.......#.#...
.....#..#..#.........#...#.#.........#...#.#...##...#......##........#...............#.......#................#.....#...#.#........
........#.....###.....................#.........#.........#.........#....##............#..##.............#.........#..#.......#....
.#.........#....##..##.................#...#................................#...#.....#.........#.......#............#....#......#.
..#.........#.......#..................#..#.#...#........#.#.......#...##.#........#..........#.#..........#..#.....#.........#....
..#...............#...................##.#.......#...#..........#....................##.........#.................#..#......##..#..
.#........#.......#............##...........##........#.......................#................#....................#...###......#.
........###..........#..............#.............#..#.#.#............##...............#........#...#........#...................#.
...#............................#...##.##........#......#..#...................#.#.....#...#.##...............#........#...#.......
..#...##....................#.....##......#.......#..........#......#.........#...#..............#..............#..................
.....#..#....................#....###.....#..#.............#...#....#................#.....#.....................#........#........
.....#.#...#.....#..............##............#....##.#....#.#........##...........#....#.........................#....#......##...
....#..#.....##...........#.#.#.#............#....#.....#.........#........................##.......#.#..............##...#........
...............#..............#................................#....#........#.......#.......##......#.#............#......#....#..
.#......#....##........#.............#..#.#.............#...#..#.........#.........#................#..................#...........
.........#..............#....#......#.....##......#............#....#.........#....#...................#....#.........#......#..#..
..............................#....#.#........#.#.....#..#.................#....#...#..........#............##.......#.#.#....#....
.#..................#....#..#.......#.##..............#...#.......#................#...............................................
.#..##.........................#.....###......#....#......#.....#............#.#......##......##......##....#..........##.....#....
..........................##.#.....#..........................................#.#..#....#..#..................#...........#........
..##.....#.......#....#.........#..........#....................#.........#........###........................#..........#.........
.#.#...............#..........#.......#.....#....##.#..#.##...............#...#...#.#......#.......#.......#.#.............#....##.
..................#...............##.........##..#........#..#..........#.....................#............................#.......
.....#................#...##.......##.........#.....#.#....#.#........#...#..#....#..............#..#....#....#....#...............
..##.#........#...............#.#..#...................##...#......#.#...#..#.....##.................##...#.#...................#..
...#...............#......#.....#.......#......#.........#...#......#...#..#....#..#......#.......#.......#...#.##.#...........##..
..............##..........##..........#..##...............#...........##..#..#..#.#.......#...#.............#......................
..........#.#........................#...#.#..#.#...##..#.#.#.#.......#....#.#.#..............#...#...#........###..##...........#.
......................#...#.#..##.....#....#.....###.#..#.....#..........#........#...........##...#..#...........##..#............
..................................####.#..............#.................#........#.#............##......#.#..........#.............
..................#..........#.............................#...........#..#..#......#................#.......##...##..#............
....................#...#....#.#.#.##......#................#.................#...........#....#..........#....#...##.###..........
.................#.......#...#............###.###..#.......#......#.......#..##......#.#.....#.....................#...............
.................................................................S.................................................................
.......##...........#.........###.......#....###.#.#....#.#....#....#........#.......#...#...#.#.........#...................#.....
.......#...............#............#...#..#.......##...#...#.#............#.............#......##..........#..............#.......
.......##.........#.....................##...#...#.................#...#.......#..####......#.....#..............#..##.............
........#..#.............#.#..##..............#...#.............#.....#......#...#.#.......#...............##...##.................
.........#..#...#..#.#..#..#...................##......#.....#..#...##..............#......#..........#.##...#.#.##.#..............
..............#..........#....................................#.........#.......#..#............##................#................
...........#...#.....#.........#....#..###....#...#.......#....#...............##.....#.......#.#.....#.#....#.#..#................
..#...................#........###..............#.#................#...###...##.............#.###......#...#...#.....#..........#..
.#.#............#.....#....###......................................#..........................#..................#................
................#..#...#................#.................##.................##..........#.......#...#.............#...............
.....##...........#....#.......#......#.#.....#.....#................#.....#.........#..#.................#........#........#......
.#.#.............#..#.#..............#.....#..#.#.....#..#......#.........#.....#.#......#..#.......#.#......##............#..#....
...................#............#....#...........#........#...................#.....##..............#........###...............#...
......###..........###.#.......#.................................................#..#.........#.#...#.........#.#..........#.#.....
..#.................#..#..#...#............#...#...#..##.#....##..#..................##.....#......#.........................#...#.
......................#.#.....#.#...#.......##...........#...#....#.............#.......#.............#.#.#.#......................
......#..#.#..........#....#.........#......#................#.........##.#....#.......#........#.#....................#......#....
..#....#....#...............#..........#...#.#......#...................#.........#..#.#......#..#.........................##....#.
..............#..........##......#.##...#...#.#................#...#..#.......#.#.....#........#...###..##.........#..##.........#.
........##...........................##.......#.#..................#........#.......#.#........#.........................##....#...
..#.#...........#.......................#.#.....#....#.....#...............####...#..............#...#....................#.#......
.......#...#....#.#.......#####...##.....#.#.......#....#.#........#................................#.##..........##....#..#.......
.........#.....#................##.#..................#.....................#...#................#.###.#.......###....#............
............#.#....#........#....#..................#...##.............#............#.......#.....#..#............##...............
....#.....#..........#..............#...#...#........##.....#.#....#....#........##.............................#.#.......#........
..#..#.#.......#.................#................................#......##.#..#..............#.#................#...#.#...........
.....#.....#........................#..#................#......#.......#.........###.#.#.........#.........#.....#.......#.........
.......#.......................................#.......#...............#.#..###...#.#.##.......#...........#.#.....#.##........#...
......##.........#.................................#.........#........##.#................#.#...#.............#...#..#........#....
......#.....#.#.......#...........#..#...........#.........#..#.#.......#.........##.....#....#.#...............#...#...#....#...#.
..#...#.#....#....#..............................#..#...#.......#.#.#..##..................#...............#......#..###..#.#......
.....#...#..#......#.....##...............#..........#..#.#####.......#...........#...................#.....#...#.........#..#.#...
.................#.......#..................#........#.......##...##.#....#.#.............#.............#....#....#................
...........####..#.....#....#.............#.......#...#..#.....#.............#...#....#.............#.#....#.#.............#.......
...#..#..#...#...#.#.....#.......................#....#..###.###.....#.........#....................#....#..#............#.....#...
.#.##....##...#......#.#.....#......................#.##..................#........#..#................#.#.......#.............#...
....##........#.......#..#..#............#..#..#..#...#......###..#..#..#...##...............................#.#........#......#.#.
..#..#..........#..........#..#.#.............#.....#...........#.##.......#............................#...........#...#..........
..#.#..#...#....#.....#.....#...#................#.....#.....#....#..#...#..#....#....#.....................#....#.................
.......#........#...#.............#.................#...#.#.....#.#....#..........#......................#..#............#.........
....#........#........#..............#.........................#...................#..........#.........#..#.........#.............
................#........#.........#............................#.#.............#..##.......#......#..#.................#......#.#.
..#.....#.........#...#..#.#.........................#...#...#...........#.....#...........#........#.............#.....#........#.
....#...#....#......#....#...#..#.................#...##.....#.#............................##...#...#..##.#.....................#.
...#..##...............#............................#...........#......#.#.....#............#........#.##................#.........
................#..#.............#..#..............#.#....#...#.#...#...#.#.##.............................#..#...........#........
.......#.......#....###............#.#.#.....................#.#..#....#.................##.....#.#..........##..#......#..........
.......#..........##.#.......#.##...#...............##.....#..........#................#............#...#........#........#........
...###.#.............................#.....#.#............##..#...#.....###..........#...............................#.....#....#..
....###.#...#.......#.##........#......#..##.#..........#.#...#.#....#.#..............##....#..#...#...........#...#.#..#..........
.....#....#.#..##.....#..........#..#...##..............#.......#.......#.............#..#.....#.......#.....#...##...###.......#..
........##...#...##..#.#.....#..........................#.#.#..#..#...................#....#....#..#....#..........#....##.........
...........##.....#...#........##..#........#....#..........#..#...............................................#......#.#.......#..
...#..##.........##....#...........##...#.......##.........#........#...........#........#.#.##...........#....#.....###...#.......
...#...#........................#..#...#..#........................................#......#..#...#.#....#...........#..............
...#..#.......#..#......##...................#...............#.....#.#.............#.....#.........#.#..##.....#..........#..#.....
....###....#..#.....#.#........#.##.......##...#...............#...............###.###.#...#............##.....#.................#.
....#...#.........#.##............#.....#........#............................................##.#......#..##.........#....###..#..
............#...##..#..........#........#.......#.#..........................#..#.#.......#......#.......................##.#..#...
....#......#....#....#..#.....#........#......#....#..#.#..............................#..#....#............#....#.................
..#.............#...#......#...#.....................#.##...............................##...#.......#........................#.##.
....#....##........#..............#....#.......#.....................................#........#........#...##..........#...........
....#.#.##..#..#....................#.................#.##.............#....#....#.............###...#...#..##....#.....##.........
.............#.......#...............#........#.#.....#..#.#................#.....#..##.....#....#...............#....#......#...#.
...................................................................................................................................

230
21/src/main.rs Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}
}

View File

@ -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 // Take a seat in the large pile of colorful cards. How many points are they worth in
// total? // total?
fn problem1(input: InputIter) -> u64 { fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
let cards: Vec<Card> = input let cards: Vec<Card> = input
.map(|line| Card::from(line.unwrap().as_str())) .map(|line| Card::from(line.unwrap().as_str()))
.collect(); .collect();
@ -199,7 +199,7 @@ fn problem2_award_copies<'a>(orig_cards: &'a Vec<Card>, card: &Card) -> Vec<&'a
new_cards new_cards
} }
fn problem2(input: InputIter) -> u64 { fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
let orig_cards: Vec<Card> = input let orig_cards: Vec<Card> = input
.map(|line| Card::from(line.unwrap().as_str())) .map(|line| Card::from(line.unwrap().as_str()))
.collect(); .collect();
@ -218,3 +218,29 @@ fn problem2(input: InputIter) -> u64 {
(won_cards.len() + orig_cards.len()) as 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
View 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
View 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
View 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
View 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
View 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
View 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]

2
6/input Normal file
View File

@ -0,0 +1,2 @@
Time: 53 89 76 98
Distance: 313 1090 1214 1201

242
6/src/main.rs Normal file
View 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
View 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
View 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]

1000
7/input Normal file

File diff suppressed because it is too large Load Diff

267
7/src/main.rs Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}
}

View File

@ -1,5 +1,6 @@
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Lines}; use std::io::{BufRead, BufReader, Lines};
use std::time::Instant;
// BOILERPLATE // BOILERPLATE
type InputIter = Lines<BufReader<File>>; type InputIter = Lines<BufReader<File>>;
@ -11,17 +12,44 @@ fn get_input() -> InputIter {
} }
fn main() { fn main() {
println!("Problem 1 solution: {}", problem1(get_input())); let start = Instant::now();
println!("Problem 2 solution: {}", problem2(get_input())); 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 // PROBLEM 1 solution
fn problem1(input: InputIter) -> u64 { fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
0 0
} }
// PROBLEM 2 solution // PROBLEM 2 solution
fn problem2(input: InputIter) -> u64 { fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
0 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);
}
}