Compare commits
13 Commits
30ef81cfac
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| fc803d8a0f | |||
| 3a9379f877 | |||
| 241c417a77 | |||
| 4cbe831115 | |||
| a4c33ae3d2 | |||
| 48ad7e7a96 | |||
| caf307bf2d | |||
| 2792304040 | |||
| 42ead11aa0 | |||
| 8e1f42205c | |||
| c4ae25d579 | |||
| f472ace665 | |||
| a9b3c90a6c |
329
Cargo.lock
generated
329
Cargo.lock
generated
@@ -4,13 +4,28 @@ version = 3
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.6.9"
|
version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
|
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aoc_2018"
|
name = "aoc_2018"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -32,6 +47,12 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@@ -39,22 +60,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cc"
|
||||||
version = "0.1.6"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.6"
|
version = "0.4.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
|
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-integer",
|
"android-tzdata",
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"time",
|
"wasm-bindgen",
|
||||||
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -68,45 +107,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0896cb73353671dbe2b17312c97b55b7032831d28c809c703bece4a392b1df3a"
|
checksum = "0896cb73353671dbe2b17312c97b55b7032831d28c809c703bece4a392b1df3a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "iana-time-zone"
|
||||||
version = "0.7.11"
|
version = "0.1.58"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
|
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "js-sys"
|
||||||
version = "1.2.0"
|
version = "0.3.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.44"
|
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 = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
|
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.1.1"
|
version = "2.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-integer"
|
|
||||||
version = "0.1.39"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
@@ -115,89 +178,191 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
checksum = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "once_cell"
|
||||||
version = "0.1.43"
|
version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d"
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.1.0"
|
version = "1.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
|
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 = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
"thread_local",
|
|
||||||
"utf8-ranges",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.4"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.39"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ucd-util",
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "unicode-ident"
|
||||||
version = "0.3.6"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.88"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"cfg-if",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.1.40"
|
version = "0.2.88"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
|
checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"bumpalo",
|
||||||
"redox_syscall",
|
"log",
|
||||||
"winapi",
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ucd-util"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.1.3"
|
version = "0.2.88"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "utf8-ranges"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "version_check"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-i686-pc-windows-gnu",
|
"quote",
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
"wasm-bindgen-macro-support",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.4.0"
|
version = "0.2.88"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.4.0"
|
version = "0.2.88"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.51.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ authors = ["Johannes <jschaef@mail.uni-paderborn.de>"]
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = "1.1.0"
|
regex = "1.10.2"
|
||||||
chrono = "0.4.6"
|
chrono = "0.4.31"
|
||||||
itertools = "0.7.11"
|
itertools = "0.11.0"
|
||||||
gcd = "1.1.0"
|
gcd = "1.1.0"
|
||||||
lazy_static = "1.2.0"
|
lazy_static = "1.4.0"
|
||||||
bmp = "0.5.0"
|
bmp = "0.5.0"
|
||||||
4261
input/day16.txt
Normal file
4261
input/day16.txt
Normal file
File diff suppressed because it is too large
Load Diff
37
input/day19.txt
Normal file
37
input/day19.txt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#ip 4
|
||||||
|
addi 4 16 4
|
||||||
|
seti 1 9 5
|
||||||
|
seti 1 5 2
|
||||||
|
mulr 5 2 1
|
||||||
|
eqrr 1 3 1
|
||||||
|
addr 1 4 4
|
||||||
|
addi 4 1 4
|
||||||
|
addr 5 0 0
|
||||||
|
addi 2 1 2
|
||||||
|
gtrr 2 3 1
|
||||||
|
addr 4 1 4
|
||||||
|
seti 2 6 4
|
||||||
|
addi 5 1 5
|
||||||
|
gtrr 5 3 1
|
||||||
|
addr 1 4 4
|
||||||
|
seti 1 2 4
|
||||||
|
mulr 4 4 4
|
||||||
|
addi 3 2 3
|
||||||
|
mulr 3 3 3
|
||||||
|
mulr 4 3 3
|
||||||
|
muli 3 11 3
|
||||||
|
addi 1 5 1
|
||||||
|
mulr 1 4 1
|
||||||
|
addi 1 2 1
|
||||||
|
addr 3 1 3
|
||||||
|
addr 4 0 4
|
||||||
|
seti 0 2 4
|
||||||
|
setr 4 8 1
|
||||||
|
mulr 1 4 1
|
||||||
|
addr 4 1 1
|
||||||
|
mulr 4 1 1
|
||||||
|
muli 1 14 1
|
||||||
|
mulr 1 4 1
|
||||||
|
addr 3 1 3
|
||||||
|
seti 0 0 0
|
||||||
|
seti 0 2 4
|
||||||
32
input/day21.txt
Normal file
32
input/day21.txt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ip 1
|
||||||
|
seti 123 0 2
|
||||||
|
bani 2 456 2
|
||||||
|
eqri 2 72 2
|
||||||
|
addr 2 1 1
|
||||||
|
seti 0 0 1
|
||||||
|
seti 0 3 2
|
||||||
|
bori 2 65536 5
|
||||||
|
seti 4843319 1 2
|
||||||
|
bani 5 255 4
|
||||||
|
addr 2 4 2
|
||||||
|
bani 2 16777215 2
|
||||||
|
muli 2 65899 2
|
||||||
|
bani 2 16777215 2
|
||||||
|
gtir 256 5 4
|
||||||
|
addr 4 1 1
|
||||||
|
addi 1 1 1
|
||||||
|
seti 27 4 1
|
||||||
|
seti 0 7 4
|
||||||
|
addi 4 1 3
|
||||||
|
muli 3 256 3
|
||||||
|
gtrr 3 5 3
|
||||||
|
addr 3 1 1
|
||||||
|
addi 1 1 1
|
||||||
|
seti 25 0 1
|
||||||
|
addi 4 1 4
|
||||||
|
seti 17 0 1
|
||||||
|
setr 4 1 5
|
||||||
|
seti 7 3 1
|
||||||
|
eqrr 2 0 4
|
||||||
|
addr 4 1 1
|
||||||
|
seti 5 3 1
|
||||||
1405
input/day25.txt
Normal file
1405
input/day25.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,3 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
aoc_2018::tasks::day18::task2();
|
aoc_2018::tasks::day24::task2();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ pub fn task1() {
|
|||||||
for line in input.lines() {
|
for line in input.lines() {
|
||||||
let mut counts = [0u8; 26];
|
let mut counts = [0u8; 26];
|
||||||
for c in line.chars() {
|
for c in line.chars() {
|
||||||
counts[(c as usize - 'a' as usize)] += 1;
|
counts[c as usize - 'a' as usize] += 1;
|
||||||
}
|
}
|
||||||
if counts.iter().any(|count| *count == 2) {
|
if counts.iter().any(|count| *count == 2) {
|
||||||
count_two += 1;
|
count_two += 1;
|
||||||
@@ -138,7 +138,7 @@ fn check_children_for_match(node: &Node<'_>) -> Option<String> {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
// go over all suffixes and count their occurences. If # = 2, match!
|
// go over all suffixes and count their occurrences. If # = 2, match!
|
||||||
let mut suffix_counter: HashMap<&str, usize> = HashMap::new();
|
let mut suffix_counter: HashMap<&str, usize> = HashMap::new();
|
||||||
for suffix_set in suffix_candidates.values() {
|
for suffix_set in suffix_candidates.values() {
|
||||||
for suffix in suffix_set {
|
for suffix in suffix_set {
|
||||||
@@ -164,7 +164,7 @@ fn add_id_to_tree<'a>(root: &mut Node<'a>, id: &'a str) {
|
|||||||
current.same_prefix.insert(id);
|
current.same_prefix.insert(id);
|
||||||
for (i, c) in id.chars().enumerate() {
|
for (i, c) in id.chars().enumerate() {
|
||||||
{
|
{
|
||||||
let mut next = current.outgoing.entry(c).or_insert(Node::default());
|
let next = current.outgoing.entry(c).or_insert(Node::default());
|
||||||
next.depth = i + 1;
|
next.depth = i + 1;
|
||||||
next.same_prefix.insert(id);
|
next.same_prefix.insert(id);
|
||||||
next.prefix = &id[..=i];
|
next.prefix = &id[..=i];
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ fn perform_round(map: &[Vec<char>], carts: &mut Vec<Cart>) {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for cart_index in 0..carts.len() {
|
for cart_index in 0..carts.len() {
|
||||||
let mut cart = &mut carts[cart_index];
|
let cart = &mut carts[cart_index];
|
||||||
if !cart.active {
|
if !cart.active {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
630
src/tasks/day16.rs
Normal file
630
src/tasks/day16.rs
Normal file
@@ -0,0 +1,630 @@
|
|||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::ops::{BitAnd, BitOr};
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
pub fn task1() {
|
||||||
|
let count = include_str!("../../input/day16.txt")
|
||||||
|
.split_once("\n\n\n\n")
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.split("\n\n")
|
||||||
|
.map(|sample_input| parse(sample_input))
|
||||||
|
.map(matches_count)
|
||||||
|
.filter(|count| *count >= 3)
|
||||||
|
.count();
|
||||||
|
println!("Day 16 part1: {count}");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn task2() {
|
||||||
|
let (samples, program) = include_str!("../../input/day16.txt")
|
||||||
|
.split_once("\n\n\n\n")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let code_to_op_candidates = samples
|
||||||
|
.split("\n\n")
|
||||||
|
.map(|sample_input| parse(sample_input))
|
||||||
|
.map(|sample| (sample.1.opcode, matches_ops(sample)))
|
||||||
|
.into_group_map_by(|x| x.0);
|
||||||
|
|
||||||
|
// let code_to_op: HashMap<usize, HashSet<Op>> =
|
||||||
|
let mut code_to_op_candidates: HashMap<_, _> = code_to_op_candidates
|
||||||
|
.into_iter()
|
||||||
|
.map(|(code, ops)| {
|
||||||
|
let mut set: HashSet<_> = HashSet::from_iter(OPS.iter().map(ToOwned::to_owned));
|
||||||
|
for (_, candidate_set) in ops {
|
||||||
|
set = set
|
||||||
|
.intersection(&candidate_set)
|
||||||
|
.map(ToOwned::to_owned)
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
(code, set)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut codes_to_op: HashMap<usize, Op> = HashMap::new();
|
||||||
|
loop {
|
||||||
|
let single = code_to_op_candidates.iter().find(|(_, ops)| ops.len() == 1);
|
||||||
|
let Some(single) = single else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
let code = *single.0;
|
||||||
|
let op = *single.1.iter().next().unwrap();
|
||||||
|
|
||||||
|
codes_to_op.insert(code, op);
|
||||||
|
|
||||||
|
code_to_op_candidates.iter_mut().for_each(|(_, ops)| {
|
||||||
|
ops.remove(&op);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if codes_to_op.len() != OPS.len() {
|
||||||
|
panic!("Bad final opcode assignments: {codes_to_op:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let program: Vec<Instruction> = program.lines().map(parse_instruction).collect();
|
||||||
|
|
||||||
|
let mut registers = Registers([0, 0, 0, 0]);
|
||||||
|
for instruction in program {
|
||||||
|
let op: Op = codes_to_op[&instruction.opcode];
|
||||||
|
registers = op.process(registers, instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Day 16 part 2: {}", registers.0[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(sample: &str) -> Sample {
|
||||||
|
let (before, instruction, after) = sample.lines().collect_tuple().unwrap();
|
||||||
|
let before: Vec<_> = before
|
||||||
|
.trim_start_matches("Before: [")
|
||||||
|
.trim_end_matches("]")
|
||||||
|
.split(", ")
|
||||||
|
.collect();
|
||||||
|
let before = Registers::from(before);
|
||||||
|
let after: Vec<_> = after
|
||||||
|
.trim_start_matches("After: [")
|
||||||
|
.trim_end_matches("]")
|
||||||
|
.split(", ")
|
||||||
|
.collect();
|
||||||
|
let after = Registers::from(after);
|
||||||
|
let instruction = parse_instruction(instruction);
|
||||||
|
|
||||||
|
Sample(before, instruction, after)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_instruction(instruction: &str) -> Instruction {
|
||||||
|
let instruction: Vec<usize> = instruction.split(" ").map(|x| x.parse().unwrap()).collect();
|
||||||
|
let instruction = Instruction {
|
||||||
|
opcode: instruction[0],
|
||||||
|
a: instruction[1],
|
||||||
|
b: instruction[2],
|
||||||
|
c: instruction[3],
|
||||||
|
};
|
||||||
|
instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matches(sample: Sample, op: Op) -> bool {
|
||||||
|
op.process(sample.0, sample.1) == sample.2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matches_count(sample: Sample) -> usize {
|
||||||
|
let vec = OPS.iter().filter(|op| matches(sample, **op)).collect_vec();
|
||||||
|
vec.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matches_ops(sample: Sample) -> HashSet<Op> {
|
||||||
|
OPS.iter()
|
||||||
|
.filter(|op| matches(sample, **op))
|
||||||
|
.map(|op| op.to_owned())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
const OPS: &[Op] = &[
|
||||||
|
Op::AddR,
|
||||||
|
Op::AddI,
|
||||||
|
Op::MulR,
|
||||||
|
Op::MulI,
|
||||||
|
Op::BanR,
|
||||||
|
Op::BanI,
|
||||||
|
Op::BorR,
|
||||||
|
Op::BorI,
|
||||||
|
Op::SetR,
|
||||||
|
Op::SetI,
|
||||||
|
Op::GtIR,
|
||||||
|
Op::GtRI,
|
||||||
|
Op::GtRR,
|
||||||
|
Op::EqIR,
|
||||||
|
Op::EqRI,
|
||||||
|
Op::EqRR,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
|
enum Op {
|
||||||
|
AddR,
|
||||||
|
AddI,
|
||||||
|
MulR,
|
||||||
|
MulI,
|
||||||
|
BanR,
|
||||||
|
BanI,
|
||||||
|
BorR,
|
||||||
|
BorI,
|
||||||
|
SetR,
|
||||||
|
SetI,
|
||||||
|
GtIR,
|
||||||
|
GtRI,
|
||||||
|
GtRR,
|
||||||
|
EqIR,
|
||||||
|
EqRI,
|
||||||
|
EqRR,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Op {
|
||||||
|
fn process(&self, registers: Registers, instruction: Instruction) -> Registers {
|
||||||
|
let mut result = registers.0.clone();
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Op::AddR => {
|
||||||
|
result[instruction.c] = result[instruction.a] + result[instruction.b];
|
||||||
|
}
|
||||||
|
Op::AddI => {
|
||||||
|
result[instruction.c] = result[instruction.a] + instruction.b as i32;
|
||||||
|
}
|
||||||
|
Op::MulR => {
|
||||||
|
result[instruction.c] = result[instruction.a] * result[instruction.b];
|
||||||
|
}
|
||||||
|
Op::MulI => {
|
||||||
|
result[instruction.c] = result[instruction.a] * instruction.b as i32;
|
||||||
|
}
|
||||||
|
Op::BanR => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitand(result[instruction.b]);
|
||||||
|
}
|
||||||
|
Op::BanI => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitand(instruction.b as i32);
|
||||||
|
}
|
||||||
|
Op::BorR => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitor(result[instruction.b]);
|
||||||
|
}
|
||||||
|
Op::BorI => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitor(instruction.b as i32);
|
||||||
|
}
|
||||||
|
Op::SetR => {
|
||||||
|
result[instruction.c] = result[instruction.a];
|
||||||
|
}
|
||||||
|
Op::SetI => {
|
||||||
|
result[instruction.c] = instruction.a as i32;
|
||||||
|
}
|
||||||
|
Op::GtIR => {
|
||||||
|
result[instruction.c] = if instruction.a as i32 > result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::GtRI => {
|
||||||
|
result[instruction.c] = if result[instruction.a] > instruction.b as i32 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::GtRR => {
|
||||||
|
result[instruction.c] = if result[instruction.a] > result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqIR => {
|
||||||
|
result[instruction.c] = if instruction.a as i32 == result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqRI => {
|
||||||
|
result[instruction.c] = if result[instruction.a] == instruction.b as i32 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqRR => {
|
||||||
|
result[instruction.c] = if result[instruction.a] == result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Registers(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct Sample(Registers, Instruction, Registers);
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
|
struct Registers([i32; 4]);
|
||||||
|
|
||||||
|
impl From<Vec<&str>> for Registers {
|
||||||
|
fn from(value: Vec<&str>) -> Self {
|
||||||
|
let values: Vec<_> = value.iter().map(|x| x.parse().unwrap()).collect();
|
||||||
|
Registers([values[0], values[1], values[2], values[3]])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct Instruction {
|
||||||
|
opcode: usize,
|
||||||
|
a: usize,
|
||||||
|
b: usize,
|
||||||
|
c: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::tasks::day16::{matches_count, parse, Instruction, Op, Registers};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example1() {
|
||||||
|
let input = "Before: [3, 2, 1, 1]\n\
|
||||||
|
9 2 1 2\n\
|
||||||
|
After: [3, 2, 2, 1]";
|
||||||
|
assert_eq!(matches_count(parse(input)), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_AddR() {
|
||||||
|
let op = Op::AddR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([3, 4, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 0,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(7, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_AddI() {
|
||||||
|
let op = Op::AddI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 0,
|
||||||
|
b: 1337,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(1338, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_MulR() {
|
||||||
|
let op = Op::MulR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(6, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_MulI() {
|
||||||
|
let op = Op::MulI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 1337,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(2 * 1337, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_BanR() {
|
||||||
|
let op = Op::BanR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([0x10101, 0x10110, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 0,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0x10100, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_BanI() {
|
||||||
|
let op = Op::BanI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([0x10101, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 0,
|
||||||
|
b: 0x10110,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0x10100, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_BorR() {
|
||||||
|
let op = Op::BorR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([0x10101, 0x10110, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 0,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0x10111, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_BorI() {
|
||||||
|
let op = Op::BorI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([0x10101, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 0,
|
||||||
|
b: 0x10110,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0x10111, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_SetR() {
|
||||||
|
let op = Op::SetR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(2, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_SetI() {
|
||||||
|
let op = Op::SetI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1234,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(1234, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_GtIR_true() {
|
||||||
|
let op = Op::GtIR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 29, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 30,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(1, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_GtIR_false() {
|
||||||
|
let op = Op::GtIR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 1337, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1337,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_GtRI_true() {
|
||||||
|
let op = Op::GtRI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 2,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(1, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_GtRI_false() {
|
||||||
|
let op = Op::GtRI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 2,
|
||||||
|
b: 3,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_GtRR_true() {
|
||||||
|
let op = Op::GtRR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 0,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(1, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_GtRR() {
|
||||||
|
let op = Op::GtRR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_EqIR_true() {
|
||||||
|
let op = Op::EqIR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 0,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(1, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_EqIR_false() {
|
||||||
|
let op = Op::EqIR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_EqRI_true() {
|
||||||
|
let op = Op::EqRI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 2,
|
||||||
|
b: 3,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(1, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_EqRI_false() {
|
||||||
|
let op = Op::EqRI;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_EqRR_true() {
|
||||||
|
let op = Op::EqRR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(1, result.0[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn test_EqRR_false() {
|
||||||
|
let op = Op::EqRR;
|
||||||
|
let result = op.process(
|
||||||
|
Registers([1, 2, 3, 4]),
|
||||||
|
Instruction {
|
||||||
|
opcode: 0,
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(0, result.0[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
243
src/tasks/day19.rs
Normal file
243
src/tasks/day19.rs
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
use std::ops::{BitAnd, BitOr};
|
||||||
|
|
||||||
|
pub fn task1() {
|
||||||
|
let input = include_str!("../../input/day19.txt");
|
||||||
|
let result = run1(input, 1);
|
||||||
|
|
||||||
|
println!("Day 19 part 1: {result}");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn task2() {
|
||||||
|
let mut a = 1i64;
|
||||||
|
let mut d = 948;
|
||||||
|
if a == 1 {
|
||||||
|
d += 10550400;
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut f = 1;
|
||||||
|
'outer: loop {
|
||||||
|
let mut c = 1;
|
||||||
|
'inner: loop {
|
||||||
|
let b = f * c;
|
||||||
|
if b == d {
|
||||||
|
a = a + f;
|
||||||
|
} else if b > d {
|
||||||
|
// this is the important part: break the loop because otherwise we count and count
|
||||||
|
// and count ... but cannot reach the b == d condition without resetting c.
|
||||||
|
break 'inner;
|
||||||
|
}
|
||||||
|
c += 1;
|
||||||
|
if c > d {
|
||||||
|
break 'inner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f += 1;
|
||||||
|
if f > d {
|
||||||
|
break 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Day 19 part 2: {a}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run1(input: &str, start_value: i32) -> i32 {
|
||||||
|
let (config, program) = input.split_once("\n").unwrap();
|
||||||
|
let ip_register: usize = config.split_once(" ").unwrap().1.parse().unwrap();
|
||||||
|
|
||||||
|
let program: Vec<Instruction> = program.lines().map(parse_instruction).collect();
|
||||||
|
|
||||||
|
let mut registers: Registers = [start_value, 0, 0, 0, 0, 0];
|
||||||
|
let mut ip = 0;
|
||||||
|
let mut count = 0;
|
||||||
|
loop {
|
||||||
|
//print!("ip={ip}, {registers:?}");
|
||||||
|
|
||||||
|
registers[ip_register] = ip as i32;
|
||||||
|
let instruction = program.get(ip).unwrap();
|
||||||
|
|
||||||
|
if ip == 2 {
|
||||||
|
println!("{registers:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
//print!("{instruction:?}");
|
||||||
|
|
||||||
|
let op: Op = instruction.opcode;
|
||||||
|
registers = op.process(registers, *instruction);
|
||||||
|
|
||||||
|
//println!("{registers:?}");
|
||||||
|
|
||||||
|
ip = registers[ip_register] as usize;
|
||||||
|
ip += 1;
|
||||||
|
|
||||||
|
if program.get(ip).is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
println!("executed instructions: {count}");
|
||||||
|
registers[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_instruction(instruction: &str) -> Instruction {
|
||||||
|
let instruction: Vec<_> = instruction.split(" ").collect();
|
||||||
|
let opcode = match instruction[0] {
|
||||||
|
"addr" => Op::AddR,
|
||||||
|
"addi" => Op::AddI,
|
||||||
|
"mulr" => Op::MulR,
|
||||||
|
"muli" => Op::MulI,
|
||||||
|
"banr" => Op::BanR,
|
||||||
|
"bani" => Op::BanI,
|
||||||
|
"borr" => Op::BorR,
|
||||||
|
"bori" => Op::BorI,
|
||||||
|
"setr" => Op::SetR,
|
||||||
|
"seti" => Op::SetI,
|
||||||
|
"gtir" => Op::GtIR,
|
||||||
|
"gtri" => Op::GtRI,
|
||||||
|
"gtrr" => Op::GtRR,
|
||||||
|
"eqir" => Op::EqIR,
|
||||||
|
"eqri" => Op::EqRI,
|
||||||
|
"eqrr" => Op::EqRR,
|
||||||
|
&_ => {
|
||||||
|
panic!("unknown op {}", instruction[0])
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let instruction = Instruction {
|
||||||
|
opcode,
|
||||||
|
a: instruction[1].parse().unwrap(),
|
||||||
|
b: instruction[2].parse().unwrap(),
|
||||||
|
c: instruction[3].parse().unwrap(),
|
||||||
|
};
|
||||||
|
instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
|
enum Op {
|
||||||
|
AddR,
|
||||||
|
AddI,
|
||||||
|
MulR,
|
||||||
|
MulI,
|
||||||
|
BanR,
|
||||||
|
BanI,
|
||||||
|
BorR,
|
||||||
|
BorI,
|
||||||
|
SetR,
|
||||||
|
SetI,
|
||||||
|
GtIR,
|
||||||
|
GtRI,
|
||||||
|
GtRR,
|
||||||
|
EqIR,
|
||||||
|
EqRI,
|
||||||
|
EqRR,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Op {
|
||||||
|
fn process(&self, registers: Registers, instruction: Instruction) -> Registers {
|
||||||
|
let mut result = registers.clone();
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Op::AddR => {
|
||||||
|
result[instruction.c] = result[instruction.a] + result[instruction.b];
|
||||||
|
}
|
||||||
|
Op::AddI => {
|
||||||
|
result[instruction.c] = result[instruction.a] + instruction.b as i32;
|
||||||
|
}
|
||||||
|
Op::MulR => {
|
||||||
|
result[instruction.c] = result[instruction.a] * result[instruction.b];
|
||||||
|
}
|
||||||
|
Op::MulI => {
|
||||||
|
result[instruction.c] = result[instruction.a] * instruction.b as i32;
|
||||||
|
}
|
||||||
|
Op::BanR => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitand(result[instruction.b]);
|
||||||
|
}
|
||||||
|
Op::BanI => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitand(instruction.b as i32);
|
||||||
|
}
|
||||||
|
Op::BorR => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitor(result[instruction.b]);
|
||||||
|
}
|
||||||
|
Op::BorI => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitor(instruction.b as i32);
|
||||||
|
}
|
||||||
|
Op::SetR => {
|
||||||
|
result[instruction.c] = result[instruction.a];
|
||||||
|
}
|
||||||
|
Op::SetI => {
|
||||||
|
result[instruction.c] = instruction.a as i32;
|
||||||
|
}
|
||||||
|
Op::GtIR => {
|
||||||
|
result[instruction.c] = if instruction.a as i32 > result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::GtRI => {
|
||||||
|
result[instruction.c] = if result[instruction.a] > instruction.b as i32 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::GtRR => {
|
||||||
|
result[instruction.c] = if result[instruction.a] > result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqIR => {
|
||||||
|
result[instruction.c] = if instruction.a as i32 == result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqRI => {
|
||||||
|
result[instruction.c] = if result[instruction.a] == instruction.b as i32 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqRR => {
|
||||||
|
result[instruction.c] = if result[instruction.a] == result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Registers = [i32; 6];
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
struct Instruction {
|
||||||
|
opcode: Op,
|
||||||
|
a: usize,
|
||||||
|
b: usize,
|
||||||
|
c: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::tasks::day19::run1;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example1() {
|
||||||
|
let input = "#ip 0\n\
|
||||||
|
seti 5 0 1\n\
|
||||||
|
seti 6 0 2\n\
|
||||||
|
addi 0 1 0\n\
|
||||||
|
addr 1 2 3\n\
|
||||||
|
setr 1 0 0\n\
|
||||||
|
seti 8 0 4\n\
|
||||||
|
seti 9 0 5";
|
||||||
|
assert_eq!(run1(input, 0), 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
229
src/tasks/day21.rs
Normal file
229
src/tasks/day21.rs
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
use std::ops::{BitAnd, BitOr};
|
||||||
|
|
||||||
|
pub fn task1() {
|
||||||
|
let input = include_str!("../../input/day21.txt");
|
||||||
|
let result = run1(input, 3007673);
|
||||||
|
println!("{result:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run1(input: &str, start_value: i64) -> (i64, usize) {
|
||||||
|
let (config, program) = input.split_once("\n").unwrap();
|
||||||
|
let ip_register: usize = config.split_once(" ").unwrap().1.parse().unwrap();
|
||||||
|
|
||||||
|
let program: Vec<Instruction> = program.lines().map(parse_instruction).collect();
|
||||||
|
|
||||||
|
let mut registers: Registers = [start_value, 0, 0, 0, 0, 0];
|
||||||
|
let mut ip = 0;
|
||||||
|
let mut count = 0usize;
|
||||||
|
let mut seen: HashSet<_> = HashSet::new();
|
||||||
|
let mut last = 0;
|
||||||
|
loop {
|
||||||
|
//print!("ip={ip}, {registers:?}");
|
||||||
|
|
||||||
|
registers[ip_register] = ip as i64;
|
||||||
|
let instruction = program.get(ip).unwrap();
|
||||||
|
|
||||||
|
//print!("{instruction:?}");
|
||||||
|
|
||||||
|
let op: Op = instruction.opcode;
|
||||||
|
registers = op.process(registers, *instruction);
|
||||||
|
|
||||||
|
//println!("{registers:?}");
|
||||||
|
|
||||||
|
ip = registers[ip_register] as usize;
|
||||||
|
ip += 1;
|
||||||
|
|
||||||
|
// Part 1: uncomment this and print look at register 2 to find the value for register 0
|
||||||
|
// that would cause the program to halt
|
||||||
|
// if ip == 28 {
|
||||||
|
// println!("Value in register 2: {}", registers[2]);
|
||||||
|
// }
|
||||||
|
// Part 2: 9969507 too high
|
||||||
|
// 16774755 highest value
|
||||||
|
// Store all values of register 2 at the possible exit point. Once you see one you already
|
||||||
|
// saw: you've seen all (there is a loop). The one before that was the one it took the longest
|
||||||
|
// to reach without seeing anything twice.
|
||||||
|
if ip == 28 {
|
||||||
|
if seen.contains(®isters[2]) {
|
||||||
|
println!("First double: {registers:?}");
|
||||||
|
println!("Last was {last}");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
seen.insert(registers[2]);
|
||||||
|
last = registers[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if program.get(ip).is_none() {
|
||||||
|
println!("exit by leaving instruction space");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
println!("executed instructions: {count}");
|
||||||
|
(registers[0], count)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_instruction(instruction: &str) -> Instruction {
|
||||||
|
let instruction: Vec<_> = instruction.split(" ").collect();
|
||||||
|
let opcode = match instruction[0] {
|
||||||
|
"addr" => Op::AddR,
|
||||||
|
"addi" => Op::AddI,
|
||||||
|
"mulr" => Op::MulR,
|
||||||
|
"muli" => Op::MulI,
|
||||||
|
"banr" => Op::BanR,
|
||||||
|
"bani" => Op::BanI,
|
||||||
|
"borr" => Op::BorR,
|
||||||
|
"bori" => Op::BorI,
|
||||||
|
"setr" => Op::SetR,
|
||||||
|
"seti" => Op::SetI,
|
||||||
|
"gtir" => Op::GtIR,
|
||||||
|
"gtri" => Op::GtRI,
|
||||||
|
"gtrr" => Op::GtRR,
|
||||||
|
"eqir" => Op::EqIR,
|
||||||
|
"eqri" => Op::EqRI,
|
||||||
|
"eqrr" => Op::EqRR,
|
||||||
|
&_ => {
|
||||||
|
panic!("unknown op {}", instruction[0])
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let instruction = Instruction {
|
||||||
|
opcode,
|
||||||
|
a: instruction[1].parse().unwrap(),
|
||||||
|
b: instruction[2].parse().unwrap(),
|
||||||
|
c: instruction[3].parse().unwrap(),
|
||||||
|
};
|
||||||
|
instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
|
enum Op {
|
||||||
|
AddR,
|
||||||
|
AddI,
|
||||||
|
MulR,
|
||||||
|
MulI,
|
||||||
|
BanR,
|
||||||
|
BanI,
|
||||||
|
BorR,
|
||||||
|
BorI,
|
||||||
|
SetR,
|
||||||
|
SetI,
|
||||||
|
GtIR,
|
||||||
|
GtRI,
|
||||||
|
GtRR,
|
||||||
|
EqIR,
|
||||||
|
EqRI,
|
||||||
|
EqRR,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Op {
|
||||||
|
fn process(&self, registers: Registers, instruction: Instruction) -> Registers {
|
||||||
|
let mut result = registers.clone();
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Op::AddR => {
|
||||||
|
result[instruction.c] = result[instruction.a] + result[instruction.b];
|
||||||
|
}
|
||||||
|
Op::AddI => {
|
||||||
|
result[instruction.c] = result[instruction.a] + instruction.b as i64;
|
||||||
|
}
|
||||||
|
Op::MulR => {
|
||||||
|
result[instruction.c] = result[instruction.a] * result[instruction.b];
|
||||||
|
}
|
||||||
|
Op::MulI => {
|
||||||
|
result[instruction.c] = result[instruction.a] * instruction.b as i64;
|
||||||
|
}
|
||||||
|
Op::BanR => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitand(result[instruction.b]);
|
||||||
|
}
|
||||||
|
Op::BanI => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitand(instruction.b as i64);
|
||||||
|
}
|
||||||
|
Op::BorR => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitor(result[instruction.b]);
|
||||||
|
}
|
||||||
|
Op::BorI => {
|
||||||
|
result[instruction.c] = result[instruction.a].bitor(instruction.b as i64);
|
||||||
|
}
|
||||||
|
Op::SetR => {
|
||||||
|
result[instruction.c] = result[instruction.a];
|
||||||
|
}
|
||||||
|
Op::SetI => {
|
||||||
|
result[instruction.c] = instruction.a as i64;
|
||||||
|
}
|
||||||
|
Op::GtIR => {
|
||||||
|
result[instruction.c] = if instruction.a as i64 > result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::GtRI => {
|
||||||
|
result[instruction.c] = if result[instruction.a] > instruction.b as i64 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::GtRR => {
|
||||||
|
result[instruction.c] = if result[instruction.a] > result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqIR => {
|
||||||
|
result[instruction.c] = if instruction.a as i64 == result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqRI => {
|
||||||
|
result[instruction.c] = if result[instruction.a] == instruction.b as i64 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Op::EqRR => {
|
||||||
|
result[instruction.c] = if result[instruction.a] == result[instruction.b] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Registers = [i64; 6];
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
struct Instruction {
|
||||||
|
opcode: Op,
|
||||||
|
a: usize,
|
||||||
|
b: usize,
|
||||||
|
c: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::tasks::day21::run1;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example1() {
|
||||||
|
let input = "#ip 0\n\
|
||||||
|
seti 5 0 1\n\
|
||||||
|
seti 6 0 2\n\
|
||||||
|
addi 0 1 0\n\
|
||||||
|
addr 1 2 3\n\
|
||||||
|
setr 1 0 0\n\
|
||||||
|
seti 8 0 4\n\
|
||||||
|
seti 9 0 5";
|
||||||
|
assert_eq!(run1(input, 0).0, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,32 @@
|
|||||||
use crate::utils;
|
|
||||||
use std::cmp::Reverse;
|
use std::cmp::Reverse;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn task1() {
|
use itertools::Itertools;
|
||||||
let _input = "Immune System:
|
|
||||||
17 units each with 5390 hit points (weak to radiation, bludgeoning) with an attack that does 4507 fire damage at initiative 2
|
|
||||||
989 units each with 1274 hit points (immune to fire; weak to bludgeoning, slashing) with an attack that does 25 slashing damage at initiative 3
|
|
||||||
|
|
||||||
Infection:
|
use crate::utils;
|
||||||
801 units each with 4706 hit points (weak to radiation) with an attack that does 116 bludgeoning damage at initiative 1
|
|
||||||
4485 units each with 2961 hit points (immune to radiation; weak to fire, cold) with an attack that does 12 slashing damage at initiative 4";
|
pub fn task1() {
|
||||||
let input = utils::read_file("input/day24.txt");
|
let input = utils::read_file("input/day24.txt");
|
||||||
let mut game = Game::create(&input);
|
|
||||||
|
let result = play(&input, 0);
|
||||||
|
println!("Standing units after the game: {}", result.unwrap().1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn task2() {
|
||||||
|
let input = utils::read_file("input/day24.txt");
|
||||||
|
|
||||||
|
let immune_final_count = (0..)
|
||||||
|
.map(|boost| play(&input, boost))
|
||||||
|
.find(|result| result.map(|(team, _)| team) == Some(Team::ImmuneSystem))
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.1;
|
||||||
|
|
||||||
|
println!("Immune systems final count: {immune_final_count}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play(input: &str, boost: i64) -> Option<(Team, i64)> {
|
||||||
|
let mut game = Game::create(&input, boost);
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Immune start units: {}",
|
"Immune start units: {}",
|
||||||
@@ -30,31 +45,41 @@ Infection:
|
|||||||
.sum::<i64>()
|
.sum::<i64>()
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut rounds_played = 0;
|
|
||||||
while !game.is_over() {
|
while !game.is_over() {
|
||||||
game.round();
|
game.round();
|
||||||
rounds_played += 1;
|
if game.draw {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{:#?}", game);
|
Some((game.winning_team(), game.remaining_units()))
|
||||||
println!("Played {} rounds", rounds_played);
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Standing units after the game: {}",
|
|
||||||
game.groups.values().map(|it| it.units).sum::<i64>()
|
|
||||||
);
|
|
||||||
|
|
||||||
// 21107 too high
|
|
||||||
// 21004 too high
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Game {
|
struct Game {
|
||||||
groups: HashMap<usize, Group>,
|
groups: HashMap<usize, Group>,
|
||||||
|
draw: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
fn create(input: &str) -> Self {
|
fn remaining_units(&self) -> i64 {
|
||||||
|
self.groups.values().map(|it| it.units).sum::<i64>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn winning_team(&self) -> Team {
|
||||||
|
let teams: Vec<Team> = self
|
||||||
|
.groups
|
||||||
|
.values()
|
||||||
|
.map(|group| group.team)
|
||||||
|
.unique()
|
||||||
|
.collect();
|
||||||
|
if teams.len() != 1 {
|
||||||
|
panic!("No winning team. Remaining teams: {teams:?}");
|
||||||
|
}
|
||||||
|
teams[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(input: &str, boost: i64) -> Self {
|
||||||
let mut groups = HashMap::new();
|
let mut groups = HashMap::new();
|
||||||
let mut team = Team::ImmuneSystem;
|
let mut team = Team::ImmuneSystem;
|
||||||
for (id, line) in input.lines().enumerate() {
|
for (id, line) in input.lines().enumerate() {
|
||||||
@@ -67,13 +92,21 @@ impl Game {
|
|||||||
}
|
}
|
||||||
"" => (),
|
"" => (),
|
||||||
group => {
|
group => {
|
||||||
if let Some(group) = Group::from_str(group, team, id) {
|
if let Some(mut group) = Group::from_str(group, team, id) {
|
||||||
|
if group.team == Team::ImmuneSystem {
|
||||||
|
group.attack_damage += boost;
|
||||||
|
}
|
||||||
groups.insert(id, group);
|
groups.insert(id, group);
|
||||||
|
} else {
|
||||||
|
panic!("bad group: {group}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Game { groups }
|
Game {
|
||||||
|
groups,
|
||||||
|
draw: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round(&mut self) {
|
fn round(&mut self) {
|
||||||
@@ -96,7 +129,6 @@ impl Game {
|
|||||||
.values()
|
.values()
|
||||||
.filter(|it| it.team != group.team)
|
.filter(|it| it.team != group.team)
|
||||||
.filter(|it| !target.values().any(|t| *t == it.id))
|
.filter(|it| !target.values().any(|t| *t == it.id))
|
||||||
// .filter(|it| group.compute_attack_damage_to(&it) >= it.hp_each)
|
|
||||||
// .inspect(|it| {
|
// .inspect(|it| {
|
||||||
// println!(
|
// println!(
|
||||||
// "{} would deal {} damage to {}",
|
// "{} would deal {} damage to {}",
|
||||||
@@ -114,10 +146,10 @@ impl Game {
|
|||||||
})
|
})
|
||||||
{
|
{
|
||||||
if group.compute_attack_damage_to(t) <= 0 {
|
if group.compute_attack_damage_to(t) <= 0 {
|
||||||
println!(
|
// println!(
|
||||||
"Didn't find a target where {:?} can deal positive damage.",
|
// "Didn't find a target where {:?} can deal positive damage.",
|
||||||
group
|
// group
|
||||||
);
|
// );
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
target.insert(group.id, t.id);
|
target.insert(group.id, t.id);
|
||||||
@@ -129,18 +161,21 @@ impl Game {
|
|||||||
let mut all_ids_by_initiative: Vec<usize> = self.groups.values().map(|it| it.id).collect();
|
let mut all_ids_by_initiative: Vec<usize> = self.groups.values().map(|it| it.id).collect();
|
||||||
all_ids_by_initiative.sort_unstable_by_key(|id| Reverse(self.groups[id].initiative));
|
all_ids_by_initiative.sort_unstable_by_key(|id| Reverse(self.groups[id].initiative));
|
||||||
|
|
||||||
|
self.draw = true;
|
||||||
for active_id in all_ids_by_initiative {
|
for active_id in all_ids_by_initiative {
|
||||||
if !self.groups[&active_id].alive() {
|
if !self.groups[&active_id].alive() {
|
||||||
// was killed in this round
|
// was killed in this round
|
||||||
println!("Group {} already dead", active_id);
|
// println!("Group {} already dead", active_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(enemy_id) = target.get(&active_id) {
|
if let Some(enemy_id) = target.get(&active_id) {
|
||||||
let enemy = &self.groups[enemy_id];
|
let enemy = &self.groups[enemy_id];
|
||||||
let damage: i64 = self.groups[&active_id].compute_attack_damage_to(enemy);
|
let damage: i64 = self.groups[&active_id].compute_attack_damage_to(enemy);
|
||||||
let dying_units = damage / enemy.hp_each;
|
let dying_units = damage / enemy.hp_each;
|
||||||
if let Some(enemy) = self.groups.get_mut(enemy_id) {
|
self.groups.get_mut(enemy_id).unwrap().units -= dying_units;
|
||||||
enemy.units -= dying_units;
|
|
||||||
|
if dying_units > 0 {
|
||||||
|
self.draw = false;
|
||||||
}
|
}
|
||||||
// println!(
|
// println!(
|
||||||
// "{} dealt {} ({} units) damage to {}",
|
// "{} dealt {} ({} units) damage to {}",
|
||||||
@@ -155,8 +190,7 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_over(&self) -> bool {
|
fn is_over(&self) -> bool {
|
||||||
self.groups.is_empty()
|
self.groups.iter().all(|(_, it)| it.team == Team::Infection)
|
||||||
|| self.groups.iter().all(|(_, it)| it.team == Team::Infection)
|
|
||||||
|| self
|
|| self
|
||||||
.groups
|
.groups
|
||||||
.iter()
|
.iter()
|
||||||
@@ -164,7 +198,7 @@ impl Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
enum Team {
|
enum Team {
|
||||||
Infection,
|
Infection,
|
||||||
ImmuneSystem,
|
ImmuneSystem,
|
||||||
@@ -186,8 +220,9 @@ struct Group {
|
|||||||
impl Group {
|
impl Group {
|
||||||
fn from_str(input: &str, team: Team, id: usize) -> Option<Self> {
|
fn from_str(input: &str, team: Team, id: usize) -> Option<Self> {
|
||||||
// 801 units each with 4706 hit points (weak to radiation) with an attack that does 116 bludgeoning damage at initiative 1
|
// 801 units each with 4706 hit points (weak to radiation) with an attack that does 116 bludgeoning damage at initiative 1
|
||||||
|
// 2347 units each with 3322 hit points with an attack that does 12 cold damage at initiative 2
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
let regex = Regex::new(r"(\d+) units each with (\d+) hit points \((.+)\) with an attack that does (\d+) (\w+) damage at initiative (\d+)").unwrap();
|
let regex = Regex::new(r"(\d+) units each with (\d+) hit points(.*)with an attack that does (\d+) (\w+) damage at initiative (\d+)").unwrap();
|
||||||
if let Some(m) = regex.captures(input) {
|
if let Some(m) = regex.captures(input) {
|
||||||
let units: i64 = m[1].parse().unwrap();
|
let units: i64 = m[1].parse().unwrap();
|
||||||
let hp_each: i64 = m[2].parse().unwrap();
|
let hp_each: i64 = m[2].parse().unwrap();
|
||||||
@@ -196,7 +231,8 @@ impl Group {
|
|||||||
let initiative: u64 = m[6].parse().unwrap();
|
let initiative: u64 = m[6].parse().unwrap();
|
||||||
let mut weaknesses: Vec<String> = Vec::new();
|
let mut weaknesses: Vec<String> = Vec::new();
|
||||||
let mut immunities: Vec<String> = Vec::new();
|
let mut immunities: Vec<String> = Vec::new();
|
||||||
for part in m[3].split("; ") {
|
let attributes = m[3].trim().trim_start_matches("(").trim_end_matches(")");
|
||||||
|
for part in attributes.split("; ") {
|
||||||
if let Some(stripped) = part.strip_prefix("weak to ") {
|
if let Some(stripped) = part.strip_prefix("weak to ") {
|
||||||
weaknesses = stripped.split(", ").map(|it| it.to_string()).collect();
|
weaknesses = stripped.split(", ").map(|it| it.to_string()).collect();
|
||||||
} else if let Some(stripped) = part.strip_prefix("immune to ") {
|
} else if let Some(stripped) = part.strip_prefix("immune to ") {
|
||||||
@@ -246,3 +282,26 @@ impl Group {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::tasks::day24::play;
|
||||||
|
|
||||||
|
const INPUT: &str = "Immune System:
|
||||||
|
17 units each with 5390 hit points (weak to radiation, bludgeoning) with an attack that does 4507 fire damage at initiative 2
|
||||||
|
989 units each with 1274 hit points (immune to fire; weak to bludgeoning, slashing) with an attack that does 25 slashing damage at initiative 3
|
||||||
|
|
||||||
|
Infection:
|
||||||
|
801 units each with 4706 hit points (weak to radiation) with an attack that does 116 bludgeoning damage at initiative 1
|
||||||
|
4485 units each with 2961 hit points (immune to radiation; weak to fire, cold) with an attack that does 12 slashing damage at initiative 4";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example1() {
|
||||||
|
assert_eq!(5216, play(INPUT, 0).unwrap().1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example2() {
|
||||||
|
assert_eq!(51, play(INPUT, 1570).unwrap().1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
122
src/tasks/day25.rs
Normal file
122
src/tasks/day25.rs
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
use crate::utils;
|
||||||
|
|
||||||
|
pub fn task1() {
|
||||||
|
println!("{}", solve(&utils::read_file("input/day25.txt")));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve(input: &str) -> u32 {
|
||||||
|
let mut points: Vec<STP> = input.lines().map(STP::from).collect();
|
||||||
|
let mut constellations = 0;
|
||||||
|
while let Some(next_origin) = points.pop() {
|
||||||
|
constellations += 1;
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
queue.push_back(next_origin);
|
||||||
|
|
||||||
|
while let Some(next) = queue.pop_front() {
|
||||||
|
let (neighbors, remainder) = points.into_iter().partition(|p| next.is_neighbor_to(p));
|
||||||
|
points = remainder;
|
||||||
|
for n in neighbors {
|
||||||
|
queue.push_back(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
constellations
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Hash, Eq, PartialEq, Debug)]
|
||||||
|
struct STP(i32, i32, i32, i32);
|
||||||
|
|
||||||
|
impl STP {}
|
||||||
|
|
||||||
|
impl STP {
|
||||||
|
fn distance(&self, other: &Self) -> u32 {
|
||||||
|
((self.0 - other.0).abs()
|
||||||
|
+ (self.1 - other.1).abs()
|
||||||
|
+ (self.2 - other.2).abs()
|
||||||
|
+ (self.3 - other.3).abs()) as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_neighbor_to(&self, other: &Self) -> bool {
|
||||||
|
self.distance(other) <= 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for STP {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
let mut split = value.split(",");
|
||||||
|
|
||||||
|
STP(
|
||||||
|
split.next().unwrap().parse().unwrap(),
|
||||||
|
split.next().unwrap().parse().unwrap(),
|
||||||
|
split.next().unwrap().parse().unwrap(),
|
||||||
|
split.next().unwrap().parse().unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::tasks::day25::solve;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example1() {
|
||||||
|
let input = "0,0,0,0
|
||||||
|
3,0,0,0
|
||||||
|
0,3,0,0
|
||||||
|
0,0,3,0
|
||||||
|
0,0,0,3
|
||||||
|
0,0,0,6
|
||||||
|
9,0,0,0
|
||||||
|
12,0,0,0";
|
||||||
|
assert_eq!(solve(input), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example2() {
|
||||||
|
let input = "-1,2,2,0
|
||||||
|
0,0,2,-2
|
||||||
|
0,0,0,-2
|
||||||
|
-1,2,0,0
|
||||||
|
-2,-2,-2,2
|
||||||
|
3,0,2,-1
|
||||||
|
-1,3,2,2
|
||||||
|
-1,0,-1,0
|
||||||
|
0,2,1,-2
|
||||||
|
3,0,0,0";
|
||||||
|
assert_eq!(solve(input), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example3() {
|
||||||
|
let input = "1,-1,0,1
|
||||||
|
2,0,-1,0
|
||||||
|
3,2,-1,0
|
||||||
|
0,0,3,1
|
||||||
|
0,0,-1,-1
|
||||||
|
2,3,-2,0
|
||||||
|
-2,2,0,0
|
||||||
|
2,-2,0,-1
|
||||||
|
1,-1,0,-1
|
||||||
|
3,2,0,2
|
||||||
|
";
|
||||||
|
assert_eq!(solve(input), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example4() {
|
||||||
|
let input = "1,-1,-1,-2
|
||||||
|
-2,-2,0,1
|
||||||
|
0,2,1,3
|
||||||
|
-2,3,-2,1
|
||||||
|
0,2,3,-2
|
||||||
|
-1,-1,1,-2
|
||||||
|
0,-2,-1,0
|
||||||
|
-2,2,3,-1
|
||||||
|
1,2,2,0
|
||||||
|
-1,-2,0,-2
|
||||||
|
";
|
||||||
|
assert_eq!(solve(input), 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,9 +13,13 @@ pub mod day12;
|
|||||||
pub mod day13;
|
pub mod day13;
|
||||||
pub mod day14;
|
pub mod day14;
|
||||||
pub mod day15;
|
pub mod day15;
|
||||||
|
pub mod day16;
|
||||||
pub mod day17;
|
pub mod day17;
|
||||||
pub mod day18;
|
pub mod day18;
|
||||||
|
pub mod day19;
|
||||||
pub mod day20;
|
pub mod day20;
|
||||||
|
pub mod day21;
|
||||||
pub mod day22;
|
pub mod day22;
|
||||||
pub mod day23;
|
pub mod day23;
|
||||||
pub mod day24;
|
pub mod day24;
|
||||||
|
pub mod day25;
|
||||||
|
|||||||
Reference in New Issue
Block a user