diff options
| author | Shivesh Mandalia <mail@shivesh.org> | 2022-12-21 18:17:44 +0000 |
|---|---|---|
| committer | Shivesh Mandalia <mail@shivesh.org> | 2022-12-21 18:17:44 +0000 |
| commit | 666b11bc77f17d6d2b5a466c56ea7710bb9134fd (patch) | |
| tree | b19bd61fb34a190ec825e18b64a04656fc86b6cc | |
| parent | a667c19882e1feb542a122781b4efe5545dea0dd (diff) | |
| download | advent_of_code_2022-666b11bc77f17d6d2b5a466c56ea7710bb9134fd.tar.gz advent_of_code_2022-666b11bc77f17d6d2b5a466c56ea7710bb9134fd.zip | |
complete day 5
| -rw-r--r-- | Cargo.lock | 40 | ||||
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | day05a/Cargo.toml | 11 | ||||
| -rw-r--r-- | day05a/examples/input.txt | 513 | ||||
| -rw-r--r-- | day05a/examples/test.txt | 9 | ||||
| -rw-r--r-- | day05a/src/main.rs | 273 | ||||
| -rw-r--r-- | day05b/Cargo.toml | 11 | ||||
| -rw-r--r-- | day05b/examples/input.txt | 513 | ||||
| -rw-r--r-- | day05b/examples/test.txt | 9 | ||||
| -rw-r--r-- | day05b/src/main.rs | 268 |
10 files changed, 1649 insertions, 2 deletions
@@ -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" @@ -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()); +} |
