summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2021/Cargo.lock585
-rw-r--r--2021/Cargo.toml15
-rw-r--r--2021/inputs/day_1.txt2000
-rw-r--r--2021/inputs/day_10.txt94
-rw-r--r--2021/inputs/day_11.txt10
-rw-r--r--2021/inputs/day_12.txt23
-rw-r--r--2021/inputs/day_13.txt806
-rw-r--r--2021/inputs/day_14.txt102
-rw-r--r--2021/inputs/day_15.txt100
-rw-r--r--2021/inputs/day_16.txt1
-rw-r--r--2021/inputs/day_17.txt1
-rw-r--r--2021/inputs/day_18.txt100
-rw-r--r--2021/inputs/day_19.txt856
-rw-r--r--2021/inputs/day_2.txt1000
-rw-r--r--2021/inputs/day_20.txt102
-rw-r--r--2021/inputs/day_21.txt2
-rw-r--r--2021/inputs/day_22.txt420
-rw-r--r--2021/inputs/day_23.txt5
-rw-r--r--2021/inputs/day_24.txt252
-rw-r--r--2021/inputs/day_25.txt137
-rw-r--r--2021/inputs/day_3.txt1000
-rw-r--r--2021/inputs/day_4.txt601
-rw-r--r--2021/inputs/day_5.txt500
-rw-r--r--2021/inputs/day_6.txt1
-rw-r--r--2021/inputs/day_7.txt1
-rw-r--r--2021/inputs/day_8.txt200
-rw-r--r--2021/inputs/day_9.txt100
-rw-r--r--2021/proptest-regressions/bin/day_24.txt11
-rw-r--r--2021/readme.org2
-rw-r--r--2021/src/bin/day_1.rs75
-rw-r--r--2021/src/bin/day_10.rs124
-rw-r--r--2021/src/bin/day_11.rs130
-rw-r--r--2021/src/bin/day_12.rs146
-rw-r--r--2021/src/bin/day_13.rs136
-rw-r--r--2021/src/bin/day_14.rs125
-rw-r--r--2021/src/bin/day_15.rs162
-rw-r--r--2021/src/bin/day_16.rs217
-rw-r--r--2021/src/bin/day_17.rs82
-rw-r--r--2021/src/bin/day_18.rs193
-rw-r--r--2021/src/bin/day_19.rs223
-rw-r--r--2021/src/bin/day_2.rs100
-rw-r--r--2021/src/bin/day_20.rs201
-rw-r--r--2021/src/bin/day_21.rs76
-rw-r--r--2021/src/bin/day_22.rs379
-rw-r--r--2021/src/bin/day_23.rs224
-rw-r--r--2021/src/bin/day_24.rs588
-rw-r--r--2021/src/bin/day_25.rs98
-rw-r--r--2021/src/bin/day_2_part_2.rs124
-rw-r--r--2021/src/bin/day_3.rs128
-rw-r--r--2021/src/bin/day_4.rs259
-rw-r--r--2021/src/bin/day_5.rs137
-rw-r--r--2021/src/bin/day_6.rs79
-rw-r--r--2021/src/bin/day_7.rs88
-rw-r--r--2021/src/bin/day_8.rs262
-rw-r--r--2021/src/bin/day_9.rs186
-rw-r--r--2021/src/lib.rs1
-rw-r--r--2021/src/parsers.rs1
57 files changed, 13571 insertions, 0 deletions
diff --git a/2021/Cargo.lock b/2021/Cargo.lock
new file mode 100644
index 0000000..e4c9ba9
--- /dev/null
+++ b/2021/Cargo.lock
@@ -0,0 +1,585 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aoc2021"
+version = "0.1.0"
+dependencies = [
+ "cached",
+ "derive_more",
+ "nom",
+ "proptest",
+ "thiserror",
+]
+
+[[package]]
+name = "async-mutex"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
+dependencies = [
+ "event-listener",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.52"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "bit-set"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cached"
+version = "0.25.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14d3b04f85a6ef9fe543b2564ec8630bdf3363aa9bf664a1bfc85033e7350aaf"
+dependencies = [
+ "async-mutex",
+ "async-trait",
+ "cached_proc_macro",
+ "cached_proc_macro_types",
+ "futures",
+ "hashbrown",
+ "once_cell",
+]
+
+[[package]]
+name = "cached_proc_macro"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4230b8d9f5db741004bfaef172c5b2dbf0eb94f105204cc6147a220080daaa85"
+dependencies = [
+ "cached_proc_macro_types",
+ "darling",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "cached_proc_macro_types"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "darling"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "event-listener"
+version = "2.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "futures"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508"
+
+[[package]]
+name = "futures-task"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72"
+
+[[package]]
+name = "futures-util"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.112"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+ "version_check",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "proptest"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5"
+dependencies = [
+ "bit-set",
+ "bitflags",
+ "byteorder",
+ "lazy_static",
+ "num-traits",
+ "quick-error 2.0.1",
+ "rand",
+ "rand_chacha",
+ "rand_xorshift",
+ "regex-syntax",
+ "rusty-fork",
+ "tempfile",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quick-error"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
+
+[[package]]
+name = "quote"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_xorshift"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "rusty-fork"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
+dependencies = [
+ "fnv",
+ "quick-error 1.2.3",
+ "tempfile",
+ "wait-timeout",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "syn"
+version = "1.0.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "rand",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+
+[[package]]
+name = "version_check"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+
+[[package]]
+name = "wait-timeout"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/2021/Cargo.toml b/2021/Cargo.toml
new file mode 100644
index 0000000..d5058d2
--- /dev/null
+++ b/2021/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "aoc2021"
+version = "0.1.0"
+authors = ["Justin Wernick <justin@worthe-it.co.za>"]
+edition = "2021"
+
+[dependencies]
+cached = "0.25.0"
+derive_more = "0.99.2"
+nom = "7.0.0"
+proptest = "1.0.0"
+thiserror = "1.0.29"
+
+[profile.release]
+# debug = true
diff --git a/2021/inputs/day_1.txt b/2021/inputs/day_1.txt
new file mode 100644
index 0000000..42f77f8
--- /dev/null
+++ b/2021/inputs/day_1.txt
@@ -0,0 +1,2000 @@
+196
+197
+176
+182
+179
+177
+171
+172
+170
+147
+143
+153
+158
+157
+147
+151
+153
+159
+150
+167
+162
+160
+159
+161
+165
+150
+158
+157
+146
+141
+137
+127
+140
+127
+115
+114
+116
+118
+127
+133
+141
+151
+150
+148
+146
+170
+171
+168
+189
+194
+191
+205
+210
+194
+195
+191
+231
+241
+239
+241
+245
+255
+239
+244
+245
+246
+260
+262
+253
+262
+268
+289
+278
+279
+293
+312
+307
+308
+333
+336
+325
+329
+338
+334
+337
+330
+340
+341
+338
+344
+359
+361
+359
+377
+411
+450
+459
+458
+455
+450
+444
+460
+457
+458
+454
+456
+460
+465
+470
+469
+468
+462
+454
+446
+448
+449
+451
+448
+463
+470
+492
+504
+506
+508
+501
+535
+539
+547
+549
+548
+563
+565
+564
+571
+586
+599
+593
+588
+591
+597
+611
+610
+617
+619
+617
+618
+614
+604
+603
+604
+590
+593
+592
+581
+577
+604
+611
+612
+610
+634
+651
+638
+636
+633
+634
+629
+624
+611
+623
+626
+631
+632
+631
+659
+672
+686
+681
+682
+680
+666
+668
+682
+680
+681
+700
+701
+690
+685
+693
+692
+691
+693
+692
+700
+704
+713
+716
+715
+727
+726
+725
+713
+718
+714
+715
+710
+709
+718
+717
+719
+720
+716
+705
+716
+719
+735
+746
+729
+735
+726
+743
+744
+740
+739
+730
+735
+738
+736
+743
+752
+754
+758
+767
+753
+754
+756
+754
+758
+755
+750
+754
+750
+749
+745
+743
+740
+739
+740
+738
+740
+746
+747
+772
+775
+768
+769
+781
+782
+788
+799
+813
+792
+782
+783
+785
+770
+761
+771
+798
+808
+810
+811
+829
+840
+826
+833
+829
+833
+815
+816
+818
+809
+810
+813
+819
+809
+787
+770
+765
+786
+793
+792
+787
+790
+791
+794
+790
+801
+804
+803
+781
+794
+778
+779
+777
+778
+786
+773
+775
+783
+781
+790
+781
+782
+791
+792
+815
+816
+808
+803
+786
+785
+781
+780
+781
+785
+754
+741
+725
+724
+725
+724
+726
+725
+727
+721
+718
+706
+721
+731
+739
+759
+752
+749
+767
+766
+787
+788
+812
+826
+828
+829
+835
+834
+831
+818
+808
+813
+827
+847
+848
+853
+857
+859
+860
+864
+867
+871
+870
+877
+874
+858
+857
+840
+844
+848
+846
+853
+860
+866
+862
+867
+885
+898
+929
+935
+944
+946
+952
+961
+975
+974
+970
+966
+983
+981
+986
+1001
+996
+995
+982
+984
+991
+982
+990
+984
+991
+992
+997
+995
+994
+998
+1004
+1010
+1011
+1010
+1013
+1016
+1025
+1027
+1029
+1040
+1038
+1041
+1045
+1047
+1048
+1050
+1023
+1024
+1019
+1025
+1035
+1036
+1045
+1052
+1053
+1050
+1049
+1050
+1048
+1049
+1059
+1061
+1059
+1031
+1032
+1042
+1051
+1055
+1064
+1058
+1032
+1037
+1039
+1061
+1087
+1088
+1080
+1085
+1069
+1052
+1054
+1060
+1062
+1063
+1062
+1063
+1062
+1048
+1054
+1050
+1031
+1028
+1022
+1034
+1038
+1039
+1036
+1045
+1055
+1054
+1053
+1058
+1088
+1089
+1086
+1095
+1096
+1090
+1087
+1095
+1099
+1097
+1091
+1093
+1068
+1061
+1078
+1073
+1079
+1082
+1068
+1079
+1078
+1067
+1068
+1084
+1091
+1096
+1070
+1061
+1052
+1047
+1065
+1056
+1069
+1070
+1072
+1081
+1083
+1084
+1078
+1079
+1080
+1082
+1085
+1081
+1085
+1086
+1094
+1096
+1097
+1079
+1081
+1082
+1080
+1077
+1084
+1085
+1084
+1088
+1091
+1092
+1101
+1102
+1101
+1116
+1115
+1114
+1117
+1123
+1120
+1113
+1111
+1116
+1119
+1118
+1130
+1116
+1119
+1122
+1120
+1121
+1150
+1153
+1156
+1162
+1163
+1189
+1191
+1192
+1189
+1187
+1186
+1177
+1167
+1140
+1149
+1160
+1142
+1147
+1148
+1170
+1169
+1188
+1190
+1189
+1193
+1187
+1181
+1188
+1193
+1192
+1194
+1216
+1223
+1209
+1199
+1214
+1218
+1211
+1212
+1222
+1227
+1234
+1244
+1235
+1238
+1232
+1238
+1236
+1231
+1223
+1217
+1218
+1229
+1212
+1236
+1237
+1240
+1255
+1257
+1258
+1261
+1258
+1255
+1258
+1256
+1258
+1279
+1275
+1274
+1282
+1292
+1293
+1296
+1287
+1323
+1322
+1332
+1333
+1316
+1327
+1332
+1334
+1314
+1311
+1315
+1317
+1320
+1359
+1362
+1360
+1362
+1372
+1377
+1389
+1382
+1373
+1380
+1388
+1395
+1384
+1375
+1382
+1383
+1368
+1363
+1356
+1352
+1356
+1360
+1355
+1367
+1371
+1382
+1409
+1379
+1421
+1429
+1430
+1448
+1451
+1452
+1449
+1439
+1460
+1431
+1429
+1430
+1427
+1416
+1417
+1454
+1472
+1473
+1476
+1475
+1477
+1476
+1482
+1481
+1489
+1488
+1490
+1495
+1493
+1500
+1517
+1500
+1498
+1494
+1502
+1505
+1536
+1537
+1538
+1543
+1542
+1541
+1554
+1553
+1555
+1558
+1549
+1550
+1557
+1558
+1560
+1561
+1565
+1560
+1565
+1572
+1573
+1575
+1571
+1581
+1605
+1614
+1611
+1619
+1618
+1614
+1612
+1616
+1629
+1628
+1632
+1635
+1644
+1637
+1638
+1632
+1613
+1614
+1615
+1614
+1609
+1611
+1620
+1615
+1608
+1612
+1646
+1647
+1665
+1668
+1665
+1668
+1676
+1677
+1682
+1695
+1696
+1708
+1709
+1686
+1681
+1668
+1669
+1655
+1667
+1681
+1689
+1710
+1718
+1749
+1748
+1746
+1749
+1752
+1748
+1745
+1744
+1743
+1745
+1743
+1744
+1726
+1725
+1724
+1728
+1727
+1739
+1740
+1733
+1739
+1740
+1757
+1759
+1758
+1759
+1762
+1802
+1799
+1792
+1786
+1787
+1793
+1794
+1797
+1798
+1800
+1803
+1802
+1792
+1793
+1795
+1783
+1782
+1772
+1771
+1772
+1774
+1778
+1765
+1766
+1767
+1769
+1771
+1772
+1788
+1781
+1790
+1789
+1791
+1813
+1809
+1810
+1813
+1814
+1819
+1823
+1815
+1814
+1822
+1826
+1812
+1817
+1814
+1818
+1800
+1801
+1804
+1800
+1802
+1813
+1825
+1822
+1832
+1840
+1841
+1830
+1834
+1835
+1841
+1840
+1845
+1881
+1883
+1887
+1886
+1890
+1889
+1896
+1897
+1917
+1923
+1925
+1923
+1924
+1909
+1899
+1904
+1905
+1907
+1905
+1908
+1922
+1912
+1920
+1924
+1920
+1921
+1920
+1919
+1935
+1937
+1955
+1956
+1967
+1972
+1977
+1984
+1982
+1986
+1980
+1975
+2005
+2007
+2018
+2027
+2040
+2039
+2040
+2042
+2040
+2041
+2040
+2034
+2060
+2066
+2074
+2076
+2080
+2081
+2082
+2066
+2071
+2074
+2069
+2070
+2076
+2075
+2079
+2082
+2081
+2080
+2085
+2093
+2097
+2091
+2096
+2097
+2106
+2103
+2110
+2107
+2098
+2097
+2110
+2113
+2097
+2102
+2103
+2107
+2103
+2117
+2097
+2105
+2103
+2099
+2101
+2094
+2102
+2099
+2069
+2067
+2057
+2071
+2073
+2075
+2073
+2060
+2064
+2081
+2057
+2055
+2056
+2064
+2066
+2067
+2069
+2070
+2076
+2075
+2074
+2101
+2099
+2116
+2115
+2119
+2129
+2126
+2124
+2122
+2126
+2143
+2140
+2141
+2146
+2145
+2148
+2164
+2154
+2151
+2148
+2152
+2130
+2129
+2131
+2118
+2123
+2129
+2130
+2127
+2133
+2132
+2142
+2143
+2157
+2156
+2140
+2139
+2141
+2139
+2140
+2142
+2134
+2126
+2128
+2129
+2131
+2126
+2146
+2145
+2134
+2153
+2151
+2140
+2139
+2161
+2165
+2169
+2150
+2151
+2153
+2176
+2183
+2182
+2188
+2165
+2160
+2161
+2165
+2173
+2155
+2154
+2141
+2140
+2161
+2158
+2148
+2164
+2165
+2176
+2163
+2168
+2158
+2159
+2194
+2201
+2203
+2202
+2211
+2213
+2210
+2193
+2199
+2201
+2199
+2206
+2231
+2239
+2246
+2249
+2265
+2266
+2267
+2281
+2291
+2292
+2293
+2296
+2295
+2275
+2273
+2275
+2274
+2286
+2291
+2301
+2300
+2302
+2298
+2300
+2288
+2298
+2300
+2291
+2309
+2303
+2304
+2309
+2318
+2308
+2315
+2314
+2313
+2315
+2314
+2315
+2325
+2326
+2310
+2308
+2314
+2313
+2312
+2311
+2312
+2311
+2310
+2304
+2310
+2308
+2311
+2296
+2295
+2289
+2290
+2292
+2291
+2289
+2290
+2288
+2300
+2302
+2307
+2313
+2312
+2309
+2310
+2312
+2313
+2314
+2315
+2314
+2308
+2309
+2313
+2325
+2324
+2322
+2300
+2298
+2291
+2301
+2298
+2307
+2309
+2308
+2345
+2341
+2342
+2345
+2360
+2367
+2371
+2374
+2368
+2369
+2375
+2406
+2405
+2422
+2423
+2422
+2419
+2417
+2416
+2417
+2421
+2427
+2445
+2449
+2432
+2448
+2454
+2437
+2429
+2430
+2439
+2415
+2418
+2425
+2421
+2401
+2414
+2412
+2416
+2432
+2450
+2443
+2426
+2427
+2428
+2427
+2429
+2430
+2434
+2438
+2431
+2433
+2431
+2427
+2433
+2455
+2462
+2463
+2465
+2461
+2462
+2463
+2496
+2497
+2493
+2486
+2472
+2470
+2475
+2483
+2491
+2492
+2505
+2510
+2511
+2507
+2508
+2506
+2507
+2505
+2506
+2504
+2524
+2528
+2519
+2527
+2543
+2549
+2555
+2567
+2555
+2561
+2560
+2561
+2560
+2541
+2540
+2537
+2530
+2532
+2528
+2529
+2528
+2522
+2516
+2506
+2520
+2526
+2527
+2531
+2534
+2544
+2545
+2542
+2541
+2543
+2544
+2543
+2542
+2558
+2560
+2558
+2559
+2552
+2551
+2558
+2573
+2590
+2589
+2583
+2574
+2565
+2569
+2580
+2596
+2597
+2596
+2585
+2586
+2587
+2598
+2587
+2588
+2571
+2570
+2567
+2579
+2581
+2579
+2572
+2577
+2575
+2574
+2582
+2585
+2592
+2600
+2601
+2608
+2606
+2609
+2612
+2619
+2631
+2636
+2633
+2640
+2654
+2649
+2611
+2598
+2600
+2604
+2608
+2600
+2607
+2623
+2624
+2633
+2632
+2637
+2655
+2658
+2662
+2675
+2676
+2699
+2711
+2714
+2710
+2718
+2750
+2719
+2713
+2714
+2737
+2739
+2733
+2736
+2754
+2773
+2776
+2794
+2795
+2823
+2825
+2826
+2828
+2830
+2815
+2823
+2821
+2825
+2829
+2833
+2834
+2833
+2832
+2844
+2838
+2840
+2845
+2837
+2849
+2878
+2859
+2858
+2859
+2864
+2868
+2870
+2863
+2859
+2860
+2858
+2860
+2857
+2851
+2852
+2856
+2818
+2820
+2822
+2819
+2818
+2819
+2823
+2827
+2836
+2834
+2835
+2842
+2856
+2854
+2853
+2854
+2855
+2854
+2858
+2859
+2866
+2872
+2871
+2869
+2875
+2874
+2888
+2881
+2883
+2900
+2897
+2885
+2880
+2882
+2883
+2886
+2887
+2903
+2894
+2884
+2876
+2877
+2876
+2875
+2887
+2863
+2865
+2880
+2885
+2866
+2882
+2883
+2875
+2873
+2876
+2875
+2912
+2916
+2932
+2927
+2914
+2906
+2911
+2912
+2910
+2908
+2903
+2929
+2925
+2907
+2905
+2906
+2909
+2897
+2895
+2903
+2918
+2945
+2946
+2937
+2919
+2923
+2943
+2947
+2950
+2951
+2963
+2978
+2972
+2954
+2955
+2957
+2969
+2972
+2984
+2987
+2969
+2970
+2974
+2981
+2949
+2946
+2952
+2966
+2968
+2969
+2970
+2956
+2947
+2941
+2949
+2939
+2940
+2953
+2959
+2947
+2957
+2963
+2968
+2964
+2939
+2912
+2904
+2907
+2928
+2948
+2961
+2969
+2963
+2980
+2985
+2986
+2987
+3015
+3017
+3027
+3028
+3031
+3040
+3043
+3044
+3043
+3054
+3053
+3055
+3053
+3047
+3051
+3025
+3030
+3040
+3044
+3046
+3049
+3054
+3057
+3059
+3056
+3060
+3068
+3085
+3104
+3108
+3114
+3115
+3118
+3121
+3118
+3132
+3134
+3129
+3126
+3123
+3111
+3112
+3080
+3097
+3086
+3088
+3089
+3093
+3092
+3096
+3126
+3127
+3128
+3133
+3134
+3137
+3138
+3135
+3141
+3142
+3143
+3162
+3152
+3149
+3166
+3172
+3170
+3171
+3185
+3187
+3193
+3192
+3196
+3186
+3203
+3213
+3216
+3238
+3237
+3246
+3247
+3252
+3250
+3249
+3241
+3246
+3253
+3251
+3258
+3271
+3274
+3268
+3274
+3273
+3269
+3272
+3271
+3266
+3277
+3270
+3274
+3285
+3270
+3263
+3255
+3256
+3247
+3248
+3252
+3259
+3252
+3253
+3259
+3263
+3259
+3240
+3254
+3257
+3241
+3250
+3251
+3254
+3271
+3273
+3281
+3295
+3296
+3293
+3299
+3292
+3301
+3304
+3306
+3303
+3301
+3303
+3304
+3303
+3275
+3273
+3276
+3302
+3307
+3316
+3317
+3288
+3296
+3298
+3313
+3312
+3313
+3306
+3292
+3295
+3315
+3316
+3308
+3311
+3310
+3294
+3327
+3331
+3330
+3333
+3352
+3360
+3362
+3366
+3357
+3361
+3360
+3351
+3345
+3342
+3339
+3338
+3364
+3365
+3368
+3375
+3385
+3389
+3390
+3389
+3407
+3408
+3402
+3433
+3437
+3436
+3435
+3439
+3454
+3425
+3426
+3422
+3426
+3423
+3419
+3420
+3416
+3417
+3426
+3427
+3403
+3406
+3395
+3396
+3397
+3398
+3399
+3407
+3409
+3410
+3397
+3391
+3408
+3419
+3425
+3428
+3420
+3423
+3424
+3426
+3437
+3440
+3434
+3436
+3440
+3443
+3444
+3450
+3454
+3455
+3460
+3484
+3482
+3487
+3489
+3492
+3493
+3498
+3493
+3478
+3479
+3478
+3505
+3506
+3508
+3505
+3500
+3499
+3498
+3499
+3495
+3494
+3492
+3489
+3490
+3492
+3490
+3492
+3487
+3488
+3491
+3484
+3486
+3487
+3483
+3461
+3459
+3463
+3476
+3466
+3464
+3465
+3474
+3487
+3485
+3477
+3464
+3463
+3469
+3465
+3462
+3448
+3452
+3461
+3463
+3466
+3470
+3475
+3488
+3477
+3473
+3472
+3475
+3469
+3458
+3455
+3440
+3430
+3439
+3440
+3437
+3442
+3443
+3446
+3447
+3442
+3453
+3462
+3463
+3462
+3463
+3461
+3455
+3454
+3450
+3449
+3450
+3447
+3451
+3454
+3459
+3460
+3461
+3463
+3466
+3467
+3468
+3469
+3474
+3481
+3480
+3481
+3482
+3474
+3472
+3484
+3502
+3522
+3507
+3509
+3504
+3497
+3487
+3476
+3473
+3495
+3494
+3495
+3493
+3500
+3503
+3516
+3518
+3517
+3524
+3528
+3531
+3530
+3526
+3525
+3527
+3521
+3520
+3526
+3527
+3521
+3527
+3521
+3524
+3525
+3519
+3520
+3540
+3566
+3577
+3575
+3576
+3561
+3562
+3563
+3571
+3572
+3577
+3575
+3607
+3606
+3611
+3612
+3613
+3614
+3615
+3614
+3605
+3619
+3618
+3624
+3634
+3639
+3638
+3660
+3661
+3653
+3650
+3651
+3652
+3650
+3648
+3649
+3653
+3655
+3650
+3651
+3650
+3685
+3656
+3670
+3687
+3696
+3695
+3682
+3685
+3688
+3686
+3672
+3664
+3663
+3659
+3664
+3676
+3689
+3694
+3697
+3713
+3705
+3706
+3725
+3724
+3723
+3728
diff --git a/2021/inputs/day_10.txt b/2021/inputs/day_10.txt
new file mode 100644
index 0000000..661c46a
--- /dev/null
+++ b/2021/inputs/day_10.txt
@@ -0,0 +1,94 @@
+{[<([<[[(<[({<<><>><()[]>}<(()())(())>)<(([]())){<()()><{}<>)}>][(((()<>)[{}{}]){<[]<>>({}{})})]>)[(({([{}[]]
+{{[[(<[[[<[<<{()()}(<>{})>[<<><>>[[]]]>[{{[]<>}[[]]}<<[]{}>[<>[]]>]]([[[{}<>]]<<()[]>{()<>}>]([<<
+([<{[[{{((([(<[]<>>{[]<>})<([]){<>{}}>][([<>[]][[]{}])])[[{{()[]}<()[]>}<{(){}}>]]]<{(<[{}<
+(({(<{(([<[({([]())(<>())}{([]{})[{}{}]})]{(({{}()}{<>()}](<[]<>>(()[])))({[[]{}]<[]<>>})}>[[[{<<>[]>(()
+[([<([{({{[{[([]{})[{}[]]][[{}{})]}<([<>{}]<<>()>)>]}([<{[()<>]{()<>}}[[{}{}]<(){}>]><{{{}[]}[()<>]}[{{
+<(([<{{<(<[(<{()()}>(({}()){()[]}))<[<[]()>[[]()]]<{[]()}<<>{}>>>](<[([]())]>(([()()][()<>])({()<>}<[]<>>))
+[{({<(<[{({{{[()[]](<>[])}{([]{})<<>{}>}}}{{<<{}[]>(<>)><(<><>)([]())>}<{({}<>)(<><>)}{[{}{}
+([(<{<[<{[({[<[]{}><<><>>]<({}[])({}<>)>}([{{}<>}<[]()>]<<<><>>>)){({<<><>>[[]{}]}(<()<>>{()}))<{<[
+({{([(<{{{{{{([]{}){<>{}}}}{<<()>{{}{}}>[({}())(()<>)]}}[[[[{}{}](<><>)]{<()[]><[][]>}](([[]](()()))<[[]
+(<<[<{{{({{<{{(){}}{<>()}}<({}{}){[][]}>>[{<[]{}>{<>()}}<{[]<>}[()<>]>]}}({([({}[])(<>{})][{<>}])[{[()<>]<{}
+{[(<<((<[[<{<{<>()}[{}[]]>}{{((){})[()<>]}<{(){})[{}{}]>}>]({((<<>()>){[<>()]{{}()}}){{[()()][<><>]}
+{(((([[(<[({({{}()}[<>[]])<(<><>)([]())>}{<[[]<>]><<()<>><()<>>>})<[[<[]{}><<>{}>]]>]<<{{[
+[{(<[[(<(<[{<({}[])<{}{}>>(<[]<>>)}]<{(<[]()>[()()])}>>{({<{{}()}[<>()]>})<[[(<>())(<>{})]{{{}[]}}][({{}[]}
+{[[<([{[(<<[<<()()>[[]]>[{()()}]](<[()]<()[]>><<{}()>{()()}>)>><[[([{}<>]{{}()})<{{}[]}<()[]>>]]})[([{{{<>()}
+((({[(<<{(((<<{}()>><{<><>}>)))[[{<({}[])[{}[]]>}(<[<><>][()()]><[[][]]<{}[]>>)]]}((({<(<>())>[({}{
+{<{{[(<<{(<{[({}<>)<{}[]>]([(){}](<>[]))}<(({}()){[][]}}[<()[]><{}()>]>>)}<<{(<[{}()]{<>{}}>[[[]()](()
+{(<<({{([<[<[<{}<>>{[][]}]<[<><>][()[]]>>{(({}{})){<()><()()>}}]>(<({{()()}({}<>)}<([]<>){[]{}}>){([[]<>
+<(<({{{([({{<<{}<>><()[]>>[{()<>}[<>{}]]}})({([{()[]}{(){}}]<(()<>)<{}<>>>)}<{{<{}<>>[[][]]}}<[{<>}[<>
+{({{(<<([({{[(()<>)[[]<>]][(<>{})({}())]}})]{(<[<(<>()){<><>}><<{}()>[[]]>][{{<>()}{[]()}}{[()<>]{<>()}}]>)
+([<({{{([[<<[[()[]][<><>]]<<<>[]><()()>>>(<{()<>}<()[]>><{<>()}<[]{}>>)>({(<()[]]<()()>)<[<>()][{}]>
+{[{<((<[<<({<{[]{}}[()()>>({[][]}[[]()])})(([{()}{{}()}]<<{}()>{{}{}}>)<([<>()])(<{}<>><{}[]>)>)>{[{
+{{([([{(<[[{[{()<>}({}())][[[]<>]<{}{}>]}]<<[({}[])(()<>)]({(){}}[()()])>{{(())<(){}>}}>]{[<{[[]()]{<>[]}}
+<(<({<{<<<([<([]<>)([]<>)>]<{{{}{}}<<>()>}>)<<{[[]()](<>{})}(([]())<[]()>)><[{<>{}}[(){}]]>>>>>(<{<[[[{
+(([({<{(<{[<({<><>}){{[][]}}>{<([]()){{}{}}>[([][])<{}{}>]}]}[((<{()<>}>)[{{()<>}{[][]}}])]
+(<<<(({{{([[<{(){}}>{(()())(()[])}]{({{}[]}<[][]>]<{{}<>}{()}>}])<(({[[][]]{{}{}}}(([][])<(){}>)
+{<{{[[({<<{{({{}()}({}{})><[()<>][<>{}]>}([<()[]>({}())][{()<>}[()]])}{<[{(){}}<[]{}>][[[]<>][[][]]]>([[<>]
+{{{[(<([[[[{[[(){}}<{}>]<{<>[]}{{}{}}>}]<[[(<>())((){})]((<>()))]{(<[]{}>([][])){<[]<>>(()[])}}>]
+(<{[([[<(<[<{[<>{}]}(<[]<>>{{}<>})>[{(())}]]>){<{(<(<>())<{}()>>]}({<<[]<>>[[]<>]>((()<>)[<><>])}
+[<{[[(({([((({[]{}}[()()])))]>[((<<[<><>][[]()]>{[()<>][()()]}>({{<>[]}({}<>)})))]})){((<[<[<[<>()]>
+<({[{{{<{[<[({[]{}}<[]>)(({}[])({}<>))]><{((()()))[[()<>]{<>[]}]}(<((){})<{}{}>><({}[])>)]][([<{
+<(<<<<<[(<<[{{[][]}{{}{}}}{{[][]}<()>}](<([]{})[()[]]>[[{}{}]{<>()}])>([{[[]()]<<>[]>}[<<>{}>{<>
+<(<[[<[[[<<(<(()[])<{}()>><(<>{})>)[([{}{}]([]{}))]><<<[<>[]]{<>[]}>{(()<>)({}[])}>>><[[[{<
+([[{[({<({(([<(){}><[]<>>]<{()<>}({})>))([([{}<>][{}[]]){[<>[]]({}<>)}][[({}[]){[]()}]])})>[({{(<(()[]){<>
+<[<{<[{(<<[[{{(){}}({}<>)}<(()[])>]<<<()()>(()<>)>({{}})>]({[(<>{})<{}()>]{<{}<>><<><>>}}<<{()<>}
+{[{({[[(({{{{<()()>{[]{}}}{[<>[]]<()<>>}}(<<<>()><{}<>>>({()<>}[()<>])}}{<{[()[]]{(){}}}>[<<[]{}>>[((){})<(
+{{(<[<(<(<{{(<[]()><()<>>)}{((<><>))[<<>{}>{()[]}]}}>{{<({{}{}}[()<>])[<(){}>(<>[])]><<(<>{}}[{}
+[{{{[[[[{(<{<[<>[]](()[])]{{<>{}}}}{[(()()){[][]}]{([][])}}><<{<<>()>([])}[[[]{}]<{}{}>]>(([{}<>]<[]()>)
+{[[(<([[[[((({<>{}}(<>())){<{}[]>})[([<>[]](<>[])}[({}[])([]())]])([<{{}()}(<>())><[[][]][<>()]>][([()()]<<>[
+<[{[{({(<(((<<<>{}><[]()>][{{}()}{[][]}])[(((){})([][]))[[()<>][[]{}]]])[[(((){})[()])[[(){}]<{}
+[{[[<[<{{(({([(){}]<()()>](([]<>)[()[]])}<<{[][]}([][])>>)<[[([]())<{}[]>]]>){[[[{{}()}[<>[]]]{<[]{}>
+[[<([([[<<<{{[{}[]][<><>]}}{{{{}{}}}}>>>[([[(<<>[]>({}<>))<([]())<<><>>>]{{<<>[]>{<>()}}}][<{{[
+({[<<<((<<<<<<[]{}>[()()]>{[()[]]{()<>}}>[((<>()){()()}){<[][]]<{}{}>}]>{{[[{}{}]<{}[]>]([[]<>])}((
+({<<[[{{<{[[{<()><<>>}<<()[]>([][])>]]([[({}<>)[()[]]](([]{})<<>[]])]<[([]<>){[]}]>)}(((<<{}[
+<(<(<(([([[[{{[]()}{<>()}}{<{}[]>[{}()]}]{{[{}{}]<()[]>}({<>()}<(){}>)}][[{<{}()><[][]>}](<[
+[[<{<[<[<({<<{[]}<()<>>>({<><>}{[]<>})><([<>()]([][]))>}[({[{}{}]<{}[]>})({[<><>]})])>]([[{<({
+<([{[[<<[({<<[{}()]({}[])>{<[][]>{()()}}>{<(<>[])([]{})>([{}[]}[<>])}}{{[<<>[]>{[]<>}][([][]){{}{}}]
+[([({((<[{{{[<{}><<>()>]<<()[]>>}<[{{}{}}([][])]{{()<>}<(){}>}>}<{<[[][]]>({{}<>}{()[]})}>
+[[[{([({{{<{[[[][]]{()()}]}{{<<>[]>[{}[]]}[[[]()]<<>>]}>({{(<>[])[{}[]]}({<>()}[{}[]])}{{(()<
+{<{{{<[{[<{(<{[]{}}{[][]}>{{[]<>}}}}[{((()[])<()()>)[<<>[]><{}()>]}<[{<>{}}[()<>]]<[<>[]][<>{}]>>]>[<[
+<[<{[[<{<[([{({}[])(()<>)}[[<>()]{()[]}]])][[<{[<>[]][<>[]]}<{<>{}}{<>{}}>>{<<()()><()<>>>{([]()
+<[{{({<[<([[[([]{})({}())]]<[{{}}[()<>]]<{<>{}}{()}>>])<[<[<<>()>]{<{}{}>[[]<>]}><({[]()}<<><>>)[(()<>)(<>())
+{<[[[<(<[<{<({<>{}}[<><>])([{}<>]<[][]>)><<[(){}](<>[])>[({}[])<<>[]}]>}{{{(<>())(<>{})}}<((<>())
+<{(<<[{[{<{<<((){})[[]{}]><([]<>)<{}[]>>>{[[[][]]<()()>]}}{({{<>()}<<>()>}{<{}<>><()[]>})}>}<[<([<()()>{()()
+{{([<{[[((<<{<<>()><<>[]>}<(()<>)>>><<[<[][]><{}<>>]>{<([]()){[]<>}>}>))]<{(((<[[]<>]([]<>)>[{{}()}<<
+([{{({{<[[(((<[][]>{<>{}}){<()[]>{[]()}})(<({}<>)([]<>)>(([])[()<>])))(([([][]){()<>}]{{[]<>}{[](
+[{{<{({[<{<{((<>())({}[]))<{<>()}({}[])>}(<[{}()]<{}<>>>({[][]}{()<>}))}{([({}[]){{}[]}]<([][])>)}}{<{({{}(
+[{(([[[([<<(<([]()){<>}>(({}<>)(()())))[((<>{})){[()<>]<<>{}>}]>>][<{{[<()<>>{{}[]}]<<{}[]><{}[]>]}[
+{<<<(<[<[{<[<({}[])>(([])<[]<>>)]<<<{}{}>({}())>{[<>{}}<[][]>}>>[{[<<>()><()()>]{[<>[]]<[]>}}[<<<>[]>{[]()
+([(((<<(<[[<[<{}<>>(<><>)]>([<{}[]>{<>{}}]({<>{}}[()()]))]](<({<<>[]>({}[])}<[[]<>]{<>[]}>)(<{
+([{({{{[(((<<{[]()}<{}<>>>((<><>){[]()>)>({<{}()><(){}>}<[<>()]>))){((([[][]]{<>{}})[([]<>){<>[]}]
+<(({{{[(([<[{<(){}>([]<>)}(<[]><()<>>)]><<([()[]]([]()))>{[(()<>}<{}>]}>]){{[{(({}{})<(){}>){[[]]{[]
+[<{(<({<{((<<<[]<>>([]())>(((){})[[]()])>{[[<>]<{}<>>]}){[<[<>[]]({}())]{{()[]}<()>}]})<([[([]())<<
+[[<<[<{{[{({<[()<>]{<>[]}>{([][]){<><>}}}<[[{}()]][<<><>>{{}[]}]>)}{<{{({}<>)(()())}[{{}{}}[{}()]]
+({<({[{[{(([<<()()>{<>[]}>[([]<>)<()<>>]]{<{<>()}[{}{}]>((<>{}){<>{}})})([<([][])[[]{}]>(<[]()>{<>
+{[[((<{[[<<({<[]<>>[()<>]}{[()]{<>}})>[<{<<>()><()[]>}{{()[]}<()<>>}>(([{}[]]))]>[[{({<><>})}
+{{(<[{{[{<[({(()){{}<>}}(<{}[]>[[]()]))]>}({(<((()[])((){}))<{<><>}[<>()]>>)}(<<[(())<{}<>>]{[[]]<{}
+<{{([<<<<[([<[<><>][[]]><<(){}>[()()]>]<{(<><>)<<><>>}([{}{}])>)][[([<()()><<>()>])(({[]<>}([]{}]){<[]><[]
+{(<<[[<{{((([<[]<>>[{}<>]][([][]){{}{}}>)(<<<><>><[]{}>>{{(){}}[<>{}]}))({<(())[<>()]><{<>{}}(<>[])>}(({
+[[[([({([<<[[[<>{}]{<>{}}]<[<><>]{{}<>}>]>[({[()()]<<>()>}{[()()][{}()]}){({{}()}[(){}))}]>[(<{[()<>
+[{{(<<<[{(((<<()<>>([])>({<>{}}<()[]>)))[{(([]){()<>})(({}[])<{}})}<{([]{})({}())}<(<>[])<<>[]>>>
+{<<<<[{[{({{[<<>()><{}[]>]<[[]{}][{}{}]>}(<({}{})<()<>>>{{()<>}})}{[[{{}{}}[{}{}]]<[<><>](<>{})>]})(([{[<>()
+<(<[<{(<{[{<{[[]{}]{{}[]}}>[{[[]<>][{}{}]}(([]())(<>))]}<{{[{}{}]([]{})}[({}())]}{<<<>()>>([(
+<{{[{[<{[[<[{<[]{}><<>{}>}]{({()<>}(<><>)){[<>[]]}}>{([[<>{}]({}{})](({}{})<[]{}>))<{[{}<>
+{{<<{<<<[{[[([[]()][()()])(({}()))][[({}[])<()()>]]]{<[<{}[]>{{}{}}]>}}[[[[([]())]([<>[]][[]{}]>]]
+[[<<[({{{(<[(<()<>>[<>])]([(()<>){<>())]([<>[]][[]<>]))>{{[[[]()]([]())]{<[]{}>{()<>}}}[<([]<>)<()>>({<>{}}[<
+([[([<{<[<((<(<>[])(<>[])>(<<><>><{}[]>)){<<{}<>>>({{}{}}<()[]>)}>[{{(<><>)(()<>)}[<<>[]>]}]>]<{{
+{{{((<<{[[{<([[]{}][{}<>])>}<[((()())<()<>>)[[[]{}]{[][]}]]<<<[]{}>{{}[]}>(<<>()><(){}>)>>](<
+{(([[{{<[[<{(({}<>)[<>[]])}<{({}{}){{}}}[[()[]](()())]>>]([<[{()[]})({<>}[<>{}])>{[{{}{}}{(){}}]{<{}{}>}}])
+{([(<{<<({[<[{()()}<[]<>>]{<[]{}>}><[[<>][()<>]]>]{<{{[]{}}<(){}>}[({})]>{{<{}{}><()<>>}([{}
+{{[[({{({[(([{{}()}[{}]]({{}<>}([][]))){({{}<>}[[]{}])<<()<>>>})]{(<[<{}{}>{<>()}](({}())((){
+{<({{<<{{([{{{[]<>}{<>{}}}((<><>)<()<>>)}[<[{}<>][()[]]><[<>()][<><>]>]]{{[[()<>]<<>[]>]<(<><>)
+<(<[(<<[[<<<[({}())<[][]>](({}<>)[{}<>])>>[<{{{}}<()<>>}<(()<>){{}{}}>>]>({{<[<><>](<><>)>[(<>{}
+[((<{[{{(<{[({{}[]}((){}))([[][]]{<>[]})]<{<{}[]>[{}<>]}[<{}()><{}<>>]>]>)}}]}{{{(<[(<{{()()}}>{[<{}<>><<>[]>
+{([<<{(<([[({{{}<>}<(){}>}<<()[]>{<>{}}>)((<[][]>[<><>])<<[][]>{<>()}>)]((<{<>[]}{[][]}>[[<>()]{<>[]}]]{{[
+[<{(<{([{{(([<<>()>]{<(){}><()<>>}){(([]{}>)<(<><>)>})}({({[<>]{<>[]}}[[{}<>]])}[{<[()[]]<{}<>
+{[(<(<{(<<[{[<[]()>(<>[])][{{}}[()[]]]}{{[[]{}]{()()}}<<<>>[[]()]>}]>{{<[<{}()>([]())]({(){}}(()<>))>([(<>(
+{{([[([[[<(({<{}<>>[<>[]]}{([]<>)<<>{}>})<{{[]<>}{{}<>}}([()()]<<>[]>>>){{[[()<>]]<((){})<[]{}>>}{<<[]<>><()
+<({([[[[[({[[{{}<>}({}<>)]({<>[]}[<>{}])][([<>[]](<>()))<([]())[{}{}]>]}(((({}[])[()[]])[{{}{}}(<>)])(<<<>
+[({{<{[([(((<{[]{}}{<>()}><[{}<>>{<>[]}>)){([<{}{}><()[]>]<([]{})[{}{}]>){{[[]]<[]{}>}((()[])[(
+(({<[<<{{[[<{(<>{})([]())}([[]{}]{{}()})><[<{}()><{}{}>]<<<>()>[[]()]>>]<[<<()[]><<>()>>[{{}<>}[<>]]]>]
+((<[[<{{{[({<(()[])<()<>>>})]{<(([()()][[]]))({[[]()]{[]<>}}{[<>()]})><<(({}[])[{}{}])>>}}}[[[{{{{[]{}}({}[
+([<[<{{{{[<<{{<>[]}([]<>)}><{{()[]}[<><>]}{<[]>[()<>]}>><{[{[][]}<()[]>]({[][]}(()<>))}<{(<>())(
+{((<(([[<[(<[{()[]}([]())>>[<[<>()]<[]{}>>(<()<>><[]>)])<(<{()}>(([]<>){<>{}}))<[[[]<>]{[]()}
+[(<[([([{{{<([[]<>]<<>>)[{<>[]}{{}<>}]}({(())[{}()]}[<{}<>>{<>()}])}([<[(){}]([][])><(()())
diff --git a/2021/inputs/day_11.txt b/2021/inputs/day_11.txt
new file mode 100644
index 0000000..674e736
--- /dev/null
+++ b/2021/inputs/day_11.txt
@@ -0,0 +1,10 @@
+8826876714
+3127787238
+8182852861
+4655371483
+3864551365
+1878253581
+8317422437
+1517254266
+2621124761
+3473331514
diff --git a/2021/inputs/day_12.txt b/2021/inputs/day_12.txt
new file mode 100644
index 0000000..c3ec81f
--- /dev/null
+++ b/2021/inputs/day_12.txt
@@ -0,0 +1,23 @@
+LP-cb
+PK-yk
+bf-end
+PK-my
+end-cb
+BN-yk
+cd-yk
+cb-lj
+yk-bf
+bf-lj
+BN-bf
+PK-cb
+end-BN
+my-start
+LP-yk
+PK-bf
+my-BN
+start-PK
+yk-EP
+lj-BN
+lj-start
+my-lj
+bf-LP
diff --git a/2021/inputs/day_13.txt b/2021/inputs/day_13.txt
new file mode 100644
index 0000000..b551a62
--- /dev/null
+++ b/2021/inputs/day_13.txt
@@ -0,0 +1,806 @@
+527,872
+94,740
+502,586
+33,514
+349,784
+1292,133
+733,623
+305,336
+108,628
+1086,396
+845,128
+674,761
+768,317
+783,154
+731,697
+803,844
+865,96
+1263,567
+1141,141
+1218,644
+1115,429
+951,373
+748,326
+1088,422
+259,673
+885,885
+150,732
+181,19
+182,581
+1130,838
+647,386
+53,140
+27,726
+1198,105
+219,476
+545,779
+234,528
+1042,145
+422,852
+683,726
+636,40
+140,590
+415,824
+415,637
+238,478
+0,347
+1277,380
+1076,366
+984,112
+808,787
+321,480
+576,707
+999,810
+1283,392
+604,606
+610,724
+107,487
+657,497
+258,378
+392,224
+1044,498
+53,754
+706,606
+1191,753
+661,256
+895,637
+1015,373
+455,808
+825,753
+929,835
+581,205
+1236,30
+343,74
+207,813
+547,866
+1005,558
+113,420
+445,4
+562,326
+924,593
+209,621
+1078,42
+1265,798
+923,408
+1082,808
+910,889
+850,408
+1277,268
+984,809
+1191,813
+295,541
+108,826
+705,698
+97,666
+878,33
+1245,240
+1257,140
+1001,416
+252,478
+139,51
+75,732
+925,750
+388,502
+721,703
+509,254
+808,532
+478,386
+349,299
+328,85
+463,210
+254,126
+835,281
+895,569
+850,155
+513,782
+195,465
+1066,155
+119,529
+355,826
+1078,68
+176,350
+459,465
+1077,364
+47,567
+674,40
+169,141
+119,305
+541,485
+1009,642
+1212,894
+537,544
+674,754
+517,616
+25,38
+5,32
+191,572
+700,276
+1004,891
+492,547
+701,516
+65,45
+319,60
+1071,325
+621,575
+1131,834
+185,560
+693,571
+441,140
+157,533
+527,32
+915,221
+1212,780
+1131,501
+463,684
+1169,112
+1299,269
+832,350
+555,733
+1115,476
+432,422
+266,310
+835,393
+105,277
+820,499
+967,820
+63,894
+561,754
+301,642
+668,233
+182,600
+801,640
+502,532
+1134,554
+546,68
+11,625
+373,98
+1082,114
+654,771
+763,28
+92,102
+713,74
+869,409
+855,360
+1277,864
+1083,875
+604,288
+924,301
+11,269
+841,511
+1037,140
+868,670
+759,486
+604,222
+917,464
+1034,512
+806,126
+1004,865
+677,670
+763,866
+1305,862
+681,728
+1251,408
+955,390
+224,119
+465,598
+87,773
+442,670
+492,558
+1019,406
+929,59
+513,560
+1146,323
+947,646
+305,224
+656,632
+952,520
+639,82
+1200,99
+984,206
+951,93
+1283,502
+150,574
+825,164
+432,413
+965,579
+436,740
+445,778
+840,254
+1310,547
+93,759
+299,726
+761,725
+793,558
+1202,826
+1173,822
+951,476
+415,40
+423,226
+405,175
+813,529
+499,451
+254,630
+845,369
+73,653
+234,814
+855,808
+465,318
+12,162
+403,284
+730,478
+907,284
+224,396
+301,520
+186,590
+551,486
+832,116
+773,544
+956,362
+273,140
+234,379
+828,182
+306,865
+1193,574
+176,554
+1175,810
+711,617
+1015,541
+928,644
+426,808
+586,826
+535,753
+1173,72
+301,597
+311,532
+233,493
+838,28
+174,227
+219,110
+597,841
+884,780
+271,102
+65,240
+354,362
+932,522
+652,833
+720,894
+895,824
+371,779
+957,374
+293,799
+169,276
+791,532
+580,416
+711,726
+408,462
+239,396
+1077,135
+754,360
+609,322
+880,119
+497,500
+289,323
+875,784
+239,817
+455,154
+137,72
+1101,768
+212,126
+445,452
+1029,546
+108,68
+610,170
+579,162
+295,521
+1124,369
+797,334
+872,347
+137,822
+1202,266
+649,376
+984,645
+1280,150
+102,870
+485,164
+435,476
+924,28
+1289,819
+760,525
+483,3
+1029,348
+1255,168
+276,382
+808,219
+108,714
+1295,596
+1237,395
+556,222
+996,232
+440,341
+30,150
+349,336
+422,826
+113,754
+801,621
+811,239
+15,364
+748,568
+924,749
+661,638
+45,798
+281,546
+228,114
+359,476
+929,588
+1119,210
+470,254
+415,257
+70,698
+649,862
+999,74
+711,700
+381,140
+1305,704
+313,467
+70,366
+475,393
+1011,826
+945,634
+621,366
+1191,305
+288,728
+346,700
+513,112
+863,81
+883,161
+229,493
+507,396
+383,252
+579,732
+309,864
+324,425
+1163,501
+268,145
+1094,547
+579,396
+438,99
+157,365
+1260,606
+373,49
+266,502
+492,150
+1310,632
+381,59
+499,655
+838,313
+447,813
+420,515
+890,515
+961,670
+855,154
+199,422
+927,102
+1044,502
+1128,742
+408,581
+1223,773
+254,217
+764,628
+325,161
+902,581
+1017,416
+887,226
+1265,96
+1071,396
+535,141
+1265,123
+45,330
+562,120
+706,64
+119,813
+1205,277
+209,871
+753,661
+832,126
+53,280
+93,588
+731,396
+515,619
+473,173
+541,409
+326,533
+1163,53
+1101,452
+1285,297
+754,672
+455,740
+472,600
+1289,147
+960,640
+855,534
+311,74
+1009,252
+504,126
+53,166
+1257,754
+836,56
+758,422
+1173,476
+585,194
+465,185
+830,73
+1007,611
+633,670
+68,516
+1310,85
+955,68
+689,319
+1283,726
+513,334
+426,86
+669,427
+1049,586
+1280,744
+1125,831
+1292,854
+663,386
+1266,618
+748,341
+1148,547
+627,420
+1305,302
+268,637
+746,96
+1252,705
+232,42
+1155,239
+281,378
+351,611
+944,789
+731,249
+1004,193
+666,422
+147,277
+639,805
+991,834
+883,875
+713,841
+33,127
+924,252
+835,255
+1173,542
+355,68
+455,360
+937,116
+475,501
+549,169
+835,396
+18,488
+400,406
+523,877
+556,332
+222,33
+627,392
+301,710
+748,553
+818,150
+545,115
+584,196
+55,168
+870,341
+305,558
+634,451
+601,614
+45,123
+254,406
+393,308
+1101,871
+131,93
+970,662
+801,478
+415,817
+1119,322
+550,77
+1258,486
+1251,486
+224,567
+460,155
+1170,590
+238,416
+358,598
+835,501
+786,774
+353,168
+835,57
+855,740
+507,844
+811,655
+179,639
+1064,761
+633,784
+1029,378
+119,753
+326,85
+599,866
+1021,858
+1082,780
+1076,814
+1031,416
+385,750
+345,579
+233,530
+1078,490
+791,154
+145,142
+1056,453
+922,215
+283,331
+393,464
+1066,739
+117,621
+797,560
+609,798
+705,196
+982,137
+604,560
+957,168
+627,502
+557,681
+1128,600
+604,334
+793,542
+445,871
+386,642
+621,268
+1280,374
+231,226
+191,322
+445,96
+845,576
+1305,592
+218,42
+729,732
+435,110
+445,116
+181,478
+919,558
+525,402
+465,766
+806,574
+55,277
+731,809
+542,553
+753,681
+850,632
+1237,284
+25,616
+1265,330
+229,885
+759,72
+276,512
+472,581
+1233,623
+1216,740
+420,528
+1071,369
+1265,378
+556,534
+373,826
+917,430
+599,617
+475,709
+1310,123
+957,726
+191,292
+701,322
+295,373
+499,443
+65,849
+472,742
+682,793
+562,568
+605,698
+765,779
+865,173
+711,476
+837,875
+599,476
+597,302
+530,56
+730,416
+269,750
+1198,553
+726,196
+455,472
+524,344
+683,882
+1064,313
+431,502
+1130,607
+991,123
+361,543
+507,820
+628,793
+1173,128
+510,537
+65,654
+629,194
+432,33
+827,891
+1114,605
+182,742
+326,137
+1058,478
+962,417
+947,406
+1125,560
+738,267
+633,672
+584,698
+355,56
+227,19
+845,318
+396,378
+676,451
+72,574
+400,5
+542,341
+1163,165
+1098,126
+639,530
+436,404
+910,630
+353,642
+938,612
+884,114
+832,544
+1298,680
+1011,378
+97,213
+306,701
+12,680
+838,581
+1246,558
+1064,252
+937,49
+1108,504
+865,350
+174,362
+1094,347
+1237,205
+269,144
+325,733
+1235,732
+937,68
+1175,740
+803,820
+604,64
+601,140
+402,478
+1260,222
+468,590
+246,194
+305,523
+519,292
+1138,264
+319,834
+127,470
+415,854
+299,378
+959,283
+1223,413
+1081,885
+671,162
+186,369
+311,362
+1213,666
+1131,863
+1212,114
+649,638
+686,374
+723,445
+345,315
+565,823
+30,520
+348,254
+465,576
+801,721
+75,681
+214,117
+910,453
+1305,32
+103,408
+599,194
+580,478
+276,672
+1138,712
+689,864
+233,759
+18,133
+1059,661
+970,232
+962,254
+381,588
+922,663
+301,252
+1242,154
+519,602
+1009,374
+773,423
+117,273
+597,820
+556,0
+246,313
+1015,521
+502,308
+914,378
+82,627
+845,525
+902,462
+372,612
+918,808
+455,870
+1268,616
+517,542
+609,378
+1115,465
+874,42
+1094,795
+895,376
+1115,866
+1086,119
+656,470
+629,408
+1284,101
+105,617
+1266,276
+654,470
+714,136
+392,808
+918,224
+1015,821
+755,161
+1021,323
+1056,217
+1280,520
+87,481
+731,162
+1163,396
+244,155
+1131,498
+137,542
+937,826
+681,821
+
+fold along x=655
+fold along y=447
+fold along x=327
+fold along y=223
+fold along x=163
+fold along y=111
+fold along x=81
+fold along y=55
+fold along x=40
+fold along y=27
+fold along y=13
+fold along y=6
diff --git a/2021/inputs/day_14.txt b/2021/inputs/day_14.txt
new file mode 100644
index 0000000..e84aae5
--- /dev/null
+++ b/2021/inputs/day_14.txt
@@ -0,0 +1,102 @@
+SNPVPFCPPKSBNSPSPSOF
+
+CF -> N
+NK -> B
+SF -> B
+HV -> P
+FN -> S
+VV -> F
+FO -> F
+VN -> V
+PV -> P
+FF -> P
+ON -> S
+PB -> S
+PK -> P
+OO -> P
+SP -> F
+VF -> H
+OV -> C
+BN -> P
+OH -> H
+NC -> F
+BH -> N
+CS -> C
+BC -> N
+OF -> N
+SN -> B
+FP -> F
+FV -> K
+HP -> H
+VB -> P
+FH -> F
+HF -> P
+BB -> O
+HH -> S
+PC -> O
+PP -> B
+VS -> B
+HC -> H
+NS -> N
+KF -> S
+BO -> V
+NP -> S
+NF -> K
+BS -> O
+KK -> O
+VC -> V
+KP -> K
+CK -> P
+HN -> F
+KN -> H
+KH -> N
+SB -> S
+NO -> K
+HK -> H
+BF -> V
+SV -> B
+CV -> P
+CO -> P
+FC -> O
+CP -> H
+CC -> N
+CN -> P
+SK -> V
+SS -> V
+VH -> B
+OS -> N
+FB -> H
+NB -> N
+SC -> K
+NV -> H
+HO -> S
+SO -> P
+PH -> C
+VO -> O
+OB -> O
+FK -> S
+PN -> P
+VK -> O
+NH -> N
+OC -> B
+BP -> O
+PF -> F
+KB -> K
+KV -> B
+PO -> N
+NN -> K
+CH -> O
+KC -> P
+OP -> V
+VP -> F
+OK -> P
+FS -> K
+CB -> S
+HB -> N
+KS -> O
+BK -> C
+BV -> O
+SH -> H
+PS -> N
+HS -> K
+KO -> N
diff --git a/2021/inputs/day_15.txt b/2021/inputs/day_15.txt
new file mode 100644
index 0000000..7cd7dc4
--- /dev/null
+++ b/2021/inputs/day_15.txt
@@ -0,0 +1,100 @@
+2494188795949368426672935997553436999123973817111494977966298896479213563868828787114774871959993495
+7269295166912819128199218896192745233371189151296812199288995976199874739992471696989914173889976925
+5191212388827998986649912824634749279971948589689238817721846893532697679994545789897911889729995897
+2168589418228699841979496964487152857627622699771987389157912193827151789199146397936892984945186648
+6173939628157711976563997464999974959831921613389971361747448844585131388314689679172394799717331399
+5899695651247379821996866399919649874365217617874746871338598594867719518499554272189235565993897965
+7485394112785944858863361332818786294335182341788296167915326872949943697179245577456182671381554981
+9266892719919136231211827869936952321796769156938997799961743957799879299829979797999289996519698258
+7917921979835316979873649974359699969481697221634859899429669995158723957697928969198838877882679431
+1491236284143364659399923722198867919166499918548183212698729886479216469986191478946997662853172832
+3767398586846967844992213195183588959313371637243199793963993959286917791341794214391371939868871494
+9928742956264979397583828698198991474967144891939974212795669284197972936548635221944579878942359557
+2591296163233973188949425669798998818121787829476539915785989899996476991741928456884321481461491491
+9991453999117657667486988919926741998881973198189217569482699982656854861887538683949945599464996179
+7785121782479268191396996844959721953747843271399498791933669879859637175866291876796575659279993189
+7776716891792899824695392599338137499166496894838139256577699799459229235864327718998999599938889161
+5839791979939975731327544972918993669998884665789489989759759159981911739962619655578959489319651959
+9398937827918996618898187917114312218979818328154357119792473517498229889994917199791479298969989426
+9193149311416478995456723118877968917584864848296657785894974918318495982911493994794738911468372399
+9769827996996299982985113892343422898578915399986948881116926857688725599882867388823188133721994278
+8818187692494197511189732662739876774788519148132878987446213196194758987589658244842573992965369917
+9692985985717419377379789693788389987764679742169692881958792669418357791948997197357944583299997199
+1655589698936188425679138917313955276139596613919192843881592947255229449287767987981926864969859529
+9699242895916761696979961626847898651779897127819171988159298969595969856231117848529246839289723796
+6918899858935889816997979865999596479948574186514639447389189297279388214912422481934482758598686939
+9996124999974921628385339724671481964691768899569149945536398488739568172834846547989816384911492872
+8346834917676292979994979698956139979926678894814989654839981221562573298658346721681719173725669956
+7996658985879211759466921616176161867986927757827999273979469498688699982778999718998879599891187826
+6789987138357992752226589295829589178911828185979998763692162929329395765591169737899686919889788875
+7197637335578924955696669176672558865939999937795981568398933385959211553997726292683778819899973695
+7969119547891678248796699588889994968987939996198215675832711397499256187159534154919899797617918187
+6926911899812131895651119837176697797919392241689685965558165297919473987229989972939921478114978373
+5841994288699114592993125898675872864168987969699196889625973399229985914231352968138691482158881899
+6867891298189866894719212682879398889498489939663172817599835471792399556867597964989686389769859994
+9216183839556753967949862931537817787984781697457685114963135184139788699929447794287121297683798319
+5961184475118971259559817821178849966985528319614894877141814318889588689738389571282791915658998542
+7796517463682296191129934366199787898432878578178838999284446321338627649991196629939797121785891962
+6869179819567982969986839939999929197979374876888941369191219962943812332887931152176916191949337191
+9949555298548218159821548895199792894846453957998718924987391181922787245277994179172391848939291937
+9194554898149494418187494726757793324999959688688219769989897645955852991449724578587938397525559699
+9839395266191998228728197617917693697789375996118295993584569962144786399964589627981549488787733896
+8798892947496976899997799782965947775618684631612298893931561678929111719994767999284582998895629195
+5971923418391999545117998893871871449928897518896798992962997798871699831697768939889162189217948177
+5858919812839818645171731976975688955947178448898559483839791819932171192959869296448582448911965279
+1968371935371579114969391889167369857978852993227571182176195567113584591687978173852172998299297876
+9818595991179878228913865926959618915114684669669687682418328328426959971759423266149164699675299962
+7313169988896798377992637828717558819632818939589195963274459828798159996969414246778645986912959685
+7175987582985899179876194819674578385889199196894972994931968897971126896672969822346958482487693195
+3899899994999974339297695494999694587728925279418719657933319839559165236843874998959197285872898386
+9143179894278789613961188998997899879989984167462521348529727699979885411983992819969799931648899396
+8721719519784582186657994994597695787791988737117281949127388845793462485588977564523597916812662293
+8611192812559976315185196299139868529583964194698936966669193992848592369935883977685998128921958855
+9939897898864487468688938157636793892493993149941579971537776639995925839997995494499799341196996911
+8952975169934893855698711783493617877741259797391888882838674537287761499137286977596911311795914798
+5973819164498977729977283879968689716999899829329989552936969439956928519569699593711189175982816879
+8992169969711179987999697359795943869189334168512958869138486551393962896928198678797618959592667178
+5198893235999189515823758534932887297573118289138717189899951151794645128875863218397267732544682559
+1325921986621997358689228699823234199583753862125884477531428896914475773981149951219987772989777284
+1767578881144877899227864881927651792585225919996798399996398994171539489225941719236558689987289596
+1697693293932998829129311328298516993977484911198964347455679799762539363996979349779755395869958127
+3713898193499495896831949473519979859286519968829254986836974926445967798179318189714751879952896613
+9916216881218784598988194111975928978834317778788697936768819246855919484199948946983872997799989537
+5418692222281246379686836239999941778791771954439968621669899592193586891966947915978832988949879767
+5946329868375678638572651999898943139289184131912762798677877895898695944967941764178789929296788749
+6239775996391914149474397187426592989328499959996744188988177257137398164298656927588639947169611996
+7726974769124948598778698999782543243598997487367127713261541411788169989779736617197163837998429443
+6111148329281896798281927928447986973659988162159399599953814156215976289871288499437886599369129446
+5854951519241889185939295929639732174661849974497795351828153777386926499257888278938847986849719938
+5984221699399349924974897835513966246932291529259259986518919741383138819187699681468921932862191135
+7247744517283916799878894898841511684972958968888598899899528129686787319513181999663332357287917849
+9619575771852888429993998185894999449977654581892868719896632889994183982173959417945797894859792989
+9987887311965149698616929977895196273977999972615874679953263114467325584669891293619617955392613925
+3459233982935649168889415851457199862587819992969777358114793166474749199299992637999874364191376899
+7943688928864588361988811191325483948768896478821434855799291838959158636199538793219669994353374759
+7859289672994646496294159151719934379268389791695698878689997723696963668819627473895291179249595592
+9941314869878731534751835338688822211841761128799388619893279239832929889693971299176198322989988696
+8842227781495829982998213979935669336595995299977597191369528699162399363739696583936699198339998297
+4713836572615268829578998379651451979528877965188284221548263244343828575977462755943999496539416928
+8997969648694117619993817848699798391349937895138998191853188328148899863968896951342872529854299799
+4821998179179181915669967943833899175819993535997526988947429178781551978844594192169998492291957896
+4195189588992241478996816697172978669351926159581981999991898899275537372449313988179685677999419998
+7562897828594989799593999721399698168294159217347891591919627938573198351476731278382919975715726691
+5289289886391592468511382946949159281295428969892859956998441988997291849472619345291529291989934296
+2119968215975689967875154978999999387426829368331479442781739197214991219186498848963987197926389319
+2619398714969892292337865366952999489167916889966465489596798298768869549286862389939419119395283486
+5891141991985484321796885478397617796913878991923119711484499287684339488268919291995478738911979334
+8114983942818278171367398195885616828459999126819995888739198519259919986496918279919325994993862348
+9799778199299926255679191711375949221688768118898797284688592829217988489896761335847548468981782899
+3297828241798981838196692979721897463899191684523229918888914388941777196891967689798993724124799799
+6587642855381998719928875658181669971111961763447368283978979892939694984843414921587564196767985264
+8868499779173993666956935631879522347992698928849354893756692376863389161268189398695789183996886289
+4384313399189397465391981199547955659912476999789237991829967965898994592593315769962549121389114869
+3165989928816884816238178158923873189899685775749877366272667891986999279928649289915951524688386419
+2614193692887593891959411118711929833726848873925563723329796828281367982397811129881655482798978846
+8547195678964249376891881397319282899129476666886297539869668898819828797769638991899886419148826859
+8178778491299194939588873989868848883795996377199995921984895879486959879816117891527867619711458789
+2358691498849138995117937966497995947487954198989213589121699888997868911988859219584998799742529591
+4564249477614979424868747948799188548777892792598985751974975274769994898988419988258297291881465592
+9297979945165922849989776118448916916471698458557921916479112985169284661994778819637195998913985273
+4789996397188799369699683969576838983199839289799579353875318987692211979981993139884198857448759796
diff --git a/2021/inputs/day_16.txt b/2021/inputs/day_16.txt
new file mode 100644
index 0000000..57468d0
--- /dev/null
+++ b/2021/inputs/day_16.txt
@@ -0,0 +1 @@
+A20D5CECBD6C061006E7801224AF251AEA06D2319904921880113A931A1402A9D83D43C9FFCC1E56FF29890E00C42984337BF22C502008C26982801009426937320124E602BC01192F4A74FD7B70692F4A74FD7B700403170400F7002DC00E7003C400B0023700082C601DF8C00D30038005AA0013F40044E7002D400D10030C008000574000AB958B4B8011074C0249769913893469A72200B42673F26A005567FCC13FE673004F003341006615421830200F4608E7142629294F92861A840118F1184C0129637C007C24B19AA2C96335400013B0C0198F716213180370AE39C7620043E0D4788B440232CB34D80260008645C86D16C401B85D0BA2D18025A00ACE7F275324137FD73428200ECDFBEFF2BDCDA70D5FE5339D95B3B6C98C1DA006772F9DC9025B057331BF7D8B65108018092599C669B4B201356763475D00480010E89709E090002130CA28C62300265C188034BA007CA58EA6FB4CDA12799FD8098021400F94A6F95E3ECC73A77359A4EFCB09CEF799A35280433D1BCCA666D5EFD6A5A389542A7DCCC010958D85EC0119EED04A73F69703669466A048C01E14FFEFD229ADD052466ED37BD8B4E1D10074B3FF8CF2BBE0094D56D7E38CADA0FA80123C8F75F9C764D29DA814E4693C4854C0118AD3C0A60144E364D944D02C99F4F82100607600AC8F6365C91EC6CBB3A072C404011CE8025221D2A0337158200C97001F6978A1CE4FFBE7C4A5050402E9ECEE709D3FE7296A894F4C6A75467EB8959F4C013815C00FACEF38A7297F42AD2600B7006A0200EC538D51500010B88919624CE694C0027B91951125AFF7B9B1682040253D006E8000844138F105C0010D84D1D2304B213007213900D95B73FE914CC9FCBFA9EEA81802FA0094A34CA3649F019800B48890C2382002E727DF7293C1B900A160008642B87312C0010F8DB08610080331720FC580
diff --git a/2021/inputs/day_17.txt b/2021/inputs/day_17.txt
new file mode 100644
index 0000000..039df20
--- /dev/null
+++ b/2021/inputs/day_17.txt
@@ -0,0 +1 @@
+target area: x=206..250, y=-105..-57
diff --git a/2021/inputs/day_18.txt b/2021/inputs/day_18.txt
new file mode 100644
index 0000000..cc88c31
--- /dev/null
+++ b/2021/inputs/day_18.txt
@@ -0,0 +1,100 @@
+[[[0,6],[[8,9],[3,7]]],[[[3,4],[7,0]],[[6,9],[4,8]]]]
+[[2,2],[[[7,7],5],[[0,7],2]]]
+[6,[9,[[7,9],7]]]
+[[[[5,1],[9,3]],8],[4,[2,[6,6]]]]
+[[[4,3],[0,4]],[[[4,5],[9,3]],3]]
+[[[[2,7],7],[[6,5],6]],[[[2,3],[7,9]],[0,3]]]
+[[[3,[6,2]],[7,[9,4]]],3]
+[[[[9,3],4],[3,9]],8]
+[[[7,8],[[2,6],1]],[[[1,7],5],[[5,6],[6,1]]]]
+[[[[0,7],9],[[6,6],[8,4]]],[[[9,2],[4,8]],[[8,5],[0,6]]]]
+[[6,[[5,6],[3,8]]],[[8,9],[4,3]]]
+[[[[0,6],1],[[2,4],[1,4]]],[[7,5],[8,3]]]
+[[[[0,7],1],[[5,7],7]],[[[3,3],[6,7]],[[2,8],[2,9]]]]
+[[7,7],[[1,[3,7]],9]]
+[[8,[[3,0],0]],[[[8,3],0],9]]
+[[[[6,2],[2,6]],3],[6,[[4,7],2]]]
+[[[5,[2,3]],[8,[8,7]]],[[0,0],2]]
+[[1,6],[7,[7,[9,0]]]]
+[[[7,[7,6]],[7,4]],[[7,2],[6,5]]]
+[1,[[8,[9,5]],2]]
+[[[[8,2],[6,5]],[4,[9,2]]],[[0,[2,6]],[6,6]]]
+[[1,[[7,2],5]],[[[6,0],[8,1]],8]]
+[[[[0,6],[6,6]],2],[[4,2],[2,4]]]
+[[5,[9,0]],[2,5]]
+[7,[[9,7],[[9,9],4]]]
+[[5,[[6,4],7]],[8,[[4,4],[9,0]]]]
+[2,[[[3,2],[1,9]],[[3,8],[7,5]]]]
+[[[[8,2],0],[5,[4,3]]],0]
+[[[0,[7,8]],[[9,6],7]],[[7,[1,0]],[[0,3],7]]]
+[[[[8,3],0],[[4,8],[7,9]]],[[7,1],[[8,4],[4,4]]]]
+[[[2,0],[[6,6],7]],[[2,[3,9]],[[5,6],[4,6]]]]
+[[[[1,4],8],[9,6]],8]
+[[7,[9,1]],[1,[[8,5],[6,8]]]]
+[8,[[2,6],5]]
+[[[9,[7,8]],[[7,8],6]],3]
+[1,[[[2,1],7],[[2,6],7]]]
+[[7,[4,[6,1]]],[[[4,9],8],[[0,1],[1,7]]]]
+[[[7,9],[[2,6],[2,4]]],[[2,[1,7]],[[3,9],[8,9]]]]
+[[[[4,5],[4,7]],[[4,0],[9,9]]],0]
+[3,[[[6,9],2],[5,3]]]
+[1,[8,[[0,8],[1,3]]]]
+[[[7,[9,2]],[4,[0,3]]],2]
+[3,[[[7,7],6],[[8,4],1]]]
+[[[[6,3],[2,6]],[[6,9],[8,1]]],[[[2,1],[7,5]],[[7,3],[7,3]]]]
+[[[1,6],[[5,1],[5,0]]],[[1,0],[6,9]]]
+[[[[8,6],[3,3]],[[2,1],[4,1]]],[1,[[7,7],[8,5]]]]
+[[1,5],[6,[[2,3],[2,4]]]]
+[[0,[7,[9,0]]],[9,0]]
+[[[5,[1,9]],[0,[9,8]]],[[[6,7],[6,3]],[8,1]]]
+[[[4,7],[6,[2,1]]],5]
+[[3,[4,0]],[2,[4,5]]]
+[[[4,0],[6,[8,3]]],[[0,6],8]]
+[[[[9,9],0],[[1,8],0]],[[1,6],[3,4]]]
+[[[[4,3],4],1],[0,[[2,1],[3,9]]]]
+[[[8,[6,2]],[6,0]],7]
+[[9,[6,[3,1]]],[[[5,9],0],[4,5]]]
+[4,[7,[[2,5],4]]]
+[[2,[8,[2,9]]],[[[0,1],[3,5]],1]]
+[[[7,9],[7,3]],[[1,[7,1]],[1,2]]]
+[[[7,0],[[1,0],8]],[[9,[7,6]],[9,[7,2]]]]
+[[[8,1],[[0,6],2]],[9,[[1,8],[5,4]]]]
+[6,[[[9,5],[5,4]],3]]
+[[4,[[6,8],[8,3]]],[[9,[0,9]],7]]
+[[[6,9],[[2,3],8]],[[9,[5,1]],[[7,6],5]]]
+[[0,1],5]
+[[4,[1,9]],[[8,0],8]]
+[[5,[0,6]],[1,8]]
+[[[[9,2],7],7],[4,[1,[5,6]]]]
+[[7,[9,[6,5]]],[[6,9],1]]
+[[[5,2],[0,[1,4]]],[[0,4],[[9,4],8]]]
+[[[[7,1],[4,9]],3],[[[4,5],8],[7,[0,4]]]]
+[[[9,[8,0]],7],[[[4,5],8],[[4,3],[8,5]]]]
+[[9,[7,0]],[[3,[1,7]],[[7,0],7]]]
+[[2,[[6,2],6]],8]
+[[[8,[9,6]],[[5,8],[7,2]]],[4,[9,9]]]
+[[[[0,5],0],[[8,4],4]],[[7,9],8]]
+[[[0,[0,3]],[0,[8,8]]],[[[2,1],3],4]]
+[0,[[4,1],[[9,9],2]]]
+[[3,[7,[6,7]]],[0,2]]
+[7,2]
+[0,[3,[[3,4],[4,4]]]]
+[[[[0,1],[5,9]],[[4,2],7]],[5,[1,8]]]
+[[7,1],[[1,[9,9]],[[8,4],8]]]
+[[[1,[8,3]],[[3,7],0]],[[2,0],[[1,6],[9,9]]]]
+[[[1,4],[1,4]],[[2,[2,7]],[2,[7,1]]]]
+[[1,[[6,8],[8,6]]],[0,[8,0]]]
+[1,[[2,0],7]]
+[[[[6,0],9],[[6,9],[8,3]]],[[3,[9,9]],6]]
+[[[[9,8],[2,8]],[2,3]],[6,2]]
+[[[6,[2,2]],7],[[3,[7,8]],7]]
+[[[5,[3,7]],1],[[[4,0],3],[5,4]]]
+[[[7,[4,3]],[9,[4,4]]],7]
+[[2,[[1,5],6]],[[2,3],[[2,5],[7,1]]]]
+[[[[3,9],[1,9]],3],[5,[[0,6],[3,2]]]]
+[[[3,[7,5]],[[7,7],[2,8]]],[4,[1,[0,0]]]]
+[[4,[2,[8,7]]],[[[0,5],0],9]]
+[9,[9,[6,4]]]
+[[5,[[4,9],2]],[9,9]]
+[[1,[[6,0],[9,9]]],[[[8,4],1],[[5,2],[6,1]]]]
+[[1,[[9,0],8]],6]
diff --git a/2021/inputs/day_19.txt b/2021/inputs/day_19.txt
new file mode 100644
index 0000000..e2f977f
--- /dev/null
+++ b/2021/inputs/day_19.txt
@@ -0,0 +1,856 @@
+--- scanner 0 ---
+785,-772,752
+548,703,908
+571,658,844
+-654,-601,-321
+509,339,-583
+113,-24,5
+-685,476,-691
+-573,-837,487
+667,-785,773
+417,248,-660
+567,-853,-801
+531,655,675
+543,245,-584
+-569,714,648
+520,-824,-758
+-551,613,646
+-6,-155,84
+-645,452,-613
+-665,-681,-424
+-624,-798,555
+763,-844,821
+-455,763,640
+-583,-753,-380
+382,-897,-773
+-550,444,-612
+-567,-808,562
+
+--- scanner 1 ---
+-762,-848,417
+-470,575,-597
+510,-362,658
+-452,659,-532
+-951,675,325
+650,413,654
+653,-412,637
+-847,-836,444
+525,-542,600
+-952,-828,466
+-534,-483,-635
+263,625,-879
+487,-833,-665
+-478,-438,-584
+-58,30,-29
+494,-775,-599
+576,364,635
+283,615,-897
+-505,-387,-655
+-450,583,-662
+289,498,-824
+-955,537,301
+609,384,498
+505,-724,-559
+-929,545,377
+
+--- scanner 2 ---
+-4,133,0
+409,846,-912
+511,-669,287
+-727,-315,505
+397,674,-855
+-391,-664,-755
+455,-676,267
+-681,708,805
+-534,702,800
+-840,-409,440
+-455,-619,-732
+544,867,356
+469,-702,368
+391,832,420
+-624,-616,-772
+-547,811,-518
+410,-260,-715
+429,-224,-632
+397,616,-957
+-814,-307,456
+534,-227,-752
+-478,883,-540
+-528,703,707
+-526,824,-636
+509,845,344
+
+--- scanner 3 ---
+900,-493,416
+-792,754,522
+-424,262,-635
+-368,454,-613
+-746,-725,-569
+-752,649,599
+456,-364,-590
+-446,-588,509
+-634,-755,-694
+839,573,-420
+-749,645,413
+690,673,-399
+569,-382,-585
+-725,-651,-724
+-563,-606,561
+-516,-779,510
+804,717,-336
+845,465,483
+-362,321,-724
+772,-525,555
+406,-491,-567
+37,-7,32
+687,484,510
+821,-464,374
+751,405,481
+
+--- scanner 4 ---
+-540,515,741
+856,756,328
+562,-779,560
+797,612,394
+482,-908,548
+-585,-571,-807
+709,770,412
+-478,433,677
+-549,-545,527
+521,-609,-513
+-505,-521,-879
+-461,-510,-902
+-337,-612,537
+-32,43,-140
+644,-634,-445
+-550,533,700
+766,728,-558
+-14,-68,35
+814,686,-634
+-712,690,-680
+781,596,-529
+676,-895,583
+559,-558,-534
+-789,611,-631
+-464,-655,596
+-718,530,-751
+
+--- scanner 5 ---
+619,-451,-778
+-517,534,-801
+-617,683,-780
+-379,406,390
+423,-502,-802
+-704,-496,482
+-69,-98,-19
+485,767,293
+470,695,473
+-473,648,-864
+573,771,459
+-389,301,412
+-720,-612,534
+445,-434,-848
+532,321,-712
+-364,382,382
+-618,-586,385
+520,288,-704
+-869,-518,-476
+725,-500,380
+-736,-524,-587
+-928,-580,-565
+614,471,-707
+779,-495,407
+671,-428,522
+
+--- scanner 6 ---
+-665,672,665
+-565,744,642
+-933,-475,-523
+389,717,-914
+254,-687,-701
+523,758,561
+-662,504,-786
+468,-298,310
+480,885,502
+-960,-354,-558
+234,-687,-751
+439,637,-842
+-173,107,-115
+-647,682,706
+260,-481,-766
+413,673,492
+11,-28,-159
+418,-340,447
+369,-299,251
+-736,-356,408
+-727,-524,477
+378,761,-937
+-904,-282,-562
+-743,433,-666
+-684,-386,371
+-822,510,-715
+
+--- scanner 7 ---
+465,801,-361
+-583,551,482
+-521,633,546
+-593,533,523
+434,583,-327
+-451,-805,455
+-611,-835,-355
+666,296,811
+-574,648,-470
+30,-123,175
+-119,-152,-16
+439,-652,399
+436,-717,520
+813,310,895
+413,670,-390
+-618,484,-380
+-515,-704,545
+406,-557,567
+-581,-804,602
+754,454,829
+-765,-854,-475
+573,-842,-568
+-827,-846,-405
+718,-754,-533
+497,-753,-472
+-626,481,-462
+
+--- scanner 8 ---
+-834,731,729
+-579,282,-466
+-376,-761,734
+655,-969,-550
+641,575,492
+-789,667,706
+722,-978,710
+-530,-683,-261
+654,596,610
+693,-935,757
+538,441,-831
+-124,-92,62
+532,588,-826
+-477,308,-482
+-448,-778,-293
+-470,-760,768
+-379,-837,860
+-475,-627,-288
+-485,395,-531
+-786,498,746
+713,644,514
+719,-888,-497
+533,594,-733
+766,-950,895
+743,-966,-388
+
+--- scanner 9 ---
+374,-543,718
+-699,-584,548
+-401,-360,-681
+-666,527,782
+-147,-126,155
+695,385,-533
+-735,442,672
+763,439,817
+395,-581,769
+-676,315,715
+668,563,756
+808,-860,-376
+-438,-462,-763
+740,483,806
+-577,779,-632
+784,-767,-244
+797,-770,-315
+-564,834,-466
+-435,-398,-748
+-687,-504,419
+-12,-91,-12
+662,477,-577
+-592,758,-411
+306,-666,693
+-722,-698,432
+620,459,-474
+
+--- scanner 10 ---
+-57,48,-5
+507,768,-684
+490,702,-604
+517,-605,-365
+-442,-603,-255
+-812,583,625
+692,-604,914
+369,691,-619
+486,386,918
+-476,-772,765
+537,-625,-311
+353,-589,-374
+-896,597,781
+-904,615,790
+-358,-698,669
+-511,-531,-348
+-499,749,-395
+-332,-694,727
+624,-745,922
+398,356,966
+654,-852,912
+452,403,810
+-467,856,-399
+-477,-661,-349
+38,-3,171
+-428,739,-376
+
+--- scanner 11 ---
+709,533,-849
+-495,-544,650
+-488,600,604
+736,464,642
+-462,762,641
+-325,776,-552
+153,177,47
+-505,-304,-506
+-423,591,584
+853,499,615
+540,-737,-707
+54,23,-83
+756,-686,346
+-574,-217,-397
+808,608,647
+-412,839,-613
+-489,-491,547
+716,-646,426
+-505,-414,-420
+834,555,-697
+-518,-470,473
+800,-801,448
+683,420,-707
+471,-645,-649
+572,-781,-675
+-282,894,-529
+
+--- scanner 12 ---
+-438,505,-689
+630,785,420
+-391,-486,434
+645,789,392
+-436,452,649
+402,-547,-680
+37,27,31
+579,865,382
+-460,493,-724
+818,609,-455
+-599,491,705
+-567,-453,350
+858,631,-541
+354,-422,756
+-689,-808,-836
+-442,-405,279
+760,549,-435
+407,-440,640
+-631,-706,-836
+-459,-763,-824
+344,-643,-802
+-508,546,645
+393,-433,644
+87,142,-114
+332,-520,-754
+-473,569,-842
+
+--- scanner 13 ---
+-830,923,434
+-517,-584,-423
+526,-422,-325
+-820,786,372
+440,701,541
+-740,-600,715
+-884,499,-539
+597,-679,703
+358,548,-251
+-727,442,-487
+697,-656,775
+-741,-747,845
+302,544,-323
+-704,-546,-468
+535,-491,-493
+-640,-585,-311
+-909,441,-436
+329,509,-444
+-758,792,378
+-640,-657,781
+-53,73,94
+578,-385,-355
+615,-720,713
+519,652,464
+600,772,535
+
+--- scanner 14 ---
+574,-540,704
+285,381,-354
+515,-466,779
+300,317,-351
+471,-558,746
+733,689,881
+-554,416,557
+416,-860,-493
+804,686,868
+367,279,-317
+582,-915,-480
+13,37,-48
+-390,-407,604
+-590,513,-476
+-512,-378,568
+672,779,892
+-491,-464,-576
+-478,413,641
+-551,-420,687
+-508,525,647
+-672,399,-455
+-153,-91,69
+-406,-483,-711
+-675,542,-562
+637,-839,-508
+-516,-428,-610
+
+--- scanner 15 ---
+-654,605,-887
+290,437,636
+-681,722,-852
+449,-680,271
+-2,-62,-147
+-655,-593,-589
+478,505,-851
+596,-674,276
+259,-587,-558
+396,-562,-499
+316,335,620
+364,504,-669
+-675,388,841
+-880,-861,605
+-619,333,814
+-692,-619,-751
+339,474,-774
+-712,-554,-760
+-961,-797,552
+-958,-885,714
+-770,306,809
+602,-675,369
+-144,-143,-11
+341,-570,-441
+-649,677,-743
+403,343,571
+
+--- scanner 16 ---
+-692,-623,449
+543,-617,-551
+784,-472,679
+560,-738,-414
+803,723,736
+-868,-717,-800
+-756,-686,376
+-6,81,-80
+-528,436,506
+772,951,-366
+695,860,-458
+696,954,-492
+724,755,601
+80,-14,78
+-732,541,-520
+514,-735,-636
+-625,-757,393
+-833,-698,-600
+-534,586,602
+-796,496,-497
+-843,-726,-747
+-536,485,620
+-563,544,-480
+725,747,696
+739,-536,621
+630,-507,673
+
+--- scanner 17 ---
+-754,753,-378
+-683,-534,-954
+533,-622,603
+498,403,-673
+-907,673,-415
+811,-522,-627
+650,-422,-612
+-703,732,237
+569,491,723
+526,405,-595
+366,476,-633
+584,549,543
+-724,652,-426
+535,-770,576
+-880,-851,629
+-907,-681,559
+-680,-511,-926
+454,-669,691
+1,38,-78
+-823,-796,553
+-578,-470,-910
+799,-467,-509
+-893,683,257
+712,512,673
+-788,705,249
+
+--- scanner 18 ---
+-844,226,329
+602,395,686
+478,-694,534
+-348,-651,505
+-613,490,-691
+348,-738,-528
+99,-39,-2
+368,-688,-528
+-469,-664,619
+-819,-510,-740
+-790,-549,-933
+-605,-684,511
+582,323,-917
+-821,433,267
+465,-566,523
+483,264,-916
+-846,-545,-861
+532,460,-875
+-716,303,258
+-622,421,-859
+579,362,756
+-50,-119,-96
+-570,384,-829
+625,314,789
+545,-638,566
+374,-753,-734
+
+--- scanner 19 ---
+878,378,296
+-797,-402,-756
+718,453,-561
+862,-402,-635
+-789,-416,-632
+-580,-705,635
+-512,590,-477
+-786,752,516
+-487,713,-545
+-436,675,-566
+845,-482,-688
+-773,558,551
+808,420,-666
+-679,-738,771
+734,437,362
+962,-292,489
+-23,-11,11
+865,-472,-504
+892,525,380
+-737,-513,-660
+767,-284,520
+-657,672,528
+841,-333,477
+162,-53,-105
+850,468,-590
+-697,-659,753
+
+--- scanner 20 ---
+557,-760,464
+-477,-322,-599
+525,781,-733
+-396,-771,757
+-418,-697,598
+-517,-468,-611
+467,781,-835
+697,769,-790
+714,-334,-432
+765,-489,-513
+-115,33,18
+718,634,478
+-409,768,-593
+-376,644,-630
+-373,749,-510
+696,669,466
+-818,667,409
+-471,-462,-594
+40,-70,140
+683,787,542
+-825,723,389
+589,-405,-480
+-851,709,490
+648,-700,519
+-440,-600,673
+720,-704,425
+
+--- scanner 21 ---
+748,-630,-477
+545,-599,511
+834,985,537
+887,764,-454
+-703,755,410
+-650,656,-642
+879,715,-541
+-555,-682,-789
+617,-743,516
+-462,-670,549
+916,953,632
+-669,973,441
+-568,653,-650
+-497,-582,694
+-625,-674,-851
+717,-707,-616
+889,958,481
+100,41,-32
+718,-525,-502
+-675,-663,-635
+-560,820,-598
+-640,842,389
+785,780,-428
+-558,-581,473
+500,-708,543
+
+--- scanner 22 ---
+791,545,-530
+816,515,-425
+896,-546,-641
+-417,694,544
+-399,436,-637
+379,650,683
+670,-910,856
+759,-521,-700
+-833,-911,715
+359,617,546
+-367,551,523
+-461,-898,-819
+-853,-721,764
+408,691,527
+6,59,88
+-514,517,-738
+-537,-841,-764
+814,-529,-758
+677,546,-348
+-29,-122,-30
+532,-914,880
+-531,-925,-649
+-547,566,581
+-841,-806,737
+-487,515,-590
+540,-888,804
+
+--- scanner 23 ---
+-600,-462,-505
+969,676,350
+539,367,-688
+-757,638,-532
+659,-710,231
+589,-880,258
+420,-428,-674
+-404,819,242
+476,551,-652
+-504,-344,-579
+-747,668,-425
+981,703,435
+-768,-702,610
+514,-463,-616
+-412,743,268
+-749,706,-673
+961,654,245
+-562,-318,-583
+513,-497,-746
+106,77,-23
+-631,-761,635
+-686,-819,627
+-542,795,246
+665,-825,315
+530,531,-672
+
+--- scanner 24 ---
+-319,-979,-426
+-664,465,584
+-793,385,596
+-430,-646,617
+885,612,732
+-705,449,-405
+-372,-954,-417
+511,359,-469
+727,700,750
+533,-628,-549
+548,-575,467
+648,-647,444
+380,411,-440
+630,-637,403
+598,380,-406
+700,-680,-541
+-780,579,561
+871,759,816
+6,-30,-98
+-568,432,-526
+697,-672,-459
+-540,-561,548
+-497,-434,607
+-483,403,-408
+-519,-944,-445
+124,-106,71
+
+--- scanner 25 ---
+794,-593,-715
+-657,696,404
+-560,621,382
+743,-397,-739
+-789,-588,481
+659,644,448
+-852,-457,-625
+665,954,-502
+817,-645,585
+-132,31,-22
+749,730,545
+52,-21,55
+811,-419,-785
+-935,-576,441
+745,-699,443
+721,762,-524
+-497,487,-593
+750,-753,470
+633,746,597
+727,895,-413
+-923,-409,-750
+-486,780,360
+-768,-490,-801
+-557,542,-684
+-553,448,-756
+-795,-571,435
+
+--- scanner 26 ---
+-716,663,621
+-706,477,-410
+823,361,-502
+-749,-353,928
+-770,-739,-500
+768,334,-558
+821,555,433
+-767,-517,-454
+-649,-602,-483
+464,-656,856
+922,-661,-636
+70,56,10
+-634,666,629
+-730,-553,893
+919,-787,-712
+-769,564,-431
+-626,499,577
+512,-673,623
+-758,-406,903
+850,366,-653
+-735,346,-462
+813,604,520
+828,-695,-635
+719,539,407
+509,-633,792
+
+--- scanner 27 ---
+-781,-794,775
+523,883,-452
+491,838,-561
+-497,635,-530
+497,-432,-715
+-773,-768,699
+534,-458,-553
+690,830,848
+-417,-426,-746
+-905,811,422
+712,746,693
+-643,-790,751
+-954,737,441
+17,148,31
+591,-459,538
+-499,-409,-863
+665,-488,517
+-119,39,-120
+-522,665,-635
+-636,666,-453
+496,766,-417
+488,-465,591
+-934,770,578
+-554,-401,-805
+554,-393,-544
+792,786,733
+
+--- scanner 28 ---
+875,474,732
+751,669,-640
+-354,949,-878
+-553,986,-871
+567,-363,592
+894,-337,-815
+-322,-415,-682
+786,-364,-722
+679,761,-750
+-346,603,885
+-375,-418,576
+492,-334,586
+-419,-490,494
+902,-282,-642
+560,-373,535
+702,557,-769
+17,32,-102
+-309,425,877
+-335,-280,-784
+-417,563,824
+-328,-250,-663
+106,126,67
+815,410,807
+-316,-570,505
+823,424,663
+-456,959,-777
+
+--- scanner 29 ---
+-741,-481,-792
+-625,503,-421
+431,449,245
+585,319,-378
+460,-572,554
+-482,-517,538
+512,336,-367
+-738,270,467
+-790,320,398
+-574,543,-588
+504,-644,636
+-693,-540,-696
+881,-472,-596
+564,370,-525
+401,-724,625
+-730,256,323
+853,-428,-411
+-672,-553,-814
+-475,-527,595
+502,409,306
+-23,-53,-119
+-407,-488,544
+-595,419,-588
+838,-501,-549
+394,271,253
+
+--- scanner 30 ---
+850,573,-382
+-386,-445,574
+810,650,-487
+807,464,-491
+425,667,659
+631,651,711
+353,-371,673
+-781,-369,-563
+-746,-285,-419
+-771,932,682
+-632,-348,-463
+-629,561,-652
+336,-301,499
+-419,-437,586
+426,-562,-682
+482,-584,-874
+-3,40,-88
+-85,187,75
+-693,532,-731
+-569,-442,668
+-787,534,-671
+-699,946,479
+-671,944,575
+404,-347,477
+504,638,724
+420,-673,-815
diff --git a/2021/inputs/day_2.txt b/2021/inputs/day_2.txt
new file mode 100644
index 0000000..917f466
--- /dev/null
+++ b/2021/inputs/day_2.txt
@@ -0,0 +1,1000 @@
+forward 2
+forward 6
+forward 8
+forward 7
+down 5
+forward 8
+forward 9
+down 2
+forward 6
+down 9
+forward 1
+forward 8
+forward 6
+forward 7
+down 4
+down 5
+forward 1
+up 5
+down 7
+down 7
+down 1
+up 2
+forward 3
+forward 2
+forward 2
+forward 5
+up 5
+forward 4
+forward 9
+forward 6
+down 4
+down 9
+down 2
+up 6
+forward 9
+up 7
+forward 7
+forward 5
+up 3
+forward 4
+forward 9
+up 5
+down 3
+up 6
+down 5
+down 4
+up 6
+forward 9
+forward 6
+down 9
+up 3
+down 7
+up 1
+forward 8
+forward 3
+forward 8
+up 6
+forward 7
+forward 5
+forward 8
+up 2
+forward 2
+forward 7
+forward 7
+down 1
+forward 7
+up 7
+down 3
+forward 9
+down 5
+down 2
+forward 5
+forward 1
+forward 4
+forward 6
+up 2
+up 7
+forward 2
+forward 6
+forward 7
+down 9
+up 8
+down 9
+down 3
+up 8
+down 3
+down 2
+up 6
+forward 3
+forward 9
+down 4
+forward 5
+down 6
+up 8
+forward 1
+down 6
+down 6
+forward 5
+down 6
+forward 8
+up 7
+down 3
+forward 7
+forward 3
+forward 1
+forward 4
+forward 4
+down 3
+up 9
+up 5
+forward 1
+down 2
+up 4
+forward 7
+up 4
+down 3
+down 5
+down 8
+forward 4
+up 8
+forward 7
+up 3
+up 4
+up 9
+forward 1
+forward 1
+down 6
+forward 1
+down 8
+up 4
+forward 9
+forward 9
+down 6
+forward 9
+forward 8
+down 2
+up 3
+up 3
+down 9
+forward 7
+forward 8
+down 4
+forward 1
+up 3
+forward 3
+down 3
+down 9
+down 5
+up 7
+up 2
+forward 7
+forward 2
+forward 5
+forward 4
+down 7
+forward 7
+up 1
+up 3
+down 6
+down 4
+forward 9
+forward 8
+down 5
+down 4
+down 1
+down 5
+forward 9
+forward 8
+down 3
+forward 5
+forward 3
+forward 6
+down 6
+forward 3
+up 9
+forward 4
+down 7
+forward 3
+forward 7
+forward 1
+forward 5
+down 1
+forward 1
+down 6
+up 7
+down 3
+forward 2
+down 4
+forward 6
+up 6
+forward 8
+forward 8
+down 5
+up 4
+forward 7
+forward 6
+up 4
+forward 6
+down 1
+forward 6
+forward 2
+up 4
+down 6
+down 7
+forward 4
+down 4
+forward 1
+down 3
+forward 5
+forward 5
+forward 9
+forward 3
+up 7
+down 7
+forward 7
+forward 5
+down 1
+down 1
+forward 3
+down 8
+forward 1
+forward 2
+forward 9
+forward 1
+forward 3
+down 3
+up 4
+forward 5
+down 1
+forward 3
+up 7
+forward 3
+forward 6
+up 6
+up 3
+forward 9
+forward 5
+down 2
+up 4
+up 3
+forward 3
+forward 7
+down 1
+forward 5
+forward 5
+down 1
+forward 4
+forward 2
+down 1
+down 9
+down 7
+up 1
+forward 2
+down 2
+forward 3
+forward 8
+forward 4
+forward 6
+down 4
+down 1
+forward 5
+forward 1
+forward 7
+down 8
+forward 9
+down 6
+forward 3
+up 5
+up 1
+up 7
+down 5
+forward 7
+forward 5
+forward 5
+up 1
+forward 8
+down 8
+down 7
+forward 9
+forward 9
+down 3
+forward 7
+forward 2
+down 1
+down 6
+down 1
+forward 7
+down 3
+forward 1
+forward 1
+forward 6
+forward 6
+up 9
+down 3
+forward 9
+down 8
+forward 4
+up 6
+down 4
+down 7
+forward 5
+up 3
+forward 1
+forward 8
+up 6
+up 3
+down 2
+forward 2
+forward 5
+forward 1
+down 8
+down 8
+down 3
+forward 5
+forward 4
+forward 4
+forward 5
+up 5
+forward 2
+forward 5
+up 5
+forward 6
+forward 6
+forward 9
+up 5
+forward 4
+up 4
+forward 8
+down 8
+forward 5
+forward 2
+forward 4
+forward 3
+forward 1
+down 1
+down 9
+down 2
+forward 4
+down 3
+down 6
+forward 2
+up 7
+forward 6
+down 4
+up 9
+down 1
+forward 8
+forward 1
+forward 1
+down 9
+down 3
+down 2
+down 7
+up 5
+down 7
+up 9
+down 8
+down 7
+forward 9
+forward 7
+up 4
+forward 5
+up 9
+down 4
+forward 1
+forward 9
+down 7
+up 9
+forward 6
+forward 4
+up 8
+down 2
+forward 1
+up 6
+up 5
+down 4
+forward 8
+down 3
+down 5
+down 6
+up 1
+up 9
+up 7
+up 5
+forward 1
+forward 3
+down 7
+forward 9
+forward 2
+forward 6
+down 4
+down 7
+forward 3
+down 1
+up 5
+forward 3
+down 3
+down 1
+forward 1
+forward 4
+forward 8
+down 4
+down 1
+forward 3
+down 7
+up 9
+down 8
+down 1
+forward 2
+down 6
+down 9
+down 9
+forward 2
+forward 8
+up 2
+down 5
+down 9
+forward 1
+up 9
+down 7
+forward 8
+down 7
+up 4
+forward 8
+down 8
+down 7
+forward 6
+up 7
+down 4
+down 9
+forward 9
+up 8
+down 8
+down 8
+down 8
+down 5
+forward 2
+up 9
+down 2
+up 7
+down 7
+down 3
+down 6
+forward 9
+forward 1
+down 1
+down 5
+up 4
+down 5
+forward 5
+up 2
+forward 5
+down 5
+forward 1
+forward 9
+down 9
+forward 3
+forward 3
+down 8
+down 2
+down 8
+forward 8
+forward 7
+up 6
+down 4
+down 5
+forward 8
+forward 4
+forward 7
+forward 1
+down 9
+down 4
+down 2
+forward 5
+down 3
+down 7
+down 5
+forward 8
+up 1
+down 4
+down 7
+down 7
+forward 2
+up 5
+forward 5
+up 2
+up 4
+down 9
+forward 7
+forward 6
+forward 6
+down 2
+forward 7
+forward 7
+down 7
+forward 8
+down 2
+up 9
+down 1
+forward 9
+down 9
+forward 3
+down 9
+down 2
+forward 9
+forward 8
+down 7
+up 2
+forward 8
+forward 1
+up 2
+down 7
+up 7
+down 8
+up 1
+up 4
+up 2
+up 3
+down 7
+forward 1
+down 8
+down 4
+down 2
+down 4
+up 8
+forward 8
+down 2
+up 5
+up 4
+forward 7
+up 1
+forward 3
+down 8
+down 4
+forward 4
+down 8
+forward 2
+down 1
+up 9
+forward 9
+down 4
+up 2
+down 8
+up 9
+forward 6
+down 7
+up 7
+forward 9
+forward 1
+down 8
+forward 5
+down 9
+forward 6
+down 9
+forward 9
+forward 1
+down 8
+up 4
+forward 9
+forward 3
+down 9
+up 8
+forward 4
+up 8
+forward 7
+down 7
+up 6
+down 7
+down 2
+down 7
+forward 3
+forward 2
+down 6
+down 2
+down 7
+up 4
+forward 5
+down 5
+forward 2
+up 3
+up 8
+forward 8
+forward 1
+forward 7
+down 7
+down 2
+forward 1
+down 7
+down 7
+up 2
+up 7
+up 7
+forward 4
+down 5
+forward 5
+forward 7
+forward 7
+down 7
+down 8
+forward 8
+forward 8
+up 3
+up 9
+forward 2
+down 7
+up 3
+up 1
+up 1
+down 9
+up 5
+down 6
+up 8
+up 3
+up 5
+forward 7
+forward 3
+forward 8
+forward 4
+up 1
+forward 2
+forward 1
+up 5
+forward 9
+forward 8
+down 7
+up 1
+forward 7
+down 8
+forward 1
+forward 9
+forward 9
+forward 9
+forward 8
+down 1
+forward 8
+forward 7
+up 9
+up 3
+forward 8
+forward 2
+up 2
+down 7
+down 6
+forward 4
+forward 3
+forward 6
+up 7
+down 9
+forward 1
+forward 4
+down 1
+forward 4
+up 3
+down 8
+forward 1
+up 6
+forward 8
+forward 2
+forward 1
+forward 8
+forward 4
+down 7
+forward 4
+forward 6
+down 2
+up 4
+forward 4
+forward 3
+down 5
+forward 8
+forward 4
+forward 5
+forward 7
+forward 6
+forward 5
+forward 9
+down 4
+down 9
+forward 6
+up 7
+down 6
+down 3
+down 2
+up 9
+forward 7
+down 4
+down 5
+forward 2
+forward 3
+forward 2
+forward 9
+forward 7
+forward 8
+down 9
+down 7
+down 9
+down 7
+forward 5
+forward 2
+down 5
+forward 6
+down 1
+down 2
+down 6
+forward 9
+down 3
+up 6
+down 4
+down 5
+forward 3
+forward 7
+down 8
+forward 2
+forward 5
+down 9
+down 3
+up 5
+down 6
+forward 6
+up 3
+down 6
+down 1
+down 8
+down 5
+down 3
+forward 3
+up 6
+up 7
+forward 8
+forward 9
+forward 2
+forward 6
+forward 2
+forward 3
+down 7
+down 3
+down 3
+down 6
+down 2
+forward 4
+forward 3
+forward 8
+up 1
+down 9
+forward 5
+up 3
+down 7
+down 6
+forward 8
+forward 1
+up 6
+forward 3
+forward 1
+up 9
+forward 6
+forward 3
+down 9
+down 4
+down 9
+forward 5
+down 8
+down 3
+forward 1
+forward 1
+down 9
+down 6
+down 3
+up 7
+down 3
+forward 5
+down 2
+forward 7
+forward 2
+forward 5
+up 7
+forward 4
+forward 4
+up 3
+down 6
+down 7
+up 1
+down 6
+forward 1
+forward 9
+down 7
+down 8
+forward 5
+down 1
+down 9
+up 5
+up 4
+up 3
+forward 6
+down 6
+forward 4
+forward 8
+up 6
+up 2
+down 9
+forward 2
+forward 5
+forward 1
+forward 3
+forward 9
+up 3
+forward 2
+forward 1
+forward 3
+forward 3
+up 9
+forward 3
+forward 7
+down 6
+forward 2
+down 8
+up 9
+forward 8
+forward 5
+forward 2
+up 8
+down 9
+up 5
+forward 3
+down 4
+forward 1
+up 9
+down 4
+down 5
+up 4
+down 6
+down 4
+down 6
+down 4
+forward 4
+down 2
+down 1
+down 6
+forward 2
+down 1
+down 3
+forward 4
+down 3
+down 5
+down 5
+up 1
+up 4
+down 4
+down 4
+down 5
+down 4
+down 5
+forward 5
+down 8
+down 5
+down 5
+down 9
+up 1
+up 5
+forward 5
+down 1
+down 9
+down 4
+down 3
+forward 3
+down 2
+forward 9
+down 3
+forward 1
+down 9
+down 5
+up 7
+forward 3
+forward 1
+forward 2
+down 5
+forward 8
+down 3
+down 3
+forward 6
+down 8
+down 3
+down 8
+up 9
+forward 3
+down 6
+forward 4
+down 6
+down 4
+up 5
+forward 1
+up 6
+up 2
+forward 2
+down 8
+forward 7
+forward 8
+down 6
+down 7
+forward 7
+up 3
+forward 3
+up 6
+forward 3
+down 1
+down 7
+forward 9
+forward 5
+up 1
+forward 7
+forward 1
+down 3
+forward 1
+up 4
+up 2
+up 1
+down 8
+forward 9
+forward 3
+forward 4
+up 7
+forward 5
+down 1
+down 8
+down 3
+down 4
+down 6
+down 5
+forward 4
+down 4
+down 2
+down 4
+down 3
+down 3
+forward 4
+up 3
+forward 6
+down 7
+forward 4
+up 2
+down 7
+forward 8
+up 9
+forward 6
+forward 8
+down 1
+down 6
+forward 6
+down 6
+down 9
+up 8
+forward 8
+up 5
+forward 6
+forward 9
+forward 4
+up 2
+forward 3
+down 7
+down 8
+down 4
+up 8
+forward 8
+forward 1
+up 5
+up 4
+up 1
+down 9
+down 9
+up 2
+forward 9
+down 7
+down 2
+up 2
+down 1
+forward 6
+forward 2
+down 5
+down 8
+forward 6
+down 2
+down 3
+forward 6
+forward 7
+up 8
+down 4
+forward 5
+down 9
+down 2
+down 7
+down 9
+down 5
+forward 9
+forward 2
+down 6
+forward 7
+up 6
+forward 3
+up 2
+forward 9
+forward 2
diff --git a/2021/inputs/day_20.txt b/2021/inputs/day_20.txt
new file mode 100644
index 0000000..758420b
--- /dev/null
+++ b/2021/inputs/day_20.txt
@@ -0,0 +1,102 @@
+##.....##.#.#####.#...###...#.##..#....##..#.##.#.#....##.....#.##.##.#.#.#...#.#.#.###.##..#.#.#.#..#.##.#...#..#.#.#..#####.##.#..#..##.#..#.#...#.....#.###..#..#####.##...#..##..##...#.#...##.##..##...##.##.#......#...##.##.#####.#....####....######.#.#.......#.############.###..#..#......####......#..##.####.##....#..#.#.###..#.####.####.#.##.##.##..###.#..#.......#....#..########....##..##.#...#.#.###.###.###..#..#.###..#....#.###..#.##.##..###.#.#####....###.##.###.....#######........#.#.##...##.#....
+
+..##.#.#..#..##.###....######.####.....#.#..##..####......####...##...#.##..##.##.#.####.##.#.##.#.#
+#.#####.#.#..#.#...##.......#.#...##.#..#.######....#.#####....####...##..##..#.#####..#.##......##.
+....#..#...#...######...#.#.##.##.####..####....####.##.......#..##.#.##..#.#..##..#.##...##...#.#..
+.#..#####..#..#..#.#.....#..###.###.##.#..#....#..#...#....#####...###.....#.##.####.#######.##..##.
+###.###...###..##.##.######..####.#.###..#....####....#...#.##.#.#....#..#....#.#.#.#.#.......#..###
+.#.##.#.#####.....#...##.##..##.##...#####....#.##.###.....##.#..#.######.....###...#.###....#...#.#
+##..##.##...#######..#..#.###.##.#.###..##.#.#.#..#..#....##.#..###....#..##.#..#.#....##.##........
+#..#......#.###.#####.##..#....#...#.#.#.#.###.##.##..#.#.##.#...#.##..##....#######.######..##.#.#.
+.###.....#....###..#.#...##...#.#.####.##.###.#.##..##..###.#.##.####..##.....##....##.......#.#.###
+..#.....#####.#.#..##..##..#.###..#.##.#..#.####....##..####.###....##.##.#.#...#..###.##......#####
+#..#..####.#.#...#..#...#######.#......#.#.#..#.##.#......#......#.##.####.######....#####..##...###
+.###.#...#..####.##...#.#####.##.#...#.#...#...#.#.##.###..#.##.###..#.##...######.#.#.##..#.##..###
+####.#.##....#.#..#########.###.#.###.#..#.####.#..##.##..#.#.#....###...#..#..###..##...#..#.....#.
+....#####.#..##.....###..#..#.##...#####..##...#...#.##.###....#..####.##.#####.##.#..##..##.#..#.#.
+####...#..#####.#..#######.##.#.####...#####.#.#.##....#.###...#.###.##...#...##.##.##.#.#.....##.##
+##..##.##.#.#..##..##.#..#.#..#.##.###.#..#..##.#..##..##.##.#......#.##..##.##.##.....##..#.#...###
+#..#.#.#.#####..#.##..##....#.##.#.###.#.#...##.###.#..##.##...##..###.##...##.####...##.#..##..##..
+####....##.#.#........###..#..####.###..#.#.#....#####.#.#...#.##.####.#..#...#..#.#...#.#...#.##.##
+#..#..##.##..#....#...#.#.....#...#...##.....####.#.###.#.#.####.#..#.#.#...#.##.###...##.#.##..##.#
+##..##..#.###.####.#####.###..#..#.....####.#..#.##.#####.##.#...##...###.######.#.#...#####.#..#...
+#...##.#......#####..##..#.....#..###.#.....##.....#####....#.##.###...##.####.#.#...#.##.######.#..
+##.#.###.##.......#.##.####..######...######...####.#..######....##.#.......####...###..##.##...#...
+#.....##.#####.####..#.##.#.#.....##.#..#....#.....#.....#.#...#.###.#.....#####.#.###..##..##..###.
+#.###..######..#....#...#.#.##..#.....#.###.....#..#.##..#..#.##....#.#..#..#..####.#.##.....#.#.###
+#..##..#...##..##........#...#....###.###.#.########.#..#.............#....####..#..##.#.##.#......#
+.###..#####........##..##.###.##..#.#.#.####.#..##.##.#...#..####..####..##.##..#.#.#.#......#.##.#.
+#.##..##..######....#....##.....#...##..#.#.......#.##.#####.###..##...##.##.#..##.###...##########.
+.##.########.##..###....#####.###.###.#.#.##.#.#.#..##.#.#..#.##..#....#.####..###.##..###.....##.#.
+..##...#.###.#.#.#...#.##..#.#...#..##..##.##..#.#..##..#.##..##.###.##..##...#.###..##...#..#.#..##
+.#.#.####.###.#.##.##.#.###.#.#....##.#........#..##..##..#...##..#.#.###.#.###..#...#.#.##.##..##.#
+#.#.####.#.##...###.###.#...#.###.#.#.....#..#.##.#...#.#..#.#.##...###..###.#..#.###.#.####.###.#..
+##..####...#.#.####..#..#...###.##.###.##...##.#.#..##..#.###.#.##.##.#..#.###.#..#######.#....#.#..
+.#.#.######..##.#..###.##.#....##....#.#..###.....#.##...#..#...#.#.#.#.##....##....####....#......#
+.#.#.#.##.###...##.#...###.#....#.#.#....##...#.######.#.#.#####..#..######.#.##.#.##.....##.####.##
+..######...##..##..#.#.#.##.......##.#.#...#.#####...######..#######...####..##...#.##.##.#..#...#.#
+##..#.#.#..##....#.##....#.....#.#####..#.#.#.#.#.#####....#..###..###.###...#...######...##..#.#..#
+####.....##...##....##.##.#...#..##.#..###.#....#...###...#..######...####.###..##......##..###.##..
+##.####...#.#.#.#..#..#.#.###..##.#....##.##..#..##........##.##.####.##.#.###.#.#....#####.#.....#.
+#...#.....###..#..###..##..#.#..#.###.#..#####.#.###..###..#...##.#..##..#...##...#.#.###.#.#.##.###
+##.#...#....##.########..##....##..###.#....###.#.#....#...###.....###.#.##.#..#####......###.#.#.#.
+###.###.#...###..#.##....#.#.#.........#.#####.#.#...#######.###.#.#.#..#.#...#..##.#...###.#...##..
+.####.###.#..#.###.#.#.######..#####.#...###..#...###..#.########.#.#.#..####..##.###..#..##..##....
+#..##.#.#...####.#..#..#..###.##...#####..#.###......#..####.####.##..###.....###..#....#.#######...
+###..##.#.#.#..##..##...#..#.#......#..####....#.##..#.##.###...####..##..####...#...###...##..#.#.#
+##.##..#....###.##......#.#.##.#.###..##...##.##.#....#.#.#.###....##..#....#.########...#.....##.#.
+#.#..###.....#######..#.###....####...##......####..#...##....#..####.#....##.#...#....##.###.##....
+#....######..##.##..##.###.....##..#.....#....##...#....###.....##.##...##.#..##.####.#..####.##.#.#
+.#.#....#..####..#..#.#...#..#..###..#........###.##...##.##....#.#..#.##..#.##...#####...#..#####..
+.##..####..##...##.###.#..####...#....#..#..##.#...##...#.###.....#.#..######.#.#####..#####..######
+.#...#.#..##.#.##..#.#.#...###..#..#....###.########..######.#.####...##..#..#...##.####...#.#######
+.#####.##.#####.#.#.##.#.#....#..###.#..##......#####..#.##.#########...##..###.######.....#.#.####.
+##.#.#.#.##..##.##...#.....#########.##.#.......#..#####.#..#.#.#######...#..##.#..###.#####...##.##
+##.##...###.###...#..##.#..#.##.##.....##.#.#.###...##.#.##..#.#.#...####..#..###.####..#...##.##.#.
+#...#.#.#..#.##..#..####.#..###.#####...#..#.#..#####.#..#.......#..#.....#.#.#.#.#.##.##.###....#.#
+....##..#..####.##..#.#...#####...#...###.##.#.#...##.##.##..######......####.##.#..#.##..##...####.
+##...###..#.##..##..#.##...#.#.####.####..#.#.###..#.#..##.#...#.#.####..#.#.##.##.#.###.#.###.#.#..
+#.#.#.#..#######.#....#..#.#.####....##...##.###.####.####.#..#..##...##..#..##....#...#..##.####...
+.#####.###.##.##..##.##.##.#.##...##..#..##...#.#.##.#...####..#####..#.............###..#..#..#.#..
+.##..##..###.##.##.....#...#....#..#..#.#######....#...#......##.###..#....#.#.####.#....###..##..#.
+.##.#.###......#.###..#.#..#.##.###.#.#..#.#.##......##.#..##.###..#.###.##...##.#.........###.#.###
+.#.#.###......#..#####.###..#..#.##..........#..##.###.#.##.#..#.##.#.###.#.###..#.#...#.###..###...
+.###.####.##.##.###..#.#..###..##..##....###.###..#...###...#.##.#...#.#.##..###.##.##..###.##....##
+###.########.#.######..#.##.#.#####.###...###.###.#####.###..#...#.###..#...#..#.###.#......#......#
+.##....###...##.####....#....#..##...#....###..#..#..#...#...#..##....#####.#..###...##.####....###.
+.....#..##...##....####.#..#.#.##..####.#####..###...###.###..##..#...##.....#.#.##...#.....#.####..
+.#.###.#.#..#.####....#.#.##..#.####..#...#.#.#.#..#..#.####.###....#####.#..##..#.#..##.#.####.#.#.
+#.####.#.....###..###.#..#.####.#..#.#.##.##..##..#.#.#..##...#.####..#.###...#....#.#...#.#..##.#..
+.#.####...#.#.#..###.##..#.#...##.##.#.....######...#....#.#.##.....###......##.#...#.###..#....###.
+..##.###......#.##...###.#...######..##.#.#.#.#..#####.##...#......#....#.####..#..#..#.#.#.#..#..##
+#.##.##.#.##.#.#..#.#.#..###....#####..#.#####.####.##.##.#.##.#..#.#.#.#.###..##.##.#####..##.#####
+..#.#..##.#.##.#..###..##.#.#..#.#..#.##....#....##..#.#..#.#.##.##.#.#.#..##..###..##.##.#.###.####
+####.####..#..#.#....##.#...##....#.######...#.##.....#.##..#####.#####..##..#.####.#.##......#.#...
+.#####..##...#....#.#..#.#.##.#...#.#..#..###.#..#.#..#..##.#.....#.####.#.#...###..#..##.##......##
+###.#.....###...###########.##.##..#....##.#.####.#.#.#.....#...###.#.##..#.#.#...###..........###.#
+#.#.##.##..#..#.##.#..##.#.#.####..###.#.#..###.#.#.###..###..#.##...#..#..#.#...#...#..##..#..###..
+..#.#####.###..#.......#..#.####.#.######....#.##.##.#..#..#####..#...#.##.##.##..#...#####.##..#..#
+##..##...##...#.####...#.#....##..#.....##.###.####.##..###..#.##..#..##..####....##.#...#.####.#..#
+#.#.##...####..#.##....##...#.###..##....##.#.#.....###...####..###.###..#...##.###.#.#.#.#....#.##.
+..####.##..##.#.....##...#.#.##.#.....#.#.##..##.##..#.##...##....#.#...###..####.#.#######..##.#.##
+#.....##...#...#...#.##.#.####.###..#.#..###.#.#..#######...#.##.###.#.###.#.##.#.##.....#.#...#.##.
+#..#####.....#..#..###.#####..##.##....#.###.##.#.#..##...###...#######.##....#...###...#####..##..#
+#..############.##.####..#..#..#..#.####........#.###.###..#.######...##..####..###......##.#.#..#..
+##.............###.#.####....##.##....#.#.....#.#.###...##.##.#.#..###.##.##..#.#.#####..#.#.#....##
+.####...###.#.###.#..#.#.#.####.#......#..#..#.#...#..#..#....#.##..##.#..##.#..#....#..##.#..##.#.#
+###.#..#..###.#...#....###..########....##....#....#.###.#.##...###.#.#.#..##..#.##....#.######.#.#.
+#.###....#.##.#.#...#.##.###.##..#..###.##...####..#..#..#.####.#..#..#..#.###....#..#.##...##...###
+#..#.##.#.#.#...#.#####.##.#..###.#.#.###........####.#####..#.##..###....#..#.#.#...#.#.#..#.#####.
+#..##.##.#####...##...##.##..##.#...#.#..#...#..#..#.....#..####.#...#..#######....########.....#.##
+#.....####.#.#.#..#.##..#.#.#####..#.#..######.#.#..#...#..#....#.##.##..##.#.###..#.##...##.#...##.
+.###.#..##.##....#.##.#..#.##..####.......##..##.##.#####.###.##.....#.....##.###.#.##.#.#.##..#..##
+##....#.#.##.###.#.##.#####.#..#####.#..#####.##.#..#..#..#####.##.###.#..###...#.#...#....######..#
+####..#..#..#..######...#####..#..#.#...#.##....###...#...##......#...#####.##.#..#.#.##.#...##.##.#
+####...##...#..#..##..#.#....#####...#.#....######.#.#.....#...##..##.##..##...##.###.....##....##.#
+.#.####.#..##..####...#.##.##.##..#####..##.#.#..##....#..#.#.####..##.##.#.###.##..####......##.#..
+...#..####...##.##.#..#.#....#######.####.#...###....##.#...####.#.###.####.#.#.##.#.......###.####.
+.......#..#..#.#..#..#...#.#####.#.#..####..#..#...##..#.#.####.#...#.#.#.#.#.#...#.#.##.#..#.#.####
+...###.#...#..#.#.#.....##.##.#.#..##.#......#.#######.....#..###.#####.##..###.#..#.#######.#####.#
+.####.#..#.#.###...#..#####...#....##..####..#..#######.###.##.##..######.###..##...#####...#.##.#.#
+#..##..####.#.#.#..#.####.###...#..###.#.##.##..####..###.####.....#..#.#.####...#.#.#.##.##..#.#.##
+..#.###.#...###..#...###.###.####..##..#.#...##.#...#..#....#####.#####..##.####..##.##.##..#...####
diff --git a/2021/inputs/day_21.txt b/2021/inputs/day_21.txt
new file mode 100644
index 0000000..bfb2937
--- /dev/null
+++ b/2021/inputs/day_21.txt
@@ -0,0 +1,2 @@
+Player 1 starting position: 7
+Player 2 starting position: 5
diff --git a/2021/inputs/day_22.txt b/2021/inputs/day_22.txt
new file mode 100644
index 0000000..1d6ce39
--- /dev/null
+++ b/2021/inputs/day_22.txt
@@ -0,0 +1,420 @@
+on x=-11..33,y=-6..40,z=-16..37
+on x=-44..10,y=-24..30,z=-24..22
+on x=-34..15,y=-21..27,z=-33..11
+on x=-42..12,y=-43..9,z=1..48
+on x=-31..21,y=-11..42,z=-4..49
+on x=0..44,y=-13..37,z=-30..14
+on x=-41..12,y=-32..17,z=-7..43
+on x=-21..27,y=-16..30,z=-33..15
+on x=-28..24,y=-12..42,z=-6..45
+on x=-15..30,y=-32..14,z=-48..5
+off x=-32..-17,y=-6..11,z=-16..-5
+on x=-29..17,y=-6..48,z=-27..17
+off x=-34..-20,y=-22..-6,z=-24..-11
+on x=-39..5,y=-24..22,z=-49..2
+off x=-48..-32,y=32..45,z=31..44
+on x=-40..5,y=-9..39,z=-2..43
+off x=15..34,y=3..19,z=-46..-30
+on x=-10..36,y=-8..43,z=-36..8
+off x=8..22,y=2..11,z=27..44
+on x=-26..22,y=-17..31,z=-23..30
+on x=55966..74708,y=9028..39775,z=-23782..-12392
+on x=46912..62342,y=34758..55202,z=5912..31510
+on x=63138..67807,y=40967..45502,z=-23583..-10004
+on x=-73495..-56406,y=41511..71705,z=5127..32006
+on x=-23106..-1748,y=-86112..-68506,z=-39397..-15794
+on x=-52779..-45652,y=19079..39796,z=49639..57070
+on x=-79175..-53055,y=34141..54701,z=4583..26379
+on x=26517..36583,y=-42144..-26773,z=-80939..-45310
+on x=-47044..-23501,y=-79682..-68957,z=-6125..20082
+on x=-54276..-29269,y=-45877..-28470,z=-59917..-38428
+on x=-23998..7268,y=55542..81737,z=42421..63898
+on x=-94509..-71314,y=-22686..18,z=-22100..-3746
+on x=-74781..-51149,y=-52534..-38370,z=3590..25687
+on x=-50373..-45841,y=-28285..-6170,z=-78397..-51064
+on x=65214..88034,y=24285..54786,z=-6183..23064
+on x=-31431..-12447,y=30325..57775,z=-63903..-49927
+on x=61099..80636,y=13112..36642,z=9225..37647
+on x=49227..58281,y=-72690..-46916,z=6114..26803
+on x=49316..61601,y=52184..69325,z=-34233..-8387
+on x=-8085..8021,y=-67231..-31814,z=-70317..-60600
+on x=43203..69568,y=-38081..-12285,z=-48526..-36342
+on x=67521..77200,y=-30319..-21173,z=-39992..-23255
+on x=-24435..-910,y=-28467..-9403,z=74299..85044
+on x=-68278..-46406,y=32963..49543,z=-36781..-5810
+on x=38044..59188,y=-39588..-15132,z=-78211..-59118
+on x=-16359..8709,y=-83601..-70086,z=-41614..-18943
+on x=-67079..-53633,y=-47134..-17665,z=-33888..-12731
+on x=-10203..25856,y=-65803..-37565,z=-80018..-48632
+on x=-20788..12729,y=-7421..3011,z=-96951..-78895
+on x=36480..60613,y=-69685..-56878,z=-42024..-22583
+on x=-81439..-53199,y=30801..58467,z=5317..21254
+on x=20078..46684,y=47464..77622,z=25360..46337
+on x=51573..75800,y=-51556..-33538,z=-48932..-30407
+on x=-19220..-9675,y=29516..54528,z=58963..71318
+on x=-89405..-71366,y=329..20658,z=17088..39485
+on x=48807..65272,y=-11182..-2515,z=33689..67952
+on x=-62185..-33194,y=-32027..-4968,z=47218..70105
+on x=-49260..-25903,y=-59470..-34424,z=-75405..-44239
+on x=-69424..-62899,y=37068..55605,z=-3476..5226
+on x=-24786..-21772,y=66159..77802,z=-51515..-13605
+on x=-37464..-7009,y=-24318..-14439,z=-88882..-56080
+on x=13491..48426,y=-86533..-69233,z=-11101..8820
+on x=18137..36596,y=56982..87194,z=-26391..-7218
+on x=-73986..-65455,y=-40459..-25641,z=5811..22531
+on x=56480..72410,y=-23085..373,z=-54884..-44893
+on x=-72..9616,y=33541..62581,z=-76024..-41529
+on x=5811..29667,y=76040..84275,z=3794..19078
+on x=31769..54691,y=-72297..-54884,z=11568..30599
+on x=38705..40732,y=53076..81496,z=-20757..9517
+on x=-13332..6003,y=-92149..-67470,z=13826..25305
+on x=-36361..-18175,y=-7198..5782,z=-85116..-65760
+on x=72099..89917,y=-35339..-6561,z=-18702..3529
+on x=14916..21176,y=-17870..14037,z=66567..80508
+on x=15650..31204,y=-65831..-46311,z=-71381..-47512
+on x=57185..76911,y=-2966..9137,z=39217..42970
+on x=-21218..-9089,y=60853..66598,z=-65895..-49482
+on x=12217..37563,y=-33737..3116,z=-79589..-71994
+on x=-24435..-1179,y=61379..96140,z=5111..13700
+on x=-47837..-24016,y=24730..38884,z=62380..65554
+on x=-79483..-69531,y=-3888..15433,z=-50484..-22944
+on x=-74982..-54797,y=-59699..-43075,z=1572..23991
+on x=22536..39698,y=-69795..-36738,z=47715..68342
+on x=-16003..-2396,y=70179..88747,z=17005..49146
+on x=22554..32407,y=-80100..-66240,z=-22164..-1729
+on x=-13583..-6556,y=61638..96038,z=-13494..-7490
+on x=12236..31240,y=-82560..-68788,z=-44096..-25380
+on x=-40040..-32781,y=-7855..12988,z=-87105..-60530
+on x=-50283..-24489,y=43700..58185,z=-45955..-26056
+on x=-62151..-46123,y=-75045..-45373,z=7112..34441
+on x=-56568..-39255,y=40679..69755,z=31070..49467
+on x=-6977..-4516,y=-50981..-37765,z=53142..81539
+on x=58949..79172,y=-38054..-11546,z=-55399..-43258
+on x=12967..29648,y=55993..84110,z=30089..48256
+on x=9968..38213,y=-75798..-54386,z=-28175..-12716
+on x=-44311..-7274,y=-80148..-59517,z=-14241..1861
+on x=18546..46490,y=-65733..-40860,z=-62118..-37572
+on x=-2271..26766,y=64511..83099,z=-51416..-25251
+on x=-90601..-71814,y=6192..25836,z=-32952..-14912
+on x=-26569..820,y=-10340..22351,z=61333..79466
+on x=-9709..3302,y=57621..71334,z=28122..53666
+on x=-75028..-52307,y=-3116..31441,z=33506..37957
+on x=35446..66149,y=25301..62450,z=-42423..-34112
+on x=-63763..-42164,y=-66010..-55301,z=-33540..-2074
+on x=-51080..-35163,y=-76248..-59521,z=22498..45227
+on x=48050..69664,y=48245..50439,z=-43346..-10038
+on x=61239..88801,y=63..10257,z=16547..29381
+on x=1461..12900,y=58310..67961,z=43110..67087
+on x=-64925..-51002,y=-47822..-29558,z=-38492..-17616
+on x=-30974..-14734,y=18687..30483,z=-86407..-67736
+on x=21136..43241,y=38836..54209,z=37478..60357
+on x=57476..77217,y=8846..25808,z=23991..44615
+on x=-23202..8649,y=-73327..-58989,z=-56906..-37911
+on x=58046..60268,y=-13295..4247,z=-61356..-39657
+on x=-71350..-45157,y=-41433..-31528,z=21203..44630
+on x=-94860..-69586,y=8228..33917,z=-6572..28035
+on x=24637..30475,y=51768..66115,z=39375..45973
+on x=-12988..12447,y=-80825..-60518,z=-20069..5301
+on x=-91600..-69209,y=-30521..-20316,z=11234..22677
+on x=-7421..-3636,y=-40727..-17229,z=64137..86775
+on x=59523..76484,y=6288..39603,z=-22000..-3094
+on x=63294..78222,y=-50184..-33082,z=-14565..19078
+on x=43627..60468,y=-52929..-40706,z=27002..50322
+on x=-32412..-6949,y=-90331..-73353,z=522..4134
+on x=-19932..-835,y=43302..58246,z=55217..67369
+on x=-22140..-1580,y=72424..88097,z=-30186..-4633
+on x=32994..47253,y=35570..47312,z=-74294..-42106
+on x=-60383..-49562,y=42559..74096,z=-23034..-766
+on x=47172..63440,y=-69364..-45568,z=-6117..10614
+on x=-81089..-61599,y=27441..62058,z=12608..35576
+on x=34923..69365,y=13653..38800,z=-77261..-43750
+on x=41054..61704,y=27512..34800,z=-57849..-40312
+on x=22144..34980,y=19631..29700,z=-86432..-55572
+on x=-12122..15745,y=-75805..-66340,z=36641..49918
+on x=30910..41979,y=-51045..-39883,z=40132..60580
+on x=16087..41362,y=69442..78280,z=-20140..-6620
+on x=-2498..12657,y=66055..88671,z=24902..37865
+on x=-53541..-33332,y=40522..63114,z=17690..23330
+on x=-25486..-14848,y=-22167..-10217,z=73479..81666
+on x=-49904..-21142,y=-32441..-19796,z=-65094..-48964
+on x=-77185..-52199,y=-43621..-29163,z=-2980..29505
+on x=47628..62285,y=-27324..-6159,z=54741..76523
+on x=-68672..-53382,y=13874..29953,z=-52436..-24787
+on x=24729..35483,y=-39432..-31141,z=55462..68911
+on x=-85643..-60966,y=-16215..708,z=27959..49870
+on x=-70023..-44399,y=28742..46887,z=-48656..-27334
+on x=13237..38992,y=72316..93275,z=9371..18339
+on x=3601..27855,y=-53221..-37588,z=-79390..-59309
+on x=73624..87421,y=647..26355,z=-30957..-5423
+on x=-70851..-47736,y=-45072..-24946,z=37815..58192
+on x=-19325..7381,y=-20048..-3907,z=70818..83270
+on x=65532..77053,y=-13023..4822,z=-55535..-29335
+on x=-77943..-60312,y=18202..34941,z=12108..41626
+on x=-76720..-58569,y=-42973..-22667,z=4073..29355
+on x=46174..59694,y=44339..51223,z=28653..59550
+on x=-44238..-29509,y=-87529..-58268,z=5760..16252
+on x=-62428..-54590,y=7475..19744,z=-69355..-39348
+on x=-40490..-24926,y=11223..28033,z=53505..73784
+on x=-61821..-41060,y=-65031..-26842,z=33274..53261
+on x=-89724..-64590,y=-19721..-327,z=-26607..-9599
+on x=-34431..-20563,y=50755..68833,z=-56541..-35697
+on x=55247..88432,y=7981..44436,z=7759..16910
+on x=-66628..-53580,y=-62370..-42076,z=16219..33691
+on x=14414..42406,y=-85437..-53970,z=17700..34996
+on x=-83467..-76235,y=5890..16777,z=-7053..13257
+on x=38443..46746,y=-76565..-51921,z=-7708..3586
+on x=-68726..-52259,y=32484..44835,z=25077..37882
+on x=-74597..-50281,y=-11754..6056,z=-62256..-26807
+on x=-33170..-16817,y=59734..75543,z=5119..42517
+on x=-37088..-7851,y=21070..40392,z=52712..84858
+on x=-38459..-5698,y=-80141..-51196,z=-42325..-17367
+on x=18454..47906,y=-85662..-56686,z=14396..33029
+on x=-41249..-27006,y=59650..74737,z=-35603..-18205
+on x=-35206..-18846,y=-12542..-592,z=-88090..-60234
+on x=62210..77161,y=-43088..-16886,z=24074..54283
+on x=-15430..13172,y=1904..22129,z=-80564..-70232
+on x=-29859..-12978,y=56105..82581,z=-48724..-23210
+on x=-56887..-50053,y=-29444..-16505,z=-61442..-38029
+on x=30604..54367,y=46212..53964,z=-52852..-34343
+on x=70181..78863,y=-45106..-13492,z=-9745..19529
+on x=8322..22435,y=42430..55347,z=52882..64672
+on x=-69478..-61259,y=1778..24792,z=-63998..-37991
+on x=16179..23834,y=49247..61008,z=51575..70785
+on x=-92447..-65736,y=-35679..-10409,z=-19722..-7466
+on x=-9579..2162,y=-80611..-59056,z=-42233..-29154
+on x=48383..66349,y=-12960..16968,z=-58258..-46009
+on x=-32357..-9984,y=-68069..-49239,z=31105..47676
+on x=66946..83179,y=-5224..11437,z=-43928..-24041
+on x=13814..39369,y=-76170..-41530,z=-56800..-40886
+on x=62282..72077,y=17785..48293,z=8677..37715
+on x=-44382..-29991,y=60002..79555,z=3843..17588
+on x=75247..83629,y=-28545..-6291,z=-10819..-2122
+on x=-956..26375,y=-81524..-71549,z=26313..43930
+on x=30012..36383,y=34248..52598,z=56265..66326
+on x=-48730..-24738,y=-80273..-57415,z=6805..13225
+on x=-58593..-47213,y=-18537..4027,z=54774..80145
+on x=3810..25698,y=70004..81369,z=-51070..-24151
+on x=-24437..-5093,y=-86059..-69302,z=3319..7790
+on x=-31365..-19431,y=-88889..-63893,z=17698..43049
+on x=19977..46038,y=4288..24488,z=65477..72640
+on x=9206..45518,y=-49253..-18169,z=-75545..-51533
+on x=-4478..11513,y=-3222..14383,z=71041..92715
+on x=-83552..-57412,y=-35665..-16854,z=15963..44817
+on x=34730..53067,y=44234..58027,z=31635..55954
+on x=33780..55108,y=-85336..-63582,z=-60..19260
+on x=-60709..-48773,y=27826..52995,z=47092..56789
+on x=4599..16485,y=59775..83142,z=-8444..14929
+on x=39634..47449,y=-10709..-3483,z=56673..65961
+on x=17954..21090,y=46398..64655,z=40116..72009
+on x=51479..62837,y=-27485..-1712,z=-59021..-32232
+on x=26397..48116,y=49913..64456,z=32763..46893
+on x=-40166..-6453,y=54294..88546,z=19469..46914
+on x=-11587..-3465,y=-76385..-45142,z=-55088..-47775
+on x=25337..58818,y=-73241..-50645,z=-60403..-31242
+on x=18670..27833,y=10699..25997,z=-78411..-53777
+on x=57409..75450,y=40962..60348,z=11226..25913
+on x=55748..74851,y=-54477..-43708,z=-28494..-15041
+on x=26830..53176,y=-67735..-51525,z=13985..45082
+on x=-8911..13239,y=-74882..-67577,z=-51935..-26067
+on x=63953..87466,y=35424..47855,z=-20625..-3868
+on x=-20694..2154,y=-3805..15541,z=68000..85521
+off x=-64858..-38773,y=-22979..-12516,z=-72865..-52375
+off x=-36214..-19494,y=-48856..-31044,z=55849..67059
+on x=18769..39214,y=59223..74065,z=-25526..-7466
+off x=4093..19302,y=65172..80228,z=-18875..4459
+on x=-72853..-64913,y=-44437..-23173,z=16546..27389
+on x=-74000..-63343,y=-17952..-11976,z=26071..46600
+on x=55718..89196,y=8034..31868,z=23749..41136
+on x=-61312..-25331,y=60154..82342,z=-29251..-12808
+off x=57932..88657,y=1045..32675,z=23992..37899
+on x=41352..50542,y=-36888..-13463,z=-58939..-54480
+on x=-51121..-21791,y=-6418..16683,z=54132..72199
+on x=22624..43927,y=-9683..12070,z=69475..91968
+off x=-23521..-7662,y=64707..75601,z=-43845..-16424
+off x=-42653..-21236,y=-21354..4353,z=-77029..-71014
+off x=-4664..4504,y=52543..79156,z=29919..46671
+on x=35818..65014,y=41342..70254,z=9185..33026
+off x=-52865..-28342,y=-58289..-33044,z=45771..63238
+off x=-16924..22809,y=60544..81137,z=-66967..-44290
+off x=-30590..-350,y=68584..95548,z=-15319..250
+on x=41065..61522,y=-21779..-15976,z=-79786..-53698
+off x=9525..33346,y=-80916..-56811,z=-61811..-23799
+on x=-85466..-61472,y=-42722..-26161,z=-7728..13705
+on x=29179..51220,y=41045..65007,z=-55867..-32532
+on x=-73524..-55904,y=32162..34120,z=34985..43261
+off x=-15158..643,y=-57242..-24535,z=-75496..-57777
+on x=-26523..-3554,y=-24061..-7071,z=66096..78008
+on x=-68958..-44626,y=43052..58235,z=-27098..-9342
+on x=-84084..-64394,y=-24045..-11011,z=-38978..-15498
+on x=62184..82898,y=-27380..-1888,z=-61447..-39051
+on x=635..23767,y=-54960..-40730,z=67501..86970
+off x=32259..60280,y=41478..46289,z=-55818..-39638
+on x=-52256..-32444,y=38811..69688,z=31521..54783
+off x=2128..5231,y=-81966..-55811,z=-38574..-17048
+on x=-65624..-36454,y=-49647..-30716,z=28718..58149
+off x=33334..50958,y=-3486..16115,z=53857..80381
+on x=-58284..-34017,y=47293..84420,z=-25796..-2948
+on x=-58130..-39664,y=53973..69546,z=2549..17650
+on x=-70876..-46014,y=-61557..-30740,z=19380..39271
+off x=64070..92955,y=7220..28103,z=-4003..32849
+on x=-17535..-470,y=-22144..-17298,z=61197..92477
+off x=13631..45033,y=48414..60988,z=-54682..-42444
+on x=-83453..-72620,y=-22121..-6685,z=-31229..919
+off x=-71588..-48104,y=23697..43494,z=32068..53528
+off x=-73315..-58835,y=29130..39683,z=1818..34677
+off x=-44335..-24761,y=-39652..-28447,z=41105..78848
+on x=1354..23297,y=-87726..-59186,z=16976..34498
+on x=-77045..-53438,y=-9837..13204,z=43872..53252
+on x=-58059..-39277,y=35454..70346,z=22294..32697
+off x=8134..22913,y=27396..53406,z=52828..84609
+on x=53526..67803,y=41292..59253,z=-35827..-26953
+on x=-72413..-43823,y=-58264..-44414,z=-9911..-2235
+off x=-27147..3300,y=2538..20789,z=-91151..-70237
+on x=46087..67095,y=-48984..-29278,z=-54699..-40903
+off x=63670..64821,y=-41248..-3363,z=24908..46333
+off x=2632..22202,y=24847..51542,z=-80467..-64757
+off x=-34027..-18196,y=-47105..-23465,z=-68869..-55326
+on x=41678..54255,y=2720..29359,z=46231..75450
+off x=-4213..20821,y=48132..81158,z=-63979..-27510
+off x=-2170..16894,y=56662..79540,z=44419..50160
+on x=-19834..2114,y=-46280..-10250,z=-77417..-57318
+off x=65385..89282,y=26089..56411,z=-28795..-1266
+off x=-86617..-60352,y=-34282..-6783,z=24678..35755
+on x=-51880..-22038,y=-48878..-34685,z=-54503..-34099
+off x=-6185..7523,y=-80929..-62538,z=-49136..-32906
+on x=-69472..-44311,y=-59766..-35060,z=7986..17809
+on x=-45836..-23351,y=34528..58283,z=-62062..-39907
+off x=-65989..-53476,y=-18..21291,z=45332..55683
+on x=57549..70543,y=6235..34900,z=18154..39248
+on x=-32196..-20894,y=-88953..-64565,z=17496..42389
+on x=-72208..-61402,y=-59142..-31400,z=-29975..-19314
+on x=-25537..-17772,y=63785..78096,z=38132..43670
+off x=-10614..4852,y=1037..34081,z=-88803..-72167
+off x=-71969..-40008,y=45531..61020,z=29194..44542
+off x=-97625..-62135,y=232..24412,z=-6113..4401
+off x=28968..62715,y=-63990..-41136,z=-34394..-16528
+on x=7127..29392,y=-25905..2139,z=67977..79951
+off x=47116..69445,y=43251..70092,z=-35789..-7878
+on x=46541..71892,y=4788..27226,z=31207..52344
+on x=-39441..-22248,y=19261..53073,z=-62518..-57715
+on x=56116..84722,y=-31369..-3302,z=-50073..-34755
+on x=-65536..-47632,y=22971..39112,z=25566..54444
+on x=-8629..13229,y=-55339..-45230,z=46953..70772
+off x=-91996..-64629,y=-22054..5640,z=-18034..3409
+off x=-79435..-68358,y=-50488..-21783,z=-23189..7130
+off x=-31853..-18496,y=35962..43812,z=-78415..-57499
+off x=-53097..-43476,y=-8868..6641,z=-76785..-54439
+on x=18376..52266,y=-11181..7160,z=-77629..-69712
+on x=-53162..-28262,y=-41919..-8199,z=-62348..-54228
+on x=2939..28130,y=61801..91442,z=-11519..4615
+off x=8319..29664,y=-14307..17453,z=59897..95416
+off x=46661..65036,y=-13305..7325,z=-75798..-62581
+off x=-37957..-23478,y=47391..59983,z=35372..55611
+on x=61515..88770,y=-17267..12084,z=-23518..7771
+on x=-48305..-25680,y=-81436..-53793,z=-2439..29818
+off x=-42779..-39019,y=51297..69812,z=37178..50350
+on x=40203..63867,y=-66235..-51382,z=-34991..-11770
+off x=55954..70659,y=33330..68709,z=-12043..-2384
+off x=-29487..-3952,y=-3496..10014,z=-79573..-61455
+on x=55711..74934,y=26358..37763,z=-46597..-28486
+on x=36775..62937,y=43496..55938,z=21471..41166
+on x=-27922..-2750,y=75238..84184,z=-16664..-38
+off x=50743..58719,y=-44526..-33474,z=-67293..-43466
+on x=9282..16932,y=-96919..-64095,z=10331..30664
+off x=-95473..-72710,y=-28988..-8136,z=-10970..9409
+on x=-85389..-67764,y=13685..19641,z=-9526..33
+off x=19898..50323,y=-68676..-46162,z=-62425..-39053
+off x=60425..65023,y=-8453..14534,z=-58877..-45278
+on x=-25428..-720,y=-80104..-62018,z=-1677..13124
+on x=-48530..-37691,y=52321..74595,z=-26453..-21715
+off x=-14126..19313,y=64721..76129,z=-54258..-25715
+on x=-24136..-16023,y=7633..27624,z=56759..87267
+on x=-41213..-21916,y=-34990..-16249,z=-76987..-54730
+on x=-22621..13916,y=62123..74807,z=39068..51378
+off x=-16365..-9094,y=-6481..22514,z=-93559..-64057
+on x=9583..36843,y=-71013..-49912,z=33751..53993
+off x=-65469..-44611,y=25911..46482,z=40095..65714
+off x=-57145..-39149,y=48498..63803,z=12913..42535
+on x=57651..61770,y=-28419..-6391,z=40364..49746
+off x=-75576..-61139,y=-10503..5482,z=-46770..-27191
+on x=-49397..-16777,y=54120..63032,z=-60010..-24837
+on x=-4249..14013,y=20636..52130,z=-75802..-60246
+off x=15523..45332,y=14920..27687,z=-85777..-65031
+on x=50324..75616,y=-58333..-39550,z=1860..9173
+off x=-10760..13032,y=63819..67101,z=30106..45713
+on x=-54735..-16505,y=27874..38730,z=57002..66636
+off x=70142..77459,y=-34967..-4642,z=-28373..-18318
+off x=12924..33851,y=50318..76053,z=33776..47995
+on x=16848..37045,y=39096..53275,z=-64850..-39585
+on x=-48828..-46005,y=-37976..-11049,z=49769..63745
+on x=46761..70212,y=7696..34085,z=-72620..-51191
+on x=-10919..12760,y=-7270..780,z=-93456..-79203
+off x=-12629..17924,y=-81153..-62978,z=-38501..-34017
+on x=33047..42293,y=21628..52131,z=-74825..-42520
+off x=-84656..-57493,y=-29917..-648,z=-39715..-19579
+off x=-39926..-16074,y=-75937..-72179,z=-10631..-2155
+off x=42338..63456,y=-10927..24423,z=-69719..-51820
+on x=-37883..-27447,y=-17784..-7063,z=53825..76661
+on x=72563..90078,y=-2936..19833,z=-26987..-9538
+off x=-61796..-59595,y=-52405..-15746,z=-41889..-25050
+on x=-72693..-53462,y=-25228..-8310,z=16685..25001
+on x=16133..36168,y=-81922..-62779,z=4714..35868
+off x=-38135..-35256,y=40495..63520,z=33859..50700
+on x=-46578..-23290,y=-38997..-19018,z=-80304..-53511
+off x=-68102..-46534,y=33132..63478,z=23336..43023
+on x=-46386..-13403,y=53450..62050,z=34840..56841
+off x=-69714..-58168,y=42581..60977,z=-43045..-15973
+off x=38139..58983,y=33227..67599,z=37065..46982
+on x=-68743..-57954,y=34901..65113,z=14186..30879
+on x=-27159..-2946,y=58211..72993,z=24144..40462
+on x=-12488..3541,y=24512..47183,z=61876..94098
+off x=-21147..-2889,y=12986..18356,z=-92621..-55775
+off x=35806..71388,y=1638..37737,z=-64849..-46796
+on x=-57793..-36707,y=58839..68998,z=-17534..3308
+on x=-59750..-40225,y=-69581..-44645,z=-9931..5157
+on x=-8485..20686,y=-65003..-40249,z=51991..65690
+on x=-39133..-20148,y=9640..31346,z=-93338..-57726
+off x=32301..60879,y=-67384..-38498,z=38892..50795
+off x=-17417..849,y=-29007..-5825,z=75615..94231
+off x=4371..14179,y=18655..31552,z=69630..80480
+on x=-30156..1315,y=-75493..-59188,z=-45573..-23628
+on x=-19974..-7274,y=48510..70738,z=55087..64610
+on x=21319..39947,y=-76865..-54489,z=-36911..-27790
+off x=19086..32378,y=42017..57587,z=-68959..-44763
+off x=-83..8471,y=-72344..-50195,z=36481..68586
+off x=-36375..-25938,y=-69174..-48526,z=-48854..-46853
+on x=-15285..11416,y=-76130..-59563,z=-46407..-22439
+off x=-69367..-52426,y=25391..46453,z=-10234..7828
+on x=-72727..-60225,y=-38827..-25690,z=-42223..-18667
+on x=42838..64386,y=12680..29933,z=-68831..-52183
+on x=18070..42298,y=-78992..-57543,z=-20906..-13301
+on x=-55875..-39308,y=-55098..-35781,z=30971..57698
+on x=35119..47623,y=-73663..-54295,z=-3539..26342
+on x=-84065..-61161,y=-3207..33256,z=-32001..-15249
+off x=-54756..-30571,y=58767..68023,z=12370..28119
+off x=-87490..-62979,y=5645..40459,z=-21364..-3385
+on x=24194..37541,y=-33900..-28321,z=-78880..-54593
+on x=-62478..-38761,y=22212..41436,z=36708..62622
+off x=56713..68194,y=-20789..-14297,z=-61095..-50322
+on x=-72902..-44221,y=-42793..-26280,z=-48733..-33791
+on x=64373..86115,y=15064..33167,z=16921..49077
+off x=24753..42194,y=-6759..12099,z=70552..85054
+off x=-12199..24098,y=49705..63058,z=-63860..-38435
+on x=3734..42354,y=61212..95571,z=-10562..17698
+on x=-17408..-5695,y=-609..8253,z=-97454..-74672
+on x=-42167..-22341,y=-71935..-42581,z=-50253..-24178
+on x=-54481..-38663,y=-16909..21415,z=-77181..-44426
+off x=-11477..9297,y=-50630..-26321,z=55462..79296
+off x=-84974..-60153,y=-48601..-19827,z=8848..26585
+on x=-62596..-36034,y=-58415..-41586,z=-55666..-27573
+off x=47430..67745,y=18197..49591,z=31865..42439
+off x=23925..32353,y=32122..54623,z=57938..79131
+on x=-16801..4162,y=-98731..-68459,z=4760..29002
+off x=20414..42287,y=44769..56648,z=-67173..-38591
+on x=57757..79682,y=-35686..-15384,z=37594..53205
+on x=43425..77866,y=-54033..-33577,z=-14291..1892
+off x=61941..77486,y=-15977..7549,z=-42755..-23589
+off x=-46801..-17722,y=-76833..-62069,z=-16214..21958
+on x=-33113..-17668,y=36644..50102,z=50787..74022
+off x=60521..75760,y=23551..43986,z=-20580..-6589
+on x=-14911..14191,y=57578..66612,z=-60746..-39130
diff --git a/2021/inputs/day_23.txt b/2021/inputs/day_23.txt
new file mode 100644
index 0000000..3d20443
--- /dev/null
+++ b/2021/inputs/day_23.txt
@@ -0,0 +1,5 @@
+#############
+#...........#
+###B#B#D#D###
+ #C#A#A#C#
+ #########
diff --git a/2021/inputs/day_24.txt b/2021/inputs/day_24.txt
new file mode 100644
index 0000000..9c0248a
--- /dev/null
+++ b/2021/inputs/day_24.txt
@@ -0,0 +1,252 @@
+inp w
+mul x 0
+add x z
+mod x 26
+div z 1
+add x 12
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 6
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 1
+add x 10
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 6
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 1
+add x 13
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 3
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 26
+add x -11
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 11
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 1
+add x 13
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 9
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 26
+add x -1
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 3
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 1
+add x 10
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 13
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 1
+add x 11
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 6
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 26
+add x 0
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 14
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 1
+add x 10
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 10
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 26
+add x -5
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 12
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 26
+add x -16
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 10
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 26
+add x -7
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 11
+mul y x
+add z y
+inp w
+mul x 0
+add x z
+mod x 26
+div z 26
+add x -11
+eql x w
+eql x 0
+mul y 0
+add y 25
+mul y x
+add y 1
+mul z y
+mul y 0
+add y w
+add y 15
+mul y x
+add z y
diff --git a/2021/inputs/day_25.txt b/2021/inputs/day_25.txt
new file mode 100644
index 0000000..15fb35a
--- /dev/null
+++ b/2021/inputs/day_25.txt
@@ -0,0 +1,137 @@
+..>>.....>.v.>..v.v..vv..v..>.v.v.>>..>v....>.>>..v>vv..v>..vv.v.v.>>>..v...>.>...v..>v...>>.>>....>...vv..>>.v>>.>>.vv.v.....v.vvv>.>>.v.>
+vvv>.>v>...>>.v>v>..>.v...vv..>>vvvv...v>..v>.>v>>..>vvvv>v.>....vvv.>.v...v..>.v..vvv>v>..v...v...>>>...vv......v>v....v>.>>.>.>.v.....v..
+..vvvv........>>..v>......>vv>>v...v.>.>..>v.>..>>>.>...>v.....v>.v....>v>>.>.....v.>...v.v>...>.>........v..v.v.>>v.v>.>v...>vv>..>>>.v..v
+.>>v>vvvv>>v.>vv>v.....>.v..>...>..>v>>>.v.v..>.>>>.v.>...>v...v....>........vv.>>v..vv.>>.>..v.>.>>v.v.>>...>>>v.>v>..v...>..>...>>>v..v>.
+.v..v.v.vvvvvv...vv..>>.>......v>..v.>>..>v>>.v>v.>.v.>>..vv...v.>..v>.>.>v>>.>v..v.>>.>.v>v>.v>>>vv>.v..v>v....v.vv....v.....v..v.>...>.v.
+v..>..>.>....vv..vvvv.v..>>.>.v.>v>..vv>..>..>..>.vv.vv.vvvvvv.v>vvv.v>v.v..>..v.vv.vv..v..>>vv...v.v.v..>..>v....>.>..v..v>....v>>>..>..vv
+>>..>..v.>>..>>>.v.>>.>v.>..v.v>..v..vv..>vv>..v.>.>v.v..v>...v.>v>.v>vv>v>.......v........>.vv>>.>.v>.>v>..v.vv>vv>>.>vv...v.>>v>v.vv...vv
+>v>..>v.>v.vvvvv>>.v.v.v>v...>>.v>.v..v>>v...vv..>...v.v.v.vvv>.>>vv.>...>..v..v.>>.>.>..>...>....v.>v....v.v.v>>v..>v>.>.v>v.>v...>..v..vv
+v..>..v..v>.>>.>v.....>v..>.v.v..>.>>.>>v...v>vv..>.v.>.v>.v>.v......v.>>>..>>>.>>..>.v>.vv>>..v...v...>...v>..>v>.>>v>...vv......>>v...v..
+.....>vv.....v.>v>...>>.>>.>>.vv........>v.>......vvvv...>v...v.v>vvvvv>..v.vv.>v>>vv.v.>.>.>....vv...v....>.v>.v>v..>v.v..>.>.v.>>v.>.....
+..v.>>.>..v>v.v.v>.v.v.>v...vv.>v.vvv>.v>>.....v>>.vv..>v..vv>>.vv..>..>v.vv.vv>>vv....v..>.vv..vv.>v.>vv>v>.v>..>>.>v..>>.....>>v.....v>v.
+v.>v.v...v....v.v>.vv.>..>>v>v>.>v>...>.....>.>>...>>..v...>..>v>>.v..>>......v>v>.v>.>>.>....>v.>..v...v.>>v>v.v..vv>>.v.>...>vvvvv.vv...v
+..>v...>.vv.>.v.v..>v.v..>...>v.>>.v.v>..vv>>.v.v>.>v.>..v.>.v>....vv.v.>.v>......v>.v>..>>..vv..vvv.>.>..>.vvv....>v>...>>>.v.......>.>...
+.>vv...v......>vv.v.vv>...>v>>v.>>>>....v.v>.>.>v....>.......>..v...vv>.v....vv...vvv.v.vv>.>>vvvv>v..v....vvv.v>....v.....>...v.v>vv.v...>
+..>.vv>vv>>>v..vv.>..>>....v>v.>..>vv>....vv.v.vv>.>..>...v...vv>v.v>>>v>>...>v..>>.>..v>........v.vvv.v.v.v>..>..vv.>v.vv..vv>vv.>.>>.>>..
+....>...>....v..>v.>...v.>v.>v.>.>v>.v.v>>.>...v.>>v.>vv.v>>v..>.>>vv>v.>.>>..v....>vvv.v>...>...v>>>v>vvvvvv..v...vv....v.>.>vv....vv>...v
+.>v>.v.vv..vvv..v>>>vv.v>..v.>vv>...>.>v>v>..>......>>v....v.>>.>>>>...>.v>.....v.v.>.>.>.vv>>.>.vv..>>v.>v...vvv..v..v..>........vv.....>v
+...vv>v....v..vv..>.>...>>>>vv.>...>>.vv>..v..>....>.......v>.v.>>v>>v>>v>.v.vvv.....>>>>v..>v>>..vvvv.>..vv>v.>vv.v....v..v.v>v>>>v>v.>.vv
+v..vvv..vvv>>.v>..>v>v>.>>.vvv.vv>..>>v.v......v....v>..v...>..v.>v>vv>.v..v>vv.....>>........>.vvvv>..>v>.vv.v..>..>v.....>>.>>v.>>vvvv.v>
+..>.v>.v.>.vv.>....v.v.>v..>v..>v>.>...>.v.>..v>..>vv>.>>.......v..>>vvv..>>..>.v>..v...>....v.>v..>.>..>>.v>..>v.>..>.>....>v>..>>.>.v>>.>
+..vvvv..vvvv..v..>.v..v...>>vv.>>.>..>.v>>>.>..v>>.vv.>>.v..>v.>..>....v>>v>..>....v....>.>..>v>>...v...>>.vvvv..>>..v...v>v>.v.>v>.>.>.vvv
+..v>v.vv>>.v.>>.>.>v.v>..>>.v>.v.v..vv.v>....v....>>.vv..>.>vvv.v.v.v..>..vvv>>..v>vv..>>.vv...>.>>v.>v...v.>vv>v.>.>v>.v..>>vv>.>>..>>v>..
+....v>v.....>v>v.vvv..vv....>..vvv.v.>.>.>...v>.>..vv..>>.v....>.v.>>.>v>>.>>...v...vv.....vv.>.v.....>.vv>..v>vvv>....>...v>>>v>>>...>.>v>
+.>...v.v...v....v....v..>......v>v..>>.>.>>.>vv.vvvvv.v>..v..v>..v.>v....>..v.vv>vv>.v.>v.>.....>..vv...>....vvv>....v..>.vv>.v>>>>.vv.....
+v.>v..>..vv..v.v>vv>v..>...>....>vv.v>..>v.>v..>.v.v.vvv.>..>vv..v>>.v..>v>..v.>>v...>...v.>.>.....>..vv>vv...>..v..>..v>..>>..v>..v.......
+.>v..v.>v>v..vvv>..>v....v..>.v>vv>..vv>>v...v.>.v.v>.>v.>v.>>>vv>v...v.>...>v.v>.v..>.>v..>...>.vv>>.v.v.>v..>v..>>.v..>vv..v>.v>.........
+>..vv.vvv>.>..>v>>vv>...>v>>v......v.vv.v>.v..vv.........v..>...v.v>>v.>.v.v..v.>.vv>v.....vvv>..>.>v.>...v....>.>.>>.v...>.>..>.>v>vv.....
+>.>..>>..vv>>>.>v..>vv>.>.>>v...>...>vv....v..>>v>...v.v>...vv.v...>>v.>v>.v.>>.v>v.v.v.v..v.vv>>.>.v..v.v..vv.v.>>vv>......v>>.v.>>.v>...v
+.v>..v.>..>.v.>>v>>.v.>>.v.....v>.>.v.>.vv...v...v.vv.vv>..>v..v>..>.>.>v.>v>.v.>>vv>.v..vvv>....v.>>.>...>.v.v.>v....v..>>.>..>>.>>>...v..
+>.......v....>v.>>v...>...vv>vv......>..vvv>>v.>v....>vvv.vv....v.vv>v.>..>vv>v>.>.vv>.>>.vv..>.>>v.>>v..>>>vv>>v......>v...v>.>v.v..>.v.vv
+>>v..>.>...v..>...>.v>.v>>.v.v>.vvv>v..>>vv....>vv>...v.v...v..>vv.....v..vv>.>..>....vvv....vvv.>.v.v.v.vv>vv.v......>v....>...v...v...>.>
+>>v..>...>>vv.>v...v>.....v..>.....>.>>>>>>>.vv..v..v..v.v.....vv>>..>>.>.v.v...v>>vv.......>.v>.>.>vv.vvv..>v>>v.v>........>>>....>.vv...v
+.>vv.vv>v>v.v.>...vv.v.v...>>vv...>>.v..v.>.v>...>.v..v...vv..>.v..v...>.v.v..v...v.v..v.v.>vvv.vv.....>.v>.>.>..vv..v>...v..vvvv>vv>v..>v.
+>.>v..v...v>.>>.vvv...v..vv>>..>>>vv>vv.>...>>v.v>>v>.v>.v.>vv>v.vv.>>>...>.>.v..v.>v...vv..>v>..v...v>>>>..>>>v>.v.v>.>v.vv>vv..v>>>vv>.v>
+v>v...v.>>v.>..>.v.v..>v.v.......>>>.>>v..v.>vv.....>>>v.vvvv..>.v.>.>.>v...>vv>v.>>vvv..v.v>....>v...>.>.v>...v..>v.>..v>v....>>v.vv.>v.v>
+.>............vv>..v>.>..vv.v.....>>>v>.>.v...vv..>>v>>.........v..v.v.>...v>.>v>>.v.....v>.v>vv.>..vv>.v>v.v.v...v>...>v.v...>v.v.>>>.v.v.
+.v.v>.>vvv.>.vv..vv..>..>...v>>v>...v.v.v>.v....>..vv..>.v.>vv>v>v..>>>....>.>..>.vv...>v>>.>......>.v>v....v>v.vv.v..>.vv...v..>>...v.>...
+..v...>..>....v.v>..v..>.......v.v.>>..v>>vvvv.v.>v>>>v>.>v>...>.vv>v.>.vv.v>.v>...>>.v>v...>....v>........v..vv.>..v.v..v...>.>.>..>>v.vv.
+.>...v..>.>vv>v.>...v...>v...>...v....>.>v>.vvv>..>>......>>.>>.>..v>..v.>>v>v......>>......>..v>>v.v.>.vv.>.v>>.>...vv...v.....vvv>>...v.>
+vv...v.>>>>vv.>v...>.....v>>>..vvv.>.>vvvv>v.>.>v>>>v..v>.>>v.....>>...>.>v...>>v>.v..v..v>v.v.vv>v>>>..>vvv..v..>....>..v>>v.vv.>.vv..v>v.
+....>>...>.v>..v>>>.vvvv>>.v...>vv..v.>..v>>v.v>vvv.>v>..>>.vvv>.v>.vv.>.>v>v>>.>.v..v>.>.>v.>v..>.>..v>...>>..>.....v>v.v.>v.>>>>vv.vvvv..
+..v.>vv....vv....v.>v>..>..v....>>vv.>>...>..>vv.>..>v>.v..v..v.v.v.v>v>..>......v..v>...>.v.vvvv>...v...>.>v...>v...>..vvv......>vv..v..>v
+.>vv..vv..>.v...>v..vv>.>>vv.v>...v>.v..>>.>.>v...v>..v.v.....>>.vv>v...>..vv>>v..v.v..>v.v>.vvv.vv>.>vvvvv...>>>>v>v>>....vv>..v.v.vv...vv
+.v..vvv.v.>>>v..>>v.>..>...>.>>...v......>.vv..>>v.v.v.>vv..v..>.>>..>.>v>.v>..vv.>v.vv>..>>>>vv..>..v...v.>>>>..>v.>v.v>.vv>....>>v>.>v>>>
+..vvv>v....v..v>.>v.vv>>>vv..>..>.v...>v.v>v..>>>..>v.v......>vv>...>...v..>..>v...v.>v>vv..>v.v>v.>>>>v.>...v>>.v>>...>.v>..v..v>v...>>.v.
+v.>>>>...v.>.v>.>v..v>..v.v.....>v...v...>..vv.>.v>vvv.....>...vv>...>.>.....v>.v.>>.v>...v..>.>..v...v.>>v...v>>..v>...v>..>..>....vvv.>.v
+.v>.>....>vv>.v.>>vv..>>.>v...>.>v...>>>v.>.vv>..v>>..v>v..>v>...v>.v.>>v.v>.>v....v>v>..v>vvv..>..>v>>>..>v.>.vv.v....>.v.v>.vv...>.>>v.v.
+.>v.>>...v>...>v...>v..>v.v....v.>.>>..>.v.vv>.>>v.....vvv.>....v..vvv.v..>v.....v....v.>.v.>v.>>>>..>v>v...vv.>.v>v>...v.>v.vv>v.>........
+..>>vvv....vv.v.>>vvv....v>..vv>.>v..v>v>.v..>...>.vvv.>>>>..>vv...>>>.v.v>.>.>v..>....>.........>v>v>.>v>>>v......v>>>.>..>>>.>......v>.v>
+v.>vv.>>>>v.v...v>..>v..v..v.>>>.....v...>v.v..v.>.v>vv>.>....>.v>v>.vv.>v..vv.v>.vv.v>vv>v>...v.>.>...v..>.v..>..v..>>>>...>.>>v.v.....>.v
+..v.>.v.vv..>>>v>>>...>>>.>....vv.....v>.>>.v>......v...v.>vvv>.>...vv.v>>...>v..v....v.>.v>v.v..v.>v.v.v.>.v>>vvv..>.v..>.v>v.>...v.vv>.vv
+>...>v..v..>>.v.v>.v.v>.v....>v.vvv>.>>.vv>v..>.>>v>.v...v..>.v>.v>.>.v.>...>..>>vv....v.>>..>.>.v>.>.v>..v.>.>>>....>>.>v.>...>.>v.vv.v.v>
+.>......>..>>..v..>.>v>.v...>.>.>.v.>v..>v..v>.v>.....vv.vv>.v.v..vvv.>>>v..v..>...v..>..v.>v>>>>.vv.vvv.>>v..v....>v....v.>.>v>..>>...>>.v
+>..v..v.v>v.v.>.vv....v......>..v>>vv.>..vv.>..>>v.v.>>v.v>...>.>>....v...>v.vv>v.>.vv.v....v..>>>..v.>>.vv>>vv.v>.v..>..vvv>.>v..v>...>..>
+v..v>..vv.>.....>.>>v>.>....v>>.>.v....vv.v......vv.vv.v..>.v.v..>...vv.v..>v>..>>v.>....>.vv>>....>>>v>>.>v....>>..v...>....>v.vv..v>.vv.v
+>vv>v.v.>.>.>.>>....v.>>>v.>v.>...>.vvv..>v>.v.>>v....>vv..v.vv>vv..>.v>..v>>v.v>>..v...vvv...v.>.....v>v>.>>v>...v>.....>.>.>v>..>v.>.>...
+..v>..vv....>.v..v>.>.>>.v>.>....v>.>v>....v>..>vv.>>.>.vv>.>....>>v....>vv...v..>...v..>v>>>........>.>.v.>vv...v.>v...>>>.....>>...v>.v..
+>...>vv..v.vv.....>.v.>.vv.>vv>>....vv..>vv.>vvv.vv..>v..vv......>..v...v.>......vv>.v...>>v..vvv.v>>..v.v>....v..>>..>v...v>>>v...v>.vv.>v
+vv....>.>v.....vv>.>.v..v.v.vv>v>v.>..v....v>>.v.>.>>v>..vv..v.>.>.>.v..v>v.>>v>v..vv..>.>.>v>v>...v>.v.v>>v...>v.v>v>v.>..>>v>..vv>..v>v..
+.>v....v.>vvv..v>.v>>.>.v.v.vvv>.>....v.vv..>...v..>v...v>...>>vvv...>.v>v>..>.v.>.>..vv>v>v>.v........v..v..v.>...>>v>>v>..vv>v>..>>>.v.v.
+v...v>....v....>>>v.v...v.....>...vvv>..v.>.>v>v>v>.>>...>>>>v>>.>>.......>....>v.>>v..>.v.>......vvv>..v..v>vv>..vvv>>v..vv.>v>v>>..>.>...
+..v>.v>>>v.>...>v>v..vv>...>>.v.>>.v..v..v.>.>v..v.vvv.vvv>v>.vv>.>v>v......vvv>.>.v.>...>vv.>.v>>..>v>>.v>vv.v>>.v..>v...>..v>.>.v.>.>>...
+v>vv>v>..>..vv...v.>.vv..v...>>vv>.>>>.v.....>vv>v>...v....>>...>v>v.vv.v...>.....>>v..>>.v.v.>.v.>...>>.v.v.v.v.>v..>>.....>v.......vv...>
+..vv.....v.....v>.>.v...>..v.>vv.v.v>vv.v.v.v>..v>.vvvv>..v...>.>.>.vv>v...>....v.>...>..v.>v.....>>...v>>.>.....v>v....v.vvv...v..>..v....
+>.>>.v>>v>v>v.v..>.v...>.....>.v.vv.v.....>..v>v>..>v.>.>...vv..>>..>v.>..v>.>>.>>>vv>.>v>>..v..>vv>>.>.>>.v>>...>v>.v>v..v.>vv..v>.vv.v.v>
+.v..>..vvv......>..v>vv.v.v>>v.v>.....>.v...v.v.....v..v..>...>.>>...v>>....>>v......>....>v..>v.v.>....>>v..v>v....v..v>...v.v>.>.....>v.v
+>.>..v>v.>..v...>.v.v>.vv.>>.vv.>.v>.vv.vv>vv>v.>v.>>..v>.v..>>..>vv>>>>>v..>...v...vvv>..>>....>..v.>..v.v>v.....v>vvv..>v>.>v.....v...>>.
+>.v....v.v.vvv...v..>.v.>.v>....>>v.v>>.>....v.vv..>.>.....v...v.>..>..v...v.>.>.>>.......vv..v>.>v>.v.>v.v..>v..v.....>..v..vv>.vv>..vv.>>
+..>>.v..vv.vv>v.>v>>..v>......v..v..v..>>>>v..>.>..>.v.>..>......v.v>.>.>.v>>..v..v.v..>v>.>.>>>>v...v..v..>vvvv>.>vvv>....>.v.>>.>>.>...>>
+.>v..>>..>.>v.>>>.>>...>...>..v>..vv.>vv.v...v..v.vv..>.>....>..vvv....>..>.>v.>v.>>v......>vv>v...>...>>>.vv..v..v..>>>.>>v>.....v.....v.>
+>v.v>.vv..v>...>.>v..>>...v..>..>....>...v.>v..>...v..>>.v>vvv>..v>>......v.>>.>.>.v>v>v>...>>.vv.vv....v.>v>.v>.v..v.>v...v.>>.....>.v..v.
+v....>v>v...>..v>>>>>>.>vv.>>..v....vv.>>>v..v.vv...vvv>.v..v..>v.vvv>>v.v.>v.v>.....vv>..v.v...>.>>....v>...>>>.>.v.vv.v...v..vv.>v>v...>>
+..v..v..>..>v>>.>vv.v>...vv..vv.>vv.v.v..vv>.vv>vv>.>v.v>.....vv.v.v>v>v..vv..v>...vv.vvv.v.>.v.v....>>.....>.>..vvv>>...v.>.>.v.vv.......>
+....>.>>..>..v>v..>.>v..vv>>>v...>.>...v.v.>.....vv..>.>>.>..>v.>>..>.>>>..v..v.>v...>v>>.>>..v.>..vv.vv>>v>.vv..>v>.>>vv...v.v.>vv.vv>.v.>
+.vvv..v..>.>....v>vv>>v..v.vv.v>..vvv>vvvv....>>.v>>...v.v.v>>>..v>...v..v>>v.>>.v.v>>.>..>>vv..v..>.vv.v>....>.>..>>......v>>.>.v>>..v.>>v
+.v..>.>v.....>>vvv.........v.v.v..>>.>>..>>.v..>>..>.....>...>v.v>.v..>.v>v>....>.......>>v.>v.v...>.>v....v..v.>.>v..vv.>..>>>v>..v.v>>>..
+.v..v.>.v>v>>..>..>v.>>v>>>v.v.v...vv>>.>>....>v.>vv.>...v>>.>v>v....>.>v..>.>.v.....>>v......v..vvv>..>v.v>v>>..vv....>.>....v...>v...v.>v
+..v..vv....>v..>>...v>.......vv..>.>.v>>.>>.>>.>.v..vvv>v..v.v>....>vv....v..>...v.v>.>v...v..>.>>>...>v..>v..>>>..v.>>>....v>.vv.>v......>
+..>...v.v.>v.vv>>vvv>v>.vv..>>>.v.v.vvv...v.>vv.>>.v>....v.v..>.>.v.v..v>..v..v.v...>....>>..>.v...vv.>.>v.>....v..>v..>>.>...vv>.v.v...>v.
+.>.>>.>....>vv>>>v.v.>v..v.v>.v>...v...v>>>>>..>>.......>>>..v.>v>...v>.v.>..v>..>v.vvv.>v>v>.v>.>>..>vv....>>v.v.v.>v.v>..v..v>>.>.>..vv.v
+...>..v.v>v>>.vv...v..>..>vv...>....v.v.v.v.>>.>v..v..v..>>>.>..vv.v.v..>v>.....>.v>vv....v.v>v.v...vv>>.v.>vv>...>>vv>>.>v..vv.....>v.v>vv
+>>>v....v...>.>.>>vv...vv.....>v>>>>>.>..>>..vv..v>>...>.vv>..v...v>.>.>..v>.vvvv>>v>.>.v..>vvv>>>vv....>...>.vvv.>v>>.vvv>v>.vv>vvvv....v>
+v..>.>v>>vv.v.........>.>v>..v....>>v...>>.v..v.v>v..vv>vv>>...>>>.>v.>..v>..vv.v>.v.vv.v.>v>.>...v.>.>v.vv..>>..v>........>v.>>.vvv.>>v>..
+...v>vv..>>>...>.......v.v....>...>v>>v...v...>..>>v.v....>vv>..>>.v..v.vv..vvvvvv...v>>.v...>.v....>.v>>.vv.v>....>..>....v>.>v.v>>.v>>.>>
+>.>vvvvv..>>v..>.>v>>>.......vv>v>......>>>>.v.....>.>v..>v..vv>>vv>...vv....>>..>.>..v.v.v...v.v>v.v>v..v>>>.....>.v...>v>>>......>>...v..
+>vvv>..v.>vv.vvv>>>>>v>.>>vv.v>>...>v.>>..v.....v>>>.v....>>vv.>.>v>>...>>vvv.>..v>vv>.v..vv.v...vvv>>>.v.>v>>.v>>>.vv.v>.v>>vv...vv..v>..>
+.....>.>..>....vv...vv.vvv.v.>...>>v....>.v....>.v>v.>......v....>...>>v..v.v>.v..>.vvvv..v>>vvv..v..v>.>.>...>...v>....v.>v>...>>>v.....vv
+.v>..>.>...>..v.v>vv>.>v>..>>.v>v....>....v..v.v.vvvv>.v...>>>v.>v.>.v.v...>v...v....>>>vv>..>..v...v.vv.>v..v>...vv>v..>>>>v...>vvvv...>v.
+...v.>...>.v..>v..>.>>.>......v.v..v>.v..vvv.vv.>...v>>..v..v......v..v.>....>.>>.>.>>..vvv>.>vv.vv.>.>vv>....>.>.>....v>>..>>v>..>>.v>>v>.
+>v.v..>...v..v.....vv>.v>..v>.>.>v..v.>.......>v..>>v>v.v..vv>vv.v..>.......v>.vvvv>>>>.vv>.v.v.v>v>...>.vvv.v.v...v.v.v...v.v.>v..v.vv>>>v
+>..>...>v.>v.>>.....v.>.vvv.>.>>..v.>......vvv.>>.v..v>vv.>>...v>.v...vv..v>..>..>>.>.>.vv.>.v..>vv.>>...v>v..>>v...>...v>.v.v.>>.v>>.....v
+v.....v..vv.v......>...v>..>>.>.>..v.vv...>>vv>..>..>v.>vv>v.vv...v...vvv.>vvv.>.>>..vv.v>>..>..vv.vv.v....v.v>v.>v.>.>>..v>vv....>..v>....
+>..>.>v.>v...v>..v>v.>>>>>v.vvv...v>>>.v>v..v..v..>.....v....v>.>>v..>>>.v.v......>.....vvv>.v.v>.>....>v>....v.v..>v.v>.v.>>>..>vv>v.>>...
+.>..>>....>>>.v>..>vv>v.>v...v.v.v>.>.>>>.v>>>>.>v>.>>vvv.>>........v>....vv.>...v>v....>>>....>..>.v.>..>v...v..>v>.v>.v>.>...v..>>.v>vv..
+.>..>v...>v..>vvv>v..........v>.....v..>.v>>v.vv>.....>v.>.>...v.>.>.vv..v.v.>.>v>.vvv>v>v>v.>.v.v....v.v.>...vv..>>vvv..>>....v...v.>>v>vv
+v>..v.>v>..>>.>..>.v.>vv.>>v.v>>v.vvv.>v.>.>>.>....v..v.v.v>>>>.v>>v>>.v.vvvvvvv.>.>......>.vv..v.>>.vv.>vv.vv.v...vv>vv>.>>..v>.>.v.v...>.
+.>...v.vv.v.v..>.vv.....>v>.v.v>..>........v>..>>v.vv>v.v..>vv>.>>>v...>...>...>..v>.>>.>>>>>.>v.>>..vv..>....>v>>.v>..>>..>......v....vv..
+>..>..>>.v....v>>>>.>.>v.v..>vv.v.v>..v.v>>v.>v.v..>v>......>v.vv>.v.>>>.vv>....>...>v.v.>.>..v>>.>v.v.......v..v.>.>.v>v...>v..v.>..>vv>v.
+...........v>>vvv>..>>>v....v>v>.>....vvv>.v>>v>v>>>>.>vv>vv..>vv.>..>...>v.v..v.v....>vv...v>...>.....>>..>vv..vv....>>v>.v>>v>.>v>>vv>>vv
+..>v.>.>...>....v.>v.v.....v>vv...v>>>>.>.vv....>.>.v.v..>>..v>.v>v.v....>.v..>v>>>vv.v.v>.>..v..vv>v>v...>...>>.>>.>>>v.v..v.>.......>>vv>
+v.>...>>>vvv>v>v.>>.v.>vvvv.>>v.v.>>..v...>>.>vvv..vv>>>v.v>>>>.v>vv.>.v>.vv.>>..>..>.....>....>v.v.v.....v>>...>>..v.vv..>.>...>..v...>.vv
+>...v....v.>>>v>..vv>v....v>v.>>.vvvvvvvvvv>.vv...v>..v>vvvv.>>>.>..>>.>.v.v...v>.v.....vvv.>.>>..>v..>.v.v...v.>.v>..vvv.vv..v.>v.v>>v>.v.
+.v..v.v>vvvv..>>v>.v..>...>vv.v..vvv.>v.v>>v..v.vv>vv>>..>.vv>........v>.>..>>.v>v>...>..>...v>.>.....v>>..v..>...>>>...>v..>.v.>..vv..v..>
+..>..v>v..v......>.>>>....vvv..vv..>vv.vv...vv..>.v.vv.....>.>>..>...>..>.>>>..v>.>>>.>v..v..>v.v..>..v>>vv...v....>...>v.v>.v>.v...>vvv>v.
+...>>>>vv>.>.v.v..>vv>..>.v>>v.>vv.>>v.v>>.v..>.>....>>.v>.v.v...v.v.v.>>v>>>...v.>..>..>.v.....vv..>...>..v>..vv....v.>>.>>v....>v>..v.>>v
+>.>.v.v....>v.>>...v.vv.>.>....v>.vvv>.v.>.v..v.>..v.>..>>.....v>..>..v.>vv.v.....v.vv..>v>vv>v>.v>..>.....vv>...vv....>...v>.>v..vv..>vv.>
+.v.....>..>....v.vv>>vv.>...vvv>.vvvvv...>......>.v......vv.v...>.>...>.>..vv.v>..v>...v.....v.>v.>..>>.vv>.vv.>...>v.vv>v>.....>v.>....vv.
+.v.>>.>....>.v.>.v.>.v>.>.>..>...vv..>>.>..vv>.>v.vv.vv.v>.>.>>...>vv.>..v..>.>v.v.>v>>.v..>vv.>..v>..........v..v..>vvvv>>.v.>.v.vvv....vv
+vv>.>>v>v.>.>>>vv.v.>v.v....v.vvv.>>>.v>>...>..>>..v.v>..>>>vvv>>>..v.vvv.>v..>>..v..>>..v.v..v.>....>.....>...>..v>...v..vvvvv...>v.>...v.
+>.>>>>.vv>.>...>vvv..>v..v.v.>..>>....>..v>v>v.>.......v....>v.v.>vv>v........v....v..>v.vv...>>v...>>v.>vv...>.v>.>vv..v.>...>.v>>v.v..>>.
+.v.>.>>>.vvv..v>v.v.>>..>..>>.v.vv.>>v..>>>..vvv...vv....>..>v>..>>>...>>......v....>..>v.....v>..>.vv.>.>>..vv..v>v...v..v..v>.>v>..vvvv>.
+..>.v>>...v>>....>.>>.>.vvv>v.>v>v>>.....v..>.v.v.vvv>.>.>.vv>vv.>.>......vvvvv.>..>vv..>.>....v>v..>>.>>>.......vv.vv.v.>..>...>..v.....vv
+>.vv>v.v..v>v....v..v>...>>...>>.>>..v..>>.>>.>...vvv...v...>..>>>.v>.v...v...>.>.>.>.>>vv...vv>..v>v>vvv.>v..v>.....>>>>...>vv...>>..v>v.v
+.>v.>v.>v.>v.vvvv>..v>vv>..vv...>.>...vv.vv.>...v>..>...>vv..v>..>.v.v...>v.v>>vv>vvv.v>vv.......vv>vv>v....v....v..vv..vv....v......v>v.>>
+....vv..v>>.v>..v.vv..>.v>v..>v.>>v.>vv.....>...vv>>.v..>>.v..>v...v>>..v>.>.v.v.v.>v...v>>...v>.>.........>v>vv.v..>..vv>.v...>.v..v..>>..
+>v>.>>.....>..v.v>..>..>v>..>...>.>vvvv..>.v.>v.>.v.>v...v...v..>v>.......v....>v.v..vvv>v.>>>v.>v.vv.>v....v...>>.....>..v.v>.>>>.>v>>>>.v
+>.>..>....>..v>v..>>..>>>.vv.>.v>v.v>>v.>....v.....>.>v>v.....>>v>..v>.v....>..>.vv..>>.vvv.v...>vv>...vv.>>.>..v.>..v>>v.>..v.....v>.....v
+.>>>...>..v.>v>.>.v.v.v..>.v>.v..>.>v..v....v.v>.>>v.>.v.>.>v>>.v.>v...v.v>.v.>...v..>>.>.v.>...>.v.>..vvvv.v.v>.v>...>>.>..>...v..>>.>.>.v
+..v.>>v>vvv.>.>v.>...v..>...>.vv..v>..v..v....vvv..>vv>.>v.>v>.......v>vv..v.>..v>...v.>>..>v..vvv.v..v>>>vv>v...>>>..>>...v.vv.>vv>v>.v.>v
+v.>...>.>v...>vv>>.....v.>>>.v...v....v.v.....v>vv>.>...>.v...vvv..v.>.v....>v>vv>v...>.....vv.....v..v..>v>>...>v.>.v.....v>.......>>>>.>>
+......>>..>v.vv>v.>..>>.vvvv..v..vv..........v.v.v.>>...>...vv>.>...>..>.>.>>.>>>>>.>v>.v.v.>v>vv...v.....>>.v>..>>.>>>...>.>>v.v.>...>...v
+..v>v.>.v.>v>....v..>.v.vv.....v.>v>..v...>...>.v.v>.v>.v>..v>....>>.>v...>.>>v.>.v>v>v.>>.v>v..>.>>>.v...v>...v.v.>v.v>v.v.v>v>v...v.vvv..
+..vv.>.v.>..>>>.v..v>..>v>v...v>....>.>.....v...>>..vv..v>.>vv....>...>..v>.......v.v.v..vv.>>vvv.>.v.>.>.v>v>v>.>>.....>.>>.vv>v>>>.>vv>.v
+..v..v>>>..>>.>>>v..v..v...v>>...>..>v..v..vv>v..>vv.v>>>>>..>.>>.vvv>.v....>.>.v.>>..>v>.....>vvv.>.v.v>v..>>...v>vvvv.>.>v.v>v>...v....>>
+.vv..vv>.vvvv>v..>>..v.v.v.>...>.v..>...>.v>..>..>v..>v.....>.>..v..vv>.>.>v>v.v>>....>v.vv.>>v..>>v...>..>v....vv>v.>>vv.>..>>vv>..>v>v>..
+..>v.>.>..>vvv.>.v..>v.>...>>>>..v...>v...>.>.....v>...>....v..vvv..v.v...v....vvv>>vvvv...>.v..vv>v.v>.v...>>..>.......vv.>>..vv..>.>v..v.
+.vv..v..>....v..v.>>>v>vv..v>....v..>v>......v>.>.>v.v>..>v.>v>..v...v..>..>..>..vv.vvvv>...>..>......vvv.vvv>.>>>v.v...v..v.v..vv.v>.>.>.>
+.>>>.v.v>...>.>.v..>>>v>...>.vvvv>>>v...>.>>vv....>.v..v..>.>>.............>..>>..>.>>v.>....>.>v.>>>v...vv..>v..v.vv..>v>v.vv.>v.vv>..>>.v
+>v...v>.>...>.>v>v>.>>.v.v>...>>..vv.......v.....>......>>.>>>>...v..>....>.>.>>..v>.>.v>>.v.>.v...v>vvv>..v..v>>..>v.vvv..v.v.>>v.>...>.>.
+v>.....>>>...v.vv>.>.>..>..>.v...v>>.vv>v.>v>...v..>.v..>....v>.>>>>...>>>vv>>.v...vv...vvv.vvv..v.>>v>..>.>.>>.>..>>..v>.vv>>v>.v.....>...
+.>v...vv.>vv.v...v.v>..>.>v>.....>v.>....vv..>v.>v...v>..v...v>.....v..>v.>>.>>..v>v>>.v...>>v>>.>v.v..>..>>....v>vv..v>>>....>.v>.>>..>.>>
+>>.v>.v>>....>.vv>v>v>..>v..vv>v..vv.v.....vv..>..>vv>..>>>......>.v..v.>>...>..vv..v>.vv>>>v.vv..v.>.>..>v.>>..v>v.v>v..>..>>....>>>.v...>
+v.v..>v....v.....v...>.v...>.vv..>vv.v.v>v>v>...vv..>>>v>...v>....v..>>>v..vv.v>..>v>v.>.>vvv...v..vvv>.vv>v..>v>.v>.vv.vv.v...v.v>v.vv.>..
+.>vv.v>v.>...>..vv..v>v..v.....>....>>..>..v>vv...v..vv.v.vv>v>.>>v>.v>.>.>......vv>>>.....vvvvv.>..v.>...vvv>..>>>v>>v>v>.v.vv....vv.v....
+......>>>..>..v.v>v...>v>...>>v...v>...>>v...v>v..v..vv.>vv>v.>>>......>.vv.v>v.>.v.v...>.....vv.vvvv.v.v>.vvv...>..>v...>>....>..v>>.v.vv.
+vv...v...>.>v.....>.v>.v.v.>>v..v>..>vvv.v.v......>v.>>.v.v>.>>>..>v>>v..v....>>>.v..vvv.......>..>v>>....v>.vv>........v>>..v..>...>v....v
+...vv.>v..v>>>.v.....>.v>...v>...v.>...v.v..>>.......>vv.>...>v.vv.>>.>.>.....>.v...v....>v.>.>v>>...>>>v.....v...v.>..>.>....v....v>.>.vv.
diff --git a/2021/inputs/day_3.txt b/2021/inputs/day_3.txt
new file mode 100644
index 0000000..7320494
--- /dev/null
+++ b/2021/inputs/day_3.txt
@@ -0,0 +1,1000 @@
+111100000101
+001110100010
+101110110011
+100000001101
+001101010011
+101111110000
+011101110001
+000000010111
+011011000010
+110110010000
+011101000000
+110010001001
+101110100111
+001001101111
+101001011010
+101001000001
+101110111101
+010100101100
+001000110010
+010100011110
+100100000001
+000110011000
+110100100001
+111000110000
+000111100100
+101100110100
+101111101001
+101110101001
+010010110001
+000111100001
+001100001000
+100011101001
+100010111000
+000001011000
+001011110100
+011110010001
+110000011010
+100011011111
+001001110101
+001010000101
+100000010010
+000011100010
+101010110101
+001110000101
+000111101101
+010100101010
+101111101011
+010001100000
+110101100010
+001001001111
+001101011010
+111010010101
+110001000011
+000011110100
+100010111101
+111100101110
+110110001101
+001000011011
+101110101110
+111011101110
+010000110001
+101111011111
+000001001110
+111101100011
+000100000000
+100001001111
+110010000010
+101111010011
+010000101000
+011010101111
+110101101100
+101101011100
+100101111101
+011101011110
+111001001000
+100111001101
+101101000100
+110111111010
+011001101001
+111101010110
+001111001110
+111100010111
+000100111100
+011100101001
+111100111100
+101000011100
+011100111100
+011010110010
+101111101101
+010111101010
+001011000111
+000010011111
+101000100110
+000100110101
+100101001100
+010100110110
+011111100110
+000000101011
+111111101110
+001011101101
+000010001101
+001100100100
+101010010111
+100010011001
+010100000110
+010000001101
+010001101011
+000111111001
+101110010010
+011100101000
+010101010001
+111011110111
+000010110001
+101111000111
+001101110000
+111111011011
+100010011010
+001011011010
+110111001001
+110101110100
+101100111100
+011110101010
+010000001010
+001111100001
+000110000110
+111010111010
+101110100100
+000001110010
+110111001101
+000001101000
+000010001111
+110000100011
+000000001001
+000111111110
+111101111010
+010110101010
+110101011111
+000111000110
+111001100001
+101111100000
+011011010111
+101011010111
+110011101111
+001110001111
+010001100100
+111001010000
+100111000100
+110101010100
+000011111101
+100010010000
+110110100100
+100111011110
+101011001101
+111011100110
+100000010000
+110000001111
+001000000111
+111011011011
+101111101000
+001110001010
+100110000000
+110001100110
+011110100010
+000001010110
+010100000101
+101010101010
+001101000110
+110100001111
+110000001101
+101101000000
+101101101011
+111001100101
+101010001111
+101101001101
+010111101011
+101000101101
+001010000111
+011110111001
+001011101000
+101101000010
+110111111110
+110001011011
+101111101100
+101110110101
+101100111101
+001110001101
+010111000110
+110101110110
+101001101001
+010100001000
+011011111110
+111010010001
+101110100000
+000101111100
+001111110111
+001010110011
+010011011001
+101111100001
+100101111110
+010001010011
+001101110001
+011100001000
+101100000101
+000111111101
+010101110000
+100110001100
+010101111100
+100101110100
+110111000001
+101110101000
+000011010000
+101011110101
+100011110100
+111100010110
+110100011001
+001001001100
+010110111000
+001000101111
+111101001110
+011110000011
+000111000100
+001101110101
+110111011101
+100000111001
+100000001001
+110110111011
+010011000110
+000100010101
+100101010001
+100100101100
+010001001100
+000010001010
+101100101101
+011011101111
+100010111011
+111111101111
+110001100001
+101011101111
+000100011101
+111000010001
+000001011001
+001101111101
+001000000001
+010100010100
+110010111011
+010100100011
+001010001010
+111111011010
+100101010101
+000111000010
+011010100000
+010100111111
+001011100010
+101010001011
+111011010101
+100100100111
+101110101010
+111100101001
+111010001000
+000100001111
+011010001000
+011011100100
+110011011111
+110111100010
+000100001100
+001001101101
+110111110011
+101111001001
+101010001001
+011011000111
+000110001001
+111011001010
+000110000100
+000000111011
+010110110110
+101000000000
+011100101111
+111101111000
+001110011100
+111110011001
+000010111000
+010111001100
+010010111111
+110101100111
+000110111010
+000001111110
+111000000000
+001110011101
+100000111100
+100010100001
+010011101100
+010001101010
+001001101011
+110100010100
+011000000110
+011000011001
+010001101111
+000101001111
+011101111101
+100010010011
+100101111000
+001101110111
+001000000000
+100100101011
+111000100011
+101100011011
+000000101101
+001110010011
+001010010000
+011000001110
+101011111001
+110101100000
+011011111010
+001000011111
+011000100000
+000010101100
+111100010011
+101010000011
+001100111111
+000001111000
+111101110101
+001010100111
+011100111111
+111010111000
+100101011111
+011100001101
+001011000011
+110001110110
+000011101000
+111110010111
+100010101101
+110001011101
+011010100010
+001110000011
+101001101111
+100110100100
+011010000111
+001111010011
+110111101111
+110101100101
+100011010000
+011110000100
+010110100010
+011000111001
+011111011010
+011110110101
+011011110111
+001111100101
+101110100110
+101010100000
+110100001100
+111010110101
+011010001111
+000010111110
+100110010111
+011100011011
+100101100011
+010110111100
+010011110111
+111001011101
+000011111100
+000111111111
+101000111010
+010110110011
+100110101111
+100010111010
+111001111111
+000110110011
+010010111101
+110001100011
+111100001000
+010011000011
+011011101011
+001010101101
+100011010011
+001100101110
+111000111111
+101001011101
+111011010011
+110101011101
+001011010111
+011001010100
+010011010100
+011100100110
+101111110001
+110111111101
+111110100110
+110001100000
+010110010011
+011100110001
+010111111011
+001010101000
+010100101111
+111101000001
+100000111010
+001010100000
+000001011011
+100111011101
+100011110010
+011111010000
+111001010110
+110111111100
+010110100011
+101111111010
+110111110000
+111100000110
+111101011110
+100101111100
+111110001101
+111110011110
+010101100010
+110101101101
+111100001101
+000100011100
+010011110011
+000100010100
+000110110010
+001010111000
+110111001111
+110101000101
+100011110000
+101010010010
+111110000010
+111011001011
+010110111010
+011101010100
+010010101010
+010011110001
+010000010110
+101111000011
+111111010100
+001111001001
+101001100111
+000011011111
+100111000001
+010111010110
+010100011100
+010100011101
+001111110011
+101100010111
+101110100010
+111101110100
+100100100010
+111010011011
+010110000100
+100100010100
+101000011010
+101001111101
+010000010001
+110111101101
+000001110110
+010001110100
+100100110001
+011111010111
+100000000110
+100001110110
+000001011110
+011000001100
+011001110110
+010010101110
+111100111000
+001010010011
+000001000001
+100010111001
+010001011111
+001110000000
+000010000000
+001101110011
+010100011001
+000001001010
+110001000110
+100010100101
+011100010001
+101100000110
+001001100000
+110100000000
+000010100010
+101101100111
+100001111011
+011000011101
+110100110010
+001011001101
+000111001110
+011100100100
+100010000100
+001101100000
+100010011111
+010101010111
+000101010011
+100011100000
+100001011101
+110011111100
+111010011001
+001011110111
+011010010100
+000011001110
+010110111001
+111000001001
+011100111010
+011111000010
+101100111010
+010100111101
+111001100100
+101111010110
+110111110100
+111110101010
+010011001110
+110101101001
+111101011000
+001010001101
+101111000010
+111110000111
+110000001100
+011111001101
+101001000101
+010111001011
+001010011110
+111010100100
+110000101000
+011101000011
+010010100110
+111010000001
+111101000111
+001010100101
+101011001100
+110010111001
+111000111100
+100101011101
+110010101001
+010010111000
+010101001110
+110000101111
+001101001101
+001000101011
+001110110111
+101111111011
+111001100110
+100101110000
+010000011011
+001010000000
+011001010110
+010101101010
+100100000011
+110010101110
+110011101000
+001010001000
+010000101100
+100110011110
+001010001111
+111010001101
+100100010000
+100100111001
+111111010110
+100010011101
+110100100100
+000110011101
+000101101001
+001011001100
+101000000001
+111101100000
+110110111000
+111111000010
+001010111011
+011011111000
+010111000101
+011100110011
+111111100010
+000000100010
+001000011110
+010001011001
+111100111101
+001111010010
+010110011011
+111110001110
+101111100100
+011100011101
+111001111001
+101001000100
+001011000110
+100011010101
+001101100010
+110111101110
+010101111000
+111010000111
+000110010111
+001100111101
+100000101101
+000110101000
+011000011100
+000101001110
+011010101100
+100010010100
+001001111001
+101100100000
+010011011000
+100110101011
+110111110110
+100111001100
+111010010011
+000100011110
+011100011000
+010000011001
+100110011010
+010000001000
+101010011010
+111111011100
+010110100111
+000110001101
+001011111000
+011010111001
+111011011101
+110000010110
+100110111001
+110010000001
+110001011110
+111100001010
+101110111100
+110011110100
+101111011101
+000101010010
+001111000110
+110010011010
+000010010001
+001110110110
+111101100101
+000000111101
+011110000110
+111011001101
+110111000110
+101100110101
+010001001001
+001010110101
+101100011010
+100011001010
+001011101110
+101000010110
+100100111011
+001011101100
+111110111010
+110011111010
+000001111101
+010000110111
+101101101100
+000110000000
+111110110100
+101100000010
+011000000001
+001000001001
+111101111011
+010100001110
+111100101000
+011000010111
+001000111101
+100000100101
+110111000101
+001111100000
+101110111001
+000100101111
+101011010100
+101111111001
+000010000101
+001100001111
+101001011001
+001110111000
+010011011101
+110110111001
+011111010010
+100111101011
+101110011000
+010011100110
+101111000000
+101000110111
+001100000111
+110001101111
+010011101010
+100100000111
+100011111101
+010111010010
+001010111010
+011111010110
+101101100101
+011110001000
+000100111111
+001010111100
+101101100000
+010010000011
+010011010111
+111000011110
+110111010101
+100100101000
+101001001000
+001111110100
+111011110101
+110001000100
+100111111001
+101010110100
+010111101001
+011011010010
+011111101010
+111100111110
+110011101101
+110110101101
+110010100101
+111110101111
+000011110011
+001100001011
+111110110111
+011011101100
+110111101011
+010111010000
+101000010111
+010100010001
+111101100100
+011101101010
+010000110110
+111001110000
+111111000100
+011001100000
+111100101111
+011001001011
+110100100011
+011001111000
+101010001100
+100010001110
+010111110110
+001011011111
+000001011100
+010010001111
+011101011000
+001010011010
+100010011110
+010011000111
+101011011111
+100101000010
+110111010111
+110111101010
+010100001011
+001001010011
+001011001111
+011000001111
+010100000111
+100011001111
+110100111100
+101110010000
+000010110010
+100010100010
+001010011000
+010101100101
+101100010001
+011011001010
+000101100000
+000101111010
+001001110010
+100011100001
+011110111011
+100000010111
+100001001101
+111000100010
+011000011000
+100001100010
+000000110011
+000101010111
+000101000100
+110111000111
+001100000000
+110100010110
+101001000011
+110111100100
+000111100011
+101110001001
+000010011101
+000011010111
+111101011001
+111010001111
+000100110100
+000011100001
+100100111000
+100111101110
+001110101011
+000111110100
+110000010111
+110010011111
+000001111111
+101011110011
+101100001101
+110101111011
+011111000111
+011110011011
+001000010110
+110110110100
+010101001011
+000100111000
+011101111111
+000111101001
+110101111010
+110000111001
+011000111101
+001101001010
+110100110100
+100110010001
+100000000100
+001100111000
+100000001110
+101000011000
+100010110110
+101011001001
+010010001010
+111011101100
+100010100110
+101101000111
+100110110101
+111001010100
+101000110000
+000101011010
+010001010110
+010111011110
+001101011110
+000100000101
+000001011101
+010010100000
+110110010001
+100111000111
+100010110000
+010110100000
+110111111111
+011111011111
+001011010010
+001111100011
+100010110100
+011010001011
+110011001010
+101110111000
+111001010011
+010011010101
+011100100101
+101010110011
+001001100101
+110010100000
+011000111110
+011101001110
+110110000100
+001111101100
+101100010100
+110001100101
+111111010001
+011001100001
+110100000101
+000000010000
+110101000111
+100100110100
+010010110100
+010010000100
+011000111111
+011001101010
+011111101110
+110110010100
+110001001110
+111111100011
+010001100001
+001001111011
+000101110010
+011111110111
+000011000110
+110101000001
+101110000011
+000000111010
+000101110011
+000011100111
+010010010011
+110011011010
+111100100100
+110010011101
+100001001000
+101000110001
+101001010011
+111000111101
+101011111000
+110011110110
+111110100011
+010110100100
+010101000011
+001010101100
+101010101001
+111100100000
+001111011111
+110101010011
+101111010000
+110011110010
+110110110001
+011010011110
+100010010101
+101000101010
+010111010001
+000001111100
+001000011001
+011110110001
+110100011000
+110000111110
+001001011100
+110110110101
+011011100110
+011110010100
+111011110110
+111110111001
+111010010100
+001000001011
+111101010011
+100111101010
+010100001100
+111101111111
+000111111000
+001010011101
+100000001011
+010010001110
+011011011101
+100000000111
+100101100100
+001110000010
+000000000000
+101000110100
+011010110001
+100001101110
+110001110011
+101100010000
+001111111111
+111110110101
+010111001101
+011001000001
+111110011100
+100100011010
+001000011000
+011101101100
+100110111111
+111011011010
+101001101000
+010011110000
+110010110011
+111000000001
+101101110110
+111000001101
+011111001001
+010010110101
+001100010101
+111011110010
+100011000101
+111010000100
+011001111101
+111010011110
+111011111011
+110110011010
+011111011011
+010010001100
+110100111110
+010100111011
+110110011101
+110011010000
+110001001010
+000011000111
+100011101101
+101010100010
+110111001010
+100101101110
+111100101010
+110001011001
+011010011001
+000001111010
+001010101010
+010001110000
+001001111100
+011110000010
+000100010001
+110100000110
+010110111011
+001100111100
+111100011000
+011011011010
+111001001010
+110110100111
+001011000000
+000001110001
+101100011100
+100011000011
+001100010001
+000100111011
+001001110011
+100111111100
+111010001001
+101001000110
+001101000100
+110000000100
+111010110011
+000101110000
+010000010101
+000110111001
+100100100000
+110010001011
+110111100011
+101101101001
+100001100100
+000111010100
diff --git a/2021/inputs/day_4.txt b/2021/inputs/day_4.txt
new file mode 100644
index 0000000..b01c04f
--- /dev/null
+++ b/2021/inputs/day_4.txt
@@ -0,0 +1,601 @@
+68,30,65,69,5,78,41,73,55,0,76,98,79,42,37,21,9,34,56,33,64,54,24,43,15,58,61,38,12,20,4,26,87,95,94,89,83,74,97,77,67,40,63,88,19,31,81,80,60,14,18,47,93,57,17,90,84,85,48,6,91,7,86,13,51,53,8,16,23,66,36,39,32,82,72,11,52,28,62,70,59,50,1,46,96,71,35,10,25,22,27,99,29,45,44,3,75,92,49,2
+
+68 16 83 90 69
+14 89 72 33 6
+63 21 43 64 76
+79 65 87 98 85
+41 24 32 53 93
+
+15 94 72 30 6
+14 80 66 4 78
+44 81 68 67 96
+65 21 64 97 35
+84 90 28 60 2
+
+97 39 61 15 94
+75 14 66 98 31
+58 80 9 64 56
+19 42 16 85 37
+25 22 38 65 82
+
+86 31 71 11 56
+99 12 17 10 46
+ 5 33 85 61 2
+30 1 28 88 66
+15 38 21 54 64
+
+38 52 84 75 91
+77 5 49 71 31
+45 1 60 0 10
+68 29 98 36 34
+61 90 93 14 12
+
+91 66 28 41 78
+89 16 10 77 39
+84 57 44 32 47
+60 62 26 21 50
+75 61 24 54 93
+
+ 2 69 99 8 20
+14 35 61 85 73
+39 94 37 63 12
+57 23 30 50 17
+34 70 19 28 77
+
+50 82 41 59 52
+43 76 85 63 48
+56 67 60 33 45
+42 9 91 23 16
+96 6 34 30 44
+
+ 0 41 24 42 83
+17 1 34 29 71
+46 67 86 64 21
+95 36 6 38 62
+93 8 30 77 44
+
+ 6 94 11 14 83
+65 85 97 37 55
+56 19 91 69 1
+26 59 13 96 68
+ 4 28 7 45 53
+
+96 78 2 32 65
+ 3 63 74 17 4
+76 11 91 48 70
+71 55 69 13 49
+88 30 23 59 10
+
+28 4 34 64 47
+99 86 44 59 43
+50 91 35 92 51
+32 21 19 74 33
+10 29 66 52 94
+
+ 0 27 12 23 71
+54 59 32 47 45
+22 85 94 34 31
+29 68 44 61 62
+96 46 52 33 69
+
+37 79 34 17 56
+26 62 3 77 80
+88 35 71 87 36
+89 60 86 19 48
+82 97 95 85 0
+
+62 49 48 98 10
+89 37 50 64 17
+80 5 26 42 51
+58 74 6 20 14
+72 2 9 40 69
+
+71 37 47 21 39
+36 29 26 82 53
+10 17 96 15 43
+ 8 92 19 6 32
+77 89 38 54 13
+
+16 58 67 23 98
+43 42 26 46 13
+32 22 27 20 21
+37 33 55 86 1
+99 40 17 44 94
+
+81 59 53 27 36
+11 88 92 57 44
+ 2 26 93 94 77
+76 47 82 19 75
+99 34 98 37 32
+
+28 13 57 99 7
+42 93 10 76 43
+ 1 52 3 20 53
+82 81 51 2 92
+94 35 49 37 0
+
+ 5 30 61 77 44
+82 67 98 1 90
+18 62 27 24 15
+16 20 71 69 19
+85 96 25 7 55
+
+39 51 4 32 30
+64 22 29 48 60
+78 31 44 59 92
+65 10 68 84 16
+40 70 35 26 56
+
+54 83 12 79 66
+21 49 70 2 24
+20 51 71 99 50
+82 36 57 96 22
+78 52 67 33 72
+
+ 3 62 5 14 63
+54 75 28 22 51
+ 1 55 86 30 70
+ 9 6 92 83 85
+71 78 96 47 17
+
+71 59 38 27 2
+90 6 97 75 84
+29 69 45 11 65
+46 31 79 4 8
+51 76 74 87 19
+
+83 67 10 39 57
+ 7 63 12 59 2
+54 99 95 88 40
+38 71 84 61 56
+81 90 36 58 19
+
+ 4 47 21 28 46
+22 40 94 83 86
+82 17 43 0 45
+55 36 68 35 84
+52 24 6 80 2
+
+29 16 75 26 87
+ 6 82 67 36 24
+13 95 35 43 40
+80 68 0 79 71
+34 44 21 30 85
+
+91 25 24 15 23
+93 14 50 75 74
+88 30 64 52 8
+ 1 7 0 4 80
+96 82 98 81 67
+
+52 21 71 78 4
+45 73 27 30 56
+ 7 93 67 6 1
+54 20 57 69 2
+94 36 89 46 68
+
+86 95 15 7 18
+ 8 87 29 11 74
+71 72 43 76 40
+ 6 60 44 19 99
+97 85 5 39 77
+
+49 14 5 48 33
+95 21 30 1 47
+87 84 85 10 24
+32 86 99 31 23
+69 2 43 37 60
+
+57 48 99 49 73
+31 92 76 60 96
+47 28 15 70 26
+68 19 56 67 95
+12 23 45 88 6
+
+77 49 23 42 62
+47 7 80 43 4
+59 72 87 14 84
+66 81 96 97 78
+61 91 8 17 48
+
+21 25 1 82 20
+78 31 15 30 73
+46 11 13 35 79
+60 22 97 32 4
+23 88 63 17 75
+
+ 6 3 41 5 44
+91 21 32 49 81
+29 85 47 20 14
+99 31 43 22 69
+90 4 45 8 16
+
+12 15 96 3 21
+38 71 16 39 24
+77 82 57 55 92
+27 17 19 73 31
+74 48 34 72 14
+
+80 16 10 79 55
+93 60 4 0 29
+ 7 97 3 9 86
+43 67 78 64 35
+44 83 40 33 12
+
+36 88 22 21 70
+30 60 13 6 41
+71 89 86 17 39
+73 0 75 32 9
+ 5 10 83 85 99
+
+40 41 76 38 25
+21 49 79 47 39
+27 88 34 81 24
+69 64 36 32 4
+57 5 58 67 56
+
+25 95 41 27 19
+93 0 29 56 8
+ 2 17 66 11 82
+96 55 44 39 5
+67 4 33 62 40
+
+85 12 46 59 36
+91 29 19 63 0
+72 49 14 6 95
+18 50 60 67 80
+10 62 39 82 58
+
+11 87 4 76 75
+64 47 26 74 98
+89 30 68 21 88
+45 41 77 67 53
+96 92 44 1 18
+
+33 26 21 8 76
+15 27 41 43 52
+64 85 56 57 66
+11 73 62 69 4
+36 13 94 86 55
+
+93 80 67 23 6
+57 20 29 69 1
+76 96 72 95 33
+32 91 52 16 83
+26 54 13 94 47
+
+56 0 58 15 45
+91 40 86 61 60
+14 47 30 5 24
+21 12 33 69 41
+78 98 9 99 46
+
+59 1 63 96 14
+15 56 23 85 84
+29 98 44 87 46
+75 8 21 54 65
+80 30 40 45 6
+
+99 40 87 4 63
+64 78 50 74 58
+37 47 61 48 59
+65 56 45 89 67
+18 70 71 90 32
+
+42 35 1 9 90
+89 13 0 88 17
+67 82 31 77 91
+60 29 68 10 64
+20 92 46 71 95
+
+ 0 32 81 13 63
+87 17 2 56 69
+23 33 29 67 24
+98 95 86 36 31
+99 42 35 93 1
+
+71 79 38 84 29
+26 31 73 1 48
+94 85 3 82 89
+19 17 98 92 47
+96 45 11 70 51
+
+14 69 61 56 33
+98 88 82 76 66
+87 92 42 99 35
+ 0 68 6 44 47
+ 4 91 54 62 23
+
+10 23 20 40 96
+33 0 21 94 25
+ 4 67 30 88 54
+43 41 60 1 82
+18 78 74 98 91
+
+60 95 53 7 11
+67 54 44 18 0
+89 98 24 55 37
+39 5 27 62 21
+75 25 43 47 71
+
+ 5 95 60 19 3
+13 15 42 97 67
+61 79 7 12 39
+53 58 89 25 34
+ 9 11 96 21 66
+
+89 97 45 84 67
+37 22 64 39 95
+68 63 6 90 80
+92 26 33 35 19
+29 70 5 72 31
+
+52 46 53 6 31
+77 8 59 99 49
+11 48 4 90 91
+41 70 58 16 44
+ 7 61 9 80 50
+
+75 0 38 37 33
+99 66 98 14 62
+46 51 43 34 24
+71 92 80 32 22
+60 39 17 52 45
+
+92 49 80 99 16
+ 6 77 65 9 4
+34 91 86 43 21
+ 0 3 27 84 81
+28 5 19 95 76
+
+ 5 40 26 89 1
+51 30 75 46 31
+35 58 86 80 0
+98 38 27 81 93
+63 60 39 65 87
+
+27 56 90 44 60
+48 68 47 96 73
+75 13 80 12 38
+81 21 20 46 97
+67 6 72 76 2
+
+33 96 4 55 49
+74 43 54 6 51
+30 0 75 28 62
+90 81 2 83 68
+39 95 70 84 42
+
+97 22 15 30 45
+92 96 50 16 42
+39 23 89 21 2
+72 98 58 48 82
+94 11 1 86 84
+
+41 13 84 51 76
+33 63 0 62 18
+81 32 57 68 21
+20 64 47 24 93
+ 7 56 27 66 30
+
+52 81 85 92 3
+15 91 19 13 93
+36 77 74 37 26
+67 16 73 89 33
+43 90 38 31 29
+
+ 1 52 96 66 86
+30 15 26 82 42
+ 8 94 41 54 5
+84 23 72 77 7
+34 53 18 69 90
+
+ 7 67 35 2 36
+91 51 56 85 32
+98 22 76 97 71
+70 29 68 44 1
+ 8 80 42 46 93
+
+ 4 13 90 64 97
+44 28 17 42 18
+72 77 11 35 22
+25 73 41 1 26
+51 8 92 43 2
+
+ 6 68 51 73 39
+32 60 34 74 18
+ 5 95 11 8 62
+23 3 70 94 54
+36 20 29 10 26
+
+66 80 77 82 62
+95 25 33 50 14
+94 0 91 46 23
+59 47 96 26 15
+69 6 2 34 75
+
+72 66 35 81 69
+48 44 11 16 40
+94 5 3 51 54
+89 6 78 37 59
+76 45 8 18 10
+
+30 46 96 56 69
+66 29 32 74 4
+85 84 99 87 92
+22 50 64 15 57
+78 47 1 48 10
+
+66 48 90 67 23
+ 3 21 73 71 18
+97 52 64 80 94
+49 42 75 47 38
+ 4 28 19 68 57
+
+53 46 56 84 57
+55 45 85 89 76
+80 26 2 36 23
+92 10 30 18 69
+67 49 21 8 44
+
+51 47 85 41 8
+70 34 98 30 16
+82 22 18 95 73
+65 21 49 5 15
+56 19 17 23 46
+
+25 28 47 84 8
+35 90 13 39 15
+50 86 41 33 51
+57 73 87 45 5
+31 22 48 7 27
+
+79 71 64 87 21
+10 73 1 40 9
+36 84 80 6 60
+19 81 55 50 56
+67 23 62 86 63
+
+87 45 56 67 13
+ 8 79 31 48 86
+32 15 88 6 66
+62 27 44 26 99
+64 63 3 70 90
+
+84 87 89 71 2
+63 67 72 3 75
+39 44 54 20 85
+ 1 97 14 37 98
+25 66 92 17 57
+
+27 34 64 60 87
+77 29 21 56 23
+79 53 75 72 69
+95 16 85 52 70
+92 65 62 33 15
+
+42 87 96 79 90
+97 77 58 62 55
+11 86 68 44 52
+93 23 1 61 60
+47 72 14 28 13
+
+14 78 68 48 74
+50 32 29 24 54
+73 99 57 90 64
+12 76 62 15 44
+70 58 22 1 85
+
+49 2 75 88 87
+71 61 95 5 38
+99 86 67 8 83
+17 11 9 54 33
+70 78 62 1 58
+
+11 44 53 73 13
+45 95 15 63 49
+94 34 99 64 10
+78 9 67 12 20
+50 97 96 89 14
+
+55 3 72 93 81
+25 43 60 85 26
+96 45 53 19 40
+73 42 76 47 80
+74 69 22 23 89
+
+24 59 62 91 5
+51 75 76 29 35
+86 96 94 66 55
+87 61 82 40 32
+28 22 27 21 49
+
+66 80 82 46 13
+97 67 41 63 1
+65 89 22 12 15
+94 96 9 91 48
+85 3 60 95 8
+
+57 90 97 56 33
+79 15 75 70 41
+21 26 20 98 81
+18 36 24 76 35
+42 27 11 67 0
+
+89 31 86 10 13
+81 8 16 0 77
+92 67 39 96 74
+90 7 75 55 65
+51 2 97 58 17
+
+92 55 4 83 93
+31 21 74 73 68
+18 41 32 17 77
+56 94 98 72 87
+19 6 49 11 37
+
+15 79 24 60 91
+25 41 63 32 56
+13 83 69 0 57
+77 7 62 45 98
+64 37 94 55 9
+
+81 42 29 98 44
+16 83 27 92 60
+22 63 79 64 45
+80 38 56 5 2
+ 0 4 34 37 59
+
+90 85 32 97 52
+69 37 57 29 51
+22 4 99 67 84
+ 0 2 76 34 47
+63 96 94 83 40
+
+72 68 70 40 39
+22 7 62 46 76
+25 31 41 71 9
+30 52 78 26 10
+53 17 45 16 98
+
+66 39 96 16 67
+46 34 27 49 2
+93 25 50 70 57
+33 69 64 30 45
+10 91 20 18 3
+
+32 35 71 62 43
+24 57 46 39 87
+28 21 26 31 52
+99 60 14 6 97
+ 1 44 89 33 93
+
+47 15 21 23 20
+ 4 50 6 93 44
+38 53 2 45 42
+83 57 63 17 24
+99 5 34 66 0
+
+65 91 60 50 62
+16 2 51 14 32
+81 17 58 59 77
+29 98 72 28 3
+15 99 49 37 5
+
+62 23 48 80 28
+68 2 71 89 36
+13 95 64 98 8
+60 86 51 74 11
+35 27 66 78 7
+
+65 9 57 85 30
+29 52 27 83 98
+ 7 48 45 21 93
+ 5 71 54 34 91
+96 87 25 84 63
+
+38 94 65 69 18
+79 81 80 36 91
+17 2 23 53 98
+92 68 21 74 55
+ 3 58 72 70 86
diff --git a/2021/inputs/day_5.txt b/2021/inputs/day_5.txt
new file mode 100644
index 0000000..4fa6674
--- /dev/null
+++ b/2021/inputs/day_5.txt
@@ -0,0 +1,500 @@
+105,697 -> 287,697
+705,62 -> 517,250
+531,627 -> 531,730
+21,268 -> 417,268
+913,731 -> 271,89
+214,697 -> 82,697
+376,661 -> 376,177
+519,859 -> 977,859
+782,98 -> 184,98
+612,179 -> 515,179
+340,772 -> 352,784
+111,863 -> 111,298
+944,73 -> 594,73
+465,21 -> 970,21
+122,592 -> 111,592
+975,975 -> 16,16
+327,532 -> 561,532
+811,618 -> 811,945
+623,437 -> 623,202
+380,591 -> 871,591
+278,514 -> 125,667
+797,946 -> 953,946
+325,61 -> 484,61
+450,422 -> 450,862
+923,972 -> 119,972
+813,141 -> 69,885
+926,834 -> 926,687
+137,564 -> 595,106
+415,566 -> 274,566
+726,354 -> 251,829
+889,236 -> 470,236
+282,376 -> 282,193
+343,248 -> 932,248
+790,918 -> 790,528
+532,369 -> 222,369
+15,378 -> 820,378
+279,507 -> 279,719
+641,68 -> 220,68
+340,270 -> 340,680
+939,364 -> 32,364
+686,106 -> 568,106
+919,365 -> 255,365
+870,236 -> 879,227
+322,397 -> 397,322
+984,980 -> 350,980
+392,864 -> 31,864
+846,975 -> 243,372
+253,981 -> 500,734
+98,193 -> 280,11
+477,460 -> 350,460
+690,833 -> 48,191
+469,409 -> 218,409
+321,532 -> 321,106
+868,341 -> 223,986
+185,174 -> 801,790
+256,658 -> 800,658
+808,576 -> 931,576
+959,913 -> 959,785
+976,969 -> 47,40
+891,931 -> 572,612
+600,804 -> 866,804
+149,368 -> 680,899
+799,882 -> 157,882
+803,214 -> 803,668
+53,900 -> 940,13
+424,800 -> 424,261
+985,924 -> 80,19
+158,194 -> 158,281
+683,237 -> 683,341
+493,482 -> 493,921
+664,195 -> 664,824
+689,405 -> 616,478
+946,873 -> 846,873
+977,988 -> 28,39
+305,892 -> 662,892
+891,27 -> 891,440
+136,897 -> 35,897
+948,458 -> 935,458
+569,100 -> 599,100
+542,292 -> 974,724
+501,825 -> 104,428
+875,872 -> 875,441
+631,924 -> 43,336
+874,846 -> 874,389
+947,932 -> 81,66
+75,480 -> 75,403
+211,622 -> 211,482
+344,904 -> 699,549
+227,508 -> 698,508
+677,774 -> 385,774
+279,267 -> 391,155
+294,801 -> 547,801
+717,446 -> 614,549
+490,903 -> 490,225
+872,751 -> 278,751
+580,163 -> 61,163
+198,800 -> 389,800
+147,728 -> 516,728
+675,417 -> 675,752
+147,544 -> 134,544
+977,70 -> 164,883
+349,976 -> 349,23
+897,10 -> 14,893
+602,349 -> 602,354
+326,332 -> 355,332
+53,331 -> 34,331
+617,333 -> 466,333
+661,537 -> 661,131
+985,18 -> 20,983
+953,580 -> 953,124
+70,363 -> 74,363
+448,38 -> 141,38
+957,175 -> 957,634
+88,316 -> 88,899
+231,94 -> 857,720
+643,566 -> 643,832
+724,955 -> 243,474
+368,521 -> 537,521
+649,245 -> 406,245
+92,304 -> 399,304
+978,491 -> 819,491
+99,637 -> 765,637
+243,159 -> 803,719
+139,756 -> 305,756
+815,226 -> 79,962
+317,562 -> 491,562
+783,95 -> 783,277
+207,321 -> 133,321
+752,136 -> 185,703
+752,990 -> 752,433
+282,841 -> 466,841
+314,31 -> 314,829
+637,873 -> 637,854
+60,746 -> 563,243
+646,566 -> 119,39
+260,475 -> 124,339
+603,647 -> 327,647
+990,202 -> 342,202
+981,620 -> 606,620
+475,352 -> 313,352
+184,497 -> 143,497
+130,929 -> 329,929
+779,111 -> 779,975
+892,960 -> 11,79
+37,984 -> 919,102
+589,794 -> 589,548
+665,668 -> 385,668
+668,301 -> 281,301
+860,122 -> 623,122
+18,914 -> 782,150
+691,150 -> 25,150
+117,439 -> 462,439
+926,695 -> 926,651
+907,644 -> 708,644
+545,120 -> 229,120
+181,659 -> 181,820
+362,543 -> 575,330
+603,531 -> 603,142
+754,404 -> 754,678
+703,551 -> 450,551
+794,137 -> 581,137
+866,288 -> 327,827
+676,613 -> 676,470
+874,130 -> 23,981
+132,288 -> 360,288
+706,147 -> 706,433
+734,646 -> 588,500
+641,386 -> 598,343
+743,726 -> 79,62
+308,192 -> 859,192
+858,125 -> 603,125
+694,199 -> 653,240
+251,407 -> 79,407
+254,337 -> 254,310
+586,850 -> 17,281
+937,989 -> 17,69
+503,784 -> 584,784
+17,97 -> 906,986
+909,987 -> 23,101
+11,465 -> 953,465
+645,862 -> 251,862
+741,488 -> 856,488
+488,123 -> 488,641
+720,775 -> 79,775
+228,105 -> 702,105
+344,804 -> 873,275
+953,848 -> 669,564
+188,76 -> 524,76
+473,852 -> 137,852
+515,14 -> 515,183
+362,654 -> 362,335
+76,73 -> 969,966
+987,743 -> 468,743
+912,28 -> 912,31
+464,247 -> 380,331
+171,20 -> 171,863
+855,653 -> 855,941
+505,415 -> 505,808
+947,543 -> 947,821
+907,365 -> 726,365
+475,563 -> 475,63
+927,679 -> 773,679
+938,77 -> 26,989
+345,909 -> 299,909
+46,22 -> 972,948
+197,735 -> 288,735
+552,748 -> 756,952
+946,180 -> 946,695
+956,779 -> 216,779
+120,105 -> 950,935
+924,902 -> 35,13
+530,49 -> 451,128
+491,693 -> 340,693
+533,774 -> 623,864
+177,618 -> 177,123
+543,114 -> 637,114
+503,585 -> 344,585
+34,836 -> 34,625
+618,802 -> 212,396
+863,678 -> 349,678
+26,850 -> 768,108
+99,67 -> 988,956
+11,902 -> 871,42
+658,749 -> 507,900
+967,178 -> 218,927
+671,247 -> 671,525
+421,985 -> 541,865
+279,639 -> 754,164
+627,747 -> 627,290
+77,66 -> 977,966
+177,282 -> 617,722
+400,444 -> 451,393
+540,152 -> 540,888
+521,196 -> 36,196
+32,590 -> 32,537
+145,613 -> 279,747
+45,428 -> 45,12
+785,956 -> 785,728
+205,507 -> 205,539
+117,12 -> 117,221
+395,17 -> 479,17
+104,881 -> 933,52
+918,716 -> 570,716
+121,621 -> 937,621
+516,773 -> 516,917
+311,605 -> 311,168
+611,185 -> 611,976
+373,80 -> 373,295
+987,295 -> 515,295
+416,717 -> 416,121
+251,508 -> 196,453
+498,824 -> 428,754
+956,818 -> 153,15
+266,272 -> 266,748
+769,312 -> 769,387
+604,766 -> 184,766
+656,934 -> 520,934
+224,771 -> 162,771
+588,395 -> 133,395
+219,489 -> 219,948
+67,42 -> 979,954
+684,109 -> 920,345
+168,895 -> 762,301
+761,953 -> 59,953
+583,408 -> 592,399
+129,48 -> 931,48
+694,76 -> 404,76
+808,380 -> 808,886
+643,165 -> 643,757
+714,543 -> 714,913
+258,550 -> 295,550
+400,857 -> 400,38
+267,573 -> 267,779
+124,182 -> 255,51
+399,981 -> 552,981
+197,803 -> 197,275
+791,706 -> 791,373
+500,664 -> 924,664
+177,171 -> 177,935
+703,43 -> 696,43
+265,849 -> 889,225
+847,324 -> 661,324
+369,965 -> 369,780
+169,965 -> 935,199
+742,540 -> 742,355
+210,854 -> 204,854
+58,281 -> 954,281
+858,793 -> 666,793
+276,156 -> 733,613
+537,538 -> 80,81
+985,10 -> 14,981
+79,31 -> 692,644
+77,41 -> 77,502
+684,150 -> 17,817
+295,785 -> 920,785
+171,579 -> 171,16
+763,754 -> 763,86
+719,573 -> 719,71
+183,708 -> 227,708
+826,952 -> 835,952
+124,914 -> 975,63
+807,704 -> 653,704
+140,468 -> 140,874
+408,330 -> 408,291
+501,958 -> 501,302
+834,505 -> 686,357
+267,76 -> 267,526
+18,88 -> 863,933
+147,188 -> 147,454
+922,733 -> 277,733
+509,259 -> 957,259
+614,765 -> 238,765
+77,54 -> 77,252
+591,532 -> 591,384
+539,574 -> 729,384
+347,158 -> 347,10
+389,988 -> 989,988
+696,571 -> 662,605
+656,207 -> 656,883
+802,446 -> 802,693
+121,35 -> 121,66
+967,738 -> 949,738
+12,86 -> 809,883
+96,167 -> 758,829
+790,42 -> 790,549
+14,987 -> 986,15
+363,689 -> 363,386
+148,148 -> 807,807
+891,899 -> 891,710
+445,678 -> 445,464
+649,426 -> 649,452
+641,378 -> 967,378
+580,220 -> 300,220
+376,789 -> 376,572
+770,551 -> 647,428
+651,692 -> 399,692
+432,385 -> 432,835
+242,48 -> 512,48
+955,612 -> 955,520
+926,568 -> 938,556
+626,836 -> 626,266
+973,982 -> 39,48
+64,32 -> 64,653
+503,444 -> 641,444
+593,306 -> 11,888
+287,138 -> 287,891
+529,886 -> 529,826
+217,320 -> 217,875
+11,988 -> 989,10
+291,30 -> 488,30
+864,945 -> 113,194
+550,501 -> 550,89
+269,474 -> 269,40
+953,394 -> 908,394
+451,983 -> 451,293
+135,121 -> 455,121
+30,35 -> 915,920
+31,451 -> 31,936
+300,715 -> 42,973
+577,459 -> 577,700
+291,539 -> 456,539
+373,449 -> 855,449
+222,136 -> 358,136
+206,14 -> 206,211
+977,577 -> 977,535
+183,723 -> 183,900
+888,905 -> 821,905
+51,301 -> 388,301
+859,594 -> 859,227
+767,343 -> 767,472
+36,897 -> 565,897
+450,481 -> 855,481
+137,401 -> 137,643
+771,276 -> 771,61
+767,144 -> 767,562
+212,111 -> 978,877
+841,117 -> 234,724
+975,104 -> 263,104
+839,408 -> 839,588
+122,50 -> 911,839
+748,208 -> 748,929
+230,305 -> 645,305
+107,324 -> 175,256
+726,339 -> 726,968
+780,127 -> 664,11
+392,148 -> 392,133
+228,607 -> 228,689
+469,379 -> 739,379
+797,851 -> 841,895
+896,494 -> 896,568
+351,950 -> 566,950
+593,387 -> 492,488
+939,664 -> 843,664
+463,159 -> 197,159
+164,265 -> 164,16
+164,147 -> 510,493
+989,988 -> 11,10
+98,676 -> 693,676
+118,384 -> 118,544
+220,502 -> 220,593
+530,437 -> 802,437
+321,29 -> 321,819
+438,118 -> 438,531
+268,128 -> 802,128
+602,770 -> 602,183
+841,58 -> 846,63
+582,371 -> 592,361
+174,163 -> 296,163
+927,268 -> 927,391
+579,280 -> 12,847
+52,951 -> 52,772
+645,203 -> 985,203
+725,119 -> 725,367
+155,112 -> 779,736
+988,44 -> 320,712
+438,463 -> 914,463
+193,948 -> 292,948
+217,398 -> 638,398
+70,553 -> 465,158
+271,262 -> 867,262
+964,576 -> 442,54
+253,67 -> 972,67
+537,507 -> 290,260
+537,645 -> 213,321
+366,130 -> 913,677
+834,283 -> 834,523
+858,825 -> 858,391
+146,60 -> 146,701
+865,909 -> 162,206
+503,628 -> 326,628
+49,101 -> 583,101
+692,17 -> 692,218
+704,744 -> 210,744
+144,434 -> 587,434
+630,393 -> 630,870
+606,616 -> 606,330
+41,83 -> 916,958
+80,341 -> 706,967
+426,683 -> 426,173
+919,962 -> 499,962
+442,49 -> 442,970
+740,378 -> 498,378
+563,196 -> 563,442
+222,76 -> 614,76
+398,451 -> 851,451
+62,50 -> 243,50
+775,114 -> 775,234
+650,901 -> 650,195
+164,10 -> 164,149
+127,751 -> 67,751
+122,674 -> 780,674
+325,652 -> 70,652
+944,908 -> 99,63
+40,985 -> 977,48
+946,21 -> 126,841
+872,906 -> 872,136
+365,288 -> 827,750
+348,935 -> 244,935
+371,963 -> 499,963
+816,595 -> 392,171
+953,673 -> 953,585
+223,612 -> 223,362
+327,423 -> 553,649
+661,693 -> 258,693
+10,838 -> 10,859
+985,814 -> 985,25
+331,529 -> 87,529
+611,460 -> 355,460
+928,426 -> 748,426
+540,172 -> 365,347
+57,45 -> 57,129
+20,861 -> 628,253
+460,474 -> 297,311
+549,876 -> 131,876
+748,197 -> 287,658
+639,137 -> 741,137
+917,35 -> 917,273
+482,333 -> 975,826
+176,817 -> 89,730
+894,418 -> 806,418
+555,227 -> 349,433
+317,33 -> 432,148
+93,988 -> 93,479
+635,300 -> 870,300
+301,437 -> 301,760
+660,548 -> 660,909
+696,18 -> 60,18
+231,787 -> 165,787
+500,242 -> 371,242
+88,126 -> 405,126
+983,941 -> 61,19
+242,519 -> 242,489
+519,957 -> 926,550
+606,181 -> 606,432
+873,216 -> 851,194
+880,924 -> 880,844
+321,119 -> 801,599
+963,392 -> 726,155
+190,655 -> 190,305
+542,676 -> 542,819
diff --git a/2021/inputs/day_6.txt b/2021/inputs/day_6.txt
new file mode 100644
index 0000000..4b2dc63
--- /dev/null
+++ b/2021/inputs/day_6.txt
@@ -0,0 +1 @@
+4,3,4,5,2,1,1,5,5,3,3,1,5,1,4,2,2,3,1,5,1,4,1,2,3,4,1,4,1,5,2,1,1,3,3,5,1,1,1,1,4,5,1,2,1,2,1,1,1,5,3,3,1,1,1,1,2,4,2,1,2,3,2,5,3,5,3,1,5,4,5,4,4,4,1,1,2,1,3,1,1,4,2,1,2,1,2,5,4,2,4,2,2,4,2,2,5,1,2,1,2,1,4,4,4,3,2,1,2,4,3,5,1,1,3,4,2,3,3,5,3,1,4,1,1,1,1,2,3,2,1,1,5,5,1,5,2,1,4,4,4,3,2,2,1,2,1,5,1,4,4,1,1,4,1,4,2,4,3,1,4,1,4,2,1,5,1,1,1,3,2,4,1,1,4,1,4,3,1,5,3,3,3,4,1,1,3,1,3,4,1,4,5,1,4,1,2,2,1,3,3,5,3,2,5,1,1,5,1,5,1,4,4,3,1,5,5,2,2,4,1,1,2,1,2,1,4,3,5,5,2,3,4,1,4,2,4,4,1,4,1,1,4,2,4,1,2,1,1,1,1,1,1,3,1,3,3,1,1,1,1,3,2,3,5,4,2,4,3,1,5,3,1,1,1,2,1,4,4,5,1,5,1,1,1,2,2,4,1,4,5,2,4,5,2,2,2,5,4,4
diff --git a/2021/inputs/day_7.txt b/2021/inputs/day_7.txt
new file mode 100644
index 0000000..84d7622
--- /dev/null
+++ b/2021/inputs/day_7.txt
@@ -0,0 +1 @@
+1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,1304,510,261,432,1,767,525,1663,1598,125,84,924,216,1049,365,4,21,226,131,178,666,1134,58,839,1065,670,419,11,297,28,80,258,811,659,1288,21,17,436,1184,823,667,7,499,249,406,157,112,715,220,93,710,148,152,1192,15,493,1551,473,760,503,177,124,123,236,848,221,658,771,347,23,264,739,1583,747,17,336,998,159,679,119,2,160,412,873,1480,337,92,369,136,3,188,683,496,214,131,330,493,649,136,503,249,342,240,728,494,150,25,146,95,1328,401,580,743,385,85,1011,466,36,228,1394,77,1009,46,751,782,1501,464,1046,4,317,1566,1661,822,107,487,208,727,53,55,355,370,1319,16,18,965,1582,190,38,386,169,766,111,262,229,248,318,368,70,18,302,87,218,404,265,2,109,62,557,714,1174,429,1082,786,37,470,195,408,598,935,1224,11,83,318,475,354,342,699,209,372,942,801,30,1065,4,110,969,449,266,50,314,771,890,314,394,316,211,1238,84,574,120,698,1382,1039,670,121,281,241,491,742,802,194,41,573,473,824,1283,59,371,1167,32,1645,115,58,845,11,408,1284,414,1618,240,364,991,111,517,146,256,616,968,130,98,414,13,152,332,96,816,366,214,69,1072,1225,98,122,554,236,14,499,89,793,119,945,511,476,112,1201,501,9,23,517,277,283,1600,581,290,248,472,38,144,178,645,477,1016,139,123,4,671,370,1025,290,20,1680,856,212,44,93,656,1163,384,852,461,1248,79,341,1125,812,746,511,1461,420,1070,22,126,274,1698,526,949,20,865,66,1244,157,275,670,384,1142,696,43,74,344,893,237,327,135,272,690,1032,395,1,16,521,1573,304,512,466,243,171,913,323,325,82,16,462,457,1609,24,98,22,528,158,79,1012,60,146,58,504,503,1,42,78,164,3,439,653,217,251,94,584,333,435,254,170,1213,671,548,799,332,434,487,61,710,136,551,556,722,316,365,1403,115,104,597,137,881,577,1334,41,649,177,196,434,191,101,248,14,71,1053,44,1074,51,607,65,161,922,235,132,247,1412,500,1409,15,86,72,327,878,507,1379,454,109,1250,184,19,284,1057,353,476,807,577,305,466,40,136,16,883,516,253,150,125,49,102,404,1606,518,94,1042,204,443,444,22,1197,168,766,1466,1053,695,565,77,406,694,102,84,414,686,800,157,7,516,440,139,1538,144,1327,851,1526,69,315,1078,678,247,1579,100,254,947,758,603,44,535,1242,1117,1119,645,203,97,88,437,886,408,566,351,36,0,461,1098,415,1381,1217,1763,202,1106,466,30,237,757,313,390,38,344,1254,1275,343,278,1064,1116,70,279,276,214,1153,306,67,488,683,432,53,128,91,1082,403,117,1169,568,60,578,475,657,43,509,434,128,1115,872,333,73,954,789,590,185,1305,352,574,266,1634,731,156,562,247,356,743,689,298,637,1125,590,761,123,1508,33,0,558,146,888,236,668,53,94,619,591,422,44,1114,1284,806,39,816,47,59,76,1090,1102,7,1307,676,1161,473,376,175,224,431,284,875,86,28,99,700,459,204,673,1001,31,302,291,386,259,4,181,1048,274,1661,347,614,760,187,1118,196,1076,219,1194,226,909,189,208,265,601,503,693,213,16,63,25,108,133,979,56,195,250,294,920,231,435,1004,352,469,55,1374,605,72,714,534,504,1411,128,724,1216,7,317,948,285,668,320,97,316,298,145,605,40,486,324,399,336,612,386,328,631,44,366,103,109,219,530,39,654,341,132,1090,50,15,654,801,791,169,746,1512,660,383,67,762,46,236,184,51,1051,1161,347,673,554,523,3,463,31,132,258,413,18,293,986,699,608,289,175,70,217,136,857,473,585,14,636,189,119,128,129,358,560,580,425,236,1194,1182,213,79,36,162,200,179,170,892,1398,336,1073,76,798,231,58,216,1134,175,392,688,342,28,300,672,1160,501,44,79,357,1411,856,27,471,600,303,35,546,1466,74,359,234,1200,657,224,431,802,0,584,784,1245,15,776,28,1464,191,275,639,569,179,908,173,1041,630,907,1520,248,1,34,596,53,44,9,782,777,295,818,1295,1115,468,34,530,349,271,99,344,923,733,124,170,208,20,744,530,582,35,58,938,721,253,934,326,528,722,123,0,623,382,889,929,454,457,1024,43,293,521,548,291,654,506,307,1031,1,390,321,727,937,1000,57,52,136,69,920,19,269,950,578,119,207,14,244,274,171,971,548,335,748,553,196,531
diff --git a/2021/inputs/day_8.txt b/2021/inputs/day_8.txt
new file mode 100644
index 0000000..05a40c6
--- /dev/null
+++ b/2021/inputs/day_8.txt
@@ -0,0 +1,200 @@
+cgdf eagcbf fc adefg eacdb fbedga geafcd efc dacfe fdgaecb | dcefbag dgcf fc daefc
+bdecf dcagb gbf gcbdf deacbf fg fdebgc fegdcba dgef bgefac | dbfec gbacefd gf bfg
+cfeag becgda bag ab abcd ecgdb gdefba agcbe gdcebf fgebadc | ab cdegbf cbda cgfebad
+gc bcfgea ebdcf cbedg edbfac ebfdgc bacfged ceg dfcg abdeg | eacbdf geabd dcbef fcgebd
+fgbceda afdbge fbcad badgec cfde gfcba ebcda afd abfdce df | fad fdcab fda befcadg
+gfacd dcf bacedg afgec afdbec df agcdb agcdebf gfbd cdgbfa | df df bceagd ecafg
+gbdfe ag gda bfadcg gbedfa gdefcb beag gedaf cdaef bdgcfea | gacfdb gedfab ga gda
+deabg cag cfdea bfgcda ecgb fcbedga cg dcage agebdc gdbfea | bacefdg bdcgfa adcgfb afedc
+agfecbd gbcadf ce defc dabcfe fgeab gbdcae ecb fcabd bcafe | ebafcd ce ceb ce
+fa adfebc gdacef bfeca begca bfad bdfce febcagd dfgceb fea | afe cfdgbe af eabfc
+abge eb efbgadc cadeg cabefd gbced cgdfb abegdc acfged bce | dgeac ebdagc edagc gacbfde
+cfbedg gdafbe fgebd bc cbgdae bcagfed ecgfa bcfge bgc bdcf | gafebdc bgfdce bcfged dfgbe
+cafebgd gafdc bgcef bcagf fba cabefd ba baeg feabgc bdfcge | fba ab ab gaeb
+ecgfbda afbeg fcdeg fecbga cea afbc abdegc befagd ac gcaef | beadgc eca cae gebacfd
+cedag gf afbcd cbaedgf eacbdg acfegb fcadg fgedac gfed fgc | dacbf daecgb bagcef cgf
+fagbd gdaceb ebf efbad gacebf fcde ef ceabdf aecgbfd dbeac | dbeac bagfd cbfdae fbe
+begadcf aedb cgefa ebdgac acfdbg cdebfg agebc ba bac gdbce | ab faceg bac adbe
+bgde gb abefcg fdaecg gcbdf ebdgafc dfgce gfebdc cgb acfdb | fdbcg gb dcegaf cfdge
+efbagd gefcdb dgbefca badce cegdb efdgb gfcbae cge dcgf cg | dbeca bdaec ecg egc
+begdca caef gfebd cgbefda cgf cf gdecf cfagde cagbfd agdce | dgfcbea fcae abcfgd acdgbf
+cadfbeg acd egbad dcbf efcab cd agfbce daebc gefdac afbced | bdefacg cd abgfec dgecfa
+fd bfd bgcfd bagcfe edgf fcbge acbdg cdebgf efbadc bgeacdf | df bdcga fbd gbedfc
+fdgbca deca de edagbc ebadg gbfea bcgda bcdegf dge gcebadf | abgcfde de gdeba acde
+df gdbecaf bdfe fbcgae fedabg fdaegc cgdba fdg adbgf egbfa | gdf fbgaec egafb gadbf
+egfbd cefg gfdbac fbdea bedcg gadcfeb gdefbc gf bfg adgcbe | dfebg dbacfg gcafdb dbafe
+bgadc bacfdg acbdge egafdcb ea deca cfbaeg eab dabeg fgbde | aecd bdcag dgeacb bafdecg
+cfbeag febcgad cge dacbg facdbg ge gcbde eadg acbgde fcbed | cagbed gcabfe gdcfbae bdgec
+cgefa eabf gbedc gcefb cdbfaeg dfabgc fb beacgf gfb gfedac | bf afceg bfg fgaec
+fdg gd edfcbg gaed gfcda febcga ecdafg cgfebad fgcae dfcab | cafegd cedbagf gfcea aecgfb
+dcafbe ebcadfg adcgbf abfcd bg fdaeg agfdb gcba bgd efbgdc | cgab ecbdgf agdbf efcbgd
+adcbf dagfcb dfecb dagc feadbg ad bgacf cegdbfa bad gcafbe | cfdbage deafcbg fcagdb cedgbfa
+afbecg fe egdcf gef afde acdegf feadgbc fdbgca gdceb fgdac | edcbg edafgcb afgcdb dbgce
+gbdfc aecdgb ef bfe acdbe aefc fceadb bcaefgd agbefd bfced | fbe gcbdf fcea adbec
+fcgae ebcfa becdagf fgadcb cba bfdea bedc ebacdf bfgead bc | egbfadc cb cb caefg
+efbd abcde cfeag aecbdg daf df eafcd gcafbd fdeabc cgbefad | gbefadc fecga cgfae acdbe
+afegbc becaf gaf fcagbd egbf adbcef gafec aedcg afdcegb gf | bcfae efacb bcaef fga
+gf bgecdf gaebfdc fdcbg fdg ebfg agcdb cfdbe febacd efcgda | fdcbe gbcdf bcdga cgafde
+fdebac dgac dfega dec feadbcg fdcgea cefgb dfaegb egcdf dc | decgf gdca ecd cfgaebd
+fabdgc dceab dbfgc dagfeb begdfc bdgca dabfcge dga ga facg | gfacdb adgcbef bgedaf facg
+cfeag cgdfa aegb fecdgb dfacbe dcgbfae ebfca ge egc gcbafe | ebgfdca aebg gcebfd cbfea
+dcafg edcgba afebd faedbgc bgef edafbc fabdg bgefad dbg bg | ebdagc abgefd afcebd bfeadc
+dfbgce efcbg efgbac fcbea abdfgce fecad bgac fba ba dfaebg | cafdgeb bcag adcef ab
+acfb bec fabged gbeafc ecgabd fecdg gabfe bc cbgef gcbeadf | cbaf bafcdge baegf fagbde
+fgebcad cgadfe agbdcf gfadc edfcg badefc efag ef gdbec efd | dcfeg becdfa bdecg bgdec
+bafdgc fdcegba deafb dcbfe abf gedfa ab ecab cbaedf fecdbg | aecb ba baf dbefc
+bgfeca cadeg adfgc gea ae bcdagef edba abdceg gbdec fcebdg | dcgefab efcbag fcdag beda
+fcag afecbg cabdge dbefa cef ecbgfda begdcf fceba fc gbaec | gfca bdcegf cfe aebcfdg
+cfbga df bgaed dgef eafdgbc cdabfe bdecag adgefb dfa agbdf | fd gdfe df df
+edagfb cdfbaeg aecd gcbad dcgbef dbeagc da dcegb dab fgcba | cdae ecad abgdfec cfgab
+ebc agbcfe eb bdfcag decgbaf agecd egdbfc egacb afeb bacgf | ebc cbe abfe fegbcd
+dcefabg bfaed feg ebgfa eg egad cgdebf cgfab degbfa acdefb | edbfgca cdfaeb gfe feg
+adfebc dbgce ecfdgb ba daegb beadgc dfgea dcegfab agcb aeb | cagb acebfdg cbga eafgbcd
+afcbged gfdbc cd bdc edgfbc befacg edcf abdceg dgbfa cfegb | gfcdb gebcf bcd fdce
+gbfceda bf bfd cedgf fgdeb gfab befgad gcebda debacf gbade | gfdbe fdebag adegfb gdeba
+eacd cdegafb bac gbedcf gcebd afgdb ca gadbc gdcbae eabfgc | becgd fcbgea aedc edac
+bagd bfgac adbfc aefcg gcbfad cadfbe dgecfb gfb gb gefdabc | fbg dcegabf bgad bdcfa
+bfaedg bfcga cdgfe fcdgba gabcfe eacb debfcag eb fbe gcefb | bef efdcbag cbfaegd ebca
+afcebg dbfag dabe dgbef cebfgd gdafc egadbcf ba abg afdgbe | bga bga gab ba
+ecdabg defgc bdacgf dae eadcg cdbag gcbdafe aecb adebgf ea | bfedagc adcbg eagdc bdgeaf
+acgde bcdea bfcd bface becfad afdcgeb dfaebg bd adb cfgeba | eacdb cbgefa fabcge bcdea
+gecfad fbcegd dbfaceg fgabe dge gfbed fbdgca gdfcb bdec ed | gdbfec egd eagbf gadcfe
+dagfe cbafdge bag dgebcf cfab dafcgb adgbf ab fgdcb geacdb | gacfdb fgbcd gafdb afbc
+afecbdg bdc adefb eabdcg fcged bfdce bfgead bdafce bc bfca | dbcega bc dabgefc fcba
+cdgafb bafcge fb bdfg dagcb cbgafed fcdba cedfa cbdgea fba | deacf dbecga fdbacg gabfdc
+dcf bcadf ebgdfa bcadgf bedac fc dfcbeg beadfcg afgbd fagc | dcf bgdfa cbgdfe agebdcf
+gadbf egdba gfdeca aeg cegdb gdbcfa faeb ae gdaefcb gebfda | ebdag eafb baged ae
+ebfgc daeb cae gceba cgabfde cgabdf ea abcgd bdaecg ecgadf | ace eagbcfd ea efacgd
+bdeaf ag bgdeca dag agfdb agcf dcgbf cfgbeda dfcbeg cdagbf | fbaed fgdabce beacdg ecabdfg
+ecagf gcfdea ba gbfa badgce cab abfce fecdb bagcfe bafegcd | faecdg ab bedcf edcfb
+geadf adgebf eda cdgfab bedg bfadec de gefbdca adfbg gafce | ecagfbd cafge de eda
+fb agcbe gbfc cbaegd ecgfdab edafg bdcefa efgba bfa gabecf | bfa fcbade gceab fba
+bdaefcg dgacfe fbgadc gfbea dcae aegdf ad gcdfe bgdcef dga | cdae da cade gdfcae
+cbeg eacfg fbcage acfdge bgeafd gbfacde afcgb bga gb cbdfa | bg gabfde gba fdagbe
+bca defgab bc gfcae gaebd dfebac bcage deafgcb gcebda cgbd | edbgfa cb gfcea cb
+fcb cgadfeb bcagf abdgf cegdfa begcaf gcbe fcebda cafeg cb | cfeadbg cfb dfbga gdaecf
+fdebag abdcge gfdb efbac gcefad eagfb agb degaf bg acfegbd | agefbdc gfdb gb bedafg
+ec dce cgbaed egabdf dbeacf cagdf ebcg agcde gbedacf eagbd | bafecd eadgbc cdgfa degac
+beg fageb bfgad ge abecf bdcfae caeg efadgbc egbfdc cgebaf | dfabg fabgd fbdceg beg
+gdcfe bacfeg dfb db cfbdae bade aegfcdb fbecd bagdfc fceab | cbagfe bd bd bd
+gab cagdfb fgecdb fgaed ab gcbdf baecgd abcdfge gbfad bacf | gbdfca gab bgdcea abg
+ecfga afdbeg gdceafb gcedf ecgabf afc dcgfab ca bcae gbaef | cgeadbf fagec cfa aebfdcg
+fgaebc aefcdg fdceb dfbeg gbf agefbd fegdbac bdga bg fgdae | bcdfe fgb acfgbe gdab
+dgaecf fadbgc cdfeab cagbe cbd bd bdeac gadbfce afced bdfe | gfdace febd db cgfade
+bfdgac efgdab abd edcbf baeg ab afegd dagecf cgbfdae edbfa | gdaef dbefc dab ba
+acgb bda gdaefb eabcfdg ba abced gdcbe dacef gcdeab bcdefg | adefc bcade deagcb adb
+fgabc cdfabg cga dgcfeb deagbc ag fgda dcfagbe caefb fgbdc | dagfbec bfacg gfdbac edgcab
+gcfdeb fbgdca beagf fgbad ecfba efg egbfacd ge daeg defgba | fcbgade fbgae fbcae adgbfe
+abe dgab defca dbeacg ba fgbdce cbdeg bfceag cebagdf eadcb | bgda dfgbce dfegbc gbcfaed
+cbafg efdgcb cfaebg afecb aefg gafcdeb ecf ef becda fdgcab | cafgeb acgbf acebgf dcbfag
+eb cebg dbe dceab dcbage ecgadf gcaed cbfda agbdef gadefcb | agebdc baedc dacfb gcebda
+degcb cagbef dfceba gbf fg gbacdf gfeacdb fbgec fgae ebafc | bfcdga bfg fbaec fbg
+dbgaf bca gacde cefbga acebgd edcb gbacd fbcagde cb cdefga | gcdea fgcebad cab cdebfga
+bdgfea gb fcdeg gfcdae ecgfbd cdgb egcfb ebafdcg befca gbf | gb dagebcf dgfec dfgcbe
+geacb fg badfc dagecfb bfcgad gfb fcbga gcdf efadbg befadc | dfbgcae badgcf dcbfa aebcg
+febdc aecfd aebgfd gcdfbe dbgcf bef adbfcg dbefacg gbce be | feb eb ebdcf dceaf
+acde cdegb decfbga gebac eag cegfbd ea cdbgea ebgafd cbagf | ae gea bgdafe cagbe
+gefac egbfadc degbfa badgce gef fe efgbac agecb fcdag bfec | afdegb adbecg agbcde agfce
+gfceb bg edcbf afcegd gacb fagec fegdbca gbaefc fgb edgafb | bgf agcb eagcf facged
+bdcagef dcfbg ceafd bead adfcb fgeadc cba cefbga ba cfdeba | gcabfed decfag ecgdfa fgbdc
+cdbfge bfgac efgad cbae daegbcf fgaecb ebg begfa be gdacbf | eb be efbga adefg
+gfabd bgaed gf cebfga fgb eafcbdg degf aegfbd acdfb gdbeac | abged aebdfg bfgeca bdagec
+gcafd efagcd edcg bafdeg bfgdeac ebcgaf gd facdb dgf efagc | fbadc fbcda cbeafg cdebgfa
+dfeba cfb dbcgef dbceafg efgca cbeaf fecdag fbgcea bc gacb | aebcf fcb adgfce fcbea
+badgf agdcef dafbec ag gabe dfeab dgfeab bdgaefc gfa gdbfc | eadfb dcefag cafdebg edfagc
+bef eb abec fabgec facbdg afbcg defbag dcfge fcbge deafgbc | cgebaf eacb dcagbf bfcga
+bdfe dgebcf bcgefa ed cbeadg gefdcba fbceg dcgfe facdg dge | dcfge de cgdabe dge
+gbadc dgbefac cgbafd dfcg dfacb ecgabf cg gcb bcfdae bedag | cbdga cdbag gdabfc bdeag
+bagecd cf fbedcg cefa cafbd bfc cbedfa gafbd baecfgd caedb | gfdebc cdeab cfae cfb
+fgdab efbacd decb cgaefb dbcaf acfdge fbc fdaec edgabcf cb | edbc bc fgecab cfgade
+dcbga adfbc df decfab fbed cfeba afd egfcadb dcaegf befcga | ebfd bgafec aebcgf ebdf
+cbdaegf fdegcb cgbd dafecg dbfgae dfbce gdfec bdf bd eafcb | cbdg dcgb gdfaec ecabfdg
+bgfade bdeagc befcd daecgfb efb abecd eacbfd gdcbf cfae ef | cfea ecdba agdcbfe gbaefcd
+fagd dcafbe gdabfec df bgcfe cgfdba bgadce agdbc fbd gbcdf | bgcdf df edbcfag df
+gfceb ae eac adbegfc gadcef dcbfge afceb adcbf gfbeca ageb | cbegfa cfdab ae ae
+adgeb fcbdg fbdgec cbged ecb ce efgabc dgefcab bfcgad dcfe | abdegfc fgbcae cdbfag gfdbc
+dfbegc cb dgeac afedbg cebf ebacdfg dfegb gdbce cbg fgbdca | efagdb gdbecf dbgec bacgfd
+fdcgabe adfceg fegbcd bg cdefg bfg cegfb ebfca bfagcd edgb | gbf dbge fcedg gb
+dgefc cdaef cbafgd dbgecaf egfb bcegfd gabced eg bdfgc gde | acgdbf bedgac dfgce adcef
+fgeac dgbfeca gaecdf cb bcegfa cgbf ebc cdageb defba ecbaf | fbace ecb gface gbecad
+abedfg cdefb gfb egafd bg ecagfd gbfde agcfbe bdga dgceafb | fbg efgbd bfg bdfce
+gbfcde fb ebdga faced bfca eadfgc adbcef eabdf gedfabc bef | bfca bf bdefa fb
+fbgadec gcbe bfgca cg bacfde egfdca cag afbec gadbf cagbfe | gbecafd bacdfe cga egcb
+cfead fcdbge ebf bace eafdcg bagdf fgbecad be eadfb fecbda | efcdab feb aefdb ebf
+dabfc cfeabd ec cae cagbdf fadeg cdafbeg dbecag bcfe efcad | bcef aec eac bfacd
+fed fbdgea adgfce gfcd acdge acdef afbec df gcabed bdcefga | aebgfd afecd bcfae ecdga
+fcabe da deac fdgeb fbead facebg gcdbefa fcabgd dfbeac dab | fecab bcfgae fcaeb ecbgaf
+cdebg dgebac abe fagcbed ea cbagf adeg cfdbge gacbe edbcaf | dcebaf fgbca adeg cafgbed
+gedfcb bg bgc gfacd fdgcabe dgba bfagc afbec bgacdf eadcfg | gfcab bcg bg dgba
+fecga fgbeda fadec fdcbega cdefba becdf dgfbec ad dacb dfa | cedbfg gebadf agefdb bdac
+bcgade agefd ebfg bag gfdbea afegdcb cfdba dagfb bg gfcdae | adfbg bga gb agb
+fgaced bcdag dcbagef gedcbf dcfge fga af efda gacdf eabgfc | bdcga fga dcfeag fead
+dega abd adbgc eabdgfc dbcefg da fadbec ebcgd cafgb adgcbe | cbdga cabdg adgefbc bfcgde
+bfdacg eabgc bce abgdc cebgafd be ecadgb faebdc bdge gface | bdeg acefg gefbadc dcgba
+fedgc cadefg cedagbf adcfe abfdc efa ae agfedb gace bfecgd | acbfd ae gcbafed cdabefg
+egdcab egdfba gca abfec bafgd gcbefda gfbcad cg fcdg bcfga | gc gc edabgc cga
+eb gdbfca befdc gdcfb ebdg efb edcbgaf ecfdbg fedac egbfca | gbdcf acfegb aedfc dafcebg
+aebcgd bacg ecgbafd dafbec ga dcbae aedbg gad bdgef fadgce | adegb gad becagd edbcfa
+cgad ceabdfg fedbc gd cfbage gfcba abgefd fdabgc dcgfb gdf | dcgfb gbdafec gbfadc dgca
+acgebd fdebga cde cedfa gfceabd baefd cfeb cgadf ce fedcab | afedb deabf afdce fabged
+gcabe adge bcdfea cgebf bgcfda aeb gdacb ea aegdcb cefagbd | bea gaed agbce dgfacb
+cefad cadgbfe cgeafd eg agdbfe acgbf fge cged gfcea ebfacd | dacebf dceafb fabecd gcde
+gbfcde fcg ecgadb cbdge eagdf edgfc bfdc bfecag fc dbcagfe | cfbd gfdecb gfc efdga
+gebafc bcfae fcebd gfabed bea bfagc fdcgba ea ceag gacbefd | ebacfg egac bacfg febac
+ed gfde dcgea cdagf ead cfdgaeb gcdafb aedgfc dbaefc ceagb | dae eda gfabcd gdbfca
+cfbgd bfaecg dgbecf fgcdab dbgaf fba bdcefga af gebad cdfa | feadbcg fcad bfaegcd af
+gbd eabfgc egdfbc dcge dg bdcgfae dbacf cdfbg fbedga cefbg | ecgd gbd dgce dbg
+gac gcdaebf agfcbe gdebcf ga bcfdag adcbg bfgcd dafg cedab | gcafeb agcdb cbfdag ag
+dfg bcfaegd dg gacef dgbefc dbcaef gfcbad ebdg efcdb degfc | efcga dfcgbe gbde cefdb
+bcae aegfb egdaf gdcbfa eb fbcgae afgcbde ebg dbfcge bcfga | cdbegf ebg fbacg egb
+ceafgb ab edbgfac aedcgf abfc fgaedb eab bcedg ebagc acegf | fbac ba ecagf abcgfe
+geafd bgeacfd bcfgda bdca cebfga gdbaf fgdcbe dgfbc ba bga | efagd gfbda cebafgd agfde
+gacfed agc cfgdbe ca ecfdg fagdc agfbced bacdeg bdfga eafc | egdfc badgf egcfbd bfadg
+eca ac cadgef eacbdg fecgdba dbace gbca dfgbec afedb bgcde | gbecad bcag dcaeb cae
+gfaebc fg fcaebd facbe fgeab cbdafg aebgd gfce caefbgd afg | gf cfbea edbag efgc
+fgaed gacedf fbdcga ecfa degabf cga ac efabgdc gecad begdc | efca acg edbgc cag
+afdbgec gcebad fecgad ecagd fdac af bfaegc fae efadg efgdb | acdge afegcb gafde fa
+eadcf dbecgfa dfaegb gdcb ecg adbegc gc geacd ecabgf edabg | gdbace bcdg ebagfd cbdg
+fgade dgb gcbe gafcdb fecdb bfacde ecgdabf bdegf febgcd bg | cdgfab cgbe gdb gacdebf
+dcfbe dbfeag dgebca fbagcde gbafdc cagf bgf dcgfb fg gcbda | abcfdg bfg gcbfd dcfgab
+bgf dgcbef acbefd egadcbf bafdge bfdae bg eagb acfgd dgbfa | deafb bdfae dfagc cdgaf
+bafcd egcbdaf dg cfbgde eagd gfbea bgd adbgf gdeabf befgca | badcf fbaeg dfgab fdgeabc
+gea fecdag gadbfe aegdc acfde dbcefa ge bcagd bgdacef egfc | ecgf defac gea defca
+bfgdae gefabc fd edgcb gefab abgcdf aecgfdb fdea fgbed dbf | fbd cgedb fbd df
+adbgec bc dabfge dafeb dcb cegfd cafb becfd cgdebaf bdecaf | febcd cbfa cb adbcgef
+ecgdf fbdgcae acfbg fdgaeb adf afgcbd dagfc ad adcb acgbef | dbaefg cbfga cabgf gfacd
+cefa ae adcbg gefbad eagfcb decbgf aeg gebcf gfdacbe abgec | cefdgb fedbcg cfeabg gbcea
+ebfag fdbcge gdbaf fcdag fgbace bfd abde gfcdeba db gefbda | bdgecf ebad deafbg fbaged
+bgecd edcba bgacef dgacbe fdcabeg fbeacd gbc fgdce dgab bg | decab bcdeg fcgbea caedb
+bc abged abgfdc dgbac edfgca cfba gcdbef dafgc dbc cbgdfae | adebg bcefgd cabfedg cdgafb
+gcfad fb bceadf cgaeb agfbdc fbc gfaced acdbfge cgbfa gbfd | afedbc cadfg gcbae ecbag
+cgadb begfcad gdcbfe bdegc edab cabfg cagfde dca ad egbdca | adc da adc da
+gfcbd cbegfda dbga da bgdcef bgdcaf gceaf cfebda fdgca acd | dcgfa fedagbc bgcfd afgdc
+afge ge beg abcgd afgcedb fgcabe fcbae cdebfa dgebfc cabge | acefbgd geb fage eadcfb
+fgecadb fcae edgfcb aedgf gdfce eagdb af dagcef fcdabg adf | adfecg ecaf dbafceg cgefbd
+gabfd bedag abegcf df fad abcgfd bafgc bfgcdae fcdb gacfed | aefgbc agdcfb cagdfe afd
+degbafc ga efcga age fdcgae agcd dgfeba dgefcb fcgde cbaef | eadfgb afcbedg degfcab fabecdg
+beg aefgbc eb efbd cbagd gaedb aegcfd afdge dafecbg eagdbf | dagcb geb febd cefdga
+da cagfd fbgcae fgbcda gfbcaed edfcg fad ebfcad dabg bgfac | fcgde daf cgfabe afd
+gefdc ebafgd fgacbd agbc fdacg dcabgef ac cda bafdec abfgd | gacb gdfca fedcbga fdcga
+gedfba bgdca dfgbc bcfgde bdace bacgdf cafg ga dag bdcafeg | debcfg cgbad acfg ecdgbf
+fagde fdgeca agc gc afedbg ecgf agcedb dfaecbg acdfb fgdac | cg adfeg fdgae efcg
+dgcbe fe abcfg cfgead gdcbfa efc egfbadc bgacef fbae gfbce | fbcag abef faeb cafbdg
+beadfc eb gbef fbgda cfbgda gadbe gdace gefadb edb cgdabef | aedcg deb bde dgbaf
+afbdge dbgfcea fadcbe cb febcd bcd gfdce cfagbd bcae bdfea | bdc gfadeb cebdf afdbe
+degca adbfgec bfcgda fa eafb fac bafecd fedbc cfade bgecfd | cbdafg edbacf agcfedb fa
+fabde egdacb bfd fdgbac ebcda bf bdecfa fadge dfegabc fcbe | feabd fdb cfdeba bf
+aedbfcg fadbg cefgba ecdfga efg ge adefc dfebac afdeg dceg | bdfeca gcde aedcfb faecd
+dgaecbf cefdgb bcgdfa edb ed beafc gfed bgfcd dacegb dcfbe | deb gdbcfa cfgdeb gfecabd
+bdagfc bf gcdaeb dbgac gdfce cbdfg abgf bfc abfgdec bdacfe | dcgfb defgc bfga bf
+gef bgcf dafbec bcfde decgf bcefdg fg bgcfade cedag fdbgea | bacefgd gcbf fg dbfagce
+fagcdb cf bcafed cefa bdegf cdaeb edfcb ecdgafb daegcb bcf | dcfgba eagcbdf caebd afbdcg
+ecd dcebaf bgeafdc adfbcg gdafe cbagde ecbf fceda ce fdacb | bgecad decfabg ec bfce
+begda gfbd fbgade agdbcfe gfe gacebd bfega gf bcfae adcgef | efg fcabe geadcf abfcedg
+cbfga ef efcgb befcga fcea fge cbdeg dgebaf fcbgad afegcbd | fadebg ef abefdg fe
+dagbc dab fbdg cdfag efcbda gecba bdcefga gdbcaf cdefga bd | feabdc dgabc db cadgef
+ge beg afcbed edbag fbgcea dgaebcf adbce fbadg bgacde gdce | gced egdc feadcb eagcdb
+geafbdc ca gdafce adbeg cfab bagdc dcgebf adc gdfbc gbcafd | cegfbd adc ecfgbd cfdgb
+adg afgdc gcedfba cadfb bgfaed agbc cabdgf dgfec ag febacd | fbecda cdgafb ga dga
+abcdfge egc egfabc ce gedabc dgfcb edgab gbdec fbaged adce | ec gdbce ceg cbefga
+acbgf ebdfg gefadc fae efbag gcaefb ea cbea cgbafd cagdbfe | bcae ea fdcgbae ecbfag
diff --git a/2021/inputs/day_9.txt b/2021/inputs/day_9.txt
new file mode 100644
index 0000000..9494363
--- /dev/null
+++ b/2021/inputs/day_9.txt
@@ -0,0 +1,100 @@
+6587893456954341398543210234567899875421012578932123459998764323569999996432345899989359878998654345
+5476894579873210197654328757678910976532323457891012398997653212998798789521256789879498764679795456
+5345679989864321349865479869799929987643498598932923987989543209876697654320145679965987653567989767
+3235678999965443567976567878999898997654587678949899876878994319965498765421236789764398532479879878
+0124789339897764678987878989998767898986798989298798765756989498754349899535456899879987691298568989
+1235693219799865889698989990987856789997899592139679984445678987643237998646567890998698989987457899
+2348789398678976789569999921976745678998985431095459873234569998765145689987899932349579768976567978
+4567899976599989895478999899875435899359876545984398765145678999843234567898976543998498657697798964
+7688999875487899976789298767986546789999988769873239876234567892954345678909997659876597646579899543
+9799998764325578987899109654397967999879999898764346984345678921986456789319889799989986534466989542
+9989879875413467998998923993239878998758999969975899876476789210987567895498779989992395421355678954
+9876569974324678959987899889101989987646489459896789976567894321297678976987667879893987510134569999
+8765498765456899769996798767992493499832367999789893987678965456998989989876546758789997921235678988
+9874349876567998998965689656789569989753458987678962398989879599879799992965434345678986437367889876
+8765456987678987987654678945679678979768667896569541239899998989965678901977321237899876545459993998
+9876567898789996796543489939798989764979778965499432345789997879974589919898934348901997668567892109
+9987998999896789899755569898987897653989899012378945497899965467893469898789895459919898877679954919
+9898919789965678989876798767346789762399943234569767989999854359932599787698789667899769989789899897
+8759105679654569878998899856235999321239854355878979879998765567893987654589678978998953599896798786
+6543214598979698968899999843123568910198765467989998767899976779964599643279567899687892498945697655
+7954323497898966556789987654013467892499976589099987756789987889995798732153456789576931987432398543
+9899435986577942347896598732123458999987899693239865347991298999989987643012348894345899876541239432
+8798949765456891238965439653234567898976798789399876456789459999879876532145457896876789987832396543
+7686799887347920145976549878347698987755679899989986567897667898965987674234668999987895498743987965
+6595789998967891247897656989498999876544587999879987678998778987864398765545979998998989359654599876
+5434678999298932346789767896569098987623456796567898989539899876543219876656897987889874298765678987
+4323576789399543456789978998789197898212345679335679999421921988754301998767986576569763189896789198
+3212345789987676577899899239899976789853458789124679878999890199865492999878975432478952076999893239
+4523456897898787689998789129998765698767569991012399865788799345987989899989896543578943145698994345
+5635567896789898799029569098899987999878978962193987654647678976799878799998798654567899239987989469
+8756678935978999898998678987799999899989989643989996543234567897898968678987698785678998998795878978
+9897889123467893967899789876678999768393498959878989654346778998987654567896539876789457789654769899
+6998993234679932456999899865589996543212347898765578995487899989998785678974323987992345678943456797
+4349965345789531345799987643499987664324456987654456789598999878999876789865434598943567889752589895
+6459876459999910239898798101989198976535967899532345678949988767899989899989545999759878997643569994
+9878987767899891398989543219879239987649898998721235789039879857999994978998769899998989498957698989
+7999999878986789997679654598768945798959799987632345892129967234678943567899898798767894329878987978
+6989987989345679896598995987654999899898679876543566943298654123487892389989987657656789210989876569
+5978996591236798789456789998743878998786567987664689954679942012456799459876799543234568921298975497
+9769889432445987679345699865432459987675478998785799895799842123867898967995698432123556932967964326
+8958778956759876531256789987543579876564367899896895789998763435798957899854597543012345899859873214
+7643568997969765430347893987654678976444259899987924556799878976899645798643498632124556789645995403
+8532456789879876321346932398767889987320145789699012345679989987896536899854987653246787896539876912
+7421345678989985442457893599898994598321237894556923966889999998998745698765698764345678954321989893
+6530496989498996584668999989999213469644345892349899897899999879799656789876789875456799987553598789
+7699989892397987676789998979992101278955456789498756789999898765688979897987894989667976599679699667
+8987979789986599987899887968989232349866667899976546689998765544567899956598923499878987698798986545
+9976867678965434598999765457678945458978878999895634578987654333456989645459012398989898789987654436
+8765454567897665679998654346567896567989989998764323689999765212345678932399923987698789892498742123
+6874343789799779789876543213458998678999799987653212387921976924566789543989899876554678943985431012
+5432102345678989999965432102349999799987678987654501276892989896677899959876798765432567899876543243
+7643412456789999989878676413456899989876469898876612345999898789998998899995439876753458976987654354
+7655324577897899878989654329567988764514345789987843456798766599889987689984323987764967894398766456
+8786734678976799767998765567978976543101234599998954567899954349778996569876212398876878999989877767
+9897645689565698757899887679999098654332345698999875678999843234567897678965104569997889798976998978
+1998756789434569943535998789899129786445689997999989899998785123456998789874315678998996567895329989
+2349967896513479892124569896788939896576898786789996921989632013667899892965326679019965456996210197
+3959879974323569769023456975767945987687987675678985439876543124589976920976434567997894346789321256
+9899989965434679658934567894556899998999876554567976545987654565697895439876565879876543235678932345
+9768999899565798747895879913445678989678965423456897656898765677796796549987676789998432126799543556
+6756897788979899656789989101236789676569874312345798968999879788954789678999789899987643235689699789
+4346796567898998767899894212345896545456965101276789879998999899432688989989892968998754345678988999
+5657893456987899878998765523466789634349876514567892989987656999543567899876901259789895466789877889
+8789932678976789989579865434567898722298765423698921291296545678957678998765432345678976989898656878
+9897643789865678996469876558778969810129895434789210199986534589998989349876553499899989999986543566
+8987654898754567902345998669899654323345987567994391987673323467899995456987694989999999999986432345
+7898765998843236899458998789998969834589998989879989876542012456945896678998989878998788898976521289
+6569976987654345678967999898587897655678999898765779765432135578935789789459976568986577667898432478
+9439898998765469989998987967476789767789988766434568976543234689124678992349865457997402456789543567
+8998789659989598898989876653345678978999876654323456897654345691012567891998754349876212398897654678
+7987679743497697767878965422234567899999875421012698998765676789323456789876542298765435678998865789
+6592578932398986656467897910123456979899986534123589239876797896454567997984321059876568789999976890
+9421349890199875433356789891954569456798986546254678998987898989765679545975472347998678899897989921
+8210445789987654321245898799895698969897698755378999467998949678976889439986567656999789998796597532
+7421234894599943210134987688789987898987549875489312359879234567987899998797678797899899989689459843
+6439345943239874321345798454698976767895434976678954598762123456899999897698989989989979876568998754
+6598997894999765633466954343567895456795323987889895689953234567999898789439899879876569965457998765
+7987889999889876545789875212398954346789412398998789998764348789898775678919789767996498754345689896
+9895678987676987986791995101457893244898901999975698789765459898799654567997637657984349843234569987
+8654567896565698997892983212346789123457899899894987699986567899654523456789521749873249654445678999
+7643298789434569898939865423567891012346798798795699789297978999543312978898430123965398979966989645
+8964345679323458789920977674578942199967989689589999892198989998662106899986521239877987897897895434
+9876798789012345699891988795689543987899876567477899943019799987543245679199542345998976545789999321
+2989899893123556798789599876897659896789765435356789942165678998765358989098993556799865434668998910
+1094945943238767987699432987999798765679976321234567893234569679878767899987689698899987323457897892
+9943237895445898958567941098998999654789897542348788954345689456989878999865567989989865412368956789
+8832146789556999543479892129987678932396789656569899995456791349897989987654349878878954323779768999
+7654258997697976432358789234987467890145698767678998789767890998756399899785498765469895965689979889
+8765767989989999751234689345986358943235699898989998689878999876543268799996789874399769898789898776
+9979979878879987642956796569875467894346789969799987578989998987654156678998992986987656789899787545
+9898998765968899799899898679989878976459894356678965467899887598721034567899321987896545678998676434
+9767897654656789988778999789398989997568999234579874356789756459842125788965439999999767899876545323
+8656789843234899876567899892127898987678988946698763244578942398763236999877898999899978975975432102
+6545678952123678975457989942016567898789767897987653123569321987654349989989987998799989764986548726
+2135678953234567894345678932123459989894356789796542012459432798789498978990196754678997653297659645
+6545699975545678943234569643234569878943234598679765423498943679899987867891985653589987654398799856
+7678789987656989434126678964365798569892125679569876536567894567998766756789873542357898765989923987
+9989890199788999321018999765456987456789287894379987789879976898987654347898762101237789889875210198
+0198931369899998732129678976569876345994399965456998897989197899599875456999854345345679998764321239
+1987642456910987654334567897679985456895679876597899956791098965431986567899965456786789459875643467
diff --git a/2021/proptest-regressions/bin/day_24.txt b/2021/proptest-regressions/bin/day_24.txt
new file mode 100644
index 0000000..c9b9ac2
--- /dev/null
+++ b/2021/proptest-regressions/bin/day_24.txt
@@ -0,0 +1,11 @@
+# Seeds for failure cases proptest has generated in the past. It is
+# automatically read and these particular cases re-run before any
+# novel cases are generated.
+#
+# It is recommended to check this file in to source control so that
+# everyone who runs the test benefits from these saved cases.
+cc 3ff1975a827f0f896df7fad66e81f158bb513003aa57b9392c7be206d91c401e # shrinks to input = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
+cc 34000b524f14fadce85ab48285657651fd5756cb94b8ad9868e068d808705ec5 # shrinks to input = [1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
+cc df520bbe1425f1b68bcd1e837caa8c6cea82fe8ac2fc8f58e3044cace37c5f9e # shrinks to input = [1, 1, 9, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
+cc 2cff9266126660d75f7f6e9c8872fb4a7e91e5225507126c18f4488ebe52d4c4 # shrinks to input = [1, 1, 1, 1, 1, 1, 1, 1, 5, 3, 8, 3, 1, 1]
+cc 113d1afb9c126057c1d0d46b73c603364647fd914104f7c4dd23334d286089c1 # shrinks to input = [1, 1, 1, 1, 1, 1, 1, 2, 8, 2, 7, 6, 1, 1]
diff --git a/2021/readme.org b/2021/readme.org
new file mode 100644
index 0000000..642364f
--- /dev/null
+++ b/2021/readme.org
@@ -0,0 +1,2 @@
+* Advent of Code 2021
+
diff --git a/2021/src/bin/day_1.rs b/2021/src/bin/day_1.rs
new file mode 100644
index 0000000..62ab045
--- /dev/null
+++ b/2021/src/bin/day_1.rs
@@ -0,0 +1,75 @@
+use nom::{
+ character::complete::{line_ending, u64 as nom_u64},
+ combinator::map,
+ multi::separated_list1,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_1.txt")?;
+ let sonar_scan = parse_sonar_scan(&input).unwrap().1;
+
+ let simple_increase_counter = count_increases(sonar_scan.iter());
+ dbg!(simple_increase_counter);
+
+ let windowed_sonar_scan = sonar_scan
+ .iter()
+ .zip(sonar_scan.iter().skip(1))
+ .zip(sonar_scan.iter().skip(2))
+ .map(|((depth1, depth2), depth3)| ThreeDepthWindowSum::new([*depth1, *depth2, *depth3]))
+ .collect::<Vec<_>>();
+
+ let windowed_increase_counter = count_increases(windowed_sonar_scan.iter());
+ dbg!(windowed_increase_counter);
+
+ Ok(())
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+struct Depth(u64);
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+struct ThreeDepthWindowSum(u64);
+
+impl ThreeDepthWindowSum {
+ fn new(depths: [Depth; 3]) -> ThreeDepthWindowSum {
+ ThreeDepthWindowSum(depths.into_iter().map(|d| d.0).sum())
+ }
+}
+
+fn parse_sonar_scan(input: &str) -> IResult<&str, Vec<Depth>> {
+ separated_list1(line_ending, parse_depth)(input)
+}
+
+fn parse_depth(input: &str) -> IResult<&str, Depth> {
+ map(nom_u64, Depth)(input)
+}
+
+#[derive(Default, Debug)]
+struct DepthIncreaseCounter(u64);
+
+impl DepthIncreaseCounter {
+ fn increment(&mut self) {
+ self.0 += 1;
+ }
+}
+
+fn count_increases<T: Ord>(i: impl IntoIterator<Item = T> + Clone) -> DepthIncreaseCounter {
+ let mut increases = DepthIncreaseCounter::default();
+ for (depth, next_depth) in i.clone().into_iter().zip(i.into_iter().skip(1)) {
+ if next_depth > depth {
+ increases.increment();
+ }
+ }
+ increases
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ #[test]
+ fn parses_a_depth() {
+ assert_eq!(parse_depth("96\n"), Ok(("\n", Depth(96))));
+ }
+}
diff --git a/2021/src/bin/day_10.rs b/2021/src/bin/day_10.rs
new file mode 100644
index 0000000..a9a9f75
--- /dev/null
+++ b/2021/src/bin/day_10.rs
@@ -0,0 +1,124 @@
+use nom::{
+ branch::alt, character::complete::char as nom_char, combinator::map, multi::many0, IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_10.txt")?;
+
+ let mut syntax_error_score = 0;
+ let mut autocomplete_scores = Vec::new();
+ for line in input.split("\n") {
+ match parse_lisp(line) {
+ Ok(_) => {
+ // boring
+ }
+ Err(nom::Err::Failure(ParseError::MismatchedExpectation(_, actual))) => {
+ syntax_error_score += match actual {
+ ')' => 3,
+ ']' => 57,
+ '}' => 1197,
+ '>' => 25137,
+ _ => 0,
+ }
+ }
+ Err(nom::Err::Failure(ParseError::EndOfInput(_))) => {
+ let mut line = line.to_owned();
+ let mut autocomplete_score = 0u64;
+ while let Err(nom::Err::Failure(ParseError::EndOfInput(expected))) =
+ parse_lisp(&line)
+ {
+ autocomplete_score *= 5;
+ autocomplete_score += match expected {
+ ')' => 1,
+ ']' => 2,
+ '}' => 3,
+ '>' => 4,
+ _ => 0,
+ };
+ line.push(expected);
+ }
+ autocomplete_scores.push(autocomplete_score);
+ }
+ Err(_) => panic!("Unexpected nom error type"),
+ }
+ }
+ dbg!(syntax_error_score);
+ autocomplete_scores.sort();
+ dbg!(autocomplete_scores[autocomplete_scores.len() / 2]);
+
+ Ok(())
+}
+
+#[derive(Debug)]
+enum ParseError<'a> {
+ MismatchedExpectation(char, char),
+ EndOfInput(char),
+ Other(nom::error::Error<&'a str>),
+}
+
+impl<'a> From<nom::error::Error<&'a str>> for ParseError<'a> {
+ fn from(e: nom::error::Error<&'a str>) -> Self {
+ ParseError::Other(e)
+ }
+}
+
+impl<'a> nom::error::ParseError<&'a str> for ParseError<'a> {
+ fn from_error_kind(input: &'a str, kind: nom::error::ErrorKind) -> Self {
+ nom::error::Error::from_error_kind(input, kind).into()
+ }
+
+ fn append(_input: &'a str, _kind: nom::error::ErrorKind, other: Self) -> Self {
+ other
+ }
+
+ fn from_char(input: &'a str, c: char) -> Self {
+ nom::error::Error::from_char(input, c).into()
+ }
+}
+
+#[derive(Debug)]
+struct Lisp {
+ blocks: Vec<Block>,
+}
+
+#[derive(Debug)]
+struct Block {
+ opening: char,
+ blocks: Vec<Block>,
+}
+
+fn parse_lisp(input: &str) -> IResult<&str, Lisp, ParseError> {
+ map(parse_blocks, |blocks| Lisp { blocks })(input)
+}
+
+fn parse_blocks(input: &str) -> IResult<&str, Vec<Block>, ParseError> {
+ many0(parse_block)(input)
+}
+
+fn parse_block(input: &str) -> IResult<&str, Block, ParseError> {
+ alt((
+ block('{', '}'),
+ block('[', ']'),
+ block('(', ')'),
+ block('<', '>'),
+ ))(input)
+}
+
+fn block(opening: char, closing: char) -> impl Fn(&str) -> IResult<&str, Block, ParseError> {
+ move |input: &str| {
+ let (input, _) = nom_char(opening)(input)?;
+ let (input, blocks) = parse_blocks(input)?;
+ let (input, _) = match nom_char(closing)(input) {
+ Ok((input, closing)) => (input, closing),
+ Err(nom::Err::Error(_)) => {
+ return Err(nom::Err::Failure(match input.chars().next() {
+ Some(actual) => ParseError::MismatchedExpectation(closing, actual),
+ None => ParseError::EndOfInput(closing),
+ }))
+ }
+ Err(e) => return Err(e),
+ };
+ Ok((input, Block { opening, blocks }))
+ }
+}
diff --git a/2021/src/bin/day_11.rs b/2021/src/bin/day_11.rs
new file mode 100644
index 0000000..2a4cd89
--- /dev/null
+++ b/2021/src/bin/day_11.rs
@@ -0,0 +1,130 @@
+use nom::{
+ character::complete::{line_ending, one_of},
+ combinator::map_res,
+ multi::{many1, separated_list1},
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_11.txt")?;
+ let squid_grid = parse_squid_grid(&input).unwrap().1;
+
+ {
+ let mut squid_grid = squid_grid.clone();
+ let mut flashes_on_100 = 0;
+ for _ in 0..100 {
+ flashes_on_100 += squid_grid.flash();
+ }
+ dbg!(flashes_on_100);
+ }
+
+ {
+ let mut squid_grid = squid_grid.clone();
+ let sync_time = std::iter::repeat_with(|| squid_grid.flash())
+ .position(|flashes| flashes == 100)
+ .map(|x| x + 1);
+ dbg!(sync_time);
+ }
+
+ Ok(())
+}
+
+#[derive(Debug, Clone)]
+struct Squid {
+ energy: u8,
+ has_flashed: bool,
+}
+
+impl Squid {
+ fn should_flash(&self) -> bool {
+ self.energy > 9 && !self.has_flashed
+ }
+
+ fn reset(&mut self) {
+ self.energy = 0;
+ self.has_flashed = false;
+ }
+}
+
+#[derive(Debug, Clone)]
+struct SquidGrid {
+ squids: [[Squid; 10]; 10],
+}
+
+impl SquidGrid {
+ fn flash(&mut self) -> usize {
+ for y in 0..10 {
+ for x in 0..10 {
+ self.squids[y][x].energy += 1;
+ }
+ }
+
+ let mut any_new_flashes = true;
+ while any_new_flashes {
+ any_new_flashes = false;
+ for y in 0..10 {
+ for x in 0..10 {
+ if self.squids[y][x].should_flash() {
+ any_new_flashes = true;
+ self.squids[y][x].has_flashed = true;
+ if y > 0 && x > 0 {
+ self.squids[y - 1][x - 1].energy += 1;
+ }
+ if y > 0 {
+ self.squids[y - 1][x].energy += 1;
+ }
+ if y > 0 && x < 9 {
+ self.squids[y - 1][x + 1].energy += 1;
+ }
+ if x > 0 {
+ self.squids[y][x - 1].energy += 1;
+ }
+ if x < 9 {
+ self.squids[y][x + 1].energy += 1;
+ }
+ if y < 9 && x > 0 {
+ self.squids[y + 1][x - 1].energy += 1;
+ }
+ if y < 9 {
+ self.squids[y + 1][x].energy += 1;
+ }
+ if y < 9 && x < 9 {
+ self.squids[y + 1][x + 1].energy += 1;
+ }
+ }
+ }
+ }
+ }
+
+ let mut flashes = 0;
+ for y in 0..10 {
+ for x in 0..10 {
+ if self.squids[y][x].has_flashed {
+ self.squids[y][x].reset();
+ flashes += 1;
+ }
+ }
+ }
+ flashes
+ }
+}
+
+fn parse_squid_grid(input: &str) -> IResult<&str, SquidGrid> {
+ map_res(separated_list1(line_ending, parse_squid_row), |squids| {
+ squids.try_into().map(|squids| SquidGrid { squids })
+ })(input)
+}
+
+fn parse_squid_row(input: &str) -> IResult<&str, [Squid; 10]> {
+ map_res(many1(parse_squid), |squids| squids.try_into())(input)
+}
+
+fn parse_squid(input: &str) -> IResult<&str, Squid> {
+ map_res(one_of("0123456789"), |digit| {
+ digit.to_string().parse().map(|energy| Squid {
+ energy,
+ has_flashed: false,
+ })
+ })(input)
+}
diff --git a/2021/src/bin/day_12.rs b/2021/src/bin/day_12.rs
new file mode 100644
index 0000000..708037d
--- /dev/null
+++ b/2021/src/bin/day_12.rs
@@ -0,0 +1,146 @@
+use nom::{
+ character::complete::{alpha1, char as nom_char, line_ending},
+ combinator::map,
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::{collections::BTreeMap, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_12.txt")?;
+ let cave_system = parse_cave_system(&input).unwrap().1;
+ dbg!(cave_system.find_all_paths(0).len());
+ dbg!(cave_system.find_all_paths(1).len());
+
+ Ok(())
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+struct CaveId(String);
+
+impl CaveId {
+ fn big(&self) -> bool {
+ self.0.chars().next().map_or(false, char::is_uppercase)
+ }
+ fn terminal(&self) -> bool {
+ self.0 == "start" || self.0 == "end"
+ }
+}
+
+#[derive(Debug)]
+struct Cave {
+ id: CaveId,
+ exits: Vec<CaveId>,
+}
+
+impl Cave {
+ fn new(id: CaveId) -> Cave {
+ Cave {
+ id,
+ exits: Vec::new(),
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+struct CavePath {
+ path: Vec<CaveId>,
+ remaining_small_cave_visits: usize,
+}
+
+impl CavePath {
+ fn new(max_small_cave_visits: usize) -> CavePath {
+ CavePath {
+ path: vec![CaveId("start".into())],
+ remaining_small_cave_visits: max_small_cave_visits,
+ }
+ }
+
+ fn push(&mut self, next: CaveId) {
+ if !next.big() && self.path.iter().any(|visited| visited == &next) {
+ self.remaining_small_cave_visits -= 1;
+ }
+ self.path.push(next);
+ }
+
+ fn can_go_to(&self, dest: &CaveId) -> bool {
+ dest.big()
+ || !self.path.iter().any(|visited| visited == dest)
+ || (!dest.terminal() && self.remaining_small_cave_visits > 0)
+ }
+
+ fn is_complete(&self) -> bool {
+ self.tail() == &CaveId("end".into())
+ }
+
+ fn tail(&self) -> &CaveId {
+ self.path
+ .get(self.path.len() - 1)
+ .expect("There should not be empty paths")
+ }
+}
+
+#[derive(Debug)]
+struct CaveSystem {
+ caves: BTreeMap<CaveId, Cave>,
+}
+
+impl CaveSystem {
+ fn new(tunnels: Vec<(CaveId, CaveId)>) -> CaveSystem {
+ let mut caves = BTreeMap::new();
+ for (tunnel_start, tunnel_end) in tunnels {
+ let start = caves
+ .entry(tunnel_start.clone())
+ .or_insert(Cave::new(tunnel_start.clone()));
+ start.exits.push(tunnel_end.clone());
+
+ let end = caves
+ .entry(tunnel_end.clone())
+ .or_insert(Cave::new(tunnel_end.clone()));
+ end.exits.push(tunnel_start);
+ }
+ CaveSystem { caves }
+ }
+
+ fn find_all_paths(&self, max_small_cave_visits: usize) -> Vec<CavePath> {
+ self.find_paths(CavePath::new(max_small_cave_visits))
+ }
+
+ fn find_paths(&self, active_path: CavePath) -> Vec<CavePath> {
+ if active_path.is_complete() {
+ vec![active_path]
+ } else {
+ let current = self.caves.get(active_path.tail()).expect("Unknown path");
+ current
+ .exits
+ .iter()
+ .filter(|next| active_path.can_go_to(next))
+ .flat_map(|next| {
+ let mut active_path = active_path.clone();
+ active_path.push(next.clone());
+ self.find_paths(active_path)
+ })
+ .collect()
+ }
+ }
+}
+
+fn parse_cave_system(input: &str) -> IResult<&str, CaveSystem> {
+ map(parse_tunnels, CaveSystem::new)(input)
+}
+
+fn parse_tunnels(input: &str) -> IResult<&str, Vec<(CaveId, CaveId)>> {
+ separated_list1(line_ending, parse_tunnel)(input)
+}
+
+fn parse_tunnel(input: &str) -> IResult<&str, (CaveId, CaveId)> {
+ map(
+ tuple((parse_cave_id, nom_char('-'), parse_cave_id)),
+ |(a, _, b)| (a, b),
+ )(input)
+}
+
+fn parse_cave_id(input: &str) -> IResult<&str, CaveId> {
+ map(alpha1, |s: &str| CaveId(s.to_owned()))(input)
+}
diff --git a/2021/src/bin/day_13.rs b/2021/src/bin/day_13.rs
new file mode 100644
index 0000000..547c7a2
--- /dev/null
+++ b/2021/src/bin/day_13.rs
@@ -0,0 +1,136 @@
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{char as nom_char, line_ending, u32 as nom_u32},
+ combinator::map,
+ multi::{many0, separated_list1},
+ sequence::tuple,
+ IResult,
+};
+use std::{collections::BTreeSet, fmt, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_13.txt")?;
+ let mut page = parse_page(&input).unwrap().1;
+ page.do_next_fold();
+ dbg!(page.count_points());
+ while page.do_next_fold() {}
+ println!("{}", page);
+
+ Ok(())
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
+struct Point {
+ x: u32,
+ y: u32,
+}
+
+#[derive(Debug)]
+enum Fold {
+ X(u32),
+ Y(u32),
+}
+
+#[derive(Debug)]
+struct Page {
+ points: BTreeSet<Point>,
+ folds: Vec<Fold>,
+}
+
+impl Page {
+ fn do_next_fold(&mut self) -> bool {
+ let fold = self.folds.pop();
+ match fold {
+ Some(Fold::X(x)) => {
+ self.points = std::mem::take(&mut self.points)
+ .into_iter()
+ .filter(|point| point.x != x)
+ .map(|point| {
+ if point.x > x {
+ Point {
+ x: x - (point.x - x),
+ y: point.y,
+ }
+ } else {
+ point
+ }
+ })
+ .collect();
+ true
+ }
+ Some(Fold::Y(y)) => {
+ self.points = std::mem::take(&mut self.points)
+ .into_iter()
+ .filter(|point| point.y != y)
+ .map(|point| {
+ if point.y > y {
+ Point {
+ x: point.x,
+ y: y - (point.y - y),
+ }
+ } else {
+ point
+ }
+ })
+ .collect();
+ true
+ }
+ None => false,
+ }
+ }
+
+ fn count_points(&self) -> usize {
+ self.points.len()
+ }
+}
+
+impl fmt::Display for Page {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+ let width = self.points.iter().map(|p| p.x).max().unwrap_or(0);
+ let height = self.points.iter().map(|p| p.y).max().unwrap_or(0);
+ for y in 0..=height {
+ for x in 0..=width {
+ let p = Point { x, y };
+ if self.points.contains(&p) {
+ write!(f, "#")?;
+ } else {
+ write!(f, ".")?;
+ }
+ }
+ writeln!(f)?;
+ }
+ Ok(())
+ }
+}
+
+fn parse_page(input: &str) -> IResult<&str, Page> {
+ let (input, points) = separated_list1(line_ending, parse_point)(input)?;
+ let (input, _) = many0(line_ending)(input)?;
+ let (input, mut folds) = separated_list1(line_ending, parse_fold)(input)?;
+ folds.reverse();
+ Ok((
+ input,
+ Page {
+ points: points.into_iter().collect(),
+ folds,
+ },
+ ))
+}
+
+fn parse_fold(input: &str) -> IResult<&str, Fold> {
+ alt((
+ map(tuple((tag("fold along x="), nom_u32)), |(_, val)| {
+ Fold::X(val)
+ }),
+ map(tuple((tag("fold along y="), nom_u32)), |(_, val)| {
+ Fold::Y(val)
+ }),
+ ))(input)
+}
+
+fn parse_point(input: &str) -> IResult<&str, Point> {
+ map(tuple((nom_u32, nom_char(','), nom_u32)), |(x, _, y)| {
+ Point { x, y }
+ })(input)
+}
diff --git a/2021/src/bin/day_14.rs b/2021/src/bin/day_14.rs
new file mode 100644
index 0000000..e757faf
--- /dev/null
+++ b/2021/src/bin/day_14.rs
@@ -0,0 +1,125 @@
+use nom::{
+ bytes::complete::tag,
+ character::complete::{alpha1, anychar, line_ending},
+ combinator::map,
+ multi::{many0, separated_list1},
+ sequence::tuple,
+ IResult,
+};
+use std::{collections::BTreeMap, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_14.txt")?;
+ let mut polymer = parse_polymer_expansion(&input).unwrap().1;
+
+ let small_expansion_counts = polymer.count_after_expansions(10);
+ dbg!(small_expansion_counts.most_common() - small_expansion_counts.least_common());
+
+ let big_expansion_counts = polymer.count_after_expansions(40);
+ dbg!(big_expansion_counts.most_common() - big_expansion_counts.least_common());
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct PolymerExpansion {
+ polymer: Vec<char>,
+ rules: Rules,
+ cache: BTreeMap<(char, char, usize), ElementCount>,
+}
+
+impl PolymerExpansion {
+ fn new(polymer: Vec<char>, rules: Rules) -> PolymerExpansion {
+ PolymerExpansion {
+ polymer,
+ rules,
+ cache: BTreeMap::new(),
+ }
+ }
+
+ fn count_after_expansions(&mut self, expansions: usize) -> ElementCount {
+ let mut counts = ElementCount::default();
+ for i in 0..self.polymer.len() - 1 {
+ counts.add(self.polymer[i]);
+ counts.append(self.count_between(self.polymer[i], self.polymer[i + 1], expansions));
+ }
+ counts.add(self.polymer[self.polymer.len() - 1]);
+ counts
+ }
+
+ fn count_between(
+ &mut self,
+ left: char,
+ right: char,
+ remaining_expansions: usize,
+ ) -> ElementCount {
+ if remaining_expansions == 0 {
+ ElementCount::default()
+ } else if let Some(cached) = self.cache.get(&(left, right, remaining_expansions)) {
+ cached.clone()
+ } else {
+ let mut counts = ElementCount::default();
+ let middle = self.rules.get(&[left, right]).expect("No rule!");
+ counts.add(middle);
+ counts.append(self.count_between(left, middle, remaining_expansions - 1));
+ counts.append(self.count_between(middle, right, remaining_expansions - 1));
+ self.cache
+ .insert((left, right, remaining_expansions), counts.clone());
+ counts
+ }
+ }
+}
+
+#[derive(Debug, Default, Clone)]
+struct ElementCount(BTreeMap<char, u64>);
+
+impl ElementCount {
+ fn add(&mut self, c: char) {
+ *self.0.entry(c).or_insert(0) += 1;
+ }
+
+ fn append(&mut self, other: ElementCount) {
+ for (key, val) in other.0 {
+ *self.0.entry(key).or_insert(0) += val;
+ }
+ }
+
+ fn most_common(&self) -> u64 {
+ self.0.values().max().cloned().unwrap_or(0)
+ }
+
+ fn least_common(&self) -> u64 {
+ self.0.values().min().cloned().unwrap_or(0)
+ }
+}
+
+#[derive(Debug)]
+struct Rules {
+ rules: BTreeMap<[char; 2], char>,
+}
+
+impl Rules {
+ fn get(&self, key: &[char; 2]) -> Option<char> {
+ self.rules.get(key).cloned()
+ }
+}
+
+fn parse_polymer_expansion(input: &str) -> IResult<&str, PolymerExpansion> {
+ let (input, polymer) = map(alpha1, |s: &str| s.chars().collect())(input)?;
+ let (input, _) = many0(line_ending)(input)?;
+ let (input, rules) = parse_rules(input)?;
+ Ok((input, PolymerExpansion::new(polymer, rules)))
+}
+
+fn parse_rules(input: &str) -> IResult<&str, Rules> {
+ map(separated_list1(line_ending, parse_rule), |rules| Rules {
+ rules: rules.into_iter().collect(),
+ })(input)
+}
+
+fn parse_rule(input: &str) -> IResult<&str, ([char; 2], char)> {
+ map(
+ tuple((anychar, anychar, tag(" -> "), anychar)),
+ |(p1, p2, _, r)| ([p1, p2], r),
+ )(input)
+}
diff --git a/2021/src/bin/day_15.rs b/2021/src/bin/day_15.rs
new file mode 100644
index 0000000..6103384
--- /dev/null
+++ b/2021/src/bin/day_15.rs
@@ -0,0 +1,162 @@
+use nom::{
+ character::complete::{line_ending, one_of},
+ combinator::{map, map_res},
+ multi::{many1, separated_list1},
+ IResult,
+};
+use std::{collections::BTreeMap, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_15.txt")?;
+ let risk_grid = parse_risk_grid(&input).unwrap().1;
+ let big_risk_grid = risk_grid.expand();
+ {
+ let mut searcher = Searcher::new(risk_grid);
+ while searcher.end_risk().is_none() {
+ searcher.explore_next();
+ }
+ dbg!(searcher.end_risk());
+ }
+ {
+ let mut big_searcher = Searcher::new(big_risk_grid);
+ while big_searcher.end_risk().is_none() {
+ big_searcher.explore_next();
+ }
+ dbg!(big_searcher.end_risk());
+ }
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct Searcher {
+ grid: RiskGrid,
+ frontier: Vec<(Risk, Point)>,
+ explored: BTreeMap<Point, Risk>,
+}
+
+impl Searcher {
+ fn new(grid: RiskGrid) -> Searcher {
+ let start = grid.start();
+ let mut explored = BTreeMap::new();
+ explored.insert(start.clone(), Risk(0));
+ Searcher {
+ grid,
+ explored,
+ frontier: vec![(Risk(0), start)],
+ }
+ }
+
+ fn explore_next(&mut self) {
+ if let Some((next_risk, next_point)) = self.frontier.pop() {
+ for (neighbour_risk, neighbour_point) in self.grid.neighbours(&next_point) {
+ if !self.explored.contains_key(&neighbour_point) {
+ let total_risk = next_risk + neighbour_risk;
+ self.explored.insert(neighbour_point.clone(), total_risk);
+ self.frontier.push((total_risk, neighbour_point));
+ }
+ }
+ self.frontier.sort_unstable_by(|a, b| b.0.cmp(&a.0));
+ }
+ }
+
+ fn end_risk(&self) -> Option<Risk> {
+ self.explored.get(&self.grid.end()).cloned()
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+struct Point {
+ x: usize,
+ y: usize,
+}
+
+#[derive(Debug)]
+struct RiskGrid {
+ map: Vec<Vec<Risk>>,
+}
+
+impl RiskGrid {
+ fn start(&self) -> Point {
+ Point { x: 0, y: 0 }
+ }
+
+ fn end(&self) -> Point {
+ let y = self.map.len() - 1;
+ let x = self.map[y].len() - 1;
+ Point { x, y }
+ }
+
+ fn risk_at_point(&self, p: &Point) -> Option<Risk> {
+ self.map.get(p.y).and_then(|row| row.get(p.x)).cloned()
+ }
+
+ fn neighbours(&self, p: &Point) -> Vec<(Risk, Point)> {
+ let mut neighbours = Vec::new();
+ if p.x > 0 {
+ let left = Point { x: p.x - 1, y: p.y };
+ if let Some(risk) = self.risk_at_point(&left) {
+ neighbours.push((risk, left));
+ }
+ }
+ if p.y > 0 {
+ let up = Point { x: p.x, y: p.y - 1 };
+ if let Some(risk) = self.risk_at_point(&up) {
+ neighbours.push((risk, up));
+ }
+ }
+ let right = Point { x: p.x + 1, y: p.y };
+ if let Some(risk) = self.risk_at_point(&right) {
+ neighbours.push((risk, right));
+ }
+ let down = Point { x: p.x, y: p.y + 1 };
+ if let Some(risk) = self.risk_at_point(&down) {
+ neighbours.push((risk, down));
+ }
+ neighbours
+ }
+
+ fn expand(&self) -> RiskGrid {
+ let mut new_map = Vec::new();
+ for y_repeat in 0..5 {
+ for original_row in &self.map {
+ let mut new_row = Vec::new();
+ for x_repeat in 0..5 {
+ let risk_modifier = y_repeat + x_repeat;
+ for original_risk in original_row {
+ let modified_risk = original_risk.grid_wrap_increment(risk_modifier);
+ new_row.push(modified_risk);
+ }
+ }
+ new_map.push(new_row);
+ }
+ }
+ RiskGrid { map: new_map }
+ }
+}
+
+#[derive(Debug, Clone, Copy, derive_more::Add, PartialEq, Eq, PartialOrd, Ord)]
+struct Risk(u64);
+
+impl Risk {
+ fn grid_wrap_increment(&self, increment_count: u64) -> Risk {
+ let new = (self.0 + increment_count) % 9;
+ if new == 0 {
+ Risk(9)
+ } else {
+ Risk(new)
+ }
+ }
+}
+
+fn parse_risk_grid(input: &str) -> IResult<&str, RiskGrid> {
+ map(separated_list1(line_ending, many1(parse_risk)), |risks| {
+ RiskGrid { map: risks }
+ })(input)
+}
+
+fn parse_risk(input: &str) -> IResult<&str, Risk> {
+ map_res(one_of("0123456789"), |digit| {
+ digit.to_string().parse().map(Risk)
+ })(input)
+}
diff --git a/2021/src/bin/day_16.rs b/2021/src/bin/day_16.rs
new file mode 100644
index 0000000..368ecc8
--- /dev/null
+++ b/2021/src/bin/day_16.rs
@@ -0,0 +1,217 @@
+use nom::{
+ branch::alt,
+ bytes::complete::take,
+ character::complete::{char as nom_char, one_of},
+ combinator::{consumed, map, map_res},
+ error::FromExternalError,
+ multi::many0,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_16.txt")?;
+ let binary = convert_to_binary(&input).unwrap().1;
+ let packet = parse_packet(&binary).unwrap().1;
+ dbg!(packet.version_sum());
+ dbg!(packet.eval());
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct Packet {
+ version: u8,
+ data: PacketData,
+}
+
+impl Packet {
+ fn version_sum(&self) -> u32 {
+ self.version as u32
+ + match &self.data {
+ PacketData::Literal(_) => 0,
+ PacketData::Operator(data) => {
+ data.sub_packets.iter().map(|p| p.version_sum()).sum()
+ }
+ }
+ }
+
+ fn eval(&self) -> u64 {
+ match &self.data {
+ PacketData::Literal(val) => *val,
+ PacketData::Operator(data) => data.eval(),
+ }
+ }
+}
+
+#[derive(Debug)]
+enum PacketData {
+ Literal(u64),
+ Operator(OperatorData),
+}
+
+#[derive(Debug)]
+struct OperatorData {
+ type_id: OperatorType,
+ sub_packets: Vec<Packet>,
+}
+
+impl OperatorData {
+ fn eval(&self) -> u64 {
+ match &self.type_id {
+ OperatorType::Sum => self.sub_packets.iter().map(|p| p.eval()).sum(),
+ OperatorType::Product => self.sub_packets.iter().map(|p| p.eval()).product(),
+ OperatorType::Minimum => self.sub_packets.iter().map(|p| p.eval()).min().unwrap_or(0),
+ OperatorType::Maximum => self.sub_packets.iter().map(|p| p.eval()).max().unwrap_or(0),
+ OperatorType::GreaterThan => {
+ if self.sub_packets[0].eval() > self.sub_packets[1].eval() {
+ 1
+ } else {
+ 0
+ }
+ }
+ OperatorType::LessThan => {
+ if self.sub_packets[0].eval() < self.sub_packets[1].eval() {
+ 1
+ } else {
+ 0
+ }
+ }
+ OperatorType::EqualTo => {
+ if self.sub_packets[0].eval() == self.sub_packets[1].eval() {
+ 1
+ } else {
+ 0
+ }
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+enum OperatorType {
+ Sum,
+ Product,
+ Minimum,
+ Maximum,
+ GreaterThan,
+ LessThan,
+ EqualTo,
+}
+
+#[derive(Debug, thiserror::Error)]
+enum OperatorError {
+ #[error("type was not a valid operator")]
+ InvalidType,
+}
+
+impl TryFrom<u8> for OperatorType {
+ type Error = OperatorError;
+ fn try_from(num: u8) -> Result<Self, OperatorError> {
+ match num {
+ 0 => Ok(Self::Sum),
+ 1 => Ok(Self::Product),
+ 2 => Ok(Self::Minimum),
+ 3 => Ok(Self::Maximum),
+ 5 => Ok(Self::GreaterThan),
+ 6 => Ok(Self::LessThan),
+ 7 => Ok(Self::EqualTo),
+ _ => Err(OperatorError::InvalidType),
+ }
+ }
+}
+
+fn convert_to_binary(input: &str) -> IResult<&str, String> {
+ map(
+ many0(map(one_of("0123456789ABCDEF"), |hex_char| {
+ let digit = hex_char.to_digit(16).unwrap();
+ format!("{:04b}", digit)
+ })),
+ |bin_strings| bin_strings.join(""),
+ )(input)
+}
+
+fn parse_packet(input: &str) -> IResult<&str, Packet> {
+ let (input, version) = parse_bits3(input)?;
+ let (input, type_id) = parse_bits3(input)?;
+ if type_id == 4 {
+ let (input, literal) = parse_literal(input)?;
+ Ok((
+ input,
+ Packet {
+ version,
+ data: PacketData::Literal(literal),
+ },
+ ))
+ } else {
+ let (input, sub_packets) =
+ alt((parse_sub_packets_bits_mode, parse_sub_packets_count_mode))(input)?;
+ Ok((
+ input,
+ Packet {
+ version,
+ data: PacketData::Operator(OperatorData {
+ type_id: type_id.try_into().expect("Invalid operator"),
+ sub_packets,
+ }),
+ },
+ ))
+ }
+}
+
+fn parse_bits3(input: &str) -> IResult<&str, u8> {
+ map_res(take(3usize), |bin_str| u8::from_str_radix(bin_str, 2))(input)
+}
+
+fn parse_literal(input: &str) -> IResult<&str, u64> {
+ let (input, mut chunks) = many0(parse_literal_continuing_chunk)(input)?;
+ let (input, last_chunk) = parse_literal_last_chunk(input)?;
+ chunks.push(last_chunk);
+ let binary_num = chunks.join("");
+ let num = u64::from_str_radix(&binary_num, 2).map_err(|e| {
+ nom::Err::Error(nom::error::Error::from_external_error(
+ input,
+ nom::error::ErrorKind::MapRes,
+ e,
+ ))
+ })?;
+ Ok((input, num))
+}
+
+fn parse_literal_continuing_chunk(input: &str) -> IResult<&str, &str> {
+ let (input, _) = nom_char('1')(input)?;
+ take(4usize)(input)
+}
+
+fn parse_literal_last_chunk(input: &str) -> IResult<&str, &str> {
+ let (input, _) = nom_char('0')(input)?;
+ take(4usize)(input)
+}
+
+fn parse_sub_packets_bits_mode(input: &str) -> IResult<&str, Vec<Packet>> {
+ let (input, _) = nom_char('0')(input)?;
+ let (mut input, length_in_bits) =
+ map_res(take(15usize), |bin_str| usize::from_str_radix(bin_str, 2))(input)?;
+ let mut consumed_by_subpackets = String::new();
+ let mut sub_packets = Vec::new();
+ while consumed_by_subpackets.len() < length_in_bits {
+ let (next_input, (next_consumed, next_packet)) = consumed(parse_packet)(input)?;
+ input = next_input;
+ consumed_by_subpackets += next_consumed;
+ sub_packets.push(next_packet);
+ }
+ Ok((input, sub_packets))
+}
+
+fn parse_sub_packets_count_mode(input: &str) -> IResult<&str, Vec<Packet>> {
+ let (input, _) = nom_char('1')(input)?;
+ let (mut input, number_of_packets) =
+ map_res(take(11usize), |bin_str| u16::from_str_radix(bin_str, 2))(input)?;
+ let mut sub_packets = Vec::new();
+ for _ in 0..number_of_packets {
+ let (next_input, next_packet) = parse_packet(input)?;
+ input = next_input;
+ sub_packets.push(next_packet);
+ }
+ Ok((input, sub_packets))
+}
diff --git a/2021/src/bin/day_17.rs b/2021/src/bin/day_17.rs
new file mode 100644
index 0000000..0d60240
--- /dev/null
+++ b/2021/src/bin/day_17.rs
@@ -0,0 +1,82 @@
+use nom::{
+ bytes::complete::tag, character::complete::i32 as nom_i32, combinator::map, sequence::tuple,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_17.txt")?;
+ let target = parse_target(&input).unwrap().1;
+
+ let max_y_throw = 0 - target.min_y - 1;
+ let max_height = max_y_throw * (max_y_throw + 1) / 2;
+ dbg!(max_height);
+
+ let min_y_throw = target.min_y;
+ let max_x_throw = target.max_x;
+ let min_x_throw = (2.0 * target.min_x as f32).sqrt() as i32;
+
+ let mut count = 0;
+ for x in min_x_throw..=max_x_throw {
+ for y in min_y_throw..=max_y_throw {
+ if simulate_throw(x, y, &target) {
+ count += 1;
+ }
+ }
+ }
+ dbg!(count);
+
+ Ok(())
+}
+
+fn simulate_throw(mut x_vel: i32, mut y_vel: i32, target: &TargetArea) -> bool {
+ let mut x_pos = 0;
+ let mut y_pos = 0;
+ loop {
+ x_pos += x_vel;
+ y_pos += y_vel;
+ if x_vel > 0 {
+ x_vel -= 1;
+ }
+ y_vel -= 1;
+ if x_pos >= target.min_x
+ && x_pos <= target.max_x
+ && y_pos >= target.min_y
+ && y_pos <= target.max_y
+ {
+ return true;
+ }
+ if x_pos > target.max_x || y_pos < target.min_y {
+ return false;
+ }
+ }
+}
+
+#[derive(Debug)]
+struct TargetArea {
+ min_x: i32,
+ max_x: i32,
+ min_y: i32,
+ max_y: i32,
+}
+
+fn parse_target(input: &str) -> IResult<&str, TargetArea> {
+ map(
+ tuple((
+ tag("target area: x="),
+ nom_i32,
+ tag(".."),
+ nom_i32,
+ tag(", y="),
+ nom_i32,
+ tag(".."),
+ nom_i32,
+ )),
+ |(_, min_x, _, max_x, _, min_y, _, max_y)| TargetArea {
+ min_x,
+ max_x,
+ min_y,
+ max_y,
+ },
+ )(input)
+}
diff --git a/2021/src/bin/day_18.rs b/2021/src/bin/day_18.rs
new file mode 100644
index 0000000..b77f1f1
--- /dev/null
+++ b/2021/src/bin/day_18.rs
@@ -0,0 +1,193 @@
+use nom::{
+ branch::alt,
+ character::complete::{char as nom_char, line_ending, u8 as nom_u8},
+ combinator::map,
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_18.txt")?;
+ let snail_nums = parse_snail_nums(&input).unwrap().1;
+ {
+ let mut snail_nums_iter = snail_nums.clone().into_iter();
+ let sum = snail_nums_iter
+ .next()
+ .map(|first_num| snail_nums_iter.fold(first_num, |acc, next| acc + next))
+ .expect("Expected at least one snail number");
+
+ dbg!(&sum);
+ dbg!(sum.magnitude());
+ }
+
+ let mut max_magnitude = 0;
+ for i in 0..snail_nums.len() {
+ for j in 0..snail_nums.len() {
+ if i != j {
+ let new_magnitude = (snail_nums[i].clone() + snail_nums[j].clone()).magnitude();
+ if new_magnitude > max_magnitude {
+ max_magnitude = new_magnitude;
+ }
+ }
+ }
+ }
+ dbg!(max_magnitude);
+
+ Ok(())
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum SnailNum {
+ Regular(u8),
+ Pair(Box<SnailNum>, Box<SnailNum>),
+}
+
+impl Default for SnailNum {
+ fn default() -> SnailNum {
+ SnailNum::Regular(0)
+ }
+}
+
+#[derive(PartialEq, Eq)]
+enum NormalizeResult {
+ AlreadyNormalized,
+ NormalizeActionHandledInternally,
+ Explode(u8, u8),
+}
+
+impl SnailNum {
+ fn unwrap_val(&self) -> u8 {
+ match self {
+ SnailNum::Regular(val) => *val,
+ SnailNum::Pair(_, _) => panic!("unwrapped the val on a pair"),
+ }
+ }
+ fn add_to_left(&mut self, add: u8) {
+ match self {
+ Self::Regular(val) => *val += add,
+ Self::Pair(left, _) => left.add_to_left(add),
+ }
+ }
+ fn add_to_right(&mut self, add: u8) {
+ match self {
+ Self::Regular(val) => *val += add,
+ Self::Pair(_, right) => right.add_to_right(add),
+ }
+ }
+ fn normalize_split_pass(&mut self) -> NormalizeResult {
+ match self {
+ Self::Regular(val) => {
+ if *val > 9 {
+ let half = *val / 2;
+ *self = SnailNum::Pair(
+ Box::new(SnailNum::Regular(half)),
+ Box::new(SnailNum::Regular(if *val % 2 == 0 {
+ half
+ } else {
+ half + 1
+ })),
+ );
+ return NormalizeResult::NormalizeActionHandledInternally;
+ }
+ }
+ Self::Pair(left, right) => {
+ match left.normalize_split_pass() {
+ NormalizeResult::AlreadyNormalized => {}
+ _ => {
+ return NormalizeResult::NormalizeActionHandledInternally;
+ }
+ }
+ match right.normalize_split_pass() {
+ NormalizeResult::AlreadyNormalized => {}
+ _ => {
+ return NormalizeResult::NormalizeActionHandledInternally;
+ }
+ }
+ }
+ }
+ NormalizeResult::AlreadyNormalized
+ }
+ fn normalize_explode_pass(&mut self, current_depth: u8) -> NormalizeResult {
+ match self {
+ Self::Regular(_val) => {}
+ Self::Pair(left, right) => {
+ if current_depth >= 4 {
+ let result = NormalizeResult::Explode(left.unwrap_val(), right.unwrap_val());
+ *self = SnailNum::Regular(0);
+ return result;
+ }
+ match left.normalize_explode_pass(current_depth + 1) {
+ NormalizeResult::AlreadyNormalized => {}
+ NormalizeResult::NormalizeActionHandledInternally => {
+ return NormalizeResult::NormalizeActionHandledInternally;
+ }
+ NormalizeResult::Explode(leftadd, rightadd) => {
+ right.add_to_left(rightadd);
+ return NormalizeResult::Explode(leftadd, 0);
+ }
+ }
+ match right.normalize_explode_pass(current_depth + 1) {
+ NormalizeResult::AlreadyNormalized => {}
+ NormalizeResult::NormalizeActionHandledInternally => {
+ return NormalizeResult::NormalizeActionHandledInternally;
+ }
+ NormalizeResult::Explode(leftadd, rightadd) => {
+ left.add_to_right(leftadd);
+ return NormalizeResult::Explode(0, rightadd);
+ }
+ }
+ }
+ }
+ NormalizeResult::AlreadyNormalized
+ }
+
+ fn normalize(&mut self) {
+ let mut normalized = false;
+ while !normalized {
+ let explode_result = self.normalize_explode_pass(0);
+ if explode_result == NormalizeResult::AlreadyNormalized {
+ let split_result = self.normalize_split_pass();
+ if split_result == NormalizeResult::AlreadyNormalized {
+ normalized = true;
+ }
+ }
+ }
+ }
+ fn magnitude(&self) -> u64 {
+ match self {
+ Self::Regular(val) => *val as u64,
+ Self::Pair(left, right) => 3 * left.magnitude() + 2 * right.magnitude(),
+ }
+ }
+}
+
+impl std::ops::Add<SnailNum> for SnailNum {
+ type Output = SnailNum;
+ fn add(self, other: SnailNum) -> SnailNum {
+ let mut result = SnailNum::Pair(Box::new(self), Box::new(other));
+ result.normalize();
+ result
+ }
+}
+
+fn parse_snail_nums(input: &str) -> IResult<&str, Vec<SnailNum>> {
+ separated_list1(line_ending, parse_snail_num)(input)
+}
+
+fn parse_snail_num(input: &str) -> IResult<&str, SnailNum> {
+ alt((
+ map(nom_u8, SnailNum::Regular),
+ map(
+ tuple((
+ nom_char('['),
+ parse_snail_num,
+ nom_char(','),
+ parse_snail_num,
+ nom_char(']'),
+ )),
+ |(_, left, _, right, _)| SnailNum::Pair(Box::new(left), Box::new(right)),
+ ),
+ ))(input)
+}
diff --git a/2021/src/bin/day_19.rs b/2021/src/bin/day_19.rs
new file mode 100644
index 0000000..3fd8291
--- /dev/null
+++ b/2021/src/bin/day_19.rs
@@ -0,0 +1,223 @@
+use nom::{
+ bytes::complete::tag,
+ character::complete::{char as nom_char, i32 as nom_i32, line_ending, not_line_ending},
+ combinator::map,
+ multi::{many1, separated_list1},
+ sequence::tuple,
+ IResult,
+};
+use std::{collections::BTreeSet, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_19.txt")?;
+ let mut scanner_data = parse_scanner_cloud(&input).unwrap().1;
+ scanner_data.align_scanners();
+ let beacons = scanner_data.combine_beacons();
+ dbg!(&beacons.len());
+ dbg!(scanner_data.max_aligned_sensor_distance());
+ Ok(())
+}
+
+#[derive(Default, Debug)]
+struct ScannerCloud {
+ aligned_scanners: Vec<Scanner>,
+ aligned_checking_for_neighbours_scanners: Vec<Scanner>,
+ unaligned_scanners: Vec<Scanner>,
+}
+
+impl ScannerCloud {
+ fn new(mut scanners: Vec<Scanner>) -> ScannerCloud {
+ if let Some(first_aligned_scanner) = scanners.pop() {
+ ScannerCloud {
+ aligned_scanners: Vec::new(),
+ aligned_checking_for_neighbours_scanners: vec![first_aligned_scanner],
+ unaligned_scanners: scanners,
+ }
+ } else {
+ ScannerCloud::default()
+ }
+ }
+
+ fn align_scanners(&mut self) {
+ while let Some(current_aligned_scanner) =
+ self.aligned_checking_for_neighbours_scanners.pop()
+ {
+ let mut to_remove_indices = Vec::new();
+ for i in 0..self.unaligned_scanners.len() {
+ if let Some(aligned) =
+ self.unaligned_scanners[i].try_align_with(&current_aligned_scanner)
+ {
+ to_remove_indices.push(i);
+ self.aligned_checking_for_neighbours_scanners.push(aligned);
+ }
+ }
+ for i in to_remove_indices.into_iter().rev() {
+ self.unaligned_scanners.remove(i);
+ }
+
+ self.aligned_scanners.push(current_aligned_scanner);
+ }
+
+ assert_eq!(
+ self.unaligned_scanners.len(),
+ 0,
+ "Not all scanners were aligned"
+ );
+ assert_eq!(
+ self.aligned_checking_for_neighbours_scanners.len(),
+ 0,
+ "Not all aligned scanners were processed"
+ );
+ }
+
+ fn combine_beacons(&self) -> BTreeSet<Point> {
+ let mut combined_beacons = BTreeSet::new();
+ for scanner in &self.aligned_scanners {
+ combined_beacons.append(&mut scanner.beacons.clone())
+ }
+ combined_beacons
+ }
+
+ fn max_aligned_sensor_distance(&self) -> i32 {
+ let mut max_distance = 0;
+ for a in &self.aligned_scanners {
+ for b in &self.aligned_scanners {
+ let distance = a.position.manhattan_distance(&b.position);
+ if distance > max_distance {
+ max_distance = distance;
+ }
+ }
+ }
+ max_distance
+ }
+}
+
+#[derive(Debug, Clone)]
+struct Scanner {
+ position: Point,
+ beacons: BTreeSet<Point>,
+}
+
+impl Scanner {
+ fn try_align_with(&self, other: &Scanner) -> Option<Scanner> {
+ for (roll, pitch) in [(0, 0), (1, 0), (2, 0), (3, 0), (0, 1), (0, 3)] {
+ for yaw in [0, 1, 2, 3] {
+ let candidate = self.spin(roll, pitch, yaw);
+ for candidate_position in candidate.beacons.iter() {
+ for other_position in other.beacons.iter() {
+ let aligned_candidate =
+ candidate.position(*other_position - *candidate_position);
+ if aligned_candidate.count_overlap(other) >= 12 {
+ return Some(aligned_candidate);
+ }
+ }
+ }
+ }
+ }
+ None
+ }
+
+ fn spin(&self, roll: u8, pitch: u8, yaw: u8) -> Scanner {
+ let beacons = self
+ .beacons
+ .clone()
+ .into_iter()
+ .map(|mut beacon| {
+ for _ in 0..roll {
+ beacon = beacon.roll();
+ }
+ beacon
+ })
+ .map(|mut beacon| {
+ for _ in 0..pitch {
+ beacon = beacon.pitch();
+ }
+ beacon
+ })
+ .map(|mut beacon| {
+ for _ in 0..yaw {
+ beacon = beacon.yaw();
+ }
+ beacon
+ })
+ .collect();
+ Scanner {
+ position: self.position, // this is wrong, but doesn't matter because we spin then position
+ beacons,
+ }
+ }
+
+ fn position(&self, offset: Point) -> Scanner {
+ Scanner {
+ position: self.position + offset,
+ beacons: self.beacons.iter().map(|b| *b + offset).collect(),
+ }
+ }
+
+ fn count_overlap(&self, other: &Scanner) -> usize {
+ self.beacons.intersection(&other.beacons).count()
+ }
+}
+
+#[derive(
+ Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, derive_more::Sub, derive_more::Add,
+)]
+struct Point {
+ x: i32,
+ y: i32,
+ z: i32,
+}
+
+impl Point {
+ fn roll(self) -> Self {
+ Point {
+ x: self.x,
+ y: self.z,
+ z: -self.y,
+ }
+ }
+
+ fn pitch(self) -> Self {
+ Point {
+ x: -self.z,
+ y: self.y,
+ z: self.x,
+ }
+ }
+
+ fn yaw(self) -> Self {
+ Point {
+ x: -self.y,
+ y: self.x,
+ z: self.z,
+ }
+ }
+
+ fn manhattan_distance(&self, other: &Point) -> i32 {
+ (self.x - other.x).abs() + (self.y - other.y).abs() + (self.z - other.z).abs()
+ }
+}
+
+fn parse_scanner_cloud(input: &str) -> IResult<&str, ScannerCloud> {
+ map(
+ separated_list1(many1(line_ending), parse_scanner),
+ ScannerCloud::new,
+ )(input)
+}
+
+fn parse_scanner(input: &str) -> IResult<&str, Scanner> {
+ let (input, _) = tuple((tag("--- scanner"), not_line_ending, line_ending))(input)?;
+ map(separated_list1(line_ending, parse_point), |beacons| {
+ Scanner {
+ position: Point::default(),
+ beacons: beacons.into_iter().collect(),
+ }
+ })(input)
+}
+
+fn parse_point(input: &str) -> IResult<&str, Point> {
+ map(
+ tuple((nom_i32, nom_char(','), nom_i32, nom_char(','), nom_i32)),
+ |(x, _, y, _, z)| Point { x, y, z },
+ )(input)
+}
diff --git a/2021/src/bin/day_2.rs b/2021/src/bin/day_2.rs
new file mode 100644
index 0000000..08d01c3
--- /dev/null
+++ b/2021/src/bin/day_2.rs
@@ -0,0 +1,100 @@
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{i64 as nom_i64, line_ending, space1},
+ combinator::{map, value},
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_2.txt")?;
+ let route = parse_route(&input).unwrap().1;
+
+ let mut position = Position::default();
+ for instruction in &route {
+ position.advance(&instruction);
+ }
+ dbg!(position.horizontal.0 * position.depth.0);
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct Route(Vec<Instruction>);
+
+impl<'a> IntoIterator for &'a Route {
+ type Item = &'a Instruction;
+ type IntoIter = std::slice::Iter<'a, Instruction>;
+ fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
+ self.0.iter()
+ }
+}
+
+#[derive(Debug)]
+struct Instruction {
+ direction: Direction,
+ distance: Distance,
+}
+
+#[derive(Debug, Clone)]
+enum Direction {
+ Forward,
+ Up,
+ Down,
+}
+#[derive(
+ Default,
+ Debug,
+ Clone,
+ Copy,
+ derive_more::Add,
+ derive_more::AddAssign,
+ derive_more::Sub,
+ derive_more::SubAssign,
+)]
+struct Distance(i64);
+
+#[derive(Default, Debug)]
+struct Position {
+ horizontal: Distance,
+ depth: Distance,
+}
+
+impl Position {
+ fn advance(&mut self, instruction: &Instruction) {
+ match instruction.direction {
+ Direction::Forward => self.horizontal += instruction.distance,
+ Direction::Down => self.depth += instruction.distance,
+ Direction::Up => self.depth -= instruction.distance,
+ }
+ }
+}
+
+fn parse_route(input: &str) -> IResult<&str, Route> {
+ map(separated_list1(line_ending, parse_instruction), Route)(input)
+}
+
+fn parse_instruction(input: &str) -> IResult<&str, Instruction> {
+ map(
+ tuple((parse_direction, space1, parse_distance)),
+ |(direction, _, distance)| Instruction {
+ direction,
+ distance,
+ },
+ )(input)
+}
+
+fn parse_direction(input: &str) -> IResult<&str, Direction> {
+ alt((
+ value(Direction::Forward, tag("forward")),
+ value(Direction::Up, tag("up")),
+ value(Direction::Down, tag("down")),
+ ))(input)
+}
+
+fn parse_distance(input: &str) -> IResult<&str, Distance> {
+ map(nom_i64, Distance)(input)
+}
diff --git a/2021/src/bin/day_20.rs b/2021/src/bin/day_20.rs
new file mode 100644
index 0000000..4b42658
--- /dev/null
+++ b/2021/src/bin/day_20.rs
@@ -0,0 +1,201 @@
+use nom::{
+ branch::alt,
+ character::complete::{char as nom_char, line_ending},
+ combinator::{map, map_res, value},
+ multi::{many1, separated_list1},
+ sequence::tuple,
+ IResult,
+};
+use std::{collections::BTreeSet, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_20.txt")?;
+ let mut enhanceable_image = parse_enhanceable_image(&input).unwrap().1;
+ for _ in 0..2 {
+ enhanceable_image = enhanceable_image.enhance();
+ }
+ dbg!(enhanceable_image.image.count_light_spots().unwrap());
+ for _ in 2..50 {
+ enhanceable_image = enhanceable_image.enhance();
+ }
+ dbg!(enhanceable_image.image.count_light_spots().unwrap());
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct EnhanceableImage {
+ enhancement_lights: [bool; 512],
+ image: Image,
+}
+
+impl EnhanceableImage {
+ fn enhance(&self) -> EnhanceableImage {
+ let current_background_dark = matches!(self.image, Image::LightSpots(_));
+ let next_background_dark =
+ !self.enhancement_lights[if current_background_dark { 0 } else { 511 }];
+ let mut spots = BTreeSet::new();
+
+ let top_left = self.image.top_left(1);
+ let bottom_right = self.image.bottom_right(1);
+ for y in top_left.y..=bottom_right.y {
+ for x in top_left.x..=bottom_right.x {
+ let center = Point { x, y };
+ let surrounds = center.surrounds();
+ let number = self.image.to_number(surrounds);
+ let center_is_light = self.enhancement_lights[number];
+ if center_is_light == next_background_dark {
+ spots.insert(center);
+ }
+ }
+ }
+
+ EnhanceableImage {
+ enhancement_lights: self.enhancement_lights.clone(),
+ image: if next_background_dark {
+ Image::LightSpots(spots)
+ } else {
+ Image::DarkSpots(spots)
+ },
+ }
+ }
+}
+
+#[derive(Debug)]
+enum Image {
+ LightSpots(BTreeSet<Point>),
+ DarkSpots(BTreeSet<Point>),
+}
+
+#[derive(Debug)]
+enum ImageError {
+ InfiniteLight,
+}
+
+impl Image {
+ fn count_light_spots(&self) -> Result<usize, ImageError> {
+ match self {
+ Self::LightSpots(spots) => Ok(spots.len()),
+ Self::DarkSpots(_) => Err(ImageError::InfiniteLight),
+ }
+ }
+
+ fn top_left(&self, margin: i32) -> Point {
+ let (Self::LightSpots(spots) | Self::DarkSpots(spots)) = self;
+ let min_x = spots.iter().map(|p| p.x).min().unwrap_or(0);
+ let min_y = spots.iter().map(|p| p.y).min().unwrap_or(0);
+ Point {
+ x: min_x - margin,
+ y: min_y - margin,
+ }
+ }
+
+ fn bottom_right(&self, margin: i32) -> Point {
+ let (Self::LightSpots(spots) | Self::DarkSpots(spots)) = self;
+ let max_x = spots.iter().map(|p| p.x).max().unwrap_or(0);
+ let max_y = spots.iter().map(|p| p.y).max().unwrap_or(0);
+ Point {
+ x: max_x + margin,
+ y: max_y + margin,
+ }
+ }
+
+ fn to_number(&self, bit_locations: [Point; 9]) -> usize {
+ let mut result = 0;
+ for bit_location in bit_locations {
+ result <<= 1;
+ let next_is_1 = match self {
+ Self::LightSpots(spots) => spots.contains(&bit_location),
+ Self::DarkSpots(spots) => !spots.contains(&bit_location),
+ };
+ if next_is_1 {
+ result += 1;
+ }
+ }
+ result
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+impl Point {
+ fn surrounds(&self) -> [Point; 9] {
+ [
+ Point {
+ x: self.x - 1,
+ y: self.y - 1,
+ },
+ Point {
+ x: self.x,
+ y: self.y - 1,
+ },
+ Point {
+ x: self.x + 1,
+ y: self.y - 1,
+ },
+ Point {
+ x: self.x - 1,
+ y: self.y,
+ },
+ Point {
+ x: self.x,
+ y: self.y,
+ },
+ Point {
+ x: self.x + 1,
+ y: self.y,
+ },
+ Point {
+ x: self.x - 1,
+ y: self.y + 1,
+ },
+ Point {
+ x: self.x,
+ y: self.y + 1,
+ },
+ Point {
+ x: self.x + 1,
+ y: self.y + 1,
+ },
+ ]
+ }
+}
+
+fn parse_enhanceable_image(input: &str) -> IResult<&str, EnhanceableImage> {
+ map(
+ tuple((parse_enhancement_lights, many1(line_ending), parse_image)),
+ |(enhancement_lights, _, image)| EnhanceableImage {
+ enhancement_lights,
+ image,
+ },
+ )(input)
+}
+
+fn parse_enhancement_lights(input: &str) -> IResult<&str, [bool; 512]> {
+ map_res(many1(parse_pixel), |pixels| pixels.try_into())(input)
+}
+
+fn parse_image(input: &str) -> IResult<&str, Image> {
+ map(separated_list1(line_ending, many1(parse_pixel)), |pixels| {
+ let mut result = BTreeSet::new();
+ for (y, row) in pixels.into_iter().enumerate() {
+ for (x, light) in row.into_iter().enumerate() {
+ if light {
+ result.insert(Point {
+ x: x as i32,
+ y: y as i32,
+ });
+ }
+ }
+ }
+ Image::LightSpots(result)
+ })(input)
+}
+
+fn parse_pixel(input: &str) -> IResult<&str, bool> {
+ alt((value(true, nom_char('#')), value(false, nom_char('.'))))(input)
+}
diff --git a/2021/src/bin/day_21.rs b/2021/src/bin/day_21.rs
new file mode 100644
index 0000000..245a0e6
--- /dev/null
+++ b/2021/src/bin/day_21.rs
@@ -0,0 +1,76 @@
+use cached::proc_macro::cached;
+use nom::{
+ bytes::complete::tag,
+ character::complete::u32 as nom_u32,
+ combinator::map,
+ sequence::{preceded, tuple},
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_21.txt")?;
+ let player_positions = parse_starting_positions(&input).unwrap().1;
+ {
+ let mut player_positions = player_positions.clone();
+ let mut player_scores = [0, 0];
+ let mut dice = (1..=100).cycle().enumerate().peekable();
+ let mut player_turn = 0;
+ while player_scores[0] < 1000 && player_scores[1] < 1000 {
+ let dice_roll: u32 = dice.by_ref().take(3).map(|(_, roll)| roll).sum();
+ player_positions[player_turn] = (player_positions[player_turn] + dice_roll) % 10;
+ if player_positions[player_turn] == 0 {
+ player_positions[player_turn] = 10;
+ }
+ player_scores[player_turn] += player_positions[player_turn];
+ player_turn = (player_turn + 1) % 2;
+ }
+ let losing_score = player_scores.iter().min().cloned().unwrap_or(0);
+ let dice_roll_count = dice.peek().unwrap().0;
+ dbg!((losing_score, dice_roll_count));
+ dbg!(losing_score * dice_roll_count as u32);
+ }
+
+ let win_counts = player_win_counts(player_positions, [0, 0]);
+ dbg!(win_counts);
+ dbg!(win_counts.into_iter().max().unwrap_or(0));
+ Ok(())
+}
+
+#[cached]
+fn player_win_counts(player_positions: [u32; 2], player_scores: [u32; 2]) -> [u64; 2] {
+ let mut win_counts = [0; 2];
+ for dice_roll_1 in 1..=3 {
+ for dice_roll_2 in 1..=3 {
+ for dice_roll_3 in 1..=3 {
+ let dice_roll = dice_roll_1 + dice_roll_2 + dice_roll_3;
+ let mut new_position = (player_positions[0] + dice_roll) % 10;
+ if new_position == 0 {
+ new_position = 10;
+ }
+ let new_score = player_scores[0] + new_position;
+ if new_score >= 21 {
+ win_counts[0] += 1;
+ } else {
+ let recursive_wins = player_win_counts(
+ [player_positions[1], new_position],
+ [player_scores[1], new_score],
+ );
+ win_counts[0] += recursive_wins[1];
+ win_counts[1] += recursive_wins[0];
+ }
+ }
+ }
+ }
+ win_counts
+}
+
+fn parse_starting_positions(input: &str) -> IResult<&str, [u32; 2]> {
+ map(
+ tuple((
+ preceded(tag("Player 1 starting position: "), nom_u32),
+ preceded(tag("\nPlayer 2 starting position: "), nom_u32),
+ )),
+ |(a, b)| [a, b],
+ )(input)
+}
diff --git a/2021/src/bin/day_22.rs b/2021/src/bin/day_22.rs
new file mode 100644
index 0000000..85d9ec9
--- /dev/null
+++ b/2021/src/bin/day_22.rs
@@ -0,0 +1,379 @@
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{i32 as nom_i32, line_ending},
+ combinator::{map, value},
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::{cmp, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_22.txt")?;
+ let instructions = parse_instructions(&input).unwrap().1;
+ {
+ let bounds_50 = Block {
+ min_x: -50,
+ max_x: 51,
+ min_y: -50,
+ max_y: 51,
+ min_z: -50,
+ max_z: 51,
+ };
+ let mut octtree_50 = OctTree::default();
+ for instruction in &instructions {
+ octtree_50.set_block(&bounds_50, &instruction.bounds, instruction.new_state);
+ }
+ dbg!(octtree_50.count_on_blocks(&bounds_50));
+ }
+
+ {
+ let problem_boundary = Block {
+ min_x: instructions
+ .iter()
+ .map(|i| i.bounds.min_x)
+ .min()
+ .unwrap_or(0),
+ max_x: instructions
+ .iter()
+ .map(|i| i.bounds.max_x)
+ .max()
+ .unwrap_or(0),
+ min_y: instructions
+ .iter()
+ .map(|i| i.bounds.min_y)
+ .min()
+ .unwrap_or(0),
+ max_y: instructions
+ .iter()
+ .map(|i| i.bounds.max_y)
+ .max()
+ .unwrap_or(0),
+ min_z: instructions
+ .iter()
+ .map(|i| i.bounds.min_z)
+ .min()
+ .unwrap_or(0),
+ max_z: instructions
+ .iter()
+ .map(|i| i.bounds.max_z)
+ .max()
+ .unwrap_or(0),
+ }
+ .expand_to_power_cube();
+
+ // This chunking and adding partial solutions is necessary
+ // because I can't fit the whole thing in memory at once :(
+ // It runs really slowly.
+ let mut count = 0;
+ for chunk_index in 0..8 {
+ let problem_boundary = problem_boundary.oct_chunk(chunk_index);
+ for chunk_index in 0..8 {
+ let problem_boundary = problem_boundary.oct_chunk(chunk_index);
+ for chunk_index in 0..8 {
+ let problem_boundary = problem_boundary.oct_chunk(chunk_index);
+ let mut octtree = OctTree::default();
+ for instruction in &instructions {
+ octtree.set_block(
+ &problem_boundary,
+ &instruction.bounds,
+ instruction.new_state,
+ );
+ }
+ count += dbg!(octtree.count_on_blocks(&problem_boundary));
+ }
+ }
+ }
+ dbg!(count);
+ }
+
+ Ok(())
+}
+
+#[derive(Default, Clone)]
+struct OctTree {
+ data: OctTreeData,
+}
+
+impl OctTree {
+ fn set_block(&mut self, self_bounds: &Block, bounds: &Block, new_val: bool) {
+ if bounds.completely_covers(self_bounds) {
+ self.data = new_val.into();
+ } else if bounds.intersects(self_bounds) {
+ match &mut self.data {
+ OctTreeData::AllOff => {
+ if new_val {
+ self.split(self_bounds);
+ self.set_block(self_bounds, bounds, new_val);
+ }
+ }
+ OctTreeData::AllOn => {
+ if !new_val {
+ self.split(self_bounds);
+ self.set_block(self_bounds, bounds, new_val);
+ }
+ }
+ OctTreeData::BitSet(ref mut bits) => {
+ let min_x = cmp::max(self_bounds.min_x, bounds.min_x);
+ let max_x = cmp::min(self_bounds.max_x, bounds.max_x);
+ let min_x_index = (min_x - self_bounds.min_x) as usize;
+ let max_x_index = min_x_index + (max_x - min_x) as usize;
+
+ let min_y = cmp::max(self_bounds.min_y, bounds.min_y);
+ let max_y = cmp::min(self_bounds.max_y, bounds.max_y);
+ let min_y_index = (min_y - self_bounds.min_y) as usize;
+ let max_y_index = min_y_index + (max_y - min_y) as usize;
+
+ let min_z = cmp::max(self_bounds.min_z, bounds.min_z);
+ let max_z = cmp::min(self_bounds.max_z, bounds.max_z);
+ let min_z_index = (min_z - self_bounds.min_z) as usize;
+ let max_z_index = min_z_index + (max_z - min_z) as usize;
+
+ for z_index in min_z_index..max_z_index {
+ let z_bit_index = z_index << 4;
+ for y_index in min_y_index..max_y_index {
+ let y_bit_index = y_index << 2;
+ for x_index in min_x_index..max_x_index {
+ let x_bit_index = x_index;
+ let bit_mask = 1u64 << (z_bit_index + y_bit_index + x_bit_index);
+ if new_val {
+ *bits |= bit_mask;
+ } else {
+ *bits &= !bit_mask;
+ }
+ }
+ }
+ }
+
+ if *bits == 0 {
+ self.data = OctTreeData::AllOff;
+ } else if *bits == !0u64 {
+ self.data = OctTreeData::AllOn;
+ }
+ }
+ OctTreeData::Diverse(ref mut subtrees) => {
+ for (sub_index, sub) in subtrees.iter_mut().enumerate() {
+ sub.set_block(&self_bounds.oct_chunk(sub_index as u8), bounds, new_val);
+ }
+ if subtrees
+ .iter()
+ .all(|sub| matches!(sub.data, OctTreeData::AllOn))
+ {
+ self.data = OctTreeData::AllOn;
+ } else if subtrees
+ .iter()
+ .all(|sub| matches!(sub.data, OctTreeData::AllOff))
+ {
+ self.data = OctTreeData::AllOff;
+ }
+ }
+ };
+ }
+ }
+
+ fn split(&mut self, self_bounds: &Block) {
+ assert!(!matches!(self.data, OctTreeData::Diverse(_)));
+ if self_bounds.volume() == 64 {
+ let new_bitset = match self.data {
+ OctTreeData::AllOn => !0u64,
+ OctTreeData::AllOff => 0,
+ _ => panic!("weird split"),
+ };
+ self.data = OctTreeData::BitSet(new_bitset);
+ } else {
+ let template = OctTree {
+ data: self.data.clone(),
+ };
+ self.data = OctTreeData::Diverse(Box::new([
+ template.clone(),
+ template.clone(),
+ template.clone(),
+ template.clone(),
+ template.clone(),
+ template.clone(),
+ template.clone(),
+ template.clone(),
+ ]));
+ }
+ }
+
+ fn count_on_blocks(&self, self_bounds: &Block) -> usize {
+ match &self.data {
+ OctTreeData::AllOff => 0,
+ OctTreeData::AllOn => self_bounds.volume(),
+ OctTreeData::BitSet(bitset) => bitset.count_ones() as usize,
+ OctTreeData::Diverse(subtrees) => subtrees
+ .iter()
+ .enumerate()
+ .map(|(index, sub)| sub.count_on_blocks(&self_bounds.oct_chunk(index as u8)))
+ .sum(),
+ }
+ }
+}
+
+#[derive(Clone)]
+enum OctTreeData {
+ AllOff,
+ AllOn,
+ BitSet(u64),
+ Diverse(Box<[OctTree; 8]>),
+}
+
+impl Default for OctTreeData {
+ fn default() -> OctTreeData {
+ Self::AllOff
+ }
+}
+
+impl From<bool> for OctTreeData {
+ fn from(b: bool) -> Self {
+ if b {
+ Self::AllOn
+ } else {
+ Self::AllOff
+ }
+ }
+}
+
+#[derive(Debug)]
+struct Instruction {
+ new_state: bool,
+ bounds: Block,
+}
+
+#[derive(Debug, Clone)]
+struct Block {
+ min_x: i32,
+ max_x: i32,
+ min_y: i32,
+ max_y: i32,
+ min_z: i32,
+ max_z: i32,
+}
+
+impl Block {
+ fn volume(&self) -> usize {
+ let x = (self.max_x - self.min_x) as usize;
+ let y = (self.max_y - self.min_y) as usize;
+ let z = (self.max_z - self.min_z) as usize;
+ x * y * z
+ }
+
+ fn completely_covers(&self, other: &Self) -> bool {
+ self.min_x <= other.min_x
+ && self.max_x >= other.max_x
+ && self.min_y <= other.min_y
+ && self.max_y >= other.max_y
+ && self.min_z <= other.min_z
+ && self.max_z >= other.max_z
+ }
+
+ fn intersects(&self, other: &Self) -> bool {
+ if self.max_x <= other.min_x
+ || self.min_x >= other.max_x
+ || self.max_y <= other.min_y
+ || self.min_y >= other.max_y
+ || self.max_z <= other.min_z
+ || self.min_z >= other.max_z
+ {
+ false
+ } else {
+ true
+ }
+ }
+
+ fn oct_chunk(&self, chunk: u8) -> Block {
+ let lower_x = (chunk & 1) == 0;
+ let lower_y = (chunk & 2) == 0;
+ let lower_z = (chunk & 4) == 0;
+
+ let mid_x = (self.min_x + self.max_x) / 2;
+ let mid_y = (self.min_y + self.max_y) / 2;
+ let mid_z = (self.min_z + self.max_z) / 2;
+
+ Block {
+ min_x: if lower_x { self.min_x } else { mid_x },
+ max_x: if lower_x { mid_x } else { self.max_x },
+ min_y: if lower_y { self.min_y } else { mid_y },
+ max_y: if lower_y { mid_y } else { self.max_y },
+ min_z: if lower_z { self.min_z } else { mid_z },
+ max_z: if lower_z { mid_z } else { self.max_z },
+ }
+ }
+
+ fn expand_to_power_cube(&self) -> Block {
+ let mag_x = self.max_x - self.min_x;
+ let mag_y = self.max_y - self.min_y;
+ let mag_z = self.max_z - self.min_z;
+ let mag_max = cmp::max(mag_x, cmp::max(mag_y, mag_z));
+ let first_power_of_2 = (0..)
+ .map(|pow| 2_i32.pow(pow))
+ .filter(|pow_size| *pow_size >= mag_max)
+ .next()
+ .unwrap();
+
+ Block {
+ min_x: self.min_x,
+ max_x: self.max_x + first_power_of_2 - mag_x,
+ min_y: self.min_y,
+ max_y: self.max_y + first_power_of_2 - mag_y,
+ min_z: self.min_z,
+ max_z: self.max_z + first_power_of_2 - mag_z,
+ }
+ }
+}
+
+fn parse_instructions(input: &str) -> IResult<&str, Vec<Instruction>> {
+ separated_list1(line_ending, parse_instruction)(input)
+}
+
+fn parse_instruction(input: &str) -> IResult<&str, Instruction> {
+ map(
+ tuple((
+ alt((value(true, tag("on ")), value(false, tag("off ")))),
+ parse_block,
+ )),
+ |(new_state, bounds)| Instruction { new_state, bounds },
+ )(input)
+}
+
+fn parse_block(input: &str) -> IResult<&str, Block> {
+ map(
+ tuple((
+ tag("x="),
+ nom_i32,
+ tag(".."),
+ nom_i32,
+ tag(",y="),
+ nom_i32,
+ tag(".."),
+ nom_i32,
+ tag(",z="),
+ nom_i32,
+ tag(".."),
+ nom_i32,
+ )),
+ |(
+ _,
+ min_x,
+ _,
+ max_x_inclusive,
+ _,
+ min_y,
+ _,
+ max_y_inclusive,
+ _,
+ min_z,
+ _,
+ max_z_inclusive,
+ )| Block {
+ min_x,
+ max_x: max_x_inclusive + 1,
+ min_y,
+ max_y: max_y_inclusive + 1,
+ min_z,
+ max_z: max_z_inclusive + 1,
+ },
+ )(input)
+}
diff --git a/2021/src/bin/day_23.rs b/2021/src/bin/day_23.rs
new file mode 100644
index 0000000..ed2fb01
--- /dev/null
+++ b/2021/src/bin/day_23.rs
@@ -0,0 +1,224 @@
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{char as nom_char, line_ending, not_line_ending},
+ combinator::value,
+ multi::{many1, separated_list1},
+ sequence::{delimited, pair},
+ IResult,
+};
+use std::{cmp, collections::HashSet, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_23.txt")?;
+ let maze = parse_maze(&input).unwrap().1;
+ dbg!(find_shortest_path(&maze).cost);
+ Ok(())
+}
+
+fn find_shortest_path(maze: &Maze) -> Move {
+ let mut visited = HashSet::new();
+ visited.insert(maze.clone());
+ let mut frontier = vec![Move {
+ next_state: maze.clone(),
+ cost: 0,
+ }];
+
+ let mut best_so_far: Option<Move> = None;
+
+ while let Some(current) = frontier.pop() {
+ if let Some(best_so_far) = &best_so_far {
+ if current.cost >= best_so_far.cost {
+ return best_so_far.clone();
+ }
+ }
+
+ let next_moves: Vec<Move> = current
+ .next_state
+ .valid_moves()
+ .into_iter()
+ .map(|next| Move {
+ cost: next.cost + current.cost,
+ ..next
+ })
+ .collect();
+ for next in next_moves {
+ if next.next_state.is_complete() {
+ best_so_far = if let Some(best_so_far) = best_so_far {
+ if best_so_far.cost < next.cost {
+ Some(best_so_far)
+ } else {
+ Some(next.clone())
+ }
+ } else {
+ Some(next.clone())
+ };
+ } else if !visited.contains(&next.next_state) {
+ visited.insert(next.next_state.clone());
+ frontier.push(next);
+ }
+ }
+ frontier.sort_unstable_by(|a, b| b.cost.cmp(&a.cost));
+ }
+ best_so_far.expect("There is no path through!")
+}
+
+#[derive(Debug, Clone)]
+struct Move {
+ next_state: Maze,
+ cost: usize,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+struct Maze {
+ corridor: Vec<Option<usize>>,
+ rooms: Vec<Room>,
+}
+
+impl Maze {
+ fn is_complete(&self) -> bool {
+ self.rooms.iter().all(|room| room.is_complete())
+ }
+
+ fn valid_moves(&self) -> Vec<Move> {
+ let mut valid_moves = Vec::new();
+
+ for i in 0..self.corridor.len() {
+ if let Some(shrimp) = self.corridor[i] {
+ let target_room = &self.rooms[shrimp / 2 - 1];
+ if target_room.can_enter() {
+ let route_free = (cmp::min(shrimp, i)..=cmp::max(shrimp, i))
+ .all(|route_i| route_i == i || self.corridor[route_i].is_none());
+ if route_free {
+ let mut next_state = self.clone();
+ next_state.corridor[i] = None;
+ let next_room = &mut next_state.rooms[shrimp / 2 - 1];
+ let room_depth = next_room
+ .max_free()
+ .expect("no space in room, but we checked!");
+ next_room.contents[room_depth] = Some(shrimp);
+ let distance = room_depth + 1 + cmp::max(shrimp, i) - cmp::min(shrimp, i);
+ let cost = calculate_cost(shrimp, distance);
+ valid_moves.push(Move { next_state, cost });
+ }
+ }
+ }
+ }
+
+ for (room_i, room) in self
+ .rooms
+ .iter()
+ .enumerate()
+ .filter(|(_, room)| !room.can_enter())
+ {
+ if let Some((room_depth, shrimp)) = room
+ .contents
+ .iter()
+ .enumerate()
+ .filter_map(|(room_depth, maybe_shrimp)| {
+ maybe_shrimp.map(|shrimp| (room_depth, shrimp))
+ })
+ .next()
+ {
+ for corridor_i in 0..self.corridor.len() {
+ let in_entrance = self.rooms.iter().any(|room| room.entrance == corridor_i);
+ let route_free = (cmp::min(room.entrance, corridor_i)
+ ..=cmp::max(room.entrance, corridor_i))
+ .all(|route_i| self.corridor[route_i].is_none());
+ if !in_entrance && route_free {
+ let mut next_state = self.clone();
+ next_state.corridor[corridor_i] = Some(shrimp);
+ next_state.rooms[room_i].contents[room_depth] = None;
+
+ let distance = room_depth + 1 + cmp::max(room.entrance, corridor_i)
+ - cmp::min(room.entrance, corridor_i);
+ let cost = calculate_cost(shrimp, distance);
+ valid_moves.push(Move { next_state, cost });
+ }
+ }
+ }
+ }
+
+ valid_moves
+ }
+}
+
+fn calculate_cost(shrimp: usize, distance: usize) -> usize {
+ let shrimp_cost = match shrimp {
+ 2 => 1,
+ 4 => 10,
+ 6 => 100,
+ 8 => 1000,
+ _ => panic!("Unknown shrimp"),
+ };
+ shrimp_cost * distance
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+struct Room {
+ entrance: usize,
+ contents: Vec<Option<usize>>,
+}
+
+impl Room {
+ fn is_complete(&self) -> bool {
+ self.contents
+ .iter()
+ .all(|slot| slot == &Some(self.entrance))
+ }
+ fn can_enter(&self) -> bool {
+ self.contents
+ .iter()
+ .all(|slot| slot.is_none() || slot == &Some(self.entrance))
+ }
+ fn max_free(&self) -> Option<usize> {
+ self.contents.iter().rposition(|slot| slot.is_none())
+ }
+}
+
+fn parse_maze(input: &str) -> IResult<&str, Maze> {
+ let (input, _) = pair(not_line_ending, line_ending)(input)?; // skip first line
+ let (input, corridor) = delimited(nom_char('#'), many1(corridor_contents), tag("#\n"))(input)?;
+
+ let (input, rooms_line_1) = delimited(
+ tag("###"),
+ separated_list1(nom_char('#'), corridor_contents),
+ tag("###\n"),
+ )(input)?;
+ let (input, rooms_line_2) = delimited(
+ tag(" #"),
+ separated_list1(nom_char('#'), corridor_contents),
+ tag("#\n"),
+ )(input)?;
+
+ let rooms = vec![
+ Room {
+ entrance: 2,
+ contents: vec![rooms_line_1[0], Some(8), Some(8), rooms_line_2[0]],
+ },
+ Room {
+ entrance: 4,
+ contents: vec![rooms_line_1[1], Some(6), Some(4), rooms_line_2[1]],
+ },
+ Room {
+ entrance: 6,
+ contents: vec![rooms_line_1[2], Some(4), Some(2), rooms_line_2[2]],
+ },
+ Room {
+ entrance: 8,
+ contents: vec![rooms_line_1[3], Some(2), Some(6), rooms_line_2[3]],
+ },
+ ];
+
+ Ok((input, Maze { corridor, rooms }))
+}
+
+fn corridor_contents(input: &str) -> IResult<&str, Option<usize>> {
+ alt((
+ value(None, nom_char('.')),
+ value(Some(2), nom_char('A')),
+ value(Some(4), nom_char('B')),
+ value(Some(6), nom_char('C')),
+ value(Some(8), nom_char('D')),
+ ))(input)
+}
diff --git a/2021/src/bin/day_24.rs b/2021/src/bin/day_24.rs
new file mode 100644
index 0000000..2916f57
--- /dev/null
+++ b/2021/src/bin/day_24.rs
@@ -0,0 +1,588 @@
+use nom::{
+ branch::alt,
+ bytes::complete::{is_not, tag},
+ character::complete::{line_ending, space1},
+ combinator::map,
+ multi::separated_list1,
+ sequence::{pair, preceded, separated_pair},
+ IResult,
+};
+use proptest::prelude::*;
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_24.txt")?;
+ let program = parse_program(&input).unwrap().1;
+ program.print_oracle();
+
+ // input[2] - 8 == input[3]
+ // input[4] + 8 == input[5]
+ // input[7] + 6 == input[8]
+ // input[9] + 5 == input[10]
+ // input[6] - 3 == input[11]
+ // input[1] - 1 == input[12]
+ // input[0] - 5 == input[13]
+
+ dbg!(refactored([9, 9, 9, 1, 1, 9, 9, 3, 9, 4, 9, 6, 8, 4]).unwrap());
+ dbg!(refactored([6, 2, 9, 1, 1, 9, 4, 1, 7, 1, 6, 1, 1, 1]).unwrap());
+ Ok(())
+}
+
+fn subroutine_1(
+ next_input: i64,
+ running_total: i64,
+ mod_conditional: i64,
+ result_additive: i64,
+) -> i64 {
+ if next_input != (running_total % 26) + mod_conditional {
+ running_total * 26 + next_input + result_additive
+ } else {
+ running_total
+ }
+}
+
+fn subroutine_2(
+ next_input: i64,
+ running_total: i64,
+ mod_conditional: i64,
+ result_additive: i64,
+) -> i64 {
+ if next_input != running_total % 26 + mod_conditional {
+ running_total / 26 * 26 + next_input + result_additive
+ } else {
+ running_total / 26
+ }
+}
+
+fn refactored_one_to_nine_assumption(input: [i64; 14]) -> Result<i64, String> {
+ let mut z = input[0] + 6;
+ // z-stack 1
+ z = z * 26 + input[1] + 6;
+ // z-stack 2
+ z = z * 26 + input[2] + 3;
+ // z-stack 3
+ z = if input[2] - 8 == input[3] {
+ z / 26
+ } else {
+ z / 26 * 26 + input[3] + 11
+ };
+ // z-stack 2
+ z = z * 26 + input[4] + 9;
+ // z-stack 3
+ z = if input[4] + 8 == input[5] {
+ z / 26
+ } else {
+ z / 26 * 26 + input[5] + 3
+ };
+ // z-stack 2
+ z = z * 26 + input[6] + 13;
+ // z-stack 3
+ z = z * 26 + input[7] + 6;
+ // z-stack 4
+ z = if input[7] + 6 == input[8] {
+ z / 26
+ } else {
+ z / 26 * 26 + input[8] + 14
+ };
+ // z-stack 3
+ z = z * 26 + input[9] + 10;
+ // z-stack 4
+ z = if input[9] + 5 == input[10] {
+ z / 26
+ } else {
+ z / 26 * 26 + input[10] + 12
+ };
+ // z-stack 3
+ z = if input[9] + 5 == input[10] {
+ if input[7] + 6 == input[8] {
+ if input[6] + 13 - 16 == input[11] {
+ z / 26
+ } else {
+ z / 26 * 26 + input[11] + 10
+ }
+ } else {
+ if input[8] + 14 - 16 == input[11] {
+ z / 26
+ } else {
+ z / 26 * 26 + input[11] + 10
+ }
+ }
+ } else {
+ if input[10] + 12 - 16 == input[11] {
+ z / 26
+ } else {
+ z / 26 * 26 + input[11] + 10
+ }
+ };
+ // z-stack 2
+ z = subroutine_2(input[12], z, -7, 11);
+ // z-stack 1
+ z = subroutine_2(input[13], z, -11, 15);
+ // z-stack 0
+
+ Ok(z)
+}
+
+fn refactored(input: [i64; 14]) -> Result<i64, String> {
+ let mut z: i64 = 0;
+
+ z = subroutine_1(input[0], z, 12, 6);
+ z = subroutine_1(input[1], z, 10, 6);
+ z = subroutine_1(input[2], z, 13, 3);
+ z = subroutine_2(input[3], z, -11, 11);
+ z = subroutine_1(input[4], z, 13, 9);
+ z = subroutine_2(input[5], z, -1, 3);
+ z = subroutine_1(input[6], z, 10, 13);
+ z = subroutine_1(input[7], z, 11, 6);
+ z = subroutine_2(input[8], z, 0, 14);
+ z = subroutine_1(input[9], z, 10, 10);
+ z = subroutine_2(input[10], z, -5, 12);
+ z = subroutine_2(input[11], z, -16, 10);
+ z = subroutine_2(input[12], z, -7, 11);
+ z = subroutine_2(input[13], z, -11, 15);
+
+ Ok(z)
+}
+
+#[derive(Debug)]
+struct Program(Vec<Instruction>);
+impl Program {
+ fn print_oracle(&self) {
+ println!("fn oracle(input: [i64; 14]) -> Result<i64, String> {{");
+ println!("let mut w: i64 = 0;");
+ println!("let mut x: i64 = 0;");
+ println!("let mut y: i64 = 0;");
+ println!("let mut z: i64 = 0;");
+
+ let mut input_index = 0;
+ for instruction in &self.0 {
+ match instruction {
+ Instruction::Inp(a) => {
+ println!("{} = input[{}];", a, input_index);
+ input_index += 1;
+ }
+ Instruction::Add(a, b) => {
+ println!("{0} = {0} + {1};", a, b);
+ }
+ Instruction::Mul(a, b) => {
+ println!("{0} = {0} * {1};", a, b);
+ }
+ Instruction::Div(a, b) => {
+ println!("if {0} == 0 {{ return Err(\"Div by 0\".into()); }}", b);
+ println!("{0} = {0} / {1};", a, b);
+ }
+ Instruction::Mod(a, b) => {
+ println!("if {0} == 0 {{ return Err(\"Mod by 0\".into()); }}", b);
+ println!("{0} = {0} % {1};", a, b);
+ }
+ Instruction::Eql(a, b) => {
+ println!("{0} = if {0} == {1} {{ 1 }} else {{ 0 }};", a, b);
+ }
+ }
+ }
+ println!("Ok(z)");
+ println!("}}");
+ }
+}
+
+#[derive(Debug)]
+enum Instruction {
+ Inp(String),
+ Add(String, String),
+ Mul(String, String),
+ Div(String, String),
+ Mod(String, String),
+ Eql(String, String),
+}
+
+fn parse_program(input: &str) -> IResult<&str, Program> {
+ map(separated_list1(line_ending, parse_instruction), Program)(input)
+}
+
+fn parse_instruction(input: &str) -> IResult<&str, Instruction> {
+ alt((
+ map(preceded(pair(tag("inp"), space1), word), |a| {
+ Instruction::Inp(a)
+ }),
+ map(
+ preceded(pair(tag("add"), space1), separated_pair(word, space1, word)),
+ |(a, b)| Instruction::Add(a, b),
+ ),
+ map(
+ preceded(pair(tag("mul"), space1), separated_pair(word, space1, word)),
+ |(a, b)| Instruction::Mul(a, b),
+ ),
+ map(
+ preceded(pair(tag("div"), space1), separated_pair(word, space1, word)),
+ |(a, b)| Instruction::Div(a, b),
+ ),
+ map(
+ preceded(pair(tag("mod"), space1), separated_pair(word, space1, word)),
+ |(a, b)| Instruction::Mod(a, b),
+ ),
+ map(
+ preceded(pair(tag("eql"), space1), separated_pair(word, space1, word)),
+ |(a, b)| Instruction::Eql(a, b),
+ ),
+ ))(input)
+}
+
+fn word(input: &str) -> IResult<&str, String> {
+ map(is_not(" \t\r\n"), |s: &str| s.to_string())(input)
+}
+
+#[allow(unused_assignments)]
+fn oracle(input: [i64; 14]) -> Result<i64, String> {
+ let mut w: i64 = 0;
+ let mut x: i64 = 0;
+ let mut y: i64 = 0;
+ let mut z: i64 = 0;
+ w = input[0];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 1 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 1;
+ x = x + 12;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 6;
+ y = y * x;
+ z = z + y;
+ w = input[1];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 1 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 1;
+ x = x + 10;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 6;
+ y = y * x;
+ z = z + y;
+ w = input[2];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 1 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 1;
+ x = x + 13;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 3;
+ y = y * x;
+ z = z + y;
+ w = input[3];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 26 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 26;
+ x = x + -11;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 11;
+ y = y * x;
+ z = z + y;
+ w = input[4];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 1 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 1;
+ x = x + 13;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 9;
+ y = y * x;
+ z = z + y;
+ w = input[5];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 26 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 26;
+ x = x + -1;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 3;
+ y = y * x;
+ z = z + y;
+ w = input[6];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 1 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 1;
+ x = x + 10;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 13;
+ y = y * x;
+ z = z + y;
+ w = input[7];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 1 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 1;
+ x = x + 11;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 6;
+ y = y * x;
+ z = z + y;
+ w = input[8];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 26 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 26;
+ x = x + 0;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 14;
+ y = y * x;
+ z = z + y;
+ w = input[9];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 1 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 1;
+ x = x + 10;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 10;
+ y = y * x;
+ z = z + y;
+ w = input[10];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 26 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 26;
+ x = x + -5;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 12;
+ y = y * x;
+ z = z + y;
+ w = input[11];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 26 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 26;
+ x = x + -16;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 10;
+ y = y * x;
+ z = z + y;
+ w = input[12];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 26 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 26;
+ x = x + -7;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 11;
+ y = y * x;
+ z = z + y;
+ w = input[13];
+ x = x * 0;
+ x = x + z;
+ if 26 == 0 {
+ return Err("Mod by 0".into());
+ }
+ x = x % 26;
+ if 26 == 0 {
+ return Err("Div by 0".into());
+ }
+ z = z / 26;
+ x = x + -11;
+ x = if x == w { 1 } else { 0 };
+ x = if x == 0 { 1 } else { 0 };
+ y = y * 0;
+ y = y + 25;
+ y = y * x;
+ y = y + 1;
+ z = z * y;
+ y = y * 0;
+ y = y + w;
+ y = y + 15;
+ y = y * x;
+ z = z + y;
+ Ok(z)
+}
+
+proptest! {
+ #[test]
+ fn oracle_matches_refactored(input in proptest::array::uniform14(1i64..10)) {
+ let oracle_result = oracle(input.clone());
+ let refactored_result = refactored(input.clone());
+ let refactored_one_to_nine_assumption_result = refactored_one_to_nine_assumption(input);
+ assert_eq!(oracle_result, refactored_result);
+ assert_eq!(oracle_result, refactored_one_to_nine_assumption_result);
+ }
+}
diff --git a/2021/src/bin/day_25.rs b/2021/src/bin/day_25.rs
new file mode 100644
index 0000000..742c911
--- /dev/null
+++ b/2021/src/bin/day_25.rs
@@ -0,0 +1,98 @@
+use nom::{
+ branch::alt,
+ character::complete::{char as nom_char, line_ending},
+ combinator::{map, value},
+ multi::{many1, separated_list1},
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_25.txt")?;
+ let mut seafloor = parse_seafloor(&input).unwrap().1;
+ for i in 1.. {
+ let next = seafloor.next();
+ if next == seafloor {
+ dbg!(i);
+ break;
+ }
+ seafloor = next;
+ }
+ Ok(())
+}
+
+#[derive(Debug, PartialEq, Eq)]
+struct Seafloor(Vec<Vec<Option<Cucumber>>>);
+
+impl Seafloor {
+ fn next(&self) -> Seafloor {
+ self.next_east().next_south()
+ }
+
+ fn next_east(&self) -> Seafloor {
+ let mut results = Vec::new();
+ for y in 0..self.0.len() {
+ let mut current_row = Vec::new();
+ for x in 0..self.0[y].len() {
+ let old = &self.0[y][x];
+ let old_left = &self.0[y][if x == 0 { self.0[y].len() - 1 } else { x - 1 }];
+ let old_right = &self.0[y][(x + 1) % self.0[y].len()];
+
+ let new = if *old == None && *old_left == Some(Cucumber::East) {
+ old_left.clone()
+ } else if *old == Some(Cucumber::East) && *old_right == None {
+ None
+ } else {
+ old.clone()
+ };
+ current_row.push(new);
+ }
+ results.push(current_row);
+ }
+ Seafloor(results)
+ }
+
+ fn next_south(&self) -> Seafloor {
+ let mut results = Vec::new();
+ for y in 0..self.0.len() {
+ let mut current_row = Vec::new();
+ for x in 0..self.0[y].len() {
+ let old = &self.0[y][x];
+ let old_up = &self.0[if y == 0 { self.0.len() - 1 } else { y - 1 }][x];
+ let old_down = &self.0[(y + 1) % self.0.len()][x];
+
+ let new = if *old == None && *old_up == Some(Cucumber::South) {
+ old_up.clone()
+ } else if *old == Some(Cucumber::South) && *old_down == None {
+ None
+ } else {
+ old.clone()
+ };
+ current_row.push(new);
+ }
+ results.push(current_row);
+ }
+ Seafloor(results)
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum Cucumber {
+ East,
+ South,
+}
+
+fn parse_seafloor(input: &str) -> IResult<&str, Seafloor> {
+ map(
+ separated_list1(line_ending, many1(parse_cucumber)),
+ Seafloor,
+ )(input)
+}
+
+fn parse_cucumber(input: &str) -> IResult<&str, Option<Cucumber>> {
+ alt((
+ value(None, nom_char('.')),
+ value(Some(Cucumber::East), nom_char('>')),
+ value(Some(Cucumber::South), nom_char('v')),
+ ))(input)
+}
diff --git a/2021/src/bin/day_2_part_2.rs b/2021/src/bin/day_2_part_2.rs
new file mode 100644
index 0000000..de5b334
--- /dev/null
+++ b/2021/src/bin/day_2_part_2.rs
@@ -0,0 +1,124 @@
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{i64 as nom_i64, line_ending, space1},
+ combinator::map,
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_2.txt")?;
+ let route = parse_route(&input).unwrap().1;
+
+ let mut position = Position::default();
+ for instruction in &route {
+ position.advance(&instruction);
+ }
+ dbg!(position.horizontal.0 * position.depth.0);
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct Route(Vec<Instruction>);
+
+impl<'a> IntoIterator for &'a Route {
+ type Item = &'a Instruction;
+ type IntoIter = std::slice::Iter<'a, Instruction>;
+ fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
+ self.0.iter()
+ }
+}
+
+#[derive(Debug)]
+enum Instruction {
+ Forward(Distance),
+ Up(Aim),
+ Down(Aim),
+}
+
+#[derive(
+ Default,
+ Debug,
+ Clone,
+ Copy,
+ derive_more::Add,
+ derive_more::AddAssign,
+ derive_more::Sub,
+ derive_more::SubAssign,
+)]
+struct Distance(i64);
+#[derive(
+ Default,
+ Debug,
+ Clone,
+ Copy,
+ derive_more::Add,
+ derive_more::AddAssign,
+ derive_more::Sub,
+ derive_more::SubAssign,
+)]
+struct Aim(i64);
+
+impl std::ops::Mul<Distance> for Aim {
+ type Output = Distance;
+ fn mul(self, other: Distance) -> Distance {
+ Distance(self.0 * other.0)
+ }
+}
+
+#[derive(Default, Debug)]
+struct Position {
+ horizontal: Distance,
+ depth: Distance,
+ aim: Aim,
+}
+
+impl Position {
+ fn advance(&mut self, instruction: &Instruction) {
+ match instruction {
+ Instruction::Forward(distance) => {
+ self.horizontal += *distance;
+ self.depth += self.aim * *distance;
+ }
+ Instruction::Down(aim) => self.aim += *aim,
+ Instruction::Up(aim) => self.aim -= *aim,
+ }
+ }
+}
+
+fn parse_route(input: &str) -> IResult<&str, Route> {
+ map(separated_list1(line_ending, parse_instruction), Route)(input)
+}
+
+fn parse_instruction(input: &str) -> IResult<&str, Instruction> {
+ alt((parse_forward, parse_up, parse_down))(input)
+}
+
+fn parse_forward(input: &str) -> IResult<&str, Instruction> {
+ map(
+ tuple((tag("forward"), space1, parse_distance)),
+ |(_, _, distance)| Instruction::Forward(distance),
+ )(input)
+}
+fn parse_up(input: &str) -> IResult<&str, Instruction> {
+ map(tuple((tag("up"), space1, parse_aim)), |(_, _, aim)| {
+ Instruction::Up(aim)
+ })(input)
+}
+fn parse_down(input: &str) -> IResult<&str, Instruction> {
+ map(tuple((tag("down"), space1, parse_aim)), |(_, _, aim)| {
+ Instruction::Down(aim)
+ })(input)
+}
+
+fn parse_distance(input: &str) -> IResult<&str, Distance> {
+ map(nom_i64, Distance)(input)
+}
+
+fn parse_aim(input: &str) -> IResult<&str, Aim> {
+ map(nom_i64, Aim)(input)
+}
diff --git a/2021/src/bin/day_3.rs b/2021/src/bin/day_3.rs
new file mode 100644
index 0000000..2238dfb
--- /dev/null
+++ b/2021/src/bin/day_3.rs
@@ -0,0 +1,128 @@
+use nom::{
+ character::complete::{digit1, line_ending},
+ combinator::{map, map_res},
+ multi::separated_list1,
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_3.txt")?;
+ let diagnostics = parse_diagnostics(&input).unwrap().1;
+
+ dbg!(diagnostics.gamma());
+ dbg!(diagnostics.epsilon());
+ dbg!(diagnostics.oxygen());
+ dbg!(diagnostics.co2());
+ dbg!(diagnostics.gamma() * diagnostics.epsilon());
+ dbg!(diagnostics.oxygen() * diagnostics.co2());
+
+ Ok(())
+}
+
+#[derive(Debug, Clone)]
+struct Diagnostics {
+ bitsets: Vec<Bitset>,
+ bitset_len: usize,
+}
+
+impl Diagnostics {
+ fn new(bitsets: Vec<Bitset>) -> Diagnostics {
+ Diagnostics {
+ bitset_len: bitsets.iter().map(|b| b.len).max().unwrap_or(0),
+ bitsets,
+ }
+ }
+
+ fn gamma(&self) -> Bitset {
+ let mut gamma = Bitset {
+ bits: 0,
+ len: self.bitset_len,
+ };
+ for bit in 0..gamma.len {
+ let ones_count = self
+ .bitsets
+ .iter()
+ .filter(|bitset| bitset.check_bit(bit))
+ .count();
+ if ones_count >= self.bitsets.len() / 2 {
+ gamma.set_bit(bit);
+ }
+ }
+ gamma
+ }
+
+ fn epsilon(&self) -> Bitset {
+ !self.gamma()
+ }
+
+ fn oxygen(&self) -> Bitset {
+ self.bit_criteria_match(|d| d.gamma())
+ }
+
+ fn co2(&self) -> Bitset {
+ self.bit_criteria_match(|d| d.epsilon())
+ }
+
+ fn bit_criteria_match(&self, criteria: impl Fn(&Diagnostics) -> Bitset) -> Bitset {
+ let mut candidates = self.clone();
+ for bit in (0..self.bitset_len).rev() {
+ let bit_criteria = criteria(&candidates).check_bit(bit);
+ candidates
+ .bitsets
+ .retain(|candidate| candidate.check_bit(bit) == bit_criteria);
+ if candidates.bitsets.len() == 1 {
+ return candidates.bitsets[0];
+ }
+ }
+ Bitset::default()
+ }
+}
+
+#[derive(Default, Debug, Clone, Copy)]
+struct Bitset {
+ bits: u32,
+ len: usize,
+}
+
+impl Bitset {
+ fn check_bit(&self, bit: usize) -> bool {
+ self.bits & (1 << bit) != 0
+ }
+
+ fn set_bit(&mut self, bit: usize) {
+ self.bits |= 1 << bit;
+ }
+}
+
+impl std::ops::Mul for Bitset {
+ type Output = Self;
+ fn mul(self, rhs: Bitset) -> Self::Output {
+ Bitset {
+ bits: self.bits * rhs.bits,
+ len: self.len.max(rhs.len), // dodgy. This might need to grow.
+ }
+ }
+}
+impl std::ops::Not for Bitset {
+ type Output = Bitset;
+ fn not(self) -> <Self as std::ops::Not>::Output {
+ Bitset {
+ bits: !self.bits & ((1 << self.len) - 1),
+ len: self.len,
+ }
+ }
+}
+
+fn parse_diagnostics(input: &str) -> IResult<&str, Diagnostics> {
+ map(separated_list1(line_ending, parse_bitset), Diagnostics::new)(input)
+}
+
+fn parse_bitset(input: &str) -> IResult<&str, Bitset> {
+ map_res(digit1, |num| {
+ u32::from_str_radix(num, 2).map(|bits| Bitset {
+ bits,
+ len: num.len(),
+ })
+ })(input)
+}
diff --git a/2021/src/bin/day_4.rs b/2021/src/bin/day_4.rs
new file mode 100644
index 0000000..3938e14
--- /dev/null
+++ b/2021/src/bin/day_4.rs
@@ -0,0 +1,259 @@
+use nom::{
+ bytes::complete::tag,
+ character::complete::{line_ending, space0, space1, u32 as nom_u32},
+ combinator::{map, map_res},
+ multi::{many1, separated_list1},
+ sequence::{preceded, tuple},
+ IResult,
+};
+use std::fs;
+use thiserror::Error;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_4.txt")?;
+ let mut bingo_game = parse_bingo_game(&input).unwrap().1;
+ let total_boards = bingo_game.boards.len();
+
+ let mut winning_game_iter = std::iter::repeat_with(|| bingo_game.do_draw()).flatten();
+
+ let (winning_block, winning_board, winning_mask) = winning_game_iter.next().unwrap();
+ dbg!(winning_board.score(&winning_mask) * winning_block);
+
+ let (losing_block, losing_board, losing_mask) =
+ winning_game_iter.nth(total_boards - 2).unwrap();
+ dbg!(losing_board.score(&losing_mask) * losing_block);
+
+ Ok(())
+}
+
+const BINGO_BOARD_WIDTH: usize = 5;
+
+#[derive(Debug)]
+struct BingoGame {
+ draws: Vec<BingoBlock>,
+ boards: Vec<BingoBoard>,
+ masks: Vec<BingoBoardMask>,
+}
+
+impl BingoGame {
+ fn do_draw(&mut self) -> Vec<(BingoBlock, BingoBoard, BingoBoardMask)> {
+ let mut wins = Vec::new();
+ let mut results = Vec::new();
+
+ if let Some(block) = self.draws.pop() {
+ for (index, (mask, board)) in self
+ .masks
+ .iter_mut()
+ .zip(self.boards.iter())
+ .enumerate()
+ .rev()
+ {
+ if let Some((row, col)) = board.find_block(&block) {
+ mask.mark(row, col);
+ if mask.has_bingo() {
+ wins.push(index);
+ }
+ }
+ }
+ for win in wins {
+ results.push((
+ block.clone(),
+ self.boards.remove(win),
+ self.masks.remove(win),
+ ))
+ }
+ }
+
+ results
+ }
+}
+
+#[derive(Debug, Error)]
+enum BingoBoardParseError {
+ #[error("input board was the wrong width")]
+ WrongWidth,
+ #[error("input board was the wrong height")]
+ WrongHeight,
+}
+
+#[derive(Debug, Default, Clone, PartialEq, Eq)]
+struct BingoBoardMask {
+ data: [[bool; BINGO_BOARD_WIDTH]; BINGO_BOARD_WIDTH],
+}
+
+impl BingoBoardMask {
+ fn has_bingo(&self) -> bool {
+ for i in 0..BINGO_BOARD_WIDTH {
+ let row_bingo = self.data[i].iter().all(|marked| *marked);
+ let col_bingo = self.data.iter().all(|row| row[i]);
+ if row_bingo || col_bingo {
+ return true;
+ }
+ }
+ false
+ }
+
+ fn mark(&mut self, row: usize, col: usize) {
+ self.data[row][col] = true;
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+struct BingoBoard {
+ data: [[BingoBlock; BINGO_BOARD_WIDTH]; BINGO_BOARD_WIDTH],
+}
+
+impl BingoBoard {
+ fn find_block(&self, block: &BingoBlock) -> Option<(usize, usize)> {
+ for (row, row_data) in self.data.iter().enumerate() {
+ for (col, col_data) in row_data.iter().enumerate() {
+ if col_data == block {
+ return Some((row, col));
+ }
+ }
+ }
+ None
+ }
+
+ fn score(&self, mask: &BingoBoardMask) -> BingoGameScore {
+ let mut score = BingoGameScore::default();
+ for row in 0..BINGO_BOARD_WIDTH {
+ for col in 0..BINGO_BOARD_WIDTH {
+ if !mask.data[row][col] {
+ score = score + self.data[row][col];
+ }
+ }
+ }
+ score
+ }
+}
+
+impl BingoBoard {
+ fn new(data: Vec<Vec<BingoBlock>>) -> Result<BingoBoard, BingoBoardParseError> {
+ let vec_array_data: Vec<[BingoBlock; BINGO_BOARD_WIDTH]> = data
+ .into_iter()
+ .map(|row| row.try_into())
+ .collect::<Result<Vec<_>, _>>()
+ .map_err(|_| BingoBoardParseError::WrongWidth)?;
+
+ let array_array_data: [[BingoBlock; BINGO_BOARD_WIDTH]; BINGO_BOARD_WIDTH] = vec_array_data
+ .try_into()
+ .map_err(|_| BingoBoardParseError::WrongHeight)?;
+ Ok(BingoBoard {
+ data: array_array_data,
+ })
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+struct BingoBlock(u32);
+
+#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
+struct BingoGameScore(u32);
+
+impl std::ops::Add<BingoBlock> for BingoGameScore {
+ type Output = BingoGameScore;
+ fn add(self, rhs: BingoBlock) -> BingoGameScore {
+ BingoGameScore(self.0 + rhs.0)
+ }
+}
+
+impl std::ops::Mul<BingoBlock> for BingoGameScore {
+ type Output = BingoGameScore;
+ fn mul(self, rhs: BingoBlock) -> BingoGameScore {
+ BingoGameScore(self.0 * rhs.0)
+ }
+}
+
+fn parse_bingo_game(input: &str) -> IResult<&str, BingoGame> {
+ map(
+ tuple((
+ parse_draws,
+ many1(line_ending),
+ separated_list1(many1(line_ending), parse_board),
+ )),
+ |(draws, _, boards)| BingoGame {
+ draws: draws.into_iter().rev().collect(),
+ masks: vec![BingoBoardMask::default(); boards.len()],
+ boards,
+ },
+ )(input)
+}
+
+fn parse_draws(input: &str) -> IResult<&str, Vec<BingoBlock>> {
+ separated_list1(tag(","), parse_block)(input)
+}
+
+fn parse_block(input: &str) -> IResult<&str, BingoBlock> {
+ map(nom_u32, BingoBlock)(input)
+}
+
+fn parse_board(input: &str) -> IResult<&str, BingoBoard> {
+ map_res(
+ separated_list1(
+ line_ending,
+ preceded(space0, separated_list1(space1, parse_block)),
+ ),
+ BingoBoard::new,
+ )(input)
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn parses_a_board() {
+ assert_eq!(
+ parse_board(
+ r##"86 31 71 11 56
+99 12 17 10 46
+ 5 33 85 61 2
+30 1 28 88 66
+15 38 21 54 64"##
+ ),
+ Ok((
+ "",
+ BingoBoard {
+ data: [
+ [
+ BingoBlock(86),
+ BingoBlock(31),
+ BingoBlock(71),
+ BingoBlock(11),
+ BingoBlock(56)
+ ],
+ [
+ BingoBlock(99),
+ BingoBlock(12),
+ BingoBlock(17),
+ BingoBlock(10),
+ BingoBlock(46)
+ ],
+ [
+ BingoBlock(5),
+ BingoBlock(33),
+ BingoBlock(85),
+ BingoBlock(61),
+ BingoBlock(2)
+ ],
+ [
+ BingoBlock(30),
+ BingoBlock(1),
+ BingoBlock(28),
+ BingoBlock(88),
+ BingoBlock(66)
+ ],
+ [
+ BingoBlock(15),
+ BingoBlock(38),
+ BingoBlock(21),
+ BingoBlock(54),
+ BingoBlock(64)
+ ]
+ ]
+ }
+ ))
+ );
+ }
+}
diff --git a/2021/src/bin/day_5.rs b/2021/src/bin/day_5.rs
new file mode 100644
index 0000000..08eaecd
--- /dev/null
+++ b/2021/src/bin/day_5.rs
@@ -0,0 +1,137 @@
+use nom::{
+ bytes::complete::tag,
+ character::complete::{char as nom_char, line_ending, u32 as nom_u32},
+ combinator::map,
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::{collections::BTreeMap, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_5.txt")?;
+ let lines = parse_lines(&input).unwrap().1;
+ {
+ let mut map_simple = Bitmap::default();
+ for line in &lines {
+ map_simple.mark_line_only_simple(line);
+ }
+ dbg!(map_simple.count_overlapped_points());
+ }
+ {
+ let mut map = Bitmap::default();
+ for line in &lines {
+ map.mark_line(line);
+ }
+ dbg!(map.count_overlapped_points());
+ }
+
+ Ok(())
+}
+
+#[derive(Default)]
+struct Bitmap(BTreeMap<Point, usize>);
+impl Bitmap {
+ fn mark_line_only_simple(&mut self, l: &Line) {
+ if l.is_horizontal() {
+ for x in l.a.x..=l.b.x {
+ self.mark_point(&Point { x, y: l.a.y });
+ }
+ } else if l.is_vertical() {
+ for y in l.a.y..=l.b.y {
+ self.mark_point(&Point { x: l.a.x, y });
+ }
+ } else {
+ }
+ }
+
+ fn mark_line(&mut self, l: &Line) {
+ if l.is_horizontal() {
+ for x in l.a.x..=l.b.x {
+ self.mark_point(&Point { x, y: l.a.y });
+ }
+ } else if l.is_vertical() {
+ for y in l.a.y..=l.b.y {
+ self.mark_point(&Point { x: l.a.x, y });
+ }
+ } else if l.is_diagonal_up() {
+ for delta in 0..=(l.b.x - l.a.x) {
+ self.mark_point(&Point {
+ x: l.a.x + delta,
+ y: l.a.y + delta,
+ });
+ }
+ } else if l.is_diagonal_down() {
+ for delta in 0..=(l.b.x - l.a.x) {
+ let reverse_delta = l.b.x - l.a.x - delta;
+ self.mark_point(&Point {
+ x: l.a.x + delta,
+ y: l.b.y + reverse_delta,
+ });
+ }
+ } else {
+ panic!("There shouldn't be other cases...")
+ }
+ }
+
+ fn mark_point(&mut self, p: &Point) {
+ *self.0.entry(p.clone()).or_insert(0) += 1;
+ }
+
+ fn count_overlapped_points(&self) -> usize {
+ self.0.values().filter(|v| **v > 1).count()
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
+struct Point {
+ x: u32,
+ y: u32,
+}
+
+#[derive(Debug)]
+struct Line {
+ a: Point,
+ b: Point,
+}
+
+impl Line {
+ fn is_horizontal(&self) -> bool {
+ self.a.y == self.b.y
+ }
+
+ fn is_vertical(&self) -> bool {
+ self.a.x == self.b.x
+ }
+
+ fn is_diagonal_up(&self) -> bool {
+ self.a.x < self.b.x && self.a.y < self.b.y
+ }
+
+ fn is_diagonal_down(&self) -> bool {
+ self.a.x < self.b.x && self.a.y > self.b.y
+ }
+}
+
+fn parse_lines(input: &str) -> IResult<&str, Vec<Line>> {
+ separated_list1(line_ending, parse_line)(input)
+}
+
+fn parse_line(input: &str) -> IResult<&str, Line> {
+ map(
+ tuple((parse_point, tag(" -> "), parse_point)),
+ |(a, _, b)| {
+ if a < b {
+ Line { a, b }
+ } else {
+ Line { a: b, b: a }
+ }
+ },
+ )(input)
+}
+
+fn parse_point(input: &str) -> IResult<&str, Point> {
+ map(tuple((nom_u32, nom_char(','), nom_u32)), |(x, _, y)| {
+ Point { x, y }
+ })(input)
+}
diff --git a/2021/src/bin/day_6.rs b/2021/src/bin/day_6.rs
new file mode 100644
index 0000000..9a40f9e
--- /dev/null
+++ b/2021/src/bin/day_6.rs
@@ -0,0 +1,79 @@
+use nom::{
+ bytes::complete::tag,
+ character::complete::u32 as nom_u32,
+ combinator::{map, map_res},
+ multi::separated_list1,
+ IResult, ToUsize,
+};
+use std::{collections::VecDeque, fs};
+use thiserror::Error;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_6.txt")?;
+ let mut swarm = parse_swarm(&input).unwrap().1;
+ for _ in 0..80 {
+ swarm.grow();
+ }
+ dbg!(swarm.fish_sum());
+
+ for _ in 80..256 {
+ swarm.grow();
+ }
+ dbg!(swarm.fish_sum());
+
+ Ok(())
+}
+
+#[derive(
+ Default, Debug, Clone, Copy, derive_more::Add, derive_more::AddAssign, derive_more::Sum,
+)]
+struct FishCount(u64);
+
+const FISH_INITIAL_SPAWN_COUNTDOWN: usize = 9;
+const FISH_REPEAT_SPAWN_COUNTDOWN: usize = 7;
+#[derive(Debug)]
+struct Swarm {
+ fish: VecDeque<FishCount>,
+}
+
+#[derive(Debug, Error)]
+enum SwarmParseError {
+ #[error("input was out of range")]
+ OutOfRange,
+}
+
+impl Swarm {
+ fn new(fish_counters: Vec<usize>) -> Result<Swarm, SwarmParseError> {
+ let mut fish = VecDeque::with_capacity(FISH_INITIAL_SPAWN_COUNTDOWN);
+ for _ in 0..FISH_INITIAL_SPAWN_COUNTDOWN {
+ fish.push_back(FishCount::default());
+ }
+ for fish_counter in fish_counters {
+ if fish_counter > fish.len() {
+ return Err(SwarmParseError::OutOfRange);
+ }
+ fish[fish_counter] += FishCount(1);
+ }
+ Ok(Swarm { fish })
+ }
+
+ fn grow(&mut self) {
+ let spawning = self
+ .fish
+ .pop_front()
+ .expect("Fish buffer should maintain exactly 9 entries");
+ self.fish[FISH_REPEAT_SPAWN_COUNTDOWN - 1] += spawning;
+ self.fish.push_back(spawning);
+ }
+
+ fn fish_sum(&self) -> FishCount {
+ self.fish.iter().copied().sum()
+ }
+}
+
+fn parse_swarm(input: &str) -> IResult<&str, Swarm> {
+ map_res(
+ separated_list1(tag(","), map(nom_u32, |n| n.to_usize())),
+ Swarm::new,
+ )(input)
+}
diff --git a/2021/src/bin/day_7.rs b/2021/src/bin/day_7.rs
new file mode 100644
index 0000000..b568e07
--- /dev/null
+++ b/2021/src/bin/day_7.rs
@@ -0,0 +1,88 @@
+use nom::{
+ bytes::complete::tag, character::complete::u64 as nom_u64, combinator::map,
+ multi::separated_list1, IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_7.txt")?;
+ let crabs = parse_swarm(&input).unwrap().1;
+ dbg!(crabs.linear_min_fuel_sum());
+ dbg!(crabs.exponential_min_fuel_sum());
+ Ok(())
+}
+
+#[derive(
+ Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, derive_more::Add, derive_more::Sum,
+)]
+struct Fuel(u64);
+
+#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+struct CrabPosition(u64);
+
+impl CrabPosition {
+ fn linear_fuel(&self, rhs: &Self) -> Fuel {
+ if self > rhs {
+ Fuel(self.0 - rhs.0)
+ } else {
+ Fuel(rhs.0 - self.0)
+ }
+ }
+
+ fn exponential_fuel(&self, rhs: &Self) -> Fuel {
+ let linear_difference = if self > rhs {
+ self.0 - rhs.0
+ } else {
+ rhs.0 - self.0
+ };
+ Fuel(linear_difference * (linear_difference + 1) / 2)
+ }
+}
+
+#[derive(Default, Debug)]
+struct CrabSwarm {
+ crabs: Vec<CrabPosition>,
+}
+
+impl CrabSwarm {
+ fn new(mut crabs: Vec<CrabPosition>) -> CrabSwarm {
+ crabs.sort();
+ CrabSwarm { crabs }
+ }
+
+ fn linear_min_fuel_sum(&self) -> (CrabPosition, Fuel) {
+ (self.crabs[0].0..self.crabs[self.crabs.len() - 1].0)
+ .map(CrabPosition)
+ .map(|pos| {
+ (
+ pos,
+ self.crabs.iter().map(|crab| crab.linear_fuel(&pos)).sum(),
+ )
+ })
+ .min_by_key(|(_pos, fuel)| *fuel)
+ .expect("Expected at least one crab")
+ }
+
+ fn exponential_min_fuel_sum(&self) -> (CrabPosition, Fuel) {
+ (self.crabs[0].0..self.crabs[self.crabs.len() - 1].0)
+ .map(CrabPosition)
+ .map(|pos| {
+ (
+ pos,
+ self.crabs
+ .iter()
+ .map(|crab| crab.exponential_fuel(&pos))
+ .sum(),
+ )
+ })
+ .min_by_key(|(_pos, fuel)| *fuel)
+ .expect("Expected at least one crab")
+ }
+}
+
+fn parse_swarm(input: &str) -> IResult<&str, CrabSwarm> {
+ map(
+ separated_list1(tag(","), map(nom_u64, CrabPosition)),
+ CrabSwarm::new,
+ )(input)
+}
diff --git a/2021/src/bin/day_8.rs b/2021/src/bin/day_8.rs
new file mode 100644
index 0000000..6dc2bed
--- /dev/null
+++ b/2021/src/bin/day_8.rs
@@ -0,0 +1,262 @@
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{line_ending, space1},
+ combinator::{map, map_res, value},
+ multi::{many1, separated_list1},
+ sequence::tuple,
+ IResult,
+};
+use std::{
+ collections::{BTreeMap, BTreeSet},
+ fs,
+};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_8.txt")?;
+ let encrypted = parse_encrypted_inputs(&input).unwrap().1;
+ let permutations = WiringPermutation::all();
+
+ let unencrypted: Vec<Input> = encrypted
+ .into_iter()
+ .map(|encrypted_line| {
+ for permutation in &permutations {
+ if let Ok(input) = encrypted_line.decrypt(&permutation) {
+ return input;
+ }
+ }
+ panic!("Didn't find a solution!")
+ })
+ .collect();
+
+ let part1_sum: usize = unencrypted
+ .iter()
+ .map(|input| {
+ input
+ .plaintext
+ .iter()
+ .filter(|digit| {
+ digit.value == 1 || digit.value == 4 || digit.value == 7 || digit.value == 8
+ })
+ .count()
+ })
+ .sum();
+ dbg!(part1_sum);
+
+ let part2_sum: u32 = unencrypted
+ .iter()
+ .map(|input| {
+ input.plaintext[0].value * 1000
+ + input.plaintext[1].value * 100
+ + input.plaintext[2].value * 10
+ + input.plaintext[3].value
+ })
+ .sum();
+ dbg!(part2_sum);
+ Ok(())
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+enum Wire {
+ A,
+ B,
+ C,
+ D,
+ E,
+ F,
+ G,
+}
+
+impl Wire {
+ fn all() -> Vec<Wire> {
+ vec![
+ Wire::A,
+ Wire::B,
+ Wire::C,
+ Wire::D,
+ Wire::E,
+ Wire::F,
+ Wire::G,
+ ]
+ }
+}
+
+#[derive(Debug)]
+struct WiringPermutation {
+ mapping: BTreeMap<Wire, Wire>,
+}
+
+impl WiringPermutation {
+ fn all() -> Vec<WiringPermutation> {
+ let all_wires = Wire::all();
+ let all_wires_set: BTreeSet<Wire> = all_wires.iter().cloned().collect();
+ WiringPermutation::permutations(&all_wires, &all_wires_set)
+ }
+
+ fn permutations(
+ remaining_starts: &[Wire],
+ remaining_ends: &BTreeSet<Wire>,
+ ) -> Vec<WiringPermutation> {
+ let mut permutations = Vec::new();
+ if remaining_starts.is_empty() {
+ } else if remaining_starts.len() == 1 {
+ for end in remaining_ends {
+ let mut permutation = BTreeMap::new();
+ permutation.insert(remaining_starts[0], *end);
+ permutations.push(WiringPermutation {
+ mapping: permutation,
+ });
+ }
+ } else {
+ let start = remaining_starts[0];
+ for first_end in remaining_ends {
+ let mut inner_remaining_ends = remaining_ends.clone();
+ inner_remaining_ends.remove(first_end);
+ let inner_permutations =
+ WiringPermutation::permutations(&remaining_starts[1..], &inner_remaining_ends);
+ for mut permutation in inner_permutations {
+ permutation.mapping.insert(start, *first_end);
+ permutations.push(permutation);
+ }
+ }
+ }
+ permutations
+ }
+}
+
+#[derive(Debug)]
+struct Digit {
+ value: u32,
+ wires: BTreeSet<Wire>,
+}
+
+#[derive(Debug)]
+struct Input {
+ plaintext: [Digit; 4],
+}
+
+#[derive(Debug, thiserror::Error)]
+enum WiringError {
+ #[error("digit was not a known digit")]
+ InvalidDigit,
+ #[error("wrong number of numbers")]
+ WrongNumberOfNumbers,
+}
+
+impl Digit {
+ fn new(wires: BTreeSet<Wire>) -> Result<Digit, WiringError> {
+ let valid_digits: [BTreeSet<Wire>; 10] = [
+ [Wire::A, Wire::B, Wire::C, Wire::E, Wire::F, Wire::G].into(),
+ [Wire::C, Wire::F].into(),
+ [Wire::A, Wire::C, Wire::D, Wire::E, Wire::G].into(),
+ [Wire::A, Wire::C, Wire::D, Wire::F, Wire::G].into(),
+ [Wire::B, Wire::C, Wire::D, Wire::F].into(),
+ [Wire::A, Wire::B, Wire::D, Wire::F, Wire::G].into(),
+ [Wire::A, Wire::B, Wire::D, Wire::E, Wire::F, Wire::G].into(),
+ [Wire::A, Wire::C, Wire::F].into(),
+ [
+ Wire::A,
+ Wire::B,
+ Wire::C,
+ Wire::D,
+ Wire::E,
+ Wire::F,
+ Wire::G,
+ ]
+ .into(),
+ [Wire::A, Wire::B, Wire::C, Wire::D, Wire::F, Wire::G].into(),
+ ];
+
+ valid_digits
+ .into_iter()
+ .position(|digit| digit == wires)
+ .map(|pos| Digit {
+ value: pos as u32,
+ wires,
+ })
+ .ok_or(WiringError::InvalidDigit)
+ }
+}
+
+#[derive(Debug)]
+struct EncryptedDigit {
+ wires: BTreeSet<Wire>,
+}
+
+impl EncryptedDigit {
+ fn decrypt(&self, permutation: &WiringPermutation) -> Result<Digit, WiringError> {
+ let mut fixed_wires = BTreeSet::new();
+ for wire in &self.wires {
+ fixed_wires.insert(permutation.mapping[wire]);
+ }
+ Digit::new(fixed_wires)
+ }
+}
+
+#[derive(Debug)]
+struct EncryptedInput {
+ digits: [EncryptedDigit; 10],
+ ciphertext: [EncryptedDigit; 4],
+}
+
+impl EncryptedInput {
+ fn decrypt(&self, permutation: &WiringPermutation) -> Result<Input, WiringError> {
+ for test_digit in &self.digits {
+ let _ = test_digit.decrypt(&permutation)?;
+ }
+
+ let plaintext = self
+ .ciphertext
+ .iter()
+ .map(|digit| digit.decrypt(&permutation))
+ .collect::<Result<Vec<Digit>, WiringError>>()?;
+ Ok(Input {
+ plaintext: plaintext
+ .try_into()
+ .map_err(|_| WiringError::WrongNumberOfNumbers)?,
+ })
+ }
+}
+
+fn parse_encrypted_inputs(input: &str) -> IResult<&str, Vec<EncryptedInput>> {
+ separated_list1(line_ending, parse_encrypted_input)(input)
+}
+
+fn parse_encrypted_input(input: &str) -> IResult<&str, EncryptedInput> {
+ map_res(
+ tuple((
+ separated_list1(space1, parse_encrypted_digit),
+ tag(" | "),
+ separated_list1(space1, parse_encrypted_digit),
+ )),
+ |(digits, _, ciphertext)| {
+ let digits = digits
+ .try_into()
+ .map_err(|_| WiringError::WrongNumberOfNumbers)?;
+ let ciphertext = ciphertext
+ .try_into()
+ .map_err(|_| WiringError::WrongNumberOfNumbers)?;
+ let result: Result<EncryptedInput, WiringError> =
+ Ok(EncryptedInput { digits, ciphertext });
+ result
+ },
+ )(input)
+}
+
+fn parse_encrypted_digit(input: &str) -> IResult<&str, EncryptedDigit> {
+ map(many1(parse_wire), |wires| EncryptedDigit {
+ wires: wires.into_iter().collect(),
+ })(input)
+}
+
+fn parse_wire(input: &str) -> IResult<&str, Wire> {
+ alt((
+ value(Wire::A, tag("a")),
+ value(Wire::B, tag("b")),
+ value(Wire::C, tag("c")),
+ value(Wire::D, tag("d")),
+ value(Wire::E, tag("e")),
+ value(Wire::F, tag("f")),
+ value(Wire::G, tag("g")),
+ ))(input)
+}
diff --git a/2021/src/bin/day_9.rs b/2021/src/bin/day_9.rs
new file mode 100644
index 0000000..5ef0dae
--- /dev/null
+++ b/2021/src/bin/day_9.rs
@@ -0,0 +1,186 @@
+use nom::{
+ character::complete::{line_ending, one_of},
+ combinator::{map, map_res},
+ multi::{many1, separated_list1},
+ IResult,
+};
+use std::fs;
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_9.txt")?;
+ let height_map = parse_height_map(&input).unwrap().1;
+ let risk_level_sum: RiskLevel = height_map.risk_levels().into_iter().sum();
+ dbg!(risk_level_sum);
+
+ let mut basin_sizes: Vec<u32> = height_map.basins.iter().map(|basin| basin.size).collect();
+ basin_sizes.sort_unstable_by(|a, b| b.cmp(a));
+ dbg!(basin_sizes.iter().take(3).product::<u32>());
+
+ Ok(())
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+struct Height(u8);
+#[derive(
+ Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, derive_more::Add, derive_more::Sum,
+)]
+struct RiskLevel(u32);
+
+impl From<Height> for RiskLevel {
+ fn from(h: Height) -> Self {
+ RiskLevel(h.0 as u32 + 1)
+ }
+}
+
+#[derive(Debug, Default)]
+struct Basin {
+ size: u32,
+}
+
+#[derive(Debug)]
+struct HeightMap {
+ heights: Vec<Vec<Height>>,
+ low_points: Vec<(usize, usize)>,
+ basins: Vec<Basin>,
+ basin_map: Vec<Vec<Option<usize>>>,
+}
+
+impl HeightMap {
+ fn new(heights: Vec<Vec<Height>>) -> HeightMap {
+ let mut height_map = HeightMap {
+ heights,
+ low_points: Vec::new(),
+ basins: Vec::new(),
+ basin_map: Vec::new(),
+ };
+ height_map.init_low_points();
+ height_map.init_basins();
+ height_map
+ }
+}
+
+impl HeightMap {
+ fn init_low_points(&mut self) {
+ self.low_points = Vec::new();
+ for y in 0..self.heights.len() {
+ for x in 0..self.heights[y].len() {
+ let current = self.heights[y][x];
+ let mut is_low_point = true;
+ let edges = [
+ (x as isize - 1, y as isize),
+ (x as isize + 1, y as isize),
+ (x as isize, y as isize - 1),
+ (x as isize, y as isize + 1),
+ ];
+ for edge in edges {
+ if self
+ .get_height(edge.0, edge.1)
+ .map_or(false, |other| other <= current)
+ {
+ is_low_point = false;
+ }
+ }
+
+ if is_low_point {
+ self.low_points.push((x, y));
+ }
+ }
+ }
+ }
+
+ fn init_basins(&mut self) {
+ for low_point in self.low_points.clone() {
+ if self
+ .get_basin(low_point.0 as isize, low_point.1 as isize)
+ .is_some()
+ {
+ continue;
+ }
+
+ let mut basin = Basin::default();
+ let basin_index = self.basins.len();
+ self.set_basin(basin_index, low_point.0, low_point.1);
+ basin.size += 1;
+ let mut boundary = vec![low_point];
+ while boundary.len() > 0 {
+ let (x, y) = boundary.pop().unwrap();
+ let edges = [
+ (x as isize - 1, y as isize),
+ (x as isize + 1, y as isize),
+ (x as isize, y as isize - 1),
+ (x as isize, y as isize + 1),
+ ];
+ for edge in edges {
+ if self
+ .get_height(edge.0, edge.1)
+ .map_or(false, |other| other != Height(9))
+ && self.get_basin(edge.0, edge.1).is_none()
+ {
+ let x = edge.0 as usize;
+ let y = edge.1 as usize;
+ self.set_basin(basin_index, x, y);
+ basin.size += 1;
+ boundary.push((x, y));
+ }
+ }
+ }
+ self.basins.push(basin);
+ }
+ }
+
+ fn get_height(&self, x: isize, y: isize) -> Option<Height> {
+ if x < 0 || y < 0 {
+ None
+ } else {
+ let x = x as usize;
+ let y = y as usize;
+ self.heights.get(y).and_then(|row| row.get(x)).cloned()
+ }
+ }
+
+ fn get_basin(&self, x: isize, y: isize) -> Option<usize> {
+ if x < 0 || y < 0 {
+ None
+ } else {
+ let x = x as usize;
+ let y = y as usize;
+ self.basin_map
+ .get(y)
+ .and_then(|row| row.get(x))
+ .cloned()
+ .flatten()
+ }
+ }
+
+ fn set_basin(&mut self, basin: usize, x: usize, y: usize) {
+ while self.basin_map.len() <= y {
+ self.basin_map.push(Vec::new());
+ }
+ while self.basin_map[y].len() <= x {
+ self.basin_map[y].push(None);
+ }
+ self.basin_map[y][x] = Some(basin);
+ }
+
+ fn risk_levels(&self) -> Vec<RiskLevel> {
+ self.low_points
+ .iter()
+ .copied()
+ .map(|(x, y)| self.heights[y][x].clone().into())
+ .collect()
+ }
+}
+
+fn parse_height_map(input: &str) -> IResult<&str, HeightMap> {
+ map(separated_list1(line_ending, parse_row), HeightMap::new)(input)
+}
+
+fn parse_row(input: &str) -> IResult<&str, Vec<Height>> {
+ many1(parse_height)(input)
+}
+
+fn parse_height(input: &str) -> IResult<&str, Height> {
+ map_res(one_of("0123456789"), |digit| {
+ digit.to_string().parse().map(Height)
+ })(input)
+}
diff --git a/2021/src/lib.rs b/2021/src/lib.rs
new file mode 100644
index 0000000..be756a0
--- /dev/null
+++ b/2021/src/lib.rs
@@ -0,0 +1 @@
+pub mod parsers;
diff --git a/2021/src/parsers.rs b/2021/src/parsers.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/2021/src/parsers.rs
@@ -0,0 +1 @@
+