From 5ce4e2b51bf74be33aebf7e3121fb3a20d1768a9 Mon Sep 17 00:00:00 2001 From: Fabian Schmidt Date: Fri, 20 Dec 2024 10:53:03 +0100 Subject: [PATCH] y2024d20p1 really inefficient, got more efficient version now --- Cargo.lock | 46 ++++ Cargo.toml | 1 + y2024/Cargo.toml | 1 + y2024/resources/20_input.txt | 141 +++++++++++ y2024/src/bin/d20.rs | 27 +++ y2024/src/days/d20.rs | 436 +++++++++++++++++++++++++++++++++++ y2024/src/days/mod.rs | 2 + 7 files changed, 654 insertions(+) create mode 100644 y2024/resources/20_input.txt create mode 100644 y2024/src/bin/d20.rs create mode 100644 y2024/src/days/d20.rs diff --git a/Cargo.lock b/Cargo.lock index 3605560..676d4a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,31 @@ dependencies = [ "memchr", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "either" version = "1.13.0" @@ -42,6 +67,26 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "regex" version = "1.11.1" @@ -129,6 +174,7 @@ name = "y2024" version = "0.1.0" dependencies = [ "itertools", + "rayon", "regex", "utils", ] diff --git a/Cargo.toml b/Cargo.toml index 2a740e3..03443b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,3 +23,4 @@ utils = { path = "../utils" } itertools = "0.13.0" regex = "1.11.1" md5 = "0.7.0" +rayon = "1.10" diff --git a/y2024/Cargo.toml b/y2024/Cargo.toml index 8912744..886c068 100644 --- a/y2024/Cargo.toml +++ b/y2024/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" regex = "1.11.1" utils = { workspace = true } itertools = { workspace = true } +rayon = { workspace = true } diff --git a/y2024/resources/20_input.txt b/y2024/resources/20_input.txt new file mode 100644 index 0000000..cf184da --- /dev/null +++ b/y2024/resources/20_input.txt @@ -0,0 +1,141 @@ +############################################################################################################################################# +#...###.....#...#...#...#...#...#...###...#.....#.........#...#.......#...#.....#...#.........###...#.....#.............#...#...#.......#...# +#.#.###.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.###.#.#######.#.#.#.#####.#.#.#.###.#.#.#.#######.###.#.#.###.#.###########.#.#.#.#.#.#####.#.#.# +#.#.#...#...#.#...#...#...#...#...#...#.#...#...#.#.......#.#.#.#.....#.#.#...#...#.#.#.......#...#...#...#.#.....#.....#.#.#.#.#.#.....#.#.# +#.#.#.###.###.#######################.#.#####.###.#.#######.#.#.#.#####.#.###.#####.#.#.#######.#######.###.#.###.#.#####.#.#.#.#.#.#####.#.# +#.#.#...#.###.....#.............#...#.#.#...#.#...#.#...###.#...#.......#.#...#...#.#.#.###.....#.....#.....#.###...#.....#.#.#...#.......#.# +#.#.###.#.#######.#.###########.#.#.#.#.#.#.#.#.###.#.#.###.#############.#.###.#.#.#.#.###.#####.###.#######.#######.#####.#.#############.# +#.#.....#.#...#...#...#.....###...#.#.#.#.#...#...#...#...#.#...#.........#.....#.#...#...#.......#...#...#...#...###.....#.#.#.............# +#.#######.#.#.#.#####.#.###.#######.#.#.#.#######.#######.#.#.#.#.###############.#######.#########.###.#.#.###.#.#######.#.#.#.############# +#.......#.#.#.#.......#...#...#.....#.#.#.#...###.#.......#...#.#.#.......#...#...#.......#.....###.#...#...###.#...#.....#...#...#.........# +#######.#.#.#.###########.###.#.#####.#.#.#.#.###.#.###########.#.#.#####.#.#.#.###.#######.###.###.#.#########.###.#.###########.#.#######.# +#...#...#.#.#.#...###...#...#.#.....#.#.#...#.#...#.#...###.....#...#.....#.#.#.#...###...#...#.#...#.#...#...#...#...#...........#.#.......# +#.#.#.###.#.#.#.#.###.#.###.#.#####.#.#.#####.#.###.#.#.###.#########.#####.#.#.#.#####.#.###.#.#.###.#.#.#.#.###.#####.###########.#.####### +#.#.#...#.#.#.#.#...#.#...#.#.#...#.#.#.#.....#.#...#.#...#.....#.....###...#...#.#...#.#.#...#.#...#.#.#...#...#...#...#...#.....#.#.......# +#.#.###.#.#.#.#.###.#.###.#.#.#.#.#.#.#.#.#####.#.###.###.#####.#.#######.#######.#.#.#.#.#.###.###.#.#.#######.###.#.###.#.#.###.#.#######.# +#.#.....#.#.#.#.#...#...#...#...#...#...#.......#.....#...#...#.#.......#.....#...#.#.#.#.#...#.###.#.#.....#...#...#.....#...#...#.#.......# +#.#######.#.#.#.#.#####.###############################.###.#.#.#######.#####.#.###.#.#.#.###.#.###.#.#####.#.###.#############.###.#.####### +#.......#...#.#.#...###...#...#.....#...#.............#.#...#.#.#.......#.....#.....#.#.#.#...#...#.#.###...#.###.#.............#...#.......# +#######.#####.#.###.#####.#.#.#.###.#.#.#.###########.#.#.###.#.#.#######.###########.#.#.#.#####.#.#.###.###.###.#.#############.#########.# +#.....#.....#.#.#...#...#...#.#.#...#.#.#.#.....#...#...#...#...#.....#...#...........#.#.#.....#...#.#...#...#...#.......###...#.#.........# +#.###.#####.#.#.#.###.#.#####.#.#.###.#.#.#.###.#.#.#######.#########.#.###.###########.#.#####.#####.#.###.###.#########.###.#.#.#.######### +#...#.......#...#...#.#.#...#...#.....#.#.#.#...#.#...###...#.........#...#...#.....#...#.#.....#...#.#...#.#...#...#.....#...#.#.#.#.......# +###.###############.#.#.#.#.###########.#.#.#.###.###.###.###.###########.###.#.###.#.###.#.#####.#.#.###.#.#.###.#.#.#####.###.#.#.#.#####.# +###.#.....#.......#...#.#.#.....#.......#...#.....#...#...#...#.....#...#.#...#...#.#.#...#...#...#...#...#...#...#.#...###...#...#...#...#.# +###.#.###.#.#####.#####.#.#####.#.#################.###.###.###.###.#.#.#.#.#####.#.#.#.#####.#.#######.#######.###.###.#####.#########.#.#.# +#...#.###...###...#...#...#.....#.........#...#.....###...#...#.#...#.#.#.#.###...#.#.#...#...#.#...###.....#...###...#...###.#.....#...#.#.# +#.###.#########.###.#.#####.#############.#.#.#.#########.###.#.#.###.#.#.#.###.###.#.###.#.###.#.#.#######.#.#######.###.###.#.###.#.###.#.# +#...#.#...#.....#...#.....#.#...###.......#.#...###...#...#...#.#.#...#.#.#...#...#.#.#...#.#...#.#...#...#.#.....###...#.....#...#...###...# +###.#.#.#.#.#####.#######.#.#.#.###.#######.#######.#.#.###.###.#.#.###.#.###.###.#.#.#.###.#.###.###.#.#.#.#####.#####.#########.########### +###...#.#.#...#...#.......#...#...#.......#...#...#.#...#...###.#.#...#.#...#.#...#.#.#...#.#.###.#...#.#.#.#.....#...#.#...#...#...#...#...# +#######.#.###.#.###.#############.#######.###.#.#.#.#####.#####.#.###.#.###.#.#.###.#.###.#.#.###.#.###.#.#.#.#####.#.#.#.#.#.#.###.#.#.#.#.# +#.......#.....#...#.........#...#.#...#...#...#.#.#.....#.#...#.#.#...#.#...#.#.#...#.#...#.#...#.#...#.#.#.#.....#.#.#...#...#.....#.#...#.# +#.###############.#########.#.#.#.#.#.#.###.###.#.#####.#.#.#.#.#.#.###.#.###.#.#.###.#.###.###.#.###.#.#.#.#####.#.#.###############.#####.# +#.......#...#.....#...#...#...#.#...#.#.#...###.#.#...#.#.#.#.#.#.#...#.#.#...#.#.###.#.###.#...#...#.#.#...#...#...#...###...#...#...#...#.# +#######.#.#.#.#####.#.#.#.#####.#####.#.#.#####.#.#.#.#.#.#.#.#.#.###.#.#.#.###.#.###.#.###.#.#####.#.#.#####.#.#######.###.#.#.#.#.###.#.#.# +#...###...#...#.....#...#.....#.....#...#.#...#.#.#.#...#...#.#.#...#.#.#.#.#...#...#.#...#.#...#...#.#.#.....#.........#...#...#...#...#...# +#.#.###########.#############.#####.#####.#.#.#.#.#.#########.#.###.#.#.#.#.#.#####.#.###.#.###.#.###.#.#.###############.###########.####### +#.#.#...###...#.............#.#...#.....#...#.#.#.#...#.......#...#...#.#.#.#.#.....#...#.#.#...#...#.#.#.............###.#.......#...#...### +#.#.#.#.###.#.#############.#.#.#.#####.#####.#.#.###.#.#########.#####.#.#.#.#.#######.#.#.#.#####.#.#.#############.###.#.#####.#.###.#.### +#.#...#.....#.#...#...#.....#...#.......#.....#.#.#...#.....#...#...#...#.#.#.#.#...#...#...#.#...#.#.#.#.......#...#.....#.....#.#.....#...# +#.###########.#.#.#.#.#.#################.#####.#.#.#######.#.#.###.#.###.#.#.#.#.#.#.#######.#.#.#.#.#.#.#####.#.#.###########.#.#########.# +#.#.....#...#...#...#...#...#...#...#...#.....#.#.#.......#...#.#...#...#.#...#...#.#.....#...#.#...#...#.....#...#...#...#.....#...........# +#.#.###.#.#.#############.#.#.#.#.#.#.#.#####.#.#.#######.#####.#.#####.#.#########.#####.#.###.#############.#######.#.#.#.################# +#.#.#...#.#.........#...#.#.#.#.#.#...#.....#...#.#.....#.#.....#...###.#.#.........#...#.#.....#...........#.......#.#.#.#...#...#...#...### +#.#.#.###.#########.#.#.#.#.#.#.#.#########.#####.#.###.#.#.#######.###.#.#.#########.#.#.#######.#########.#######.#.#.#.###.#.#.#.#.#.#.### +#.#.#.....#.......#.#.#...#.#.#.#.#.......#.#.....#.###.#.#...#...#...#...#.....#...#.#...###...#.........#.#...#...#...#...#...#...#.#.#...# +#.#.#######.#####.#.#.#####.#.#.#.#.#####.#.#.#####.###.#.###.#.#.###.#########.#.#.#.#######.#.#########.#.#.#.#.#########.#########.#.###.# +#...###...#.....#.#...#.....#.#...#.....#.#.#.....#...#.#...#...#...#...#.......#.#.#...###...#...........#...#...#...#####...........#...#.# +#######.#.#####.#.#####.#####.#########.#.#.#####.###.#.###.#######.###.#.#######.#.###.###.#######################.#.###################.#.# +#...#...#.#.....#.#...#.......#.........#...###...#...#.#...#.......#...#.#.....#.#...#...#.#...#...#.....#...#...#.#...###...#...#...#...#.# +#.#.#.###.#.#####.#.#.#########.###############.###.###.#.###.#######.###.#.###.#.###.###.#.#.#.#.#.#.###.#.#.#.#.#.###.###.#.#.#.#.#.#.###.# +#.#.#...#.#.....#.#.#.#...###...#.............#.#...###.#.#...#...#...###.#.#...#...#.#...#...#...#.#.#...#.#.#.#...#...#...#...#...#...#...# +#.#.###.#.#####.#.#.#.#.#.###.###.###########.#.#.#####.#.#.###.#.#.#####.#.#.#####.#.#.###########.#.#.###.#.#.#####.###.###############.### +#.#.....#.......#...#...#...#...#.#...#.......#...#...#...#...#.#.#.....#...#.#...#.#.#.#...........#.#.....#...#.....#...#...#.....#...#...# +#.#########################.###.#.#.#.#.###########.#.#######.#.#.#####.#####.#.#.#.#.#.#.###########.###########.#####.###.#.#.###.#.#.###.# +#.....#...#.............#...###...#.#...#...#####...#.......#...#.#.....###...#.#.#.#...#...........#.###.....#...###...#...#...###...#.....# +#####.#.#.#.###########.#.#########.#####.#.#####.#########.#####.#.#######.###.#.#.###############.#.###.###.#.#####.###.################### +#...#...#.#.#...........#...#.......#...#.#...#...#.........###...#.......#...#.#.#.#.............#.#.#...#...#.......#...#...#...#.........# +#.#.#####.#.#.#############.#.#######.#.#.###.#.###.###########.#########.###.#.#.#.#.###########.#.#.#.###.###########.###.#.#.#.#.#######.# +#.#.....#...#.............#.#...#.....#...#...#...#.#...###...#...#.......###.#.#...#...........#.#...#...#...........#...#.#.#.#.#.....#...# +#.#####.#################.#.###.#.#########.#####.#.#.#.###.#.###.#.#########.#.###############.#.#######.###########.###.#.#.#.#.#####.#.### +#.#...#...###...#.........#...#...#...#...#.......#...#.#...#...#.#.....#.....#.....#.....#.....#.#...###...........#.....#.#...#.###...#...# +#.#.#.###.###.#.#.###########.#####.#.#.#.#############.#.#####.#.#####.#.#########.#.###.#.#####.#.#.#############.#######.#####.###.#####.# +#.#.#...#.....#...#.....#...#...#...#...#.#...#...#...#...#...#.#.#.....#.......#...#...#.#.....#.#.#...............#.......#.....#...#.....# +#.#.###.###########.###.#.#.###.#.#######.#.#.#.#.#.#.#####.#.#.#.#.###########.#.#####.#.#####.#.#.#################.#######.#####.###.##### +#.#.###.....#...#...###...#...#.#...#...#...#...#...#.#.....#.#.#.#.....#.......#.#.....#.#.....#...#...............#...#.....#...#...#.#...# +#.#.#######.#.#.#.###########.#.###.#.#.#############.#.#####.#.#.#####.#.#######.#.#####.#.#########.#############.###.#.#####.#.###.#.#.#.# +#.#.#.......#.#.#.#.......###.#.###...#.#...#.......#.#.....#...#.#...#.#...#...#.#.....#.#...........#.........#...###.#.......#.....#...#.# +#.#.#.#######.#.#.#.#####.###.#.#######.#.#.#.#####.#.#####.#####.#.#.#.###.#.#.#.#####.#.#############.#######.#.#####.###################.# +#...#.#...#...#...#.....#.....#.......#...#...#...#.#...#...#.....#.#.#.###.#.#...#.....#.....#.......#.......#.#.#.....#.........#...#...#.# +#####.#.#.#.###########.#############.#########.#.#.###.#.###.#####.#.#.###.#.#####.#########.#.#####.#######.#.#.#.#####.#######.#.#.#.#.#.# +#...#...#...#.......###...#.........#.#.....#...#...#...#...#.......#.#.#...#...###...#.....#...#...#.........#...#.#.....#.....#.#.#.#.#...# +#.#.#########.#####.#####.#.#######.#.#.###.#.#######.#####.#########.#.#.#####.#####.#.###.#####.#.###############.#.#####.###.#.#.#.#.##### +#.#...........#...#.......#...#.....#...###.#.....###.......#...#.....#.#...#...#.....#.###.......#.......#...#...#.#.......#...#...#...#...# +#.#############.#.###########.#.###########.#####.###########.#.#.#####.###.#.###.#####.#################.#.#.#.#.#.#########.###########.#.# +#.#.............#.........#...#...........#.#...#.............#.#.#.....###.#...#.#.....#...........#...#...#.#.#.#.#.....#...#...........#.# +#.#.#####################.#.#############.#.#.#.###############.#.#.#######.###.#.#.#####.#########.#.#.#####.#.#.#.#.###.#.###.###########.# +#...#...#.................#.###...#...#...#...#.#.......#.......#...#.......#...#...#.....#.......#...#.......#.#...#...#...###.#.......#...# +#####.#.#.#################.###.#.#.#.#.#######.#.#####.#.###########.#######.#######.#####.#####.#############.#######.#######.#.#####.#.### +#.....#...#...#.....#.....#.#...#...#...#...###.#.....#.#.....###...#.........#.......#...#.#...#.....#...#.....#.....#.........#.....#...### +#.#########.#.#.###.#.###.#.#.###########.#.###.#####.#.#####.###.#.###########.#######.#.#.#.#.#####.#.#.#.#####.###.###############.####### +#.#.....#...#...###...###...#.............#...#...#...#.......#...#...#...#...#.........#...#.#.#...#...#...#.....###.#.......#.......#...### +#.#.###.#.###################################.###.#.###########.#####.#.#.#.#.###############.#.#.#.#########.#######.#.#####.#.#######.#.### +#...###...#.......###...#...#.........#.......###...###...###...#.....#.#.#.#.#############...#...#.#...#...#.......#.#.....#...#.......#...# +###########.#####.###.#.#.#.#.#######.#.###############.#.###.###.#####.#.#.#.#############.#######.#.#.#.#.#######.#.#####.#####.#########.# +#...........#...#.#...#...#...#.....#.#...#...#...#...#.#.#...#...#...#.#.#.#S#############.......#...#...#...#...#.#.#...#...###.#.........# +#.###########.#.#.#.###########.###.#.###.#.#.#.#.#.#.#.#.#.###.###.#.#.#.#.#####################.###########.#.#.#.#.#.#.###.###.#.######### +#.....#.......#.#...#...#.......#...#.#...#.#.#.#...#.#.#.#...#.#...#.#.#.#.........#########...#.#.........#...#...#...#...#.....#.........# +#####.#.#######.#####.#.#.#######.###.#.###.#.#.#####.#.#.###.#.#.###.#.#.#########.#########.#.#.#.#######.###############.###############.# +#.....#.#.......#.....#...#...###...#...###.#.#.....#...#...#.#.#.#...#.#.#...#...#.#########.#...#.#.......#.............#...#.............# +#.#####.#.#######.#########.#.#####.#######.#.#####.#######.#.#.#.#.###.#.#.#.#.#.#.#########.#####.#.#######.###########.###.#.############# +#.#...#.#.........#.........#.......#.......#.....#...#.....#.#...#.....#.#.#.#.#.#.#########.....#.#.....#...#.......#...###.#.........#...# +#.#.#.#.###########.#################.###########.###.#.#####.###########.#.#.#.#.#.#############.#.#####.#.###.#####.#.#####.#########.#.#.# +#...#...#...........#...#...#.........#...........###.#.....#.........#...#.#.#.#...#############...#...#...#...#...#.#.#...#.#...#.....#.#.# +#########.###########.#.#.#.#.#########.#############.#####.#########.#.###.#.#.#####################.#.#####.###.#.#.#.#.#.#.#.#.#.#####.#.# +#.......#...#...#.....#...#.#.#.......#...........#...#.....#...#...#.#.#...#.#.....#####......E#.....#.......###.#.#...#.#.#.#.#.#.......#.# +#.#####.###.#.#.#.#########.#.#.#####.###########.#.###.#####.#.#.#.#.#.#.###.#####.#####.#######.###############.#.#####.#.#.#.#.#########.# +#.....#.###...#...#...###...#.#.#...#...#...#...#.#...#.#...#.#...#...#.#...#.#...#.#.....#.....#.................#.....#.#.#.#.#.#.....#...# +#####.#.###########.#.###.###.#.#.#.###.#.#.#.#.#.###.#.#.#.#.#########.###.#.#.#.#.#.#####.###.#######################.#.#.#.#.#.#.###.#.### +###...#...#.........#.....#...#...#...#...#...#...#...#...#.#.....#.....#...#.#.#...#.......#...#...#...#...#.....#.....#.#.#...#.#.#...#.### +###.#####.#.###############.#########.#############.#######.#####.#.#####.###.#.#############.###.#.#.#.#.#.#.###.#.#####.#.#####.#.#.###.### +#...#.....#.......#.........#.........#.....#.....#.....#...###...#.#...#...#.#.#.............#...#.#.#.#.#...###...#.....#.#...#...#...#...# +#.###.###########.#.#########.#########.###.#.###.#####.#.#####.###.#.#.###.#.#.#.#############.###.#.#.#.###########.#####.#.#.#######.###.# +#...#...#.........#.###...###.......###.#...#.#...#...#.#.#...#.#...#.#.###.#.#.#.###...###...#.#...#.#.#...#...#...#.#.....#.#.#.....#.#...# +###.###.#.#########.###.#.#########.###.#.###.#.###.#.#.#.#.#.#.#.###.#.###.#.#.#.###.#.###.#.#.#.###.#.###.#.#.#.#.#.#.#####.#.#.###.#.#.### +###...#.#.........#.#...#...#.......#...#.#...#.#...#...#.#.#.#.#...#.#.....#.#.#.....#.#...#.#.#.#...#...#...#...#...#.......#...#...#.#...# +#####.#.#########.#.#.#####.#.#######.###.#.###.#.#######.#.#.#.###.#.#######.#.#######.#.###.#.#.#.#####.#########################.###.###.# +#.....#.........#...#.....#...#...#...#...#.#...#...#.....#.#.#...#...###.....#.....#...#.###...#.#.###...#...#...#...#.............###...#.# +#.#############.#########.#####.#.#.###.###.#.#####.#.#####.#.###.#######.#########.#.###.#######.#.###.###.#.#.#.#.#.#.#################.#.# +#.....#...#...#.......###.#.....#.#.###...#.#...#...#.....#.#.#...#.......#...#...#.#...#.....###.#.#...#...#...#.#.#.#.............#.....#.# +#####.#.#.#.#.#######.###.#.#####.#.#####.#.###.#.#######.#.#.#.###.#######.#.#.#.#.###.#####.###.#.#.###.#######.#.#.#############.#.#####.# +#.....#.#...#.......#.....#.#.....#...###...#...#.......#...#.#.###.#.....#.#.#.#.#.#...#...#...#...#...#.###...#.#.#.#...#...#.....#.#...#.# +#.#####.###########.#######.#.#######.#######.#########.#####.#.###.#.###.#.#.#.#.#.#.###.#.###.#######.#.###.#.#.#.#.#.#.#.#.#.#####.#.#.#.# +#.....#.#...........#...#...#.....#...#.......#...#.....#.....#...#...#...#.#.#.#.#.#.#...#.#...#.......#.....#.#...#...#...#.#.....#...#.#.# +#####.#.#.###########.#.#.#######.#.###.#######.#.#.#####.#######.#####.###.#.#.#.#.#.#.###.#.###.#############.#############.#####.#####.#.# +#.....#.#...........#.#.#...###...#...#...#...#.#.#.....#...#...#.###...#...#.#.#.#.#.#.#...#.#...#.....#.....#.............#.#...#.....#.#.# +#.#####.###########.#.#.###.###.#####.###.#.#.#.#.#####.###.#.#.#.###.###.###.#.#.#.#.#.#.###.#.###.###.#.###.#############.#.#.#.#####.#.#.# +#...#...#...........#.#...#.#...#...#...#...#...#.#.....###.#.#.#.#...#...###.#.#...#...#...#.#.#...###.#...#.#...#.....#...#...#.......#...# +###.#.###.###########.###.#.#.###.#.###.#########.#.#######.#.#.#.#.###.#####.#.###########.#.#.#.#####.###.#.#.#.#.###.#.################### +###.#...#...........#.#...#.#...#.#...#.#.........#.###.....#.#.#.#...#.....#.#...#.......#.#.#.#...#...#...#.#.#.#...#.#...###.............# +###.###.###########.#.#.###.###.#.###.#.#.#########.###.#####.#.#.###.#####.#.###.#.#####.#.#.#.###.#.###.###.#.#.###.#.###.###.###########.# +#...#...###.........#.#.....#...#...#...#.........#...#.#.....#.#.###...#...#.....#.....#...#.#.#...#...#...#.#.#.#...#...#.....#...#...#...# +#.###.#####.#########.#######.#####.#############.###.#.#.#####.#.#####.#.#############.#####.#.#.#####.###.#.#.#.#.#####.#######.#.#.#.#.### +#.....#.....#.....#...#.......#.....#...#.........#...#.#...###.#.#.....#.#...###.......#...#.#.#.#.....#...#...#.#.....#.#.......#.#.#.#...# +#######.#####.###.#.###.#######.#####.#.#.#########.###.###.###.#.#.#####.#.#.###.#######.#.#.#.#.#.#####.#######.#####.#.#.#######.#.#.###.# +#.......#...#.#...#.###...#...#.....#.#.#.......#...###...#.#...#.#.....#...#...#...#...#.#.#.#.#.#.....#.....#...#.....#.#.......#...#...#.# +#.#######.#.#.#.###.#####.#.#.#####.#.#.#######.#.#######.#.#.###.#####.#######.###.#.#.#.#.#.#.#.#####.#####.#.###.#####.#######.#######.#.# +#...#...#.#.#.#...#...#...#.#.....#...#.#.......#.....#...#.#.#...#.....#.......###.#.#.#.#...#.#.#...#.#.....#...#.....#...#.....#.....#.#.# +###.#.#.#.#.#.###.###.#.###.#####.#####.#.###########.#.###.#.#.###.#####.#########.#.#.#.#####.#.#.#.#.#.#######.#####.###.#.#####.###.#.#.# +#...#.#.#.#.#.#...#...#.....#.....#.....#.#.....#.....#.#...#.#...#.#...#.......#...#.#.#.....#.#.#.#...#...#...#.#.....#...#.......#...#...# +#.###.#.#.#.#.#.###.#########.#####.#####.#.###.#.#####.#.###.###.#.#.#.#######.#.###.#.#####.#.#.#.#######.#.#.#.#.#####.###########.####### +#...#.#.#.#.#.#...#.#.......#.....#.....#.#.#...#.....#.#.###...#.#.#.#.#.....#.#.#...#...#...#.#.#...#.....#.#...#.....#.#...#.......#...### +###.#.#.#.#.#.###.#.#.#####.#####.#####.#.#.#.#######.#.#.#####.#.#.#.#.#.###.#.#.#.#####.#.###.#.###.#.#####.#########.#.#.#.#.#######.#.### +#...#.#.#.#.#.#...#.#.#...#.......#...#.#.#.#...#...#.#.#.#...#...#...#.#.###.#.#.#.....#.#.#...#...#.#.....#.#...#...#.#.#.#.#...#.....#...# +#.###.#.#.#.#.#.###.#.#.#.#########.#.#.#.#.###.#.#.#.#.#.#.#.#########.#.###.#.#.#####.#.#.#.#####.#.#####.#.#.#.#.#.#.#.#.#.###.#.#######.# +#.#...#...#.#.#.#...#...#...#...#...#.#.#.#...#.#.#.#.#.#...#...#.......#...#.#.#...#...#.#.#.#.....#.#.....#.#.#...#.#.#.#.#...#...#...#...# +#.#.#######.#.#.#.#########.#.#.#.###.#.#.###.#.#.#.#.#.#######.#.#########.#.#.###.#.###.#.#.#.#####.#.#####.#.#####.#.#.#.###.#####.#.#.### +#.#...#.....#.#.#.#.........#.#.#...#.#.#.#...#.#.#.#.#.#...#...#...#...#...#.#.#...#.#...#.#.#.#.....#.....#.#.....#.#.#.#...#...#...#.#...# +#.###.#.#####.#.#.#.#########.#.###.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.#.#.###.#.#.###.#.###.#.#.#.#########.#.#####.#.#.#.###.###.#.###.###.# +#.....#.......#...#...........#.....#...#...###...#...#...#...#####...#...###...#.....#.....#...#...........#.......#...#.....###...###.....# +############################################################################################################################################# diff --git a/y2024/src/bin/d20.rs b/y2024/src/bin/d20.rs new file mode 100644 index 0000000..ab6ec2d --- /dev/null +++ b/y2024/src/bin/d20.rs @@ -0,0 +1,27 @@ +use std::{fs, time::Instant}; + +use utils::time::get_elapsed_string; +use y2024::days::d20; + +fn main() { + let now = Instant::now(); + println!("Part 1:"); + part1(); + println!("Ran in {}", get_elapsed_string(now.elapsed())); + let now = Instant::now(); + println!("Part 2:"); + part2(); + println!("Ran in {}", get_elapsed_string(now.elapsed())); +} + +fn part1() { + let root = env!("CARGO_MANIFEST_DIR"); + let content = fs::read_to_string(format!("{root}/resources/20_input.txt")).unwrap(); + println!("{}", d20::process_part1(&content)); +} + +fn part2() { + let root = env!("CARGO_MANIFEST_DIR"); + let content = fs::read_to_string(format!("{root}/resources/20_input.txt")).unwrap(); + println!("{}", d20::process_part2(&content)); +} diff --git a/y2024/src/days/d20.rs b/y2024/src/days/d20.rs new file mode 100644 index 0000000..a47e149 --- /dev/null +++ b/y2024/src/days/d20.rs @@ -0,0 +1,436 @@ +use std::{ + collections::{HashMap, HashSet}, + error::Error, + sync::mpsc, +}; + +use itertools::Itertools; +use rayon::prelude::*; + +pub fn process_part1(input: &str) -> u32 { + simulate_all_2(input, 100).values().copied().sum() + //simulate_all(input) + // .iter() + // .map( + // |(time_saved, count)| { + // if *time_saved >= 100 { + // *count + // } else { + // 0 + // } + // }, + // ) + // .sum() +} + +fn simulate_all(input: &str) -> HashMap { + let mut cheats = Vec::new(); + let mut start = (0, 0); + let grid = input + .lines() + .enumerate() + .map(|(yidx, row)| { + row.chars() + .enumerate() + .map(|(xidx, chara)| { + let tile = GridTile::try_from(chara).unwrap(); + if tile == GridTile::Start { + start = (xidx, yidx); + } + tile + }) + .collect_vec() + }) + .collect_vec(); + grid[1..grid.len() - 1] + .iter() + .enumerate() + .for_each(|(yidx, row)| { + row[1..row.len() - 1] + .iter() + .enumerate() + .for_each(|(xidx, tile)| { + if *tile == GridTile::Wall && cheatable(&grid, (xidx + 1, yidx + 1)) { + cheats.push((xidx + 1, yidx + 1)); + } + }); + }); + let mut saved = HashMap::new(); + + let no_cheat = simulate(grid.clone(), start, None).unwrap(); + let (tx, rx) = mpsc::channel(); + cheats.into_par_iter().for_each(|cheat| { + let cheat = simulate(grid.clone(), start, Some(cheat)).unwrap(); + let time_saved = no_cheat - cheat; + let _ = tx.send(time_saved); + }); + drop(tx); + while let Ok(time_saved) = rx.recv() { + saved + .entry(time_saved) + .and_modify(|count| *count += 1) + .or_insert(1); + } + saved +} + +fn cheatable(grid: &[Vec], wall_position: (usize, usize)) -> bool { + let above = grid + .get(wall_position.1 - 1) + .map(|above_row| above_row[wall_position.0]); + let below = grid + .get(wall_position.1 + 1) + .map(|below_row| below_row[wall_position.0]); + let left = grid[wall_position.1].get(wall_position.0 - 1).copied(); + let right = grid[wall_position.1].get(wall_position.0 + 1).copied(); + [above, below, left, right] + .iter() + .map(|tile| { + if let Some(tile) = tile { + match tile { + GridTile::Wall => 0, + GridTile::Path | GridTile::Start | GridTile::End => 1, + } + } else { + 0 + } + }) + .sum::() + >= 2 +} + +fn simulate( + mut grid: Vec>, + start: (usize, usize), + cheat: Option<(usize, usize)>, +) -> Option { + if let Some(cheat) = cheat { + grid[cheat.1][cheat.0] = GridTile::Path; + } + let mut visited = HashSet::new(); + visited.insert(start); + let mut next_paths = vec![MazeRunner { + coords: start, + visited: visited.clone(), + ..Default::default() + }]; + let mut arrived: Vec = Vec::new(); + while !next_paths.is_empty() { + next_paths = next_paths + .iter() + .map(|maze_runner| { + let mut paths = Vec::new(); + if let Some(path) = maze_runner.get_next(&grid, Direction::Up) { + paths.push(path); + } + if let Some(path) = maze_runner.get_next(&grid, Direction::Down) { + paths.push(path); + } + if let Some(path) = maze_runner.get_next(&grid, Direction::Left) { + paths.push(path); + } + if let Some(path) = maze_runner.get_next(&grid, Direction::Right) { + paths.push(path); + } + paths + }) + .collect_vec() + .concat(); + for (idx, maze_runner) in next_paths.clone().iter().enumerate().rev() { + if maze_runner.visited.contains(&maze_runner.coords) + || visited.contains(&maze_runner.coords) + { + next_paths.remove(idx); + continue; + } + visited.insert(maze_runner.coords); + next_paths[idx].visited.insert(maze_runner.coords); + if maze_runner.state == State::Arrived { + let arrived_reindeer = next_paths.remove(idx); + arrived.push(arrived_reindeer); + } + //log_maze(&grid, maze_runner); + } + } + arrived.sort_by(|a_runner, b_runner| a_runner.visited.len().cmp(&b_runner.visited.len())); + arrived + .first() + .map(|arrived| arrived.visited.len() as u32 - 1) +} + +pub fn process_part2(input: &str) -> u32 { + simulate_all_2(input, 100).values().copied().sum() +} + +fn simulate_all_2(input: &str, time_to_saved: usize) -> HashMap { + let mut cheats = Vec::new(); + let mut start = (0, 0); + let grid = input + .lines() + .enumerate() + .map(|(yidx, row)| { + row.chars() + .enumerate() + .map(|(xidx, chara)| { + let tile = GridTile::try_from(chara).unwrap(); + if tile == GridTile::Start { + start = (xidx, yidx); + } + tile + }) + .collect_vec() + }) + .collect_vec(); + grid[1..grid.len() - 1] + .iter() + .enumerate() + .for_each(|(yidx, row)| { + row[1..row.len() - 1] + .iter() + .enumerate() + .for_each(|(xidx, tile)| { + if *tile == GridTile::Wall && cheatable(&grid, (xidx + 1, yidx + 1)) { + cheats.push((xidx + 1, yidx + 1)); + } + }); + }); + let no_cheat = simulate_2(&grid, start); + let mut saved = HashMap::new(); + for (tile_idx, tile) in no_cheat[..no_cheat.len() - time_to_saved] + .iter() + .enumerate() + { + for (cheat_idx, cheat) in no_cheat[tile_idx + time_to_saved..].iter().enumerate() { + let manhattan = tile.0.abs_diff(cheat.0) + tile.1.abs_diff(cheat.1); + if manhattan <= 2 { + let time_saved = (time_to_saved + cheat_idx).saturating_sub(2); + if time_saved != 0 { + saved + .entry(time_saved as u32) + .and_modify(|count| *count += 1) + .or_insert(1); + } + } + } + } + saved +} + +fn simulate_2(grid: &[Vec], start: (usize, usize)) -> Vec<(usize, usize)> { + let mut visited = HashSet::new(); + visited.insert(start); + let mut next_paths = vec![MazeRunner { + coords: start, + visited: visited.clone(), + ..Default::default() + }]; + let mut visited = Vec::new(); + visited.push(start); + let mut arrived: Vec = Vec::new(); + while !next_paths.is_empty() { + next_paths = next_paths + .iter() + .map(|maze_runner| { + let mut paths = Vec::new(); + if let Some(path) = maze_runner.get_next(grid, Direction::Up) { + paths.push(path); + } + if let Some(path) = maze_runner.get_next(grid, Direction::Down) { + paths.push(path); + } + if let Some(path) = maze_runner.get_next(grid, Direction::Left) { + paths.push(path); + } + if let Some(path) = maze_runner.get_next(grid, Direction::Right) { + paths.push(path); + } + paths + }) + .collect_vec() + .concat(); + for (idx, maze_runner) in next_paths.clone().iter().enumerate().rev() { + if maze_runner.visited.contains(&maze_runner.coords) + || visited.contains(&maze_runner.coords) + { + next_paths.remove(idx); + continue; + } + visited.push(maze_runner.coords); + next_paths[idx].visited.insert(maze_runner.coords); + if maze_runner.state == State::Arrived { + let arrived_reindeer = next_paths.remove(idx); + arrived.push(arrived_reindeer); + } + //log_maze(&grid, maze_runner); + } + } + visited +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Direction { + Up, + Down, + Left, + Right, +} + +#[derive(Debug, Default, Clone, PartialEq, Eq)] +enum State { + #[default] + Going, + Arrived, +} + +#[derive(Debug, Default, Clone, PartialEq, Eq)] +struct MazeRunner { + coords: (usize, usize), + visited: HashSet<(usize, usize)>, + state: State, +} + +impl MazeRunner { + fn get_next(&self, grid: &[Vec], direction: Direction) -> Option { + let tile = match direction { + Direction::Up => grid[self.coords.1 - 1][self.coords.0], + Direction::Down => grid[self.coords.1 + 1][self.coords.0], + Direction::Right => grid[self.coords.1][self.coords.0 + 1], + Direction::Left => grid[self.coords.1][self.coords.0 - 1], + }; + let coords = match direction { + Direction::Up => (self.coords.0, self.coords.1 - 1), + Direction::Down => (self.coords.0, self.coords.1 + 1), + Direction::Left => (self.coords.0 - 1, self.coords.1), + Direction::Right => (self.coords.0 + 1, self.coords.1), + }; + if tile == GridTile::Wall { + None + } else if tile == GridTile::End { + Some(MazeRunner { + state: State::Arrived, + coords, + ..self.clone() + }) + } else { + Some(MazeRunner { + coords, + ..self.clone() + }) + } + } +} + +#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)] +enum GridTile { + Wall, + #[default] + Path, + Start, + End, +} + +impl TryFrom for GridTile { + type Error = Box; + + fn try_from(value: char) -> std::result::Result> { + match value { + '#' => Ok(Self::Wall), + '.' => Ok(Self::Path), + 'S' => Ok(Self::Start), + 'E' => Ok(Self::End), + _ => Err(Box::from(format!("{value} is not a valid tile"))), + } + } +} + +fn log_maze(grid: &[Vec], maze_runner: &MazeRunner) { + for (yidx, row) in grid.iter().enumerate() { + for (xidx, tile) in row.iter().enumerate() { + let contains = { + maze_runner.visited.contains(&(xidx, yidx)) + || maze_runner.visited.contains(&(xidx, yidx)) + || maze_runner.visited.contains(&(xidx, yidx)) + || maze_runner.visited.contains(&(xidx, yidx)) + }; + if contains && !(*tile == GridTile::Start || *tile == GridTile::End) { + print!("O"); + } else if *tile == GridTile::Wall { + print!("#"); + } else if *tile == GridTile::Path { + print!("."); + } else if *tile == GridTile::Start { + print!("S"); + } else if *tile == GridTile::End { + print!("E"); + } + } + println!(); + } +} + +#[cfg(test)] +mod tests { + use std::time::Instant; + + use utils::time::get_elapsed_string; + + use super::*; + + const INPUT: &str = "############### +#...#...#.....# +#.#.#.#.#.###.# +#S#...#.#.#...# +#######.#.#.### +#######.#.#...# +#######.#.###.# +###..E#...#...# +###.#######.### +#...###...#...# +#.#####.#.###.# +#.#...#.#.#...# +#.#.#.#.#.#.### +#...#...#...### +###############"; + + #[test] + fn part1() { + let now = Instant::now(); + println!("Test 1:"); + let result = simulate_all(INPUT); + result + .iter() + .sorted_by(|a, b| a.0.cmp(b.0)) + .for_each(|(saved, count)| { + println!("There are {count} cheats that saved {saved} picoseconds"); + }); + println!("Ran in {}", get_elapsed_string(now.elapsed())); + } + + #[test] + fn part1_fast() { + let now = Instant::now(); + println!("Test 2:"); + let result = simulate_all_2(INPUT, 0); + result + .iter() + .sorted_by(|a, b| a.0.cmp(b.0)) + .for_each(|(saved, count)| { + println!("There are {count} cheats that saved {saved} picoseconds"); + }); + println!("Ran in {}", get_elapsed_string(now.elapsed())); + } + + #[test] + fn part2() { + let now = Instant::now(); + println!("Test 2:"); + let result = simulate_all_2(INPUT, 2); + result + .iter() + .sorted_by(|a, b| a.0.cmp(b.0)) + .for_each(|(saved, count)| { + println!("There are {count} cheats that saved {saved} picoseconds"); + }); + println!("Ran in {}", get_elapsed_string(now.elapsed())); + } +} diff --git a/y2024/src/days/mod.rs b/y2024/src/days/mod.rs index 194064b..bf81c6c 100644 --- a/y2024/src/days/mod.rs +++ b/y2024/src/days/mod.rs @@ -27,3 +27,5 @@ pub mod d17; pub mod d18; pub mod d19; + +pub mod d20;