generated from janezicmatej/aoc-template
Compare commits
3 Commits
Author | SHA1 | Date |
---|---|---|
Matej Janezic | 000003902f | |
Matej Janezic | 00000380c1 | |
Matej Janezic | 0000037022 |
|
@ -17,21 +17,9 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "aho-corasick"
|
|
||||||
version = "1.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aoc"
|
name = "aoc"
|
||||||
version = "46.0.0"
|
version = "46.0.0"
|
||||||
dependencies = [
|
|
||||||
"z3",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
|
@ -60,38 +48,12 @@ version = "0.21.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
|
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bindgen"
|
|
||||||
version = "0.66.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.1",
|
|
||||||
"cexpr",
|
|
||||||
"clang-sys",
|
|
||||||
"lazy_static",
|
|
||||||
"lazycell",
|
|
||||||
"peeking_take_while",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"regex",
|
|
||||||
"rustc-hash",
|
|
||||||
"shlex",
|
|
||||||
"syn 2.0.42",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "2.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.11.1"
|
version = "3.11.1"
|
||||||
|
@ -110,41 +72,12 @@ version = "1.0.78"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cexpr"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
|
||||||
dependencies = [
|
|
||||||
"nom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "clang-sys"
|
|
||||||
version = "1.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
|
|
||||||
dependencies = [
|
|
||||||
"glob",
|
|
||||||
"libc",
|
|
||||||
"libloading",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cmake"
|
|
||||||
version = "0.1.50"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.3"
|
version = "0.9.3"
|
||||||
|
@ -278,12 +211,6 @@ version = "0.28.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "glob"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.3.15"
|
version = "0.3.15"
|
||||||
|
@ -445,28 +372,12 @@ version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazycell"
|
|
||||||
version = "1.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.150"
|
version = "0.2.150"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libloading"
|
|
||||||
version = "0.7.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.17"
|
version = "0.4.17"
|
||||||
|
@ -488,12 +399,6 @@ version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minimal-lexical"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
@ -532,16 +437,6 @@ dependencies = [
|
||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom"
|
|
||||||
version = "7.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"minimal-lexical",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
|
@ -573,7 +468,7 @@ version = "0.10.45"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
|
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -590,7 +485,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.107",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -612,12 +507,6 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "peeking_take_while"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
@ -672,38 +561,9 @@ version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex"
|
|
||||||
version = "1.10.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
|
||||||
dependencies = [
|
|
||||||
"aho-corasick",
|
|
||||||
"memchr",
|
|
||||||
"regex-automata",
|
|
||||||
"regex-syntax",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-automata"
|
|
||||||
version = "0.4.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
|
||||||
dependencies = [
|
|
||||||
"aho-corasick",
|
|
||||||
"memchr",
|
|
||||||
"regex-syntax",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remove_dir_all"
|
name = "remove_dir_all"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -757,12 +617,6 @@ version = "0.1.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-hash"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
|
@ -794,7 +648,7 @@ version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c"
|
checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -840,12 +694,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "shlex"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
|
@ -886,24 +734,13 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "2.0.42"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"system-configuration-sys",
|
"system-configuration-sys",
|
||||||
]
|
]
|
||||||
|
@ -1094,7 +931,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.107",
|
"syn",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1128,7 +965,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.107",
|
"syn",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
@ -1289,23 +1126,3 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "z3"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4a7ff5718c079e7b813378d67a5bed32ccc2086f151d6185074a7e24f4a565e8"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
"z3-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "z3-sys"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d7cf70fdbc0de3f42b404f49b0d4686a82562254ea29ff0a155eef2f5430f4b0"
|
|
||||||
dependencies = [
|
|
||||||
"bindgen",
|
|
||||||
"cmake",
|
|
||||||
]
|
|
||||||
|
|
|
@ -21,6 +21,4 @@ authors.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# so much for no dependencies this year, but I really cba so here it is
|
|
||||||
z3 = { version = "0.12.1", features = [ "static-link-z3" ] }
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
broadcaster -> a
|
|
||||||
%a -> inv, con
|
|
||||||
&inv -> b
|
|
||||||
%b -> con
|
|
||||||
&con -> output
|
|
|
@ -1,11 +0,0 @@
|
||||||
...........
|
|
||||||
.....###.#.
|
|
||||||
.###.##..#.
|
|
||||||
..#.#...#..
|
|
||||||
....#.#....
|
|
||||||
.##..S####.
|
|
||||||
.##..#...#.
|
|
||||||
.......##..
|
|
||||||
.##.#.####.
|
|
||||||
.##..##.##.
|
|
||||||
...........
|
|
|
@ -1,7 +0,0 @@
|
||||||
1,0,1~1,2,1
|
|
||||||
0,0,2~2,0,2
|
|
||||||
0,2,3~2,2,3
|
|
||||||
0,0,4~0,2,4
|
|
||||||
2,0,5~2,2,5
|
|
||||||
0,1,6~2,1,6
|
|
||||||
1,1,9~1,1,8
|
|
|
@ -1,23 +0,0 @@
|
||||||
#.#####################
|
|
||||||
#.......#########...###
|
|
||||||
#######.#########.#.###
|
|
||||||
###.....#.>.>.###.#.###
|
|
||||||
###v#####.#v#.###.#.###
|
|
||||||
###.>...#.#.#.....#...#
|
|
||||||
###v###.#.#.#########.#
|
|
||||||
###...#.#.#.......#...#
|
|
||||||
#####.#.#.#######.#.###
|
|
||||||
#.....#.#.#.......#...#
|
|
||||||
#.#####.#.#.#########v#
|
|
||||||
#.#...#...#...###...>.#
|
|
||||||
#.#.#v#######v###.###v#
|
|
||||||
#...#.>.#...>.>.#.###.#
|
|
||||||
#####v#.#.###v#.#.###.#
|
|
||||||
#.....#...#...#.#.#...#
|
|
||||||
#.#########.###.#.#.###
|
|
||||||
#...###...#...#...#.###
|
|
||||||
###.###.#.###v#####v###
|
|
||||||
#...#...#.#.>.>.#.>.###
|
|
||||||
#.###.###.#.###.#.#v###
|
|
||||||
#.....###...###...#...#
|
|
||||||
#####################.#
|
|
|
@ -1,5 +0,0 @@
|
||||||
19, 13, 30 @ -2, 1, -2
|
|
||||||
18, 19, 22 @ -1, -1, -2
|
|
||||||
20, 25, 34 @ -2, -2, -4
|
|
||||||
12, 31, 28 @ -1, -2, -1
|
|
||||||
20, 19, 15 @ 1, -5, -3
|
|
|
@ -1,13 +0,0 @@
|
||||||
jqt: rhn xhk nvd
|
|
||||||
rsh: frs pzl lsr
|
|
||||||
xhk: hfx
|
|
||||||
cmg: qnr nvd lhk bvb
|
|
||||||
rhn: xhk bvb hfx
|
|
||||||
bvb: xhk hfx
|
|
||||||
pzl: lsr hfx nvd
|
|
||||||
qnr: nvd
|
|
||||||
ntq: jqt hfx bvb xhk
|
|
||||||
nvd: lhk
|
|
||||||
lsr: lhk
|
|
||||||
rzs: qnr cmg lsr rsh
|
|
||||||
frs: qnr lhk lsr
|
|
147
src/bin/20.rs
147
src/bin/20.rs
|
@ -1,16 +1,14 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
|
mem::swap,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use aoc::lcm;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
enum Module {
|
enum Module {
|
||||||
Broadcaster,
|
Broadcaster,
|
||||||
FlipFlop(bool),
|
FlipFlop(bool),
|
||||||
Conjuction,
|
Conjuction,
|
||||||
Output,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -22,8 +20,7 @@ impl FromStr for Module {
|
||||||
Ok(match s {
|
Ok(match s {
|
||||||
"%" => Module::FlipFlop(false),
|
"%" => Module::FlipFlop(false),
|
||||||
"&" => Module::Conjuction,
|
"&" => Module::Conjuction,
|
||||||
"b" => Module::Broadcaster,
|
_ => Module::Broadcaster,
|
||||||
_ => return Err(ParseModuleError),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,18 +37,13 @@ fn parse_input(input: &str) -> Vec<Node> {
|
||||||
let mut nodes = Vec::new();
|
let mut nodes = Vec::new();
|
||||||
let mut mapper: HashMap<String, usize> = HashMap::new();
|
let mut mapper: HashMap<String, usize> = HashMap::new();
|
||||||
|
|
||||||
let output = Node {
|
|
||||||
index: 0,
|
|
||||||
module: Module::Output,
|
|
||||||
inputs: Vec::new(),
|
|
||||||
outputs: Vec::new(),
|
|
||||||
};
|
|
||||||
nodes.push(output);
|
|
||||||
|
|
||||||
for line in input.lines() {
|
for line in input.lines() {
|
||||||
let (from, _) = line.split_once(" -> ").unwrap();
|
let (from, _) = line.split_once(" -> ").unwrap();
|
||||||
let (module, name) = from.split_at(1);
|
let (module, mut name) = from.split_at(1);
|
||||||
let module: Module = module.parse().unwrap();
|
let module: Module = module.parse().unwrap();
|
||||||
|
if module == Module::Broadcaster {
|
||||||
|
name = from;
|
||||||
|
}
|
||||||
|
|
||||||
*mapper.entry(name.to_string()).or_default() = nodes.len();
|
*mapper.entry(name.to_string()).or_default() = nodes.len();
|
||||||
|
|
||||||
|
@ -67,11 +59,15 @@ fn parse_input(input: &str) -> Vec<Node> {
|
||||||
|
|
||||||
for line in input.lines() {
|
for line in input.lines() {
|
||||||
let (from, to) = line.split_once(" -> ").unwrap();
|
let (from, to) = line.split_once(" -> ").unwrap();
|
||||||
let (_, name) = from.split_at(1);
|
let (module, mut name) = from.split_at(1);
|
||||||
|
let module: Module = module.parse().unwrap();
|
||||||
|
if module == Module::Broadcaster {
|
||||||
|
name = from;
|
||||||
|
}
|
||||||
|
|
||||||
let index = mapper[name];
|
let index = mapper[name];
|
||||||
for destination in to.split(", ") {
|
for destination in to.split(", ") {
|
||||||
let to_index = *mapper.get(destination).unwrap_or(&0);
|
let to_index = mapper[destination];
|
||||||
nodes[index].outputs.push(to_index);
|
nodes[index].outputs.push(to_index);
|
||||||
nodes[to_index].inputs.push(index);
|
nodes[to_index].inputs.push(index);
|
||||||
}
|
}
|
||||||
|
@ -80,57 +76,58 @@ fn parse_input(input: &str) -> Vec<Node> {
|
||||||
nodes
|
nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cycle(input: &str, button_presses: Option<usize>) -> usize {
|
pub fn part_one(input: &str) -> Option<usize> {
|
||||||
let mut nodes = parse_input(input);
|
let mut nodes = parse_input(input);
|
||||||
|
|
||||||
let mut graph = vec![vec![false; nodes.len()]; nodes.len()];
|
let mut graph = vec![vec![None; nodes.len()]; nodes.len()];
|
||||||
|
|
||||||
let mut highs = 0;
|
let mut highs = 0;
|
||||||
let mut lows = 0;
|
let mut lows = 0;
|
||||||
|
|
||||||
let broadcaster = nodes
|
let broadcaster = nodes
|
||||||
.iter()
|
.iter()
|
||||||
.find(|x| x.module == Module::Broadcaster)
|
.find(|x| x.module == Module::Broadcaster)?
|
||||||
.unwrap()
|
|
||||||
.index;
|
.index;
|
||||||
|
|
||||||
let mut hm = HashMap::new();
|
for _ in 0..1000 {
|
||||||
let critical_node = nodes[0].inputs.first().copied();
|
let mut stack = VecDeque::from([broadcaster]);
|
||||||
let critical_inputs = critical_node.map(|x| nodes[x].inputs.len());
|
while !stack.is_empty() {
|
||||||
|
let mut new_stack = VecDeque::new();
|
||||||
|
let mut new_graph = graph.clone();
|
||||||
|
|
||||||
for i in 1..=button_presses.unwrap_or(usize::MAX) {
|
while let Some(index) = stack.pop_front() {
|
||||||
if let Some(c) = critical_inputs {
|
let node = &nodes[index];
|
||||||
if button_presses.is_none() && hm.values().len() == c {
|
let mut new_module = None;
|
||||||
return hm.values().copied().reduce(lcm).unwrap_or(0);
|
|
||||||
|
match node.module {
|
||||||
|
Module::Broadcaster => {
|
||||||
|
for dest_index in node.outputs.iter() {
|
||||||
|
new_graph[index][*dest_index] = Some(false);
|
||||||
|
new_stack.push_back(*dest_index);
|
||||||
|
lows += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Module::FlipFlop(high) => {
|
||||||
|
let mut swapper = None;
|
||||||
|
for in_index in nodes[index].inputs.iter() {
|
||||||
|
let value = &mut graph[*in_index][index];
|
||||||
|
if value.is_some() {
|
||||||
|
debug_assert!(swapper.is_none());
|
||||||
|
swap(&mut swapper, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stack = VecDeque::from([(broadcaster, false)]);
|
if !swapper.unwrap() {
|
||||||
|
let signal = !high;
|
||||||
|
|
||||||
while let Some((index, signal)) = stack.pop_front() {
|
for dest_index in nodes[index].outputs.iter() {
|
||||||
|
new_graph[index][*dest_index] = Some(signal);
|
||||||
|
new_stack.push_back(*dest_index);
|
||||||
if signal {
|
if signal {
|
||||||
highs += 1;
|
highs += 1;
|
||||||
} else {
|
} else {
|
||||||
lows += 1;
|
lows += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let node = &nodes[index];
|
|
||||||
let mut new_module = None;
|
|
||||||
|
|
||||||
match node.module {
|
|
||||||
Module::Output => (),
|
|
||||||
Module::Broadcaster => {
|
|
||||||
for dest_index in node.outputs.iter().copied() {
|
|
||||||
stack.push_back((dest_index, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Module::FlipFlop(high) => {
|
|
||||||
if !signal {
|
|
||||||
let signal = !high;
|
|
||||||
|
|
||||||
for dest_index in nodes[index].outputs.iter().copied() {
|
|
||||||
graph[index][dest_index] = signal;
|
|
||||||
stack.push_back((dest_index, signal));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_module = Some(Module::FlipFlop(signal));
|
new_module = Some(Module::FlipFlop(signal));
|
||||||
|
@ -139,22 +136,18 @@ pub fn cycle(input: &str, button_presses: Option<usize>) -> usize {
|
||||||
Module::Conjuction => {
|
Module::Conjuction => {
|
||||||
let mut all = true;
|
let mut all = true;
|
||||||
|
|
||||||
for in_index in nodes[index].inputs.iter().copied() {
|
for in_index in nodes[index].inputs.iter() {
|
||||||
all &= graph[in_index][index];
|
let value = graph[*in_index][index];
|
||||||
|
all &= value.unwrap_or(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for dest_index in nodes[index].outputs.iter().copied() {
|
for dest_index in nodes[index].outputs.iter() {
|
||||||
graph[index][dest_index] = !all;
|
new_graph[index][*dest_index] = Some(!all);
|
||||||
stack.push_back((dest_index, !all));
|
new_stack.push_back(*dest_index);
|
||||||
}
|
if !all {
|
||||||
|
highs += 1;
|
||||||
if let Some(c) = critical_node {
|
} else {
|
||||||
if index == c {
|
lows += 1;
|
||||||
for in_index in nodes[index].inputs.iter().copied() {
|
|
||||||
if graph[in_index][index] {
|
|
||||||
hm.entry(in_index).or_insert(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,16 +158,17 @@ pub fn cycle(input: &str, button_presses: Option<usize>) -> usize {
|
||||||
node.module = module;
|
node.module = module;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stack = new_stack;
|
||||||
|
graph = new_graph;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
highs * lows
|
Some(highs * lows)
|
||||||
}
|
|
||||||
pub fn part_one(input: &str) -> Option<usize> {
|
|
||||||
Some(cycle(input, Some(1000)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn part_two(input: &str) -> Option<usize> {
|
pub fn part_two(input: &str) -> Option<u32> {
|
||||||
Some(cycle(input, None))
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
aoc::solution!(20);
|
aoc::solution!(20);
|
||||||
|
@ -183,24 +177,11 @@ aoc::solution!(20);
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one_first() {
|
fn test_part_one() {
|
||||||
assert_eq!(
|
assert_eq!(part_one(&aoc::template::read_file("examples", 20)), None);
|
||||||
part_one(&aoc::template::read_file_part("examples", 20, 1)),
|
|
||||||
Some(32000000)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_part_one_second() {
|
|
||||||
assert_eq!(
|
|
||||||
part_one(&aoc::template::read_file_part("examples", 20, 2)),
|
|
||||||
Some(11687500)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
assert_eq!(
|
assert_eq!(part_two(&aoc::template::read_file("examples", 20)), None);
|
||||||
part_two(&aoc::template::read_file_part("examples", 20, 2)),
|
|
||||||
Some(1)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
106
src/bin/21.rs
106
src/bin/21.rs
|
@ -1,106 +0,0 @@
|
||||||
use std::{collections::HashSet, usize};
|
|
||||||
|
|
||||||
fn parse_input(input: &str) -> (Vec<Vec<u8>>, (isize, isize)) {
|
|
||||||
let mut grid: Vec<_> = input.lines().map(|x| x.as_bytes().to_vec()).collect();
|
|
||||||
|
|
||||||
let start = grid
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.flat_map(|(y, item)| item.iter().enumerate().map(move |(x, item)| (x, y, *item)))
|
|
||||||
.find_map(|(x, y, s)| if s == b'S' { Some((y, x)) } else { None })
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
grid[start.0][start.1] = b'.';
|
|
||||||
|
|
||||||
(grid, (start.0 as isize, start.1 as isize))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn walk_return_at(
|
|
||||||
grid: &[Vec<u8>],
|
|
||||||
start: (isize, isize),
|
|
||||||
mut returns: Vec<usize>,
|
|
||||||
can_cycle: bool,
|
|
||||||
) -> Vec<usize> {
|
|
||||||
returns.sort_by(|a, b| b.cmp(a));
|
|
||||||
|
|
||||||
let h = grid.len() as isize;
|
|
||||||
let w = grid[0].len() as isize;
|
|
||||||
|
|
||||||
let invalid_indexing = |y, x| y < 0 || y >= h || x < 0 || x >= w;
|
|
||||||
|
|
||||||
let mut results = Vec::new();
|
|
||||||
let length = returns[0];
|
|
||||||
let mut next = returns.pop().unwrap();
|
|
||||||
|
|
||||||
let mut visited = HashSet::new();
|
|
||||||
visited.insert(start);
|
|
||||||
|
|
||||||
for i in 1..=length {
|
|
||||||
let mut new_visited = HashSet::new();
|
|
||||||
|
|
||||||
for (y, x) in visited.iter() {
|
|
||||||
for (dy, dx) in [(1, 0), (0, 1), (-1, 0), (0, -1)] {
|
|
||||||
let (ny, nx) = (y + dy, x + dx);
|
|
||||||
|
|
||||||
if !can_cycle && invalid_indexing(ny, nx) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (cy, cx) = (ny.rem_euclid(h) as usize, nx.rem_euclid(w) as usize);
|
|
||||||
|
|
||||||
if grid[cy][cx] == b'.' {
|
|
||||||
new_visited.insert((ny, nx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visited = new_visited;
|
|
||||||
|
|
||||||
if i == next {
|
|
||||||
results.push(visited.len());
|
|
||||||
if !returns.is_empty() {
|
|
||||||
next = returns.pop().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_one(input: &str) -> Option<usize> {
|
|
||||||
let (grid, start) = parse_input(input);
|
|
||||||
let result = walk_return_at(&grid, start, vec![64], false);
|
|
||||||
|
|
||||||
Some(result[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_two(input: &str) -> Option<usize> {
|
|
||||||
let (grid, start) = parse_input(input);
|
|
||||||
|
|
||||||
let h = grid.len();
|
|
||||||
let s = start.0 as usize;
|
|
||||||
|
|
||||||
let result = walk_return_at(&grid, start, vec![s, s + h, s + 2 * h], true);
|
|
||||||
|
|
||||||
let a = (result[2] - 2 * result[1] + result[0]) / 2;
|
|
||||||
let b = (result[1] - result[0]) - a;
|
|
||||||
let c = result[0];
|
|
||||||
|
|
||||||
let x = 26501365 / h;
|
|
||||||
|
|
||||||
Some(a * x * x + b * x + c)
|
|
||||||
}
|
|
||||||
|
|
||||||
aoc::solution!(21);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
fn test_part_one() {
|
|
||||||
assert_eq!(
|
|
||||||
part_one(&aoc::template::read_file("examples", 21)),
|
|
||||||
Some(42)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
143
src/bin/22.rs
143
src/bin/22.rs
|
@ -1,143 +0,0 @@
|
||||||
use std::{collections::HashMap, str::FromStr};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
||||||
struct Brick {
|
|
||||||
from: (usize, usize, usize),
|
|
||||||
to: (usize, usize, usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct ParseBrickError;
|
|
||||||
|
|
||||||
impl FromStr for Brick {
|
|
||||||
type Err = ParseBrickError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let (first, second) = s.split_once('~').ok_or(ParseBrickError)?;
|
|
||||||
|
|
||||||
let sorted: Vec<_> = first
|
|
||||||
.split(',')
|
|
||||||
.filter_map(|y| y.parse().ok())
|
|
||||||
.zip(second.split(',').filter_map(|y| y.parse().ok()))
|
|
||||||
.map(|(x, y)| if x < y { (x, y) } else { (y, x) })
|
|
||||||
.collect();
|
|
||||||
let from = (sorted[0].0, sorted[1].0, sorted[2].0);
|
|
||||||
let to = (sorted[0].1, sorted[1].1, sorted[2].1);
|
|
||||||
|
|
||||||
Ok(Self { from, to })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Brick {
|
|
||||||
fn height(&self) -> usize {
|
|
||||||
self.to.2 - self.from.2 + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn points(&self) -> impl Iterator<Item = (usize, usize, usize)> + '_ {
|
|
||||||
(self.from.0..=self.to.0).flat_map(move |x| {
|
|
||||||
(self.from.1..=self.to.1)
|
|
||||||
.flat_map(move |y| (self.from.2..=self.to.2).map(move |z| (x, y, z)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for Brick {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for Brick {
|
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
||||||
self.from
|
|
||||||
.2
|
|
||||||
.cmp(&other.from.2)
|
|
||||||
.then((self.from.0, self.from.1).cmp(&(other.from.0, other.from.1)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Tower {
|
|
||||||
bricks: Vec<Brick>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Tower {
|
|
||||||
fn new(mut bricks: Vec<Brick>) -> Self {
|
|
||||||
bricks.sort();
|
|
||||||
let mut ret = Self { bricks };
|
|
||||||
ret.compress(None);
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compress(&mut self, skip: Option<usize>) -> usize {
|
|
||||||
let mut heights: HashMap<(usize, usize), usize> = HashMap::new();
|
|
||||||
let mut moved = 0;
|
|
||||||
|
|
||||||
for brick in self
|
|
||||||
.bricks
|
|
||||||
.iter_mut()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|(i, _)| *i != skip.unwrap_or(usize::MAX))
|
|
||||||
.map(|(_, x)| x)
|
|
||||||
{
|
|
||||||
let height = brick.height();
|
|
||||||
let new_height = brick
|
|
||||||
.points()
|
|
||||||
.map(|(x, y, _)| *heights.entry((x, y)).or_default())
|
|
||||||
.max()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for (x, y, _) in brick.points() {
|
|
||||||
*heights.get_mut(&(x, y)).unwrap() = new_height + height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_height + 1 == brick.from.2 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if skip.is_none() {
|
|
||||||
brick.from.2 = new_height + 1;
|
|
||||||
brick.to.2 = new_height + height;
|
|
||||||
}
|
|
||||||
|
|
||||||
moved += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
moved
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_one(input: &str) -> Option<usize> {
|
|
||||||
let mut tower = Tower::new(input.lines().filter_map(|x| x.parse().ok()).collect());
|
|
||||||
|
|
||||||
Some(
|
|
||||||
(0..tower.bricks.len())
|
|
||||||
.map(|i| tower.compress(Some(i)))
|
|
||||||
.filter(|m| *m == 0)
|
|
||||||
.count(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_two(input: &str) -> Option<usize> {
|
|
||||||
let mut tower = Tower::new(input.lines().filter_map(|x| x.parse().ok()).collect());
|
|
||||||
|
|
||||||
Some(
|
|
||||||
(0..tower.bricks.len())
|
|
||||||
.map(|i| tower.compress(Some(i)))
|
|
||||||
.sum(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
aoc::solution!(22);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
fn test_part_one() {
|
|
||||||
assert_eq!(part_one(&aoc::template::read_file("examples", 22)), Some(5));
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_part_two() {
|
|
||||||
assert_eq!(part_two(&aoc::template::read_file("examples", 22)), Some(7));
|
|
||||||
}
|
|
||||||
}
|
|
161
src/bin/23.rs
161
src/bin/23.rs
|
@ -1,161 +0,0 @@
|
||||||
use std::{
|
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
iter::once,
|
|
||||||
};
|
|
||||||
|
|
||||||
const DIRS: [(isize, isize); 4] = [(1, 0), (0, 1), (-1, 0), (0, -1)];
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
struct Node {
|
|
||||||
neighbours: Vec<(usize, usize)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_graph(input: &str, two_way: bool) -> (Vec<Node>, usize) {
|
|
||||||
let mut grid: Vec<Vec<_>> = input.lines().map(|x| x.as_bytes().to_vec()).collect();
|
|
||||||
|
|
||||||
let l = grid[0].len();
|
|
||||||
|
|
||||||
let border: Vec<_> = once(b'#').cycle().take(l).collect();
|
|
||||||
grid.insert(0, border.clone());
|
|
||||||
grid.push(border);
|
|
||||||
|
|
||||||
let start = (1, 1);
|
|
||||||
let end = (grid.len() - 2, grid[0].len() - 2);
|
|
||||||
|
|
||||||
let mut nodes = Vec::new();
|
|
||||||
|
|
||||||
let mut mapper = HashMap::new();
|
|
||||||
mapper.insert(start, 0);
|
|
||||||
|
|
||||||
let mut visited: HashSet<(usize, usize)> = HashSet::new();
|
|
||||||
|
|
||||||
let mut stack = Vec::new();
|
|
||||||
// (from_node, at, len)
|
|
||||||
stack.push((start, start, 0));
|
|
||||||
|
|
||||||
let forced = |x| match x {
|
|
||||||
b'>' => (0, 1),
|
|
||||||
b'v' => (1, 0),
|
|
||||||
_ => (0, 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
while let Some((from, (y, x), len)) = stack.pop() {
|
|
||||||
let is_node = DIRS
|
|
||||||
.iter()
|
|
||||||
.filter(|(dy, dx)| {
|
|
||||||
grid[((y as isize) + dy) as usize][((x as isize) + dx) as usize] != b'#'
|
|
||||||
})
|
|
||||||
.count()
|
|
||||||
> 2
|
|
||||||
|| (y, x) == start
|
|
||||||
|| (y, x) == end;
|
|
||||||
|
|
||||||
if is_node {
|
|
||||||
if !visited.contains(&(y, x)) {
|
|
||||||
mapper.insert((y, x), nodes.len());
|
|
||||||
nodes.push(Node::default());
|
|
||||||
}
|
|
||||||
|
|
||||||
if from != (y, x) {
|
|
||||||
nodes[mapper[&from]].neighbours.push((mapper[&(y, x)], len));
|
|
||||||
if two_way {
|
|
||||||
nodes[mapper[&(y, x)]].neighbours.push((mapper[&from], len));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !visited.insert((y, x)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (ny, nx, _, _) in DIRS
|
|
||||||
.iter()
|
|
||||||
.map(|(dy, dx)| {
|
|
||||||
(
|
|
||||||
((y as isize) + dy) as usize,
|
|
||||||
((x as isize) + dx) as usize,
|
|
||||||
dy,
|
|
||||||
dx,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.filter(|(ny, nx, _, _)| grid[*ny][*nx] != b'#')
|
|
||||||
.filter(|(ny, nx, dy, dx)| {
|
|
||||||
let (fy, fx) = forced(grid[*ny][*nx]);
|
|
||||||
(fy + **dy, fx + **dx) != (0, 0)
|
|
||||||
})
|
|
||||||
{
|
|
||||||
let new_len = if is_node { 1 } else { len + 1 };
|
|
||||||
let new_from = if is_node { (y, x) } else { from };
|
|
||||||
stack.push((new_from, (ny, nx), new_len));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(nodes, mapper[&end])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn longest_path(
|
|
||||||
nodes: &[Node],
|
|
||||||
mut visited: usize,
|
|
||||||
location: usize,
|
|
||||||
target: usize,
|
|
||||||
length: usize,
|
|
||||||
) -> Option<usize> {
|
|
||||||
if location == target {
|
|
||||||
return Some(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// binary mask for visited since < 64 nodes in input
|
|
||||||
// nth bit tells if location n was visited already
|
|
||||||
visited |= 1 << location;
|
|
||||||
|
|
||||||
let mut max_len = 0;
|
|
||||||
|
|
||||||
for (n, l) in nodes[location]
|
|
||||||
.neighbours
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.filter(|(n, _)| (visited & 1 << n) == 0)
|
|
||||||
{
|
|
||||||
if let Some(new_len) = longest_path(nodes, visited, n, target, length + l) {
|
|
||||||
if max_len < new_len {
|
|
||||||
max_len = new_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if max_len > 0 {
|
|
||||||
Some(max_len)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_one(input: &str) -> Option<usize> {
|
|
||||||
let (nodes, target) = build_graph(input, false);
|
|
||||||
longest_path(&nodes, 0, 0, target, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_two(input: &str) -> Option<usize> {
|
|
||||||
let (nodes, target) = build_graph(input, true);
|
|
||||||
longest_path(&nodes, 0, 0, target, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
aoc::solution!(23);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
fn test_part_one() {
|
|
||||||
assert_eq!(
|
|
||||||
part_one(&aoc::template::read_file("examples", 23)),
|
|
||||||
Some(94)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_part_two() {
|
|
||||||
assert_eq!(
|
|
||||||
part_two(&aoc::template::read_file("examples", 23)),
|
|
||||||
Some(154)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
use z3::ast::{Ast, Int};
|
|
||||||
|
|
||||||
type Vector3 = (f64, f64, f64);
|
|
||||||
|
|
||||||
fn parse_input(input: &str) -> Vec<(Vector3, Vector3)> {
|
|
||||||
input
|
|
||||||
.lines()
|
|
||||||
.filter_map(|x| x.split_once(" @ "))
|
|
||||||
.map(|(a, b)| {
|
|
||||||
let av: Vec<_> = a.splitn(3, ", ").filter_map(|x| x.parse().ok()).collect();
|
|
||||||
let bv: Vec<_> = b.splitn(3, ", ").filter_map(|x| x.parse().ok()).collect();
|
|
||||||
((av[0], av[1], av[2]), (bv[0], bv[1], bv[2]))
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part_one_with_area(input: &str, min: f64, max: f64) -> u32 {
|
|
||||||
let points = parse_input(input);
|
|
||||||
|
|
||||||
let mut c = 0;
|
|
||||||
|
|
||||||
let test_area = |x: f64, y: f64| x <= max && x >= min && y <= max && y >= min;
|
|
||||||
|
|
||||||
for (i, ((x1, y1, _), (dx1, dy1, _))) in points.iter().copied().enumerate() {
|
|
||||||
for ((x2, y2, _), (dx2, dy2, _)) in points.iter().skip(i + 1).copied() {
|
|
||||||
let n2 = (x2 - x1 + (y1 - y2) * dx1 / dy1) / (dy2 * dx1 / dy1 - dx2);
|
|
||||||
let n1 = (x1 - x2 + (y2 - y1) * dx2 / dy2) / (dy1 * dx2 / dy2 - dx1);
|
|
||||||
|
|
||||||
if n1 <= 0.0 || n2 <= 0.0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let x = x1 + n1 * dx1;
|
|
||||||
let y = y1 + n1 * dy1;
|
|
||||||
|
|
||||||
if test_area(x, y) {
|
|
||||||
c += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c
|
|
||||||
}
|
|
||||||
pub fn part_one(input: &str) -> Option<u32> {
|
|
||||||
let min = 200000000000000.0;
|
|
||||||
let max = 400000000000000.0;
|
|
||||||
Some(part_one_with_area(input, min, max))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_two(input: &str) -> Option<u64> {
|
|
||||||
let points = parse_input(input);
|
|
||||||
|
|
||||||
let ctx = z3::Context::new(&z3::Config::new());
|
|
||||||
let solver = z3::Solver::new(&ctx);
|
|
||||||
|
|
||||||
let zero = Int::from_u64(&ctx, 0);
|
|
||||||
let [a, b, c, da, db, dc] = ["a", "b", "c", "da", "db", "dc"].map(|x| Int::new_const(&ctx, x));
|
|
||||||
|
|
||||||
for (i, ((x, y, z), (dx, dy, dz))) in points.iter().enumerate().take(3) {
|
|
||||||
let [x, y, z, dx, dy, dz] = [x, y, z, dx, dy, dz].map(|w| Int::from_i64(&ctx, *w as i64));
|
|
||||||
let t = Int::new_const(&ctx, format!("t_{i}").as_str());
|
|
||||||
solver.assert(&t.ge(&zero));
|
|
||||||
solver.assert(&((&x + &dx * &t)._eq(&(&a + &da * &t))));
|
|
||||||
solver.assert(&((&y + &dy * &t)._eq(&(&b + &db * &t))));
|
|
||||||
solver.assert(&((&z + &dz * &t)._eq(&(&c + &dc * &t))));
|
|
||||||
}
|
|
||||||
|
|
||||||
solver.check();
|
|
||||||
let model = solver.get_model().unwrap();
|
|
||||||
let res = model.eval(&(&a + &b + &c), true).unwrap();
|
|
||||||
|
|
||||||
res.as_u64()
|
|
||||||
}
|
|
||||||
|
|
||||||
aoc::solution!(24);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
fn test_part_one() {
|
|
||||||
let input = aoc::template::read_file("examples", 24);
|
|
||||||
let min = 7.0;
|
|
||||||
let max = 27.0;
|
|
||||||
assert_eq!(part_one_with_area(&input, min, max), 2);
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_part_two() {
|
|
||||||
assert_eq!(
|
|
||||||
part_two(&aoc::template::read_file("examples", 24)),
|
|
||||||
Some(47)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
fn build_graph(input: &str, skips: &[(&str, &str)]) -> Vec<Vec<usize>> {
|
|
||||||
let mut nodes = Vec::new();
|
|
||||||
let mut mapper = HashMap::new();
|
|
||||||
|
|
||||||
for (node, neighs) in input.lines().filter_map(|x| x.split_once(": ")) {
|
|
||||||
if !mapper.contains_key(node) {
|
|
||||||
mapper.insert(node, nodes.len());
|
|
||||||
nodes.push(Vec::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
let index_a = mapper[node];
|
|
||||||
|
|
||||||
for n in neighs.split(' ') {
|
|
||||||
if !mapper.contains_key(n) {
|
|
||||||
mapper.insert(n, nodes.len());
|
|
||||||
nodes.push(Vec::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
if skips.contains(&(node, n)) || skips.contains(&(n, node)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let index_b = mapper[n];
|
|
||||||
nodes[index_a].push(index_b);
|
|
||||||
nodes[index_b].push(index_a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_one_wrapped(input: &str, skips: &[(&str, &str)]) -> Option<usize> {
|
|
||||||
let nodes = build_graph(input, skips);
|
|
||||||
|
|
||||||
let mut visited = vec![false; nodes.len()];
|
|
||||||
let mut stack = vec![0];
|
|
||||||
|
|
||||||
while let Some(node) = stack.pop() {
|
|
||||||
if visited[node] {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
visited[node] = true;
|
|
||||||
for n in nodes[node].iter().copied() {
|
|
||||||
if !visited[n] {
|
|
||||||
stack.push(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let counter = visited.iter().copied().filter(|&x| x).count();
|
|
||||||
Some((nodes.len() - counter) * counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_one(input: &str) -> Option<usize> {
|
|
||||||
// to figure out which nodes to skip
|
|
||||||
// echo "graph A {\n$(cat data/inputs/25.txt)\n}" | \
|
|
||||||
// sed 's/\(.*\): \(.*\)$/\1 -- {\2}/' | \
|
|
||||||
// dot -Tsvg -Kneato > graph.svg
|
|
||||||
let skips = [("sfm", "vmt"), ("vph", "mfc"), ("fql", "rmg")];
|
|
||||||
part_one_wrapped(input, &skips)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part_two(_input: &str) -> Option<String> {
|
|
||||||
Some("Happy chrismas!".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
aoc::solution!(25);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
fn test_part_one() {
|
|
||||||
let skips = [("pzl", "hfx"), ("bvb", "cmg"), ("nvd", "jqt")];
|
|
||||||
let input = aoc::template::read_file("examples", 25);
|
|
||||||
assert_eq!(part_one_wrapped(&input, &skips), Some(54));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue