summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShivesh Mandalia <mail@shivesh.org>2022-12-21 18:17:44 +0000
committerShivesh Mandalia <mail@shivesh.org>2022-12-21 18:17:44 +0000
commit666b11bc77f17d6d2b5a466c56ea7710bb9134fd (patch)
treeb19bd61fb34a190ec825e18b64a04656fc86b6cc
parenta667c19882e1feb542a122781b4efe5545dea0dd (diff)
downloadadvent_of_code_2022-666b11bc77f17d6d2b5a466c56ea7710bb9134fd.tar.gz
advent_of_code_2022-666b11bc77f17d6d2b5a466c56ea7710bb9134fd.zip
complete day 5
-rw-r--r--Cargo.lock40
-rw-r--r--Cargo.toml4
-rw-r--r--day05a/Cargo.toml11
-rw-r--r--day05a/examples/input.txt513
-rw-r--r--day05a/examples/test.txt9
-rw-r--r--day05a/src/main.rs273
-rw-r--r--day05b/Cargo.toml11
-rw-r--r--day05b/examples/input.txt513
-rw-r--r--day05b/examples/test.txt9
-rw-r--r--day05b/src/main.rs268
10 files changed, 1649 insertions, 2 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 97f37c2..c0862c3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -129,6 +129,24 @@ dependencies = [
]
[[package]]
+name = "day05a"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "itertools",
+ "nom",
+]
+
+[[package]]
+name = "day05b"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "itertools",
+ "nom",
+]
+
+[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -181,6 +199,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
name = "once_cell"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index dfd8d44..17d12d3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,8 +9,8 @@ members = [
"day03b",
"day04a",
"day04b",
- # "day05a",
- # "day05b",
+ "day05a",
+ "day05b",
# "day06a",
# "day06b",
# "day07a",
diff --git a/day05a/Cargo.toml b/day05a/Cargo.toml
new file mode 100644
index 0000000..4ff4967
--- /dev/null
+++ b/day05a/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "day05a"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clap = { version = "3.2.20", features = ["derive"] }
+nom = "7.1.1"
+itertools = "0.10.5"
diff --git a/day05a/examples/input.txt b/day05a/examples/input.txt
new file mode 100644
index 0000000..ca57552
--- /dev/null
+++ b/day05a/examples/input.txt
@@ -0,0 +1,513 @@
+[C] [S] [H]
+[F] [B] [C] [S] [W]
+[B] [W] [W] [M] [S] [B]
+[L] [H] [G] [L] [P] [F] [Q]
+[D] [P] [J] [F] [T] [G] [M] [T]
+[P] [G] [B] [N] [L] [W] [P] [W] [R]
+[Z] [V] [W] [J] [J] [C] [T] [S] [C]
+[S] [N] [F] [G] [W] [B] [H] [F] [N]
+ 1 2 3 4 5 6 7 8 9
+
+move 2 from 5 to 9
+move 3 from 1 to 7
+move 2 from 3 to 9
+move 6 from 9 to 5
+move 2 from 3 to 8
+move 9 from 7 to 8
+move 15 from 8 to 9
+move 3 from 1 to 6
+move 6 from 4 to 2
+move 6 from 5 to 6
+move 1 from 4 to 2
+move 14 from 6 to 2
+move 2 from 1 to 5
+move 1 from 7 to 3
+move 1 from 4 to 8
+move 2 from 5 to 6
+move 25 from 2 to 4
+move 2 from 6 to 4
+move 1 from 8 to 1
+move 2 from 9 to 1
+move 1 from 6 to 1
+move 2 from 1 to 7
+move 1 from 7 to 3
+move 2 from 1 to 8
+move 1 from 2 to 6
+move 1 from 3 to 8
+move 4 from 5 to 6
+move 1 from 5 to 3
+move 1 from 9 to 6
+move 2 from 3 to 4
+move 1 from 2 to 6
+move 12 from 9 to 7
+move 1 from 9 to 1
+move 1 from 5 to 8
+move 1 from 3 to 8
+move 28 from 4 to 5
+move 1 from 4 to 3
+move 1 from 2 to 6
+move 1 from 3 to 9
+move 12 from 7 to 2
+move 1 from 9 to 6
+move 6 from 6 to 4
+move 1 from 7 to 4
+move 1 from 1 to 2
+move 28 from 5 to 1
+move 2 from 2 to 8
+move 3 from 8 to 2
+move 7 from 4 to 1
+move 4 from 8 to 6
+move 9 from 2 to 8
+move 7 from 6 to 5
+move 3 from 5 to 9
+move 1 from 9 to 7
+move 1 from 7 to 1
+move 5 from 8 to 4
+move 4 from 1 to 9
+move 6 from 9 to 4
+move 5 from 1 to 5
+move 5 from 2 to 3
+move 4 from 8 to 2
+move 5 from 1 to 4
+move 4 from 5 to 9
+move 9 from 4 to 9
+move 10 from 9 to 8
+move 1 from 9 to 1
+move 2 from 2 to 8
+move 4 from 3 to 8
+move 1 from 2 to 3
+move 2 from 9 to 2
+move 1 from 2 to 6
+move 4 from 4 to 3
+move 3 from 5 to 1
+move 12 from 1 to 4
+move 1 from 5 to 3
+move 1 from 5 to 3
+move 5 from 8 to 5
+move 7 from 8 to 5
+move 8 from 3 to 4
+move 1 from 5 to 1
+move 1 from 6 to 7
+move 2 from 1 to 6
+move 8 from 5 to 9
+move 2 from 5 to 1
+move 9 from 1 to 4
+move 20 from 4 to 2
+move 1 from 5 to 2
+move 4 from 4 to 2
+move 5 from 9 to 2
+move 2 from 8 to 9
+move 23 from 2 to 4
+move 2 from 2 to 5
+move 5 from 1 to 2
+move 28 from 4 to 3
+move 2 from 8 to 1
+move 2 from 5 to 7
+move 1 from 6 to 9
+move 1 from 4 to 8
+move 1 from 8 to 9
+move 1 from 4 to 6
+move 2 from 7 to 2
+move 13 from 3 to 4
+move 5 from 9 to 7
+move 1 from 9 to 6
+move 14 from 2 to 6
+move 1 from 4 to 1
+move 10 from 3 to 2
+move 1 from 6 to 9
+move 2 from 3 to 2
+move 3 from 1 to 9
+move 1 from 3 to 5
+move 3 from 9 to 3
+move 6 from 7 to 4
+move 1 from 9 to 4
+move 1 from 9 to 2
+move 1 from 5 to 3
+move 5 from 3 to 1
+move 17 from 4 to 7
+move 2 from 2 to 8
+move 1 from 3 to 9
+move 1 from 8 to 2
+move 1 from 9 to 6
+move 4 from 6 to 2
+move 10 from 6 to 5
+move 4 from 1 to 5
+move 15 from 2 to 9
+move 1 from 8 to 6
+move 1 from 2 to 8
+move 6 from 9 to 2
+move 3 from 4 to 8
+move 11 from 7 to 1
+move 6 from 9 to 6
+move 1 from 6 to 2
+move 3 from 9 to 3
+move 6 from 2 to 7
+move 6 from 7 to 8
+move 7 from 1 to 9
+move 4 from 1 to 6
+move 2 from 1 to 2
+move 4 from 6 to 7
+move 1 from 2 to 9
+move 1 from 2 to 3
+move 1 from 2 to 1
+move 6 from 8 to 4
+move 2 from 6 to 7
+move 13 from 5 to 9
+move 1 from 5 to 4
+move 3 from 4 to 7
+move 1 from 1 to 7
+move 14 from 9 to 2
+move 2 from 9 to 3
+move 3 from 8 to 5
+move 4 from 3 to 4
+move 8 from 4 to 1
+move 7 from 1 to 9
+move 5 from 6 to 9
+move 4 from 9 to 2
+move 1 from 1 to 9
+move 17 from 2 to 4
+move 1 from 6 to 3
+move 4 from 7 to 5
+move 5 from 7 to 5
+move 1 from 6 to 4
+move 1 from 8 to 3
+move 5 from 7 to 1
+move 2 from 7 to 6
+move 2 from 3 to 6
+move 1 from 2 to 9
+move 7 from 9 to 6
+move 2 from 3 to 7
+move 8 from 6 to 4
+move 3 from 9 to 2
+move 1 from 6 to 4
+move 26 from 4 to 8
+move 2 from 7 to 8
+move 5 from 5 to 9
+move 2 from 6 to 7
+move 4 from 9 to 1
+move 2 from 7 to 5
+move 14 from 8 to 6
+move 3 from 2 to 8
+move 3 from 6 to 8
+move 3 from 6 to 1
+move 10 from 8 to 4
+move 5 from 9 to 4
+move 3 from 8 to 5
+move 1 from 8 to 2
+move 12 from 4 to 8
+move 1 from 9 to 3
+move 6 from 6 to 4
+move 6 from 8 to 2
+move 1 from 3 to 8
+move 1 from 8 to 4
+move 10 from 1 to 9
+move 2 from 1 to 3
+move 7 from 4 to 9
+move 1 from 2 to 1
+move 11 from 8 to 9
+move 1 from 3 to 9
+move 2 from 2 to 7
+move 1 from 3 to 6
+move 2 from 7 to 9
+move 2 from 4 to 6
+move 4 from 6 to 4
+move 2 from 2 to 8
+move 2 from 8 to 4
+move 1 from 1 to 7
+move 2 from 2 to 8
+move 9 from 5 to 2
+move 3 from 5 to 9
+move 1 from 8 to 3
+move 30 from 9 to 7
+move 1 from 6 to 2
+move 7 from 4 to 8
+move 13 from 7 to 2
+move 8 from 7 to 4
+move 2 from 4 to 8
+move 8 from 8 to 1
+move 1 from 8 to 3
+move 2 from 8 to 9
+move 1 from 3 to 7
+move 5 from 7 to 6
+move 1 from 3 to 1
+move 7 from 4 to 8
+move 20 from 2 to 6
+move 2 from 2 to 7
+move 1 from 9 to 5
+move 4 from 7 to 6
+move 3 from 7 to 8
+move 1 from 7 to 2
+move 7 from 8 to 6
+move 3 from 6 to 7
+move 4 from 9 to 1
+move 1 from 2 to 6
+move 1 from 9 to 7
+move 1 from 2 to 8
+move 1 from 7 to 6
+move 3 from 6 to 3
+move 4 from 8 to 1
+move 8 from 6 to 4
+move 3 from 7 to 2
+move 1 from 3 to 2
+move 1 from 4 to 5
+move 2 from 3 to 5
+move 1 from 4 to 6
+move 4 from 1 to 5
+move 4 from 2 to 9
+move 2 from 1 to 6
+move 4 from 9 to 2
+move 3 from 2 to 8
+move 2 from 8 to 4
+move 13 from 6 to 1
+move 4 from 5 to 2
+move 14 from 6 to 3
+move 1 from 2 to 7
+move 2 from 2 to 4
+move 1 from 8 to 6
+move 1 from 6 to 3
+move 1 from 7 to 4
+move 1 from 2 to 3
+move 1 from 2 to 6
+move 11 from 4 to 6
+move 2 from 5 to 4
+move 1 from 5 to 6
+move 12 from 3 to 6
+move 1 from 3 to 7
+move 1 from 5 to 7
+move 3 from 3 to 6
+move 2 from 7 to 5
+move 2 from 5 to 2
+move 8 from 6 to 7
+move 24 from 1 to 3
+move 1 from 4 to 6
+move 10 from 3 to 1
+move 6 from 1 to 8
+move 1 from 6 to 3
+move 1 from 4 to 2
+move 1 from 3 to 1
+move 2 from 2 to 1
+move 1 from 7 to 6
+move 2 from 7 to 5
+move 4 from 3 to 7
+move 1 from 2 to 3
+move 6 from 1 to 6
+move 3 from 7 to 5
+move 4 from 7 to 8
+move 1 from 1 to 2
+move 1 from 2 to 7
+move 8 from 3 to 4
+move 3 from 4 to 7
+move 6 from 8 to 6
+move 2 from 3 to 2
+move 1 from 3 to 9
+move 5 from 5 to 1
+move 2 from 8 to 2
+move 1 from 9 to 2
+move 4 from 1 to 3
+move 3 from 2 to 9
+move 1 from 1 to 2
+move 2 from 9 to 7
+move 2 from 2 to 9
+move 8 from 7 to 5
+move 33 from 6 to 5
+move 20 from 5 to 9
+move 21 from 5 to 7
+move 17 from 7 to 6
+move 10 from 6 to 9
+move 5 from 4 to 7
+move 2 from 3 to 9
+move 1 from 2 to 3
+move 2 from 7 to 3
+move 3 from 9 to 5
+move 23 from 9 to 7
+move 8 from 9 to 6
+move 1 from 9 to 1
+move 1 from 5 to 3
+move 1 from 8 to 9
+move 5 from 6 to 8
+move 1 from 9 to 6
+move 18 from 7 to 2
+move 6 from 7 to 4
+move 6 from 4 to 8
+move 5 from 7 to 4
+move 6 from 6 to 3
+move 1 from 4 to 2
+move 10 from 2 to 1
+move 1 from 2 to 4
+move 7 from 1 to 6
+move 1 from 7 to 1
+move 11 from 6 to 2
+move 1 from 6 to 8
+move 12 from 3 to 1
+move 8 from 1 to 8
+move 2 from 5 to 2
+move 12 from 8 to 6
+move 15 from 2 to 4
+move 7 from 4 to 5
+move 4 from 5 to 9
+move 4 from 9 to 4
+move 5 from 4 to 6
+move 2 from 5 to 2
+move 1 from 2 to 5
+move 2 from 5 to 4
+move 2 from 1 to 3
+move 4 from 1 to 5
+move 2 from 8 to 4
+move 5 from 2 to 9
+move 17 from 6 to 8
+move 1 from 3 to 2
+move 2 from 5 to 4
+move 1 from 3 to 8
+move 1 from 1 to 6
+move 2 from 5 to 6
+move 3 from 9 to 5
+move 1 from 5 to 1
+move 3 from 1 to 8
+move 26 from 8 to 4
+move 1 from 5 to 3
+move 3 from 2 to 7
+move 1 from 5 to 7
+move 21 from 4 to 9
+move 19 from 4 to 5
+move 3 from 4 to 3
+move 2 from 7 to 5
+move 1 from 8 to 2
+move 1 from 6 to 2
+move 1 from 8 to 9
+move 1 from 6 to 7
+move 1 from 2 to 4
+move 1 from 4 to 7
+move 1 from 2 to 7
+move 1 from 7 to 1
+move 1 from 1 to 6
+move 1 from 3 to 5
+move 2 from 6 to 3
+move 13 from 5 to 8
+move 1 from 4 to 2
+move 3 from 5 to 4
+move 5 from 5 to 4
+move 5 from 8 to 9
+move 9 from 9 to 3
+move 2 from 7 to 1
+move 6 from 4 to 2
+move 8 from 9 to 4
+move 1 from 2 to 7
+move 12 from 9 to 8
+move 1 from 4 to 2
+move 3 from 7 to 3
+move 11 from 8 to 5
+move 5 from 8 to 6
+move 3 from 6 to 5
+move 2 from 4 to 1
+move 13 from 5 to 3
+move 1 from 1 to 7
+move 2 from 1 to 8
+move 3 from 4 to 9
+move 1 from 1 to 7
+move 1 from 2 to 4
+move 2 from 7 to 3
+move 1 from 5 to 3
+move 4 from 4 to 2
+move 1 from 4 to 9
+move 30 from 3 to 2
+move 1 from 9 to 7
+move 6 from 8 to 6
+move 1 from 7 to 6
+move 1 from 5 to 1
+move 1 from 3 to 5
+move 30 from 2 to 3
+move 1 from 1 to 9
+move 2 from 9 to 2
+move 9 from 6 to 9
+move 2 from 2 to 9
+move 1 from 5 to 1
+move 5 from 9 to 7
+move 8 from 2 to 5
+move 1 from 1 to 9
+move 3 from 9 to 1
+move 5 from 3 to 6
+move 8 from 5 to 9
+move 13 from 3 to 9
+move 3 from 1 to 7
+move 5 from 7 to 9
+move 17 from 9 to 6
+move 1 from 7 to 6
+move 6 from 3 to 9
+move 1 from 2 to 1
+move 2 from 7 to 1
+move 1 from 2 to 5
+move 21 from 9 to 2
+move 4 from 3 to 6
+move 6 from 6 to 5
+move 7 from 5 to 9
+move 2 from 3 to 8
+move 3 from 1 to 3
+move 4 from 6 to 5
+move 1 from 8 to 1
+move 1 from 8 to 2
+move 4 from 5 to 2
+move 4 from 9 to 1
+move 4 from 3 to 5
+move 2 from 1 to 7
+move 1 from 7 to 4
+move 3 from 9 to 5
+move 25 from 2 to 9
+move 18 from 9 to 1
+move 1 from 4 to 5
+move 1 from 3 to 8
+move 4 from 5 to 6
+move 2 from 9 to 3
+move 17 from 1 to 5
+move 1 from 2 to 7
+move 2 from 3 to 5
+move 3 from 1 to 8
+move 5 from 9 to 2
+move 4 from 8 to 9
+move 12 from 5 to 2
+move 1 from 1 to 8
+move 3 from 9 to 5
+move 1 from 8 to 2
+move 2 from 7 to 2
+move 1 from 9 to 5
+move 9 from 5 to 2
+move 6 from 6 to 2
+move 15 from 6 to 2
+move 5 from 5 to 9
+move 1 from 5 to 9
+move 3 from 9 to 2
+move 3 from 9 to 1
+move 1 from 1 to 9
+move 1 from 9 to 1
+move 19 from 2 to 8
+move 2 from 1 to 9
+move 33 from 2 to 6
+move 4 from 6 to 4
+move 1 from 2 to 6
+move 1 from 9 to 8
+move 3 from 4 to 8
+move 18 from 8 to 3
+move 1 from 4 to 9
+move 10 from 3 to 9
+move 1 from 1 to 4
+move 24 from 6 to 3
+move 1 from 4 to 3
+move 2 from 8 to 7
+move 8 from 9 to 3
+move 5 from 6 to 7
+move 35 from 3 to 2
+move 7 from 7 to 1
+move 3 from 1 to 3
+move 33 from 2 to 6
+move 6 from 3 to 7
+move 5 from 7 to 3
+move 1 from 1 to 4
+move 1 from 7 to 8
+move 1 from 4 to 8
+move 1 from 3 to 2
+move 30 from 6 to 5
+move 2 from 1 to 6
+move 5 from 8 to 1
+move 1 from 9 to 2
+move 2 from 6 to 4
+move 4 from 1 to 7
+move 21 from 5 to 8
diff --git a/day05a/examples/test.txt b/day05a/examples/test.txt
new file mode 100644
index 0000000..84933bb
--- /dev/null
+++ b/day05a/examples/test.txt
@@ -0,0 +1,9 @@
+ [D]
+[N] [C]
+[Z] [M] [P]
+ 1 2 3
+
+move 1 from 2 to 1
+move 3 from 1 to 3
+move 2 from 2 to 1
+move 1 from 1 to 2
diff --git a/day05a/src/main.rs b/day05a/src/main.rs
new file mode 100644
index 0000000..ac7a6d7
--- /dev/null
+++ b/day05a/src/main.rs
@@ -0,0 +1,273 @@
+/// --- Day 5: Supply Stacks ---
+///
+/// The expedition can depart as soon as the final supplies have been unloaded from the
+/// ships. Supplies are stored in stacks of marked crates, but because the needed supplies are
+/// buried under many other crates, the crates need to be rearranged.
+///
+/// The ship has a giant cargo crane capable of moving crates between stacks. To ensure none of
+/// the crates get crushed or fall over, the crane operator will rearrange them in a series of
+/// carefully-planned steps. After the crates are rearranged, the desired crates will be at the
+/// top of each stack.
+///
+/// The Elves don't want to interrupt the crane operator during this delicate procedure, but they
+/// forgot to ask her which crate will end up where, and they want to be ready to unload them as
+/// soon as possible so they can embark.
+///
+/// They do, however, have a drawing of the starting stacks of crates and the rearrangement
+/// procedure (your puzzle input). For example:
+///
+/// [D]
+/// [N] [C]
+/// [Z] [M] [P]
+/// 1 2 3
+///
+/// move 1 from 2 to 1
+/// move 3 from 1 to 3
+/// move 2 from 2 to 1
+/// move 1 from 1 to 2
+///
+/// In this example, there are three stacks of crates. Stack 1 contains two crates: crate Z is on
+/// the bottom, and crate N is on top. Stack 2 contains three crates; from bottom to top, they are
+/// crates M, C, and D. Finally, stack 3 contains a single crate, P.
+///
+/// Then, the rearrangement procedure is given. In each step of the procedure, a quantity of
+/// crates is moved from one stack to a different stack. In the first step of the above
+/// rearrangement procedure, one crate is moved from stack 2 to stack 1, resulting in this
+/// configuration:
+///
+/// [D]
+/// [N] [C]
+/// [Z] [M] [P]
+/// 1 2 3
+///
+/// In the second step, three crates are moved from stack 1 to stack 3. Crates are moved one at a
+/// time, so the first crate to be moved (D) ends up below the second and third crates:
+///
+/// [Z]
+/// [N]
+/// [C] [D]
+/// [M] [P]
+/// 1 2 3
+///
+/// Then, both crates are moved from stack 2 to stack 1. Again, because crates are moved one at a
+/// time, crate C ends up below crate M:
+///
+/// [Z]
+/// [N]
+/// [M] [D]
+/// [C] [P]
+/// 1 2 3
+///
+/// Finally, one crate is moved from stack 1 to stack 2:
+///
+/// [Z]
+/// [N]
+/// [D]
+/// [C] [M] [P]
+/// 1 2 3
+///
+/// The Elves just need to know which crate will end up on top of each stack; in this example, the
+/// top crates are C in stack 1, M in stack 2, and Z in stack 3, so you should combine these
+/// together and give the Elves the message CMZ.
+///
+/// After the rearrangement procedure completes, what crate ends up on top of each stack?
+use clap::Parser;
+use itertools::Itertools;
+use nom::branch::alt;
+use nom::bytes::complete::tag;
+use nom::character::complete::{alpha1, digit1, multispace1};
+use nom::combinator::{map, opt, peek};
+use nom::error::{ErrorKind as NomErrorKind, ParseError};
+use nom::multi::{many1, many1_count};
+use nom::sequence::{delimited, preceded, terminated};
+use nom::IResult;
+
+use std::fs::File;
+use std::io::prelude::*;
+use std::io::BufReader;
+use std::iter::*;
+use std::path::PathBuf;
+
+pub type Input<'a> = &'a str;
+pub type Result<'a, T> = IResult<Input<'a>, T, Error<Input<'a>>>;
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum ErrorKind {
+ Nom(NomErrorKind),
+ Context(&'static str),
+ Custom(String),
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Error<I> {
+ pub errors: Vec<(I, ErrorKind)>,
+}
+
+impl<I> ParseError<I> for Error<I> {
+ fn from_error_kind(input: I, kind: NomErrorKind) -> Self {
+ let errors = vec![(input, ErrorKind::Nom(kind))];
+ Self { errors }
+ }
+
+ fn append(input: I, kind: NomErrorKind, mut other: Self) -> Self {
+ other.errors.push((input, ErrorKind::Nom(kind)));
+ other
+ }
+}
+
+const FILEPATH: &'static str = "examples/input.txt";
+
+#[derive(Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+struct Cli {
+ #[clap(short, long, default_value = FILEPATH)]
+ file: PathBuf,
+}
+
+#[derive(Debug, Clone)]
+struct Supplies(Vec<Vec<char>>);
+
+#[derive(Debug, Clone)]
+struct Order {
+ from: usize,
+ to: usize,
+ amount: usize,
+}
+
+#[derive(Debug, Clone)]
+enum LineKind {
+ Axis(usize),
+ Crates(Vec<char>),
+}
+
+fn parse_digit(input: &str) -> Result<char> {
+ map(preceded(multispace1, digit1), |s: &str| {
+ s.chars().next().unwrap()
+ })(input)
+}
+
+fn parse_crate(input: &str) -> Result<char> {
+ map(delimited(tag("["), alpha1, tag("]")), |s: &str| {
+ s.chars().next().unwrap()
+ })(input)
+}
+
+fn parse_crate_or_empty(input: &str) -> Result<char> {
+ terminated(alt((map(tag(" "), |_| ' '), parse_crate)), opt(tag(" ")))(input)
+}
+
+fn parse_line(input: &str) -> Result<LineKind> {
+ let res = peek(parse_digit)(input);
+ if res.is_ok() {
+ map(many1_count(parse_digit), |len| LineKind::Axis(len))(input)
+ } else {
+ map(many1(parse_crate_or_empty), |v| LineKind::Crates(v))(input)
+ }
+}
+
+impl Supplies {
+ fn new() -> Self {
+ Self(Vec::<Vec<char>>::new())
+ }
+
+ fn idx_to_internal(idx: usize) -> usize {
+ idx - 1
+ }
+
+ fn initialize(&mut self, input: Vec<LineKind>) {
+ let axis = &input[input.len() - 1];
+ let LineKind::Axis(len) = axis else {
+ panic!();
+ };
+ self.resize(*len);
+
+ let _ = input
+ .into_iter()
+ .rev()
+ .skip(1)
+ .map(|x| match x {
+ LineKind::Crates(v) => v,
+ _ => panic!(),
+ })
+ .map(|vc| {
+ vc.into_iter()
+ .zip(1usize..)
+ .filter(|(c, _)| *c != ' ')
+ .collect_vec()
+ })
+ .flatten()
+ .scan(self, |state, (c, idx)| {
+ state.push(idx, c);
+ Some(())
+ })
+ .last();
+ }
+
+ fn pop(&mut self, idx: usize) -> char {
+ self.0[Self::idx_to_internal(idx)].pop().unwrap()
+ }
+
+ fn peek(&self, idx: usize) -> char {
+ self.0[Self::idx_to_internal(idx)][self.0[Self::idx_to_internal(idx)].len() - 1]
+ }
+
+ fn push(&mut self, idx: usize, letter: char) {
+ self.0[Self::idx_to_internal(idx)].push(letter)
+ }
+
+ fn resize(&mut self, len: usize) {
+ self.0.resize(len, Vec::<char>::new())
+ }
+
+ fn top_chars(&self) -> String {
+ (0..self.0.len())
+ .map(|idx| self.peek(idx + 1).to_string())
+ .join("")
+ }
+
+ fn transfer(&mut self, order: Order) {
+ for _ in 0..order.amount {
+ let v = self.pop(order.from);
+ self.push(order.to, v);
+ }
+ }
+}
+
+fn main() {
+ let args = Cli::parse();
+
+ let file = File::open(&args.file).unwrap();
+ let reader = BufReader::new(file);
+
+ let init = reader
+ .lines()
+ .map(|l| l.unwrap())
+ .take_while(|l| !l.is_empty())
+ .map(|l| parse_line(l.as_str()).unwrap().1)
+ .collect_vec();
+
+ let mut supplies = Supplies::new();
+ supplies.initialize(init);
+
+ let file = File::open(&args.file).unwrap();
+ let reader = BufReader::new(file);
+ let _ = reader
+ .lines()
+ .map(|l| l.unwrap())
+ .skip_while(|l| !l.contains("move"))
+ .map(|l| {
+ let sp = l.split_whitespace().collect_vec();
+ Order {
+ from: sp[3].parse::<usize>().unwrap(),
+ to: sp[5].parse::<usize>().unwrap(),
+ amount: sp[1].parse::<usize>().unwrap(),
+ }
+ })
+ .scan(&mut supplies, |state, order| {
+ state.transfer(order);
+ Some(())
+ })
+ .last();
+
+ println!("{}", supplies.top_chars());
+}
diff --git a/day05b/Cargo.toml b/day05b/Cargo.toml
new file mode 100644
index 0000000..92e3a21
--- /dev/null
+++ b/day05b/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "day05b"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clap = { version = "3.2.20", features = ["derive"] }
+nom = "7.1.1"
+itertools = "0.10.5"
diff --git a/day05b/examples/input.txt b/day05b/examples/input.txt
new file mode 100644
index 0000000..ca57552
--- /dev/null
+++ b/day05b/examples/input.txt
@@ -0,0 +1,513 @@
+[C] [S] [H]
+[F] [B] [C] [S] [W]
+[B] [W] [W] [M] [S] [B]
+[L] [H] [G] [L] [P] [F] [Q]
+[D] [P] [J] [F] [T] [G] [M] [T]
+[P] [G] [B] [N] [L] [W] [P] [W] [R]
+[Z] [V] [W] [J] [J] [C] [T] [S] [C]
+[S] [N] [F] [G] [W] [B] [H] [F] [N]
+ 1 2 3 4 5 6 7 8 9
+
+move 2 from 5 to 9
+move 3 from 1 to 7
+move 2 from 3 to 9
+move 6 from 9 to 5
+move 2 from 3 to 8
+move 9 from 7 to 8
+move 15 from 8 to 9
+move 3 from 1 to 6
+move 6 from 4 to 2
+move 6 from 5 to 6
+move 1 from 4 to 2
+move 14 from 6 to 2
+move 2 from 1 to 5
+move 1 from 7 to 3
+move 1 from 4 to 8
+move 2 from 5 to 6
+move 25 from 2 to 4
+move 2 from 6 to 4
+move 1 from 8 to 1
+move 2 from 9 to 1
+move 1 from 6 to 1
+move 2 from 1 to 7
+move 1 from 7 to 3
+move 2 from 1 to 8
+move 1 from 2 to 6
+move 1 from 3 to 8
+move 4 from 5 to 6
+move 1 from 5 to 3
+move 1 from 9 to 6
+move 2 from 3 to 4
+move 1 from 2 to 6
+move 12 from 9 to 7
+move 1 from 9 to 1
+move 1 from 5 to 8
+move 1 from 3 to 8
+move 28 from 4 to 5
+move 1 from 4 to 3
+move 1 from 2 to 6
+move 1 from 3 to 9
+move 12 from 7 to 2
+move 1 from 9 to 6
+move 6 from 6 to 4
+move 1 from 7 to 4
+move 1 from 1 to 2
+move 28 from 5 to 1
+move 2 from 2 to 8
+move 3 from 8 to 2
+move 7 from 4 to 1
+move 4 from 8 to 6
+move 9 from 2 to 8
+move 7 from 6 to 5
+move 3 from 5 to 9
+move 1 from 9 to 7
+move 1 from 7 to 1
+move 5 from 8 to 4
+move 4 from 1 to 9
+move 6 from 9 to 4
+move 5 from 1 to 5
+move 5 from 2 to 3
+move 4 from 8 to 2
+move 5 from 1 to 4
+move 4 from 5 to 9
+move 9 from 4 to 9
+move 10 from 9 to 8
+move 1 from 9 to 1
+move 2 from 2 to 8
+move 4 from 3 to 8
+move 1 from 2 to 3
+move 2 from 9 to 2
+move 1 from 2 to 6
+move 4 from 4 to 3
+move 3 from 5 to 1
+move 12 from 1 to 4
+move 1 from 5 to 3
+move 1 from 5 to 3
+move 5 from 8 to 5
+move 7 from 8 to 5
+move 8 from 3 to 4
+move 1 from 5 to 1
+move 1 from 6 to 7
+move 2 from 1 to 6
+move 8 from 5 to 9
+move 2 from 5 to 1
+move 9 from 1 to 4
+move 20 from 4 to 2
+move 1 from 5 to 2
+move 4 from 4 to 2
+move 5 from 9 to 2
+move 2 from 8 to 9
+move 23 from 2 to 4
+move 2 from 2 to 5
+move 5 from 1 to 2
+move 28 from 4 to 3
+move 2 from 8 to 1
+move 2 from 5 to 7
+move 1 from 6 to 9
+move 1 from 4 to 8
+move 1 from 8 to 9
+move 1 from 4 to 6
+move 2 from 7 to 2
+move 13 from 3 to 4
+move 5 from 9 to 7
+move 1 from 9 to 6
+move 14 from 2 to 6
+move 1 from 4 to 1
+move 10 from 3 to 2
+move 1 from 6 to 9
+move 2 from 3 to 2
+move 3 from 1 to 9
+move 1 from 3 to 5
+move 3 from 9 to 3
+move 6 from 7 to 4
+move 1 from 9 to 4
+move 1 from 9 to 2
+move 1 from 5 to 3
+move 5 from 3 to 1
+move 17 from 4 to 7
+move 2 from 2 to 8
+move 1 from 3 to 9
+move 1 from 8 to 2
+move 1 from 9 to 6
+move 4 from 6 to 2
+move 10 from 6 to 5
+move 4 from 1 to 5
+move 15 from 2 to 9
+move 1 from 8 to 6
+move 1 from 2 to 8
+move 6 from 9 to 2
+move 3 from 4 to 8
+move 11 from 7 to 1
+move 6 from 9 to 6
+move 1 from 6 to 2
+move 3 from 9 to 3
+move 6 from 2 to 7
+move 6 from 7 to 8
+move 7 from 1 to 9
+move 4 from 1 to 6
+move 2 from 1 to 2
+move 4 from 6 to 7
+move 1 from 2 to 9
+move 1 from 2 to 3
+move 1 from 2 to 1
+move 6 from 8 to 4
+move 2 from 6 to 7
+move 13 from 5 to 9
+move 1 from 5 to 4
+move 3 from 4 to 7
+move 1 from 1 to 7
+move 14 from 9 to 2
+move 2 from 9 to 3
+move 3 from 8 to 5
+move 4 from 3 to 4
+move 8 from 4 to 1
+move 7 from 1 to 9
+move 5 from 6 to 9
+move 4 from 9 to 2
+move 1 from 1 to 9
+move 17 from 2 to 4
+move 1 from 6 to 3
+move 4 from 7 to 5
+move 5 from 7 to 5
+move 1 from 6 to 4
+move 1 from 8 to 3
+move 5 from 7 to 1
+move 2 from 7 to 6
+move 2 from 3 to 6
+move 1 from 2 to 9
+move 7 from 9 to 6
+move 2 from 3 to 7
+move 8 from 6 to 4
+move 3 from 9 to 2
+move 1 from 6 to 4
+move 26 from 4 to 8
+move 2 from 7 to 8
+move 5 from 5 to 9
+move 2 from 6 to 7
+move 4 from 9 to 1
+move 2 from 7 to 5
+move 14 from 8 to 6
+move 3 from 2 to 8
+move 3 from 6 to 8
+move 3 from 6 to 1
+move 10 from 8 to 4
+move 5 from 9 to 4
+move 3 from 8 to 5
+move 1 from 8 to 2
+move 12 from 4 to 8
+move 1 from 9 to 3
+move 6 from 6 to 4
+move 6 from 8 to 2
+move 1 from 3 to 8
+move 1 from 8 to 4
+move 10 from 1 to 9
+move 2 from 1 to 3
+move 7 from 4 to 9
+move 1 from 2 to 1
+move 11 from 8 to 9
+move 1 from 3 to 9
+move 2 from 2 to 7
+move 1 from 3 to 6
+move 2 from 7 to 9
+move 2 from 4 to 6
+move 4 from 6 to 4
+move 2 from 2 to 8
+move 2 from 8 to 4
+move 1 from 1 to 7
+move 2 from 2 to 8
+move 9 from 5 to 2
+move 3 from 5 to 9
+move 1 from 8 to 3
+move 30 from 9 to 7
+move 1 from 6 to 2
+move 7 from 4 to 8
+move 13 from 7 to 2
+move 8 from 7 to 4
+move 2 from 4 to 8
+move 8 from 8 to 1
+move 1 from 8 to 3
+move 2 from 8 to 9
+move 1 from 3 to 7
+move 5 from 7 to 6
+move 1 from 3 to 1
+move 7 from 4 to 8
+move 20 from 2 to 6
+move 2 from 2 to 7
+move 1 from 9 to 5
+move 4 from 7 to 6
+move 3 from 7 to 8
+move 1 from 7 to 2
+move 7 from 8 to 6
+move 3 from 6 to 7
+move 4 from 9 to 1
+move 1 from 2 to 6
+move 1 from 9 to 7
+move 1 from 2 to 8
+move 1 from 7 to 6
+move 3 from 6 to 3
+move 4 from 8 to 1
+move 8 from 6 to 4
+move 3 from 7 to 2
+move 1 from 3 to 2
+move 1 from 4 to 5
+move 2 from 3 to 5
+move 1 from 4 to 6
+move 4 from 1 to 5
+move 4 from 2 to 9
+move 2 from 1 to 6
+move 4 from 9 to 2
+move 3 from 2 to 8
+move 2 from 8 to 4
+move 13 from 6 to 1
+move 4 from 5 to 2
+move 14 from 6 to 3
+move 1 from 2 to 7
+move 2 from 2 to 4
+move 1 from 8 to 6
+move 1 from 6 to 3
+move 1 from 7 to 4
+move 1 from 2 to 3
+move 1 from 2 to 6
+move 11 from 4 to 6
+move 2 from 5 to 4
+move 1 from 5 to 6
+move 12 from 3 to 6
+move 1 from 3 to 7
+move 1 from 5 to 7
+move 3 from 3 to 6
+move 2 from 7 to 5
+move 2 from 5 to 2
+move 8 from 6 to 7
+move 24 from 1 to 3
+move 1 from 4 to 6
+move 10 from 3 to 1
+move 6 from 1 to 8
+move 1 from 6 to 3
+move 1 from 4 to 2
+move 1 from 3 to 1
+move 2 from 2 to 1
+move 1 from 7 to 6
+move 2 from 7 to 5
+move 4 from 3 to 7
+move 1 from 2 to 3
+move 6 from 1 to 6
+move 3 from 7 to 5
+move 4 from 7 to 8
+move 1 from 1 to 2
+move 1 from 2 to 7
+move 8 from 3 to 4
+move 3 from 4 to 7
+move 6 from 8 to 6
+move 2 from 3 to 2
+move 1 from 3 to 9
+move 5 from 5 to 1
+move 2 from 8 to 2
+move 1 from 9 to 2
+move 4 from 1 to 3
+move 3 from 2 to 9
+move 1 from 1 to 2
+move 2 from 9 to 7
+move 2 from 2 to 9
+move 8 from 7 to 5
+move 33 from 6 to 5
+move 20 from 5 to 9
+move 21 from 5 to 7
+move 17 from 7 to 6
+move 10 from 6 to 9
+move 5 from 4 to 7
+move 2 from 3 to 9
+move 1 from 2 to 3
+move 2 from 7 to 3
+move 3 from 9 to 5
+move 23 from 9 to 7
+move 8 from 9 to 6
+move 1 from 9 to 1
+move 1 from 5 to 3
+move 1 from 8 to 9
+move 5 from 6 to 8
+move 1 from 9 to 6
+move 18 from 7 to 2
+move 6 from 7 to 4
+move 6 from 4 to 8
+move 5 from 7 to 4
+move 6 from 6 to 3
+move 1 from 4 to 2
+move 10 from 2 to 1
+move 1 from 2 to 4
+move 7 from 1 to 6
+move 1 from 7 to 1
+move 11 from 6 to 2
+move 1 from 6 to 8
+move 12 from 3 to 1
+move 8 from 1 to 8
+move 2 from 5 to 2
+move 12 from 8 to 6
+move 15 from 2 to 4
+move 7 from 4 to 5
+move 4 from 5 to 9
+move 4 from 9 to 4
+move 5 from 4 to 6
+move 2 from 5 to 2
+move 1 from 2 to 5
+move 2 from 5 to 4
+move 2 from 1 to 3
+move 4 from 1 to 5
+move 2 from 8 to 4
+move 5 from 2 to 9
+move 17 from 6 to 8
+move 1 from 3 to 2
+move 2 from 5 to 4
+move 1 from 3 to 8
+move 1 from 1 to 6
+move 2 from 5 to 6
+move 3 from 9 to 5
+move 1 from 5 to 1
+move 3 from 1 to 8
+move 26 from 8 to 4
+move 1 from 5 to 3
+move 3 from 2 to 7
+move 1 from 5 to 7
+move 21 from 4 to 9
+move 19 from 4 to 5
+move 3 from 4 to 3
+move 2 from 7 to 5
+move 1 from 8 to 2
+move 1 from 6 to 2
+move 1 from 8 to 9
+move 1 from 6 to 7
+move 1 from 2 to 4
+move 1 from 4 to 7
+move 1 from 2 to 7
+move 1 from 7 to 1
+move 1 from 1 to 6
+move 1 from 3 to 5
+move 2 from 6 to 3
+move 13 from 5 to 8
+move 1 from 4 to 2
+move 3 from 5 to 4
+move 5 from 5 to 4
+move 5 from 8 to 9
+move 9 from 9 to 3
+move 2 from 7 to 1
+move 6 from 4 to 2
+move 8 from 9 to 4
+move 1 from 2 to 7
+move 12 from 9 to 8
+move 1 from 4 to 2
+move 3 from 7 to 3
+move 11 from 8 to 5
+move 5 from 8 to 6
+move 3 from 6 to 5
+move 2 from 4 to 1
+move 13 from 5 to 3
+move 1 from 1 to 7
+move 2 from 1 to 8
+move 3 from 4 to 9
+move 1 from 1 to 7
+move 1 from 2 to 4
+move 2 from 7 to 3
+move 1 from 5 to 3
+move 4 from 4 to 2
+move 1 from 4 to 9
+move 30 from 3 to 2
+move 1 from 9 to 7
+move 6 from 8 to 6
+move 1 from 7 to 6
+move 1 from 5 to 1
+move 1 from 3 to 5
+move 30 from 2 to 3
+move 1 from 1 to 9
+move 2 from 9 to 2
+move 9 from 6 to 9
+move 2 from 2 to 9
+move 1 from 5 to 1
+move 5 from 9 to 7
+move 8 from 2 to 5
+move 1 from 1 to 9
+move 3 from 9 to 1
+move 5 from 3 to 6
+move 8 from 5 to 9
+move 13 from 3 to 9
+move 3 from 1 to 7
+move 5 from 7 to 9
+move 17 from 9 to 6
+move 1 from 7 to 6
+move 6 from 3 to 9
+move 1 from 2 to 1
+move 2 from 7 to 1
+move 1 from 2 to 5
+move 21 from 9 to 2
+move 4 from 3 to 6
+move 6 from 6 to 5
+move 7 from 5 to 9
+move 2 from 3 to 8
+move 3 from 1 to 3
+move 4 from 6 to 5
+move 1 from 8 to 1
+move 1 from 8 to 2
+move 4 from 5 to 2
+move 4 from 9 to 1
+move 4 from 3 to 5
+move 2 from 1 to 7
+move 1 from 7 to 4
+move 3 from 9 to 5
+move 25 from 2 to 9
+move 18 from 9 to 1
+move 1 from 4 to 5
+move 1 from 3 to 8
+move 4 from 5 to 6
+move 2 from 9 to 3
+move 17 from 1 to 5
+move 1 from 2 to 7
+move 2 from 3 to 5
+move 3 from 1 to 8
+move 5 from 9 to 2
+move 4 from 8 to 9
+move 12 from 5 to 2
+move 1 from 1 to 8
+move 3 from 9 to 5
+move 1 from 8 to 2
+move 2 from 7 to 2
+move 1 from 9 to 5
+move 9 from 5 to 2
+move 6 from 6 to 2
+move 15 from 6 to 2
+move 5 from 5 to 9
+move 1 from 5 to 9
+move 3 from 9 to 2
+move 3 from 9 to 1
+move 1 from 1 to 9
+move 1 from 9 to 1
+move 19 from 2 to 8
+move 2 from 1 to 9
+move 33 from 2 to 6
+move 4 from 6 to 4
+move 1 from 2 to 6
+move 1 from 9 to 8
+move 3 from 4 to 8
+move 18 from 8 to 3
+move 1 from 4 to 9
+move 10 from 3 to 9
+move 1 from 1 to 4
+move 24 from 6 to 3
+move 1 from 4 to 3
+move 2 from 8 to 7
+move 8 from 9 to 3
+move 5 from 6 to 7
+move 35 from 3 to 2
+move 7 from 7 to 1
+move 3 from 1 to 3
+move 33 from 2 to 6
+move 6 from 3 to 7
+move 5 from 7 to 3
+move 1 from 1 to 4
+move 1 from 7 to 8
+move 1 from 4 to 8
+move 1 from 3 to 2
+move 30 from 6 to 5
+move 2 from 1 to 6
+move 5 from 8 to 1
+move 1 from 9 to 2
+move 2 from 6 to 4
+move 4 from 1 to 7
+move 21 from 5 to 8
diff --git a/day05b/examples/test.txt b/day05b/examples/test.txt
new file mode 100644
index 0000000..84933bb
--- /dev/null
+++ b/day05b/examples/test.txt
@@ -0,0 +1,9 @@
+ [D]
+[N] [C]
+[Z] [M] [P]
+ 1 2 3
+
+move 1 from 2 to 1
+move 3 from 1 to 3
+move 2 from 2 to 1
+move 1 from 1 to 2
diff --git a/day05b/src/main.rs b/day05b/src/main.rs
new file mode 100644
index 0000000..4018b83
--- /dev/null
+++ b/day05b/src/main.rs
@@ -0,0 +1,268 @@
+/// --- Part Two ---
+///
+/// As you watch the crane operator expertly rearrange the crates, you notice the process isn't
+/// following your prediction.
+///
+/// Some mud was covering the writing on the side of the crane, and you quickly wipe it away. The
+/// crane isn't a CrateMover 9000 - it's a CrateMover 9001.
+///
+/// The CrateMover 9001 is notable for many new and exciting features: air conditioning, leather
+/// seats, an extra cup holder, and the ability to pick up and move multiple crates at once.
+///
+/// Again considering the example above, the crates begin in the same configuration:
+///
+/// ```
+/// [D]
+/// [N] [C]
+/// [Z] [M] [P]
+/// 1 2 3
+/// ```
+///
+/// Moving a single crate from stack 2 to stack 1 behaves the same as before:
+///
+/// ```
+/// [D]
+/// [N] [C]
+/// [Z] [M] [P]
+/// 1 2 3
+/// ```
+///
+/// However, the action of moving three crates from stack 1 to stack 3 means that those three moved
+/// crates stay in the same order, resulting in this new configuration:
+///
+/// ```
+/// [D]
+/// [N]
+/// [C] [Z]
+/// [M] [P]
+/// 1 2 3
+/// ```
+///
+/// Next, as both crates are moved from stack 2 to stack 1, they retain their order as well:
+///
+/// ```
+/// [D]
+/// [N]
+/// [C] [Z]
+/// [M] [P]
+/// 1 2 3
+/// ```
+///
+/// Finally, a single crate is still moved from stack 1 to stack 2, but now it's crate C that gets moved:
+///
+/// ```
+/// [D]
+/// [N]
+/// [Z]
+/// [M] [C] [P]
+/// 1 2 3
+/// ```
+///
+/// In this example, the CrateMover 9001 has put the crates in a totally different order: MCD.
+///
+/// Before the rearrangement process finishes, update your simulation so that the Elves know where
+/// they should stand to be ready to unload the final supplies. After the rearrangement procedure
+/// completes, what crate ends up on top of each stack?
+use clap::Parser;
+use itertools::Itertools;
+use nom::branch::alt;
+use nom::bytes::complete::tag;
+use nom::character::complete::{alpha1, digit1, multispace1};
+use nom::combinator::{map, opt, peek};
+use nom::error::{ErrorKind as NomErrorKind, ParseError};
+use nom::multi::{many1, many1_count};
+use nom::sequence::{delimited, preceded, terminated};
+use nom::IResult;
+
+use std::fs::File;
+use std::io::prelude::*;
+use std::io::BufReader;
+use std::iter::*;
+use std::path::PathBuf;
+
+pub type Input<'a> = &'a str;
+pub type Result<'a, T> = IResult<Input<'a>, T, Error<Input<'a>>>;
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum ErrorKind {
+ Nom(NomErrorKind),
+ Context(&'static str),
+ Custom(String),
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Error<I> {
+ pub errors: Vec<(I, ErrorKind)>,
+}
+
+impl<I> ParseError<I> for Error<I> {
+ fn from_error_kind(input: I, kind: NomErrorKind) -> Self {
+ let errors = vec![(input, ErrorKind::Nom(kind))];
+ Self { errors }
+ }
+
+ fn append(input: I, kind: NomErrorKind, mut other: Self) -> Self {
+ other.errors.push((input, ErrorKind::Nom(kind)));
+ other
+ }
+}
+
+const FILEPATH: &'static str = "examples/input.txt";
+
+#[derive(Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+struct Cli {
+ #[clap(short, long, default_value = FILEPATH)]
+ file: PathBuf,
+}
+
+#[derive(Debug, Clone)]
+struct Supplies(Vec<Vec<char>>);
+
+#[derive(Debug, Clone)]
+struct Order {
+ from: usize,
+ to: usize,
+ amount: usize,
+}
+
+#[derive(Debug, Clone)]
+enum LineKind {
+ Axis(usize),
+ Crates(Vec<char>),
+}
+
+fn parse_digit(input: &str) -> Result<char> {
+ map(preceded(multispace1, digit1), |s: &str| {
+ s.chars().next().unwrap()
+ })(input)
+}
+
+fn parse_crate(input: &str) -> Result<char> {
+ map(delimited(tag("["), alpha1, tag("]")), |s: &str| {
+ s.chars().next().unwrap()
+ })(input)
+}
+
+fn parse_crate_or_empty(input: &str) -> Result<char> {
+ terminated(alt((map(tag(" "), |_| ' '), parse_crate)), opt(tag(" ")))(input)
+}
+
+fn parse_line(input: &str) -> Result<LineKind> {
+ let res = peek(parse_digit)(input);
+ if res.is_ok() {
+ map(many1_count(parse_digit), |len| LineKind::Axis(len))(input)
+ } else {
+ map(many1(parse_crate_or_empty), |v| LineKind::Crates(v))(input)
+ }
+}
+
+impl Supplies {
+ fn new() -> Self {
+ Self(Vec::<Vec<char>>::new())
+ }
+
+ fn idx_to_internal(idx: usize) -> usize {
+ idx - 1
+ }
+
+ fn initialize(&mut self, input: Vec<LineKind>) {
+ let axis = &input[input.len() - 1];
+ let LineKind::Axis(len) = axis else {
+ panic!();
+ };
+ self.resize(*len);
+
+ let _ = input
+ .into_iter()
+ .rev()
+ .skip(1)
+ .map(|x| match x {
+ LineKind::Crates(v) => v,
+ _ => panic!(),
+ })
+ .map(|vc| {
+ vc.into_iter()
+ .zip(1usize..)
+ .filter(|(c, _)| *c != ' ')
+ .collect_vec()
+ })
+ .flatten()
+ .scan(self, |state, (c, idx)| {
+ state.push(idx, c);
+ Some(())
+ })
+ .last();
+ }
+
+ fn pop(&mut self, idx: usize) -> char {
+ self.0[Self::idx_to_internal(idx)].pop().unwrap()
+ }
+
+ fn peek(&self, idx: usize) -> char {
+ self.0[Self::idx_to_internal(idx)][self.0[Self::idx_to_internal(idx)].len() - 1]
+ }
+
+ fn push(&mut self, idx: usize, letter: char) {
+ self.0[Self::idx_to_internal(idx)].push(letter)
+ }
+
+ fn resize(&mut self, len: usize) {
+ self.0.resize(len, Vec::<char>::new())
+ }
+
+ fn top_chars(&self) -> String {
+ (0..self.0.len())
+ .map(|idx| self.peek(idx + 1).to_string())
+ .join("")
+ }
+
+ fn transfer(&mut self, order: Order) {
+ let popped = (0..order.amount)
+ .into_iter()
+ .map(|_| self.pop(order.from))
+ .collect_vec();
+ for c in popped.into_iter().rev() {
+ self.push(order.to, c);
+ }
+ }
+}
+
+fn main() {
+ let args = Cli::parse();
+
+ let file = File::open(&args.file).unwrap();
+ let reader = BufReader::new(file);
+
+ let init = reader
+ .lines()
+ .map(|l| l.unwrap())
+ .take_while(|l| !l.is_empty())
+ .map(|l| parse_line(l.as_str()).unwrap().1)
+ .collect_vec();
+
+ let mut supplies = Supplies::new();
+ supplies.initialize(init);
+
+ let file = File::open(&args.file).unwrap();
+ let reader = BufReader::new(file);
+ let _ = reader
+ .lines()
+ .map(|l| l.unwrap())
+ .skip_while(|l| !l.contains("move"))
+ .map(|l| {
+ let sp = l.split_whitespace().collect_vec();
+ Order {
+ from: sp[3].parse::<usize>().unwrap(),
+ to: sp[5].parse::<usize>().unwrap(),
+ amount: sp[1].parse::<usize>().unwrap(),
+ }
+ })
+ .scan(&mut supplies, |state, order| {
+ state.transfer(order);
+ Some(())
+ })
+ .last();
+
+ println!("{}", supplies.top_chars());
+}