added solutions until day 15
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
/target
|
||||
.aoc_token
|
||||
todo
|
||||
.DS_Store
|
||||
**/input.txt
|
||||
Generated
+380
@@ -0,0 +1,380 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aoc2024"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"rayon",
|
||||
"ureq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"getrandom",
|
||||
"libc",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
"rustls-webpki",
|
||||
"sct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.101.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"flate2",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
"rustls-webpki",
|
||||
"url",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.25.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
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"
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
[package]
|
||||
name = "aoc2024"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
default-run = "main"
|
||||
|
||||
[dependencies]
|
||||
fxhash = "0.2.1"
|
||||
rayon = "1.10.0"
|
||||
ureq = { version = "2.9.1" }
|
||||
|
||||
[[bin]]
|
||||
name = "main"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "d1-1"
|
||||
path = "src/day1/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d1-2"
|
||||
path = "src/day1/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d2-1"
|
||||
path = "src/day2/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d2-2"
|
||||
path = "src/day2/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d3-1"
|
||||
path = "src/day3/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d3-2"
|
||||
path = "src/day3/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d4-1"
|
||||
path = "src/day4/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d4-2"
|
||||
path = "src/day4/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d5-1"
|
||||
path = "src/day5/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d5-2"
|
||||
path = "src/day5/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d6-1"
|
||||
path = "src/day6/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d6-2"
|
||||
path = "src/day6/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d7-1"
|
||||
path = "src/day7/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d7-2"
|
||||
path = "src/day7/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d8-1"
|
||||
path = "src/day8/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d8-2"
|
||||
path = "src/day8/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d9-1"
|
||||
path = "src/day9/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d9-2"
|
||||
path = "src/day9/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d10-1"
|
||||
path = "src/day10/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d10-2"
|
||||
path = "src/day10/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d11-1"
|
||||
path = "src/day11/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d11-2"
|
||||
path = "src/day11/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d12-1"
|
||||
path = "src/day12/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d12-2"
|
||||
path = "src/day12/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d13-1"
|
||||
path = "src/day13/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d13-2"
|
||||
path = "src/day13/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d14-1"
|
||||
path = "src/day14/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d14-2"
|
||||
path = "src/day14/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d15-1"
|
||||
path = "src/day15/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d15-2"
|
||||
path = "src/day15/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d16-1"
|
||||
path = "src/day16/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d16-2"
|
||||
path = "src/day16/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d17-1"
|
||||
path = "src/day17/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d17-2"
|
||||
path = "src/day17/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d18-1"
|
||||
path = "src/day18/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d18-2"
|
||||
path = "src/day18/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d19-1"
|
||||
path = "src/day19/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d19-2"
|
||||
path = "src/day19/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d20-1"
|
||||
path = "src/day20/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d20-2"
|
||||
path = "src/day20/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d21-1"
|
||||
path = "src/day21/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d21-2"
|
||||
path = "src/day21/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d22-1"
|
||||
path = "src/day22/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d22-2"
|
||||
path = "src/day22/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d23-1"
|
||||
path = "src/day23/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d23-2"
|
||||
path = "src/day23/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d24-1"
|
||||
path = "src/day24/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d24-2"
|
||||
path = "src/day24/2.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d25-1"
|
||||
path = "src/day25/1.rs"
|
||||
|
||||
|
||||
[[bin]]
|
||||
name = "d25-2"
|
||||
path = "src/day25/2.rs"
|
||||
@@ -0,0 +1,9 @@
|
||||
# AOC 2024
|
||||
|
||||
My solutions for [Advent of Code](https://adventofcode.com) 2024!
|
||||
|
||||
### How to run?
|
||||
|
||||
Run `cargo r --release --bin d1-1` to run day 1 part 1.
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"3 4
|
||||
4 3
|
||||
2 5
|
||||
1 3
|
||||
3 9
|
||||
3 3",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
|
||||
let mut left = vec![];
|
||||
let mut right = vec![];
|
||||
|
||||
for line in input.lines() {
|
||||
let line = line.trim();
|
||||
let line: Vec<i64> = line.split(' ').filter(|x| !x.is_empty()).map(|x| x.parse::<i64>().unwrap()).collect();
|
||||
|
||||
if line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
left.push(line[0]);
|
||||
right.push(line[1]);
|
||||
}
|
||||
|
||||
left.sort_unstable();
|
||||
right.sort_unstable();
|
||||
|
||||
let mut sum = 0;
|
||||
|
||||
for (a,b) in left.into_iter().zip(right.into_iter()) {
|
||||
sum += (a - b).abs();
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use fxhash::FxHashMap;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"3 4
|
||||
4 3
|
||||
2 5
|
||||
1 3
|
||||
3 9
|
||||
3 3",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
|
||||
let mut left = vec![];
|
||||
let mut right = FxHashMap::default();
|
||||
|
||||
for line in input.lines() {
|
||||
let line = line.trim();
|
||||
let line: Vec<i64> = line.split(' ').filter(|x| !x.is_empty()).map(|x| x.parse::<i64>().unwrap()).collect();
|
||||
|
||||
if line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
left.push(line[0]);
|
||||
*right.entry(line[1]).or_insert(0) += 1;
|
||||
}
|
||||
|
||||
left.sort_unstable();
|
||||
|
||||
let mut sum = 0;
|
||||
|
||||
for a in left.into_iter() {
|
||||
let count = right.get(&a).unwrap_or(&0);
|
||||
sum += a * count;
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"89010123
|
||||
78121874
|
||||
87430965
|
||||
96549874
|
||||
45678903
|
||||
32019012
|
||||
01329801
|
||||
10456732",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> u32 {
|
||||
let input = input.as_bytes();
|
||||
let size = input.iter().position(|&x| x == b'\n').unwrap() as i32;
|
||||
let mut answer = 0;
|
||||
|
||||
assert!(size > 0);
|
||||
|
||||
for (p,&q) in input.iter().filter(|&&x| x != b'\n').enumerate() {
|
||||
if q != b'9' {
|
||||
continue;
|
||||
}
|
||||
let i = p as i32 / size;
|
||||
let j = p as i32 % size;
|
||||
answer += count_trails(&input, i, j, size);
|
||||
}
|
||||
|
||||
answer
|
||||
}
|
||||
|
||||
fn count_trails(grid: &[u8], i: i32, j: i32, size: i32) -> u32 {
|
||||
|
||||
let mut seen = Bitmap::new(size);
|
||||
let mut stack = vec![];
|
||||
stack.push((i,j, b'9'));
|
||||
|
||||
while let Some((x,y,lh)) = stack.pop() {
|
||||
if lh == b'0' {
|
||||
seen.set(x,y);
|
||||
continue;
|
||||
}
|
||||
for (dx,dy) in [(0,1), (1,0), (-1,0), (0,-1)].iter() {
|
||||
let i = x + dx;
|
||||
let j = y + dy;
|
||||
|
||||
if i < 0 || j < 0 || i >= size || j >= size {
|
||||
continue;
|
||||
}
|
||||
|
||||
let c = unsafe { *grid.get_unchecked((i*size+j+i) as usize) };
|
||||
if c == lh - 1 {
|
||||
stack.push((i,j,c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
seen.count()
|
||||
}
|
||||
|
||||
const WORD_SIZE: usize = 64;
|
||||
|
||||
struct Bitmap {
|
||||
inner: Vec<u64>,
|
||||
size: i32,
|
||||
}
|
||||
|
||||
impl Bitmap {
|
||||
fn new(size: i32) -> Self {
|
||||
Self { inner: vec![0; ((size * size) as usize / WORD_SIZE) + 1], size }
|
||||
}
|
||||
|
||||
fn set(&mut self, x: i32, y: i32) {
|
||||
let offset = (x * self.size + y) as usize;
|
||||
let index = offset / WORD_SIZE;
|
||||
let bit_offset = offset % WORD_SIZE;
|
||||
|
||||
self.inner[index] |= 1 << bit_offset;
|
||||
}
|
||||
|
||||
fn count(self) -> u32 {
|
||||
let mut count = 0;
|
||||
|
||||
for c in self.inner {
|
||||
count += c.count_ones();
|
||||
}
|
||||
count
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"89010123
|
||||
78121874
|
||||
87430965
|
||||
96549874
|
||||
45678903
|
||||
32019012
|
||||
01329801
|
||||
10456732",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> u32 {
|
||||
let input = input.as_bytes();
|
||||
let size = input.iter().position(|&x| x == b'\n').unwrap() as i32;
|
||||
let mut answer = 0;
|
||||
|
||||
assert!(size > 0);
|
||||
|
||||
for (p,&q) in input.iter().filter(|&&x| x != b'\n').enumerate() {
|
||||
if q != b'0' {
|
||||
continue;
|
||||
}
|
||||
let i = p as i32 / size;
|
||||
let j = p as i32 % size;
|
||||
answer += count_trails(&input, i, j, size);
|
||||
}
|
||||
|
||||
answer
|
||||
}
|
||||
|
||||
fn count_trails(grid: &[u8], i: i32, j: i32, size: i32) -> u32 {
|
||||
|
||||
let mut sum = 0;
|
||||
let mut stack = vec![];
|
||||
stack.push((i,j, b'0'));
|
||||
|
||||
while let Some((x,y,lh)) = stack.pop() {
|
||||
if lh == b'9' {
|
||||
sum += 1;
|
||||
continue;
|
||||
}
|
||||
for (dx,dy) in [(0,1), (1,0), (-1,0), (0,-1)].iter() {
|
||||
let i = x + dx;
|
||||
let j = y + dy;
|
||||
|
||||
if i < 0 || j < 0 || i >= size || j >= size {
|
||||
continue;
|
||||
}
|
||||
|
||||
let c = unsafe { *grid.get_unchecked((i*size+j+i) as usize) };
|
||||
if c == lh + 1 {
|
||||
stack.push((i,j,lh + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use fxhash::FxHashMap;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"125 17",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
const STEPS: u64 = 25;
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut answer = 0;
|
||||
let mut m = FxHashMap::default();
|
||||
|
||||
for num in input.split(' ').filter(|x| !x.is_empty()).map(|x| x.trim().parse::<u64>().unwrap()) {
|
||||
answer += solve(&mut m, num, 0);
|
||||
}
|
||||
|
||||
answer as i64
|
||||
}
|
||||
|
||||
fn solve(map: &mut FxHashMap<(u64,u64), u64>, num: u64, step: u64) -> u64 {
|
||||
if step == STEPS {
|
||||
return 1;
|
||||
}
|
||||
if let Some(v) = map.get(&(num,step)) {
|
||||
return *v;
|
||||
}
|
||||
|
||||
let count = if num == 0 {
|
||||
solve(map, 1, step+1)
|
||||
} else {
|
||||
let len = num.ilog(10) + 1;
|
||||
if len % 2 == 0 {
|
||||
let (a, b) = split(num);
|
||||
solve(map, a, step+1) + solve(map, b, step+1)
|
||||
} else {
|
||||
solve(map, num * 2024, step+1)
|
||||
}
|
||||
};
|
||||
|
||||
map.insert((num,step), count);
|
||||
count
|
||||
}
|
||||
|
||||
#[inline]
|
||||
const fn split(n: u64) -> (u64, u64) {
|
||||
let len = n.ilog10() + 1;
|
||||
|
||||
(n / 10u64.pow(len/2), n % 10u64.pow(len/2))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use fxhash::FxHashMap;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"125 17",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
const STEPS: u64 = 75;
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut answer = 0;
|
||||
let mut map = FxHashMap::default();
|
||||
|
||||
for num in input.split(' ').filter(|x| !x.is_empty()).map(|x| x.trim().parse::<u64>().unwrap()) {
|
||||
answer += solve(&mut map, num, 0);
|
||||
}
|
||||
|
||||
answer as i64
|
||||
}
|
||||
|
||||
fn solve(map: &mut FxHashMap<(u64,u64), u64>, num: u64, step: u64) -> u64 {
|
||||
if step == STEPS {
|
||||
return 1;
|
||||
}
|
||||
if let Some(v) = map.get(&(num,step)) {
|
||||
return *v;
|
||||
}
|
||||
|
||||
let count = if num == 0 {
|
||||
solve(map, 1, step+1)
|
||||
} else {
|
||||
let len = num.ilog(10) + 1;
|
||||
if len % 2 == 0 {
|
||||
let (a, b) = split(num);
|
||||
solve(map, a, step+1) + solve(map, b, step+1)
|
||||
} else {
|
||||
solve(map, num * 2024, step+1)
|
||||
}
|
||||
};
|
||||
|
||||
map.insert((num,step), count);
|
||||
count
|
||||
}
|
||||
|
||||
#[inline]
|
||||
const fn split(n: u64) -> (u64, u64) {
|
||||
let len = n.ilog10() + 1;
|
||||
|
||||
(n / 10u64.pow(len/2), n % 10u64.pow(len/2))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"RRRRIICCFF
|
||||
RRRRIICCCF
|
||||
VVRRRCCFFF
|
||||
VVRCCCJFFF
|
||||
VVVVCJJCFE
|
||||
VVIVCCJJEE
|
||||
VVIIICJJEE
|
||||
MIIIIIJJEE
|
||||
MIIISIJEEE
|
||||
MMMISSJEEE",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut grid = input.lines().map(|x| x.chars().collect::<Vec<char>>()).collect::<Vec<Vec<char>>>();
|
||||
let m = grid.len();
|
||||
let n = grid[0].len();
|
||||
|
||||
let mut area_total = 0;
|
||||
|
||||
for i in 0..m {
|
||||
for j in 0..n {
|
||||
let plant = grid[i][j];
|
||||
if plant == '0' {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut perimeter = 0;
|
||||
let mut area = 0;
|
||||
|
||||
let mut seen = FxHashSet::default();
|
||||
let mut stack = vec![];
|
||||
stack.push((i as i32, j as i32));
|
||||
|
||||
while let Some((i, j)) = stack.pop() {
|
||||
grid[i as usize][j as usize] = '0';
|
||||
area += 1;
|
||||
seen.insert((i, j));
|
||||
|
||||
for dir in [(0,1), (1,0), (-1,0), (0,-1)].iter() {
|
||||
let x = i as i32 + dir.0;
|
||||
let y = j as i32 + dir.1;
|
||||
|
||||
if seen.contains(&(x,y)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if x < 0 || y < 0 || x >= m as i32 || y >= n as i32 {
|
||||
perimeter += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let c = grid[x as usize][y as usize];
|
||||
if c == plant {
|
||||
seen.insert((x,y));
|
||||
stack.push((x,y));
|
||||
continue;
|
||||
}
|
||||
perimeter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
area_total += area * perimeter;
|
||||
}
|
||||
}
|
||||
|
||||
area_total
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"RRRRIICCFF
|
||||
RRRRIICCCF
|
||||
VVRRRCCFFF
|
||||
VVRCCCJFFF
|
||||
VVVVCJJCFE
|
||||
VVIVCCJJEE
|
||||
VVIIICJJEE
|
||||
MIIIIIJJEE
|
||||
MIIISIJEEE
|
||||
MMMISSJEEE",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut grid = input.lines().map(|x| x.chars().collect::<Vec<char>>()).collect::<Vec<Vec<char>>>();
|
||||
let m = grid.len();
|
||||
let n = grid[0].len();
|
||||
|
||||
let mut area_total = 0;
|
||||
|
||||
for i in 0..m {
|
||||
for j in 0..n {
|
||||
let plant = grid[i][j];
|
||||
if plant == '.' {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut area = 0;
|
||||
|
||||
let mut fence2 = vec![];
|
||||
let mut fence = FxHashSet::default();
|
||||
let mut seen = FxHashSet::default();
|
||||
let mut stack = vec![];
|
||||
stack.push((i as i32, j as i32));
|
||||
|
||||
while let Some((i, j)) = stack.pop() {
|
||||
grid[i as usize][j as usize] = '.';
|
||||
area += 1;
|
||||
seen.insert((i, j));
|
||||
|
||||
for dir in [(0,1), (1,0), (-1,0), (0,-1)].iter() {
|
||||
let x = i as i32 + dir.0;
|
||||
let y = j as i32 + dir.1;
|
||||
|
||||
let direction = match dir {
|
||||
(0,1) => 1,
|
||||
(1,0) => 2,
|
||||
(-1,0) => 0,
|
||||
(0,-1) => 3,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if seen.contains(&(x,y)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if x < 0 || y < 0 || x >= m as i32 || y >= n as i32 {
|
||||
fence.insert((x,y,direction));
|
||||
fence2.push((x,y,direction));
|
||||
continue;
|
||||
}
|
||||
|
||||
let c = grid[x as usize][y as usize];
|
||||
if c == plant {
|
||||
seen.insert((x,y));
|
||||
stack.push((x,y));
|
||||
continue;
|
||||
}
|
||||
fence.insert((x,y,direction));
|
||||
fence2.push((x,y,direction));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let mut sides = 0;
|
||||
|
||||
for f @(tx,ty,direction) in fence2 {
|
||||
if !fence.contains(&f) {
|
||||
continue;
|
||||
}
|
||||
fence.remove(&f);
|
||||
sides += 1;
|
||||
|
||||
for i in tx+1..m as i32 {
|
||||
if !fence.contains(&(i,ty,direction)) {
|
||||
break;
|
||||
}
|
||||
fence.remove(&(i, ty, direction));
|
||||
}
|
||||
for i in (0..tx).rev() {
|
||||
if !fence.contains(&(i,ty,direction)) {
|
||||
break;
|
||||
}
|
||||
fence.remove(&(i, ty, direction));
|
||||
}
|
||||
for j in ty+1..n as i32 {
|
||||
if !fence.contains(&(tx,j,direction)) {
|
||||
break;
|
||||
}
|
||||
fence.remove(&(tx, j, direction));
|
||||
}
|
||||
for j in (0..ty).rev() {
|
||||
if !fence.contains(&(tx,j,direction)) {
|
||||
break;
|
||||
}
|
||||
fence.remove(&(tx, j, direction));
|
||||
}
|
||||
}
|
||||
|
||||
area_total += area * sides;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
area_total
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"Button A: X+94, Y+34
|
||||
Button B: X+22, Y+67
|
||||
Prize: X=8400, Y=5400
|
||||
|
||||
Button A: X+26, Y+66
|
||||
Button B: X+67, Y+21
|
||||
Prize: X=12748, Y=12176
|
||||
|
||||
Button A: X+17, Y+86
|
||||
Button B: X+84, Y+37
|
||||
Prize: X=7870, Y=6450
|
||||
|
||||
Button A: X+69, Y+23
|
||||
Button B: X+27, Y+71
|
||||
Prize: X=18641, Y=10279",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
|
||||
let mut answer = 0.0;
|
||||
|
||||
for set in input.split("\n\n") {
|
||||
let mut nums = Vec::with_capacity(6);
|
||||
let mut tmp = 0;
|
||||
|
||||
for c in set.bytes() {
|
||||
if c >= b'0' && c <= b'9' {
|
||||
tmp *= 10;
|
||||
tmp += (c - b'0') as i64;
|
||||
} else if tmp != 0 {
|
||||
nums.push(tmp as f64);
|
||||
tmp = 0;
|
||||
} else {
|
||||
tmp = 0;
|
||||
}
|
||||
}
|
||||
if tmp != 0 {
|
||||
nums.push(tmp as f64);
|
||||
}
|
||||
assert!(nums.len() == 6);
|
||||
|
||||
let py = nums[5];
|
||||
let px = nums[4];
|
||||
|
||||
let by = nums[3];
|
||||
let bx = nums[2];
|
||||
|
||||
let ay = nums[1];
|
||||
let ax = nums[0];
|
||||
|
||||
/*
|
||||
* axA + bxB = px
|
||||
* ayA + byB = py
|
||||
*
|
||||
* ay*ax*A + ay*bx*B = ay*px
|
||||
* ax*ay*A + ax*by*B = ax*py
|
||||
*
|
||||
* ay*bx*B - ax*by*B = ay*px - ax*py
|
||||
* (ay*bx - ax*by) B = ay*px - ax*py
|
||||
*
|
||||
* B = (ay*px - ax*py) / (ay*bx - ax*by)
|
||||
* A = (px - bx * B) / ax;
|
||||
*/
|
||||
|
||||
const ERROR_MARGIN: f64 = 0.0001;
|
||||
let _b = (ay * px - ax * py) / (ay * bx - ax * by);
|
||||
let _a = (px - bx * _b) / ax;
|
||||
|
||||
// If there is too much error in reaching a point then we didn't actually reach it.
|
||||
// overshot or undershot
|
||||
if _b - (_b as isize) as f64 >= ERROR_MARGIN {
|
||||
continue;
|
||||
}
|
||||
if _a - (_a as isize) as f64 >= ERROR_MARGIN {
|
||||
continue;
|
||||
}
|
||||
|
||||
answer += _a * 3.0 + _b * 1.0;
|
||||
}
|
||||
|
||||
answer as i64
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"Button A: X+94, Y+34
|
||||
Button B: X+22, Y+67
|
||||
Prize: X=8400, Y=5400
|
||||
|
||||
Button A: X+26, Y+66
|
||||
Button B: X+67, Y+21
|
||||
Prize: X=12748, Y=12176
|
||||
|
||||
Button A: X+17, Y+86
|
||||
Button B: X+84, Y+37
|
||||
Prize: X=7870, Y=6450
|
||||
|
||||
Button A: X+69, Y+23
|
||||
Button B: X+27, Y+71
|
||||
Prize: X=18641, Y=10279",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
|
||||
let mut answer = 0.0;
|
||||
|
||||
for set in input.split("\n\n") {
|
||||
let mut nums = Vec::with_capacity(6);
|
||||
let mut tmp = 0;
|
||||
|
||||
for c in set.bytes() {
|
||||
if c >= b'0' && c <= b'9' {
|
||||
tmp *= 10;
|
||||
tmp += (c - b'0') as i64;
|
||||
} else if tmp != 0 {
|
||||
nums.push(tmp as f64);
|
||||
tmp = 0;
|
||||
} else {
|
||||
tmp = 0;
|
||||
}
|
||||
}
|
||||
if tmp != 0 {
|
||||
nums.push(tmp as f64);
|
||||
}
|
||||
assert!(nums.len() == 6);
|
||||
|
||||
let py = nums[5] + 10000000000000.0;
|
||||
let px = nums[4] + 10000000000000.0;
|
||||
|
||||
let by = nums[3];
|
||||
let bx = nums[2];
|
||||
|
||||
let ay = nums[1];
|
||||
let ax = nums[0];
|
||||
|
||||
/*
|
||||
* axA + bxB = px
|
||||
* ayA + byB = py
|
||||
*
|
||||
* ay*ax*A + ay*bx*B = ay*px
|
||||
* ax*ay*A + ax*by*B = ax*py
|
||||
*
|
||||
* ay*bx*B - ax*by*B = ay*px - ax*py
|
||||
* (ay*bx - ax*by) B = ay*px - ax*py
|
||||
*
|
||||
* B = (ay*px - ax*py) / (ay*bx - ax*by)
|
||||
* A = (px - bx * B) / ax;
|
||||
*/
|
||||
|
||||
const ERROR_MARGIN: f64 = 0.0001;
|
||||
let _b = (ay * px - ax * py) / (ay * bx - ax * by);
|
||||
let _a = (px - bx * _b) / ax;
|
||||
|
||||
// If there is too much error in reaching a point then we didn't actually reach it.
|
||||
// overshot or undershot
|
||||
if _b - (_b as isize) as f64 >= ERROR_MARGIN {
|
||||
continue;
|
||||
}
|
||||
if _a - (_a as isize) as f64 >= ERROR_MARGIN {
|
||||
continue;
|
||||
}
|
||||
|
||||
answer += _a * 3.0 + _b * 1.0;
|
||||
}
|
||||
|
||||
answer as i64
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"p=0,4 v=3,-3
|
||||
p=6,3 v=-1,-3
|
||||
p=10,3 v=-1,2
|
||||
p=2,0 v=2,-1
|
||||
p=0,0 v=1,3
|
||||
p=3,0 v=-2,-2
|
||||
p=7,6 v=-1,-3
|
||||
p=3,0 v=-1,-2
|
||||
p=9,3 v=2,3
|
||||
p=7,3 v=-1,2
|
||||
p=2,4 v=2,-3
|
||||
p=9,5 v=-3,-3",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut m = 0;
|
||||
let mut n = 0;
|
||||
|
||||
let mut robots = vec![];
|
||||
for line in input.lines() {
|
||||
let (p,v) = line.split_once(' ').unwrap();
|
||||
let (_, p) = p.split_once('=').unwrap();
|
||||
let (_, v) = v.split_once('=').unwrap();
|
||||
let (px, py) = p.split_once(',').unwrap();
|
||||
let px = px.parse::<i64>().unwrap();
|
||||
let py = py.parse::<i64>().unwrap();
|
||||
let (vx, vy) = v.split_once(',').unwrap();
|
||||
let vx = vx.parse::<i64>().unwrap();
|
||||
let vy = vy.parse::<i64>().unwrap();
|
||||
|
||||
m = std::cmp::max(m, px+1);
|
||||
n = std::cmp::max(n, py+1);
|
||||
robots.push((px, py, vx, vy));
|
||||
}
|
||||
|
||||
for _ in 0..100 {
|
||||
for robot in robots.iter_mut() {
|
||||
robot.0 += robot.2;
|
||||
robot.1 += robot.3;
|
||||
if robot.0 < 0 {
|
||||
robot.0 += m;
|
||||
} else if robot.0 >= m {
|
||||
robot.0 -= m;
|
||||
}
|
||||
if robot.1 < 0 {
|
||||
robot.1 += n;
|
||||
} else if robot.1 >= n {
|
||||
robot.1 -= n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mx = m / 2;
|
||||
let nx = n / 2;
|
||||
let mut quads = [0;4];
|
||||
|
||||
for (px,py, _,_) in robots {
|
||||
if px == mx || py == nx {
|
||||
continue;
|
||||
}
|
||||
|
||||
if px > mx && py > nx {
|
||||
quads[0] += 1;
|
||||
} else if px > mx && py < nx {
|
||||
quads[1] += 1;
|
||||
} else if px < mx && py > nx {
|
||||
quads[2] += 1;
|
||||
} else if px < mx && py < nx {
|
||||
quads[3] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
quads.into_iter().product()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 1] = [
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
|
||||
let mut m = 0;
|
||||
let mut n = 0;
|
||||
|
||||
let mut robots = vec![];
|
||||
for line in input.lines() {
|
||||
let line = line.chars().filter(|&x| x.is_digit(10) || x == '-' || x == ' ' || x == ',').collect::<String>();
|
||||
let (p,v) = line.split_once(' ').unwrap();
|
||||
let (px, py) = p.split_once(',').unwrap();
|
||||
let px = px.parse::<i64>().unwrap();
|
||||
let py = py.parse::<i64>().unwrap();
|
||||
let (vx, vy) = v.split_once(',').unwrap();
|
||||
let vx = vx.parse::<i64>().unwrap();
|
||||
let vy = vy.parse::<i64>().unwrap();
|
||||
|
||||
m = std::cmp::max(m, px+1);
|
||||
n = std::cmp::max(n, py+1);
|
||||
robots.push((px, py, vx, vy));
|
||||
}
|
||||
|
||||
let mut seen = Bitmap::new(std::cmp::max(m,n));
|
||||
|
||||
let mut second = 1;
|
||||
loop {
|
||||
seen.clear();
|
||||
for robot in robots.iter_mut() {
|
||||
robot.0 += robot.2;
|
||||
robot.1 += robot.3;
|
||||
if robot.0 < 0 {
|
||||
robot.0 += m;
|
||||
} else if robot.0 >= m {
|
||||
robot.0 -= m;
|
||||
}
|
||||
if robot.1 < 0 {
|
||||
robot.1 += n;
|
||||
} else if robot.1 >= n {
|
||||
robot.1 -= n;
|
||||
}
|
||||
|
||||
seen.set(robot.0, robot.1);
|
||||
}
|
||||
|
||||
if seen.test() {
|
||||
return second;
|
||||
}
|
||||
second += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const WORD_SIZE: usize = 64;
|
||||
|
||||
struct Bitmap {
|
||||
inner: Vec<u64>,
|
||||
size: i64,
|
||||
}
|
||||
|
||||
impl Bitmap {
|
||||
fn new(size: i64) -> Self {
|
||||
Self { inner: vec![0; ((size * size) as usize / WORD_SIZE) + 1], size }
|
||||
}
|
||||
|
||||
fn set(&mut self, x: i64, y: i64) {
|
||||
let offset = (x * self.size + y) as usize;
|
||||
let index = offset / WORD_SIZE;
|
||||
let bit_offset = offset % WORD_SIZE;
|
||||
|
||||
self.inner[index] |= 1 << bit_offset;
|
||||
}
|
||||
|
||||
fn test(&mut self) -> bool {
|
||||
for num in self.inner.iter() {
|
||||
for i in 0..8 {
|
||||
let mask = 0b1111_1111 << i;
|
||||
if num & mask == mask {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
for v in self.inner.iter_mut() {
|
||||
*v = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[0]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"##########
|
||||
#..O..O.O#
|
||||
#......O.#
|
||||
#.OO..O.O#
|
||||
#..O@..O.#
|
||||
#O#..O...#
|
||||
#O..O..O.#
|
||||
#.OO.O.OO#
|
||||
#....O...#
|
||||
##########
|
||||
|
||||
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
|
||||
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
|
||||
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
|
||||
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
|
||||
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
|
||||
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
|
||||
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
|
||||
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
|
||||
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
|
||||
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let (grid, moves) = input.split_once("\n\n").unwrap();
|
||||
let mut grid = grid.lines().map(|x| x.chars().collect::<Vec<char>>()).collect::<Vec<Vec<char>>>();
|
||||
let moves = moves.chars().filter(|x| !x.is_whitespace()).collect::<Vec<char>>();
|
||||
|
||||
let m = grid.len();
|
||||
let n = grid[0].len();
|
||||
|
||||
let mut answer = 0;
|
||||
|
||||
let mut sx = 0;
|
||||
let mut sy = 0;
|
||||
for i in 0..m {
|
||||
for j in 0..n {
|
||||
if grid[i][j] == '@' {
|
||||
sx = i as i64;
|
||||
sy = j as i64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for mmove in moves.into_iter() {
|
||||
let (nx, ny, ndir) = match mmove {
|
||||
'^' => (sx - 1, sy, 0),
|
||||
'>' => (sx, sy + 1, 1),
|
||||
'v' => (sx + 1, sy, 2),
|
||||
'<' => (sx, sy - 1, 3),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if validate_move(&mut grid, nx, ny, ndir) {
|
||||
grid[sx as usize][sy as usize] = '.';
|
||||
grid[nx as usize][ny as usize] = '@';
|
||||
sx = nx;
|
||||
sy = ny;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for i in 0..m {
|
||||
for j in 0..n {
|
||||
if grid[i][j] != 'O' {
|
||||
continue;
|
||||
}
|
||||
|
||||
answer += i as i64 * 100 + j as i64 ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
answer
|
||||
}
|
||||
|
||||
fn validate_move(grid: &mut Vec<Vec<char>>, x: i64, y: i64, direction: i64) -> bool {
|
||||
if grid[x as usize][y as usize] == '.' {
|
||||
return true;
|
||||
}
|
||||
|
||||
if grid[x as usize][y as usize] == '#' {
|
||||
return false;
|
||||
}
|
||||
|
||||
let delta = match direction {
|
||||
0 => (-1,0),
|
||||
1 => (0,1),
|
||||
2 => (1,0),
|
||||
3 => (0,-1),
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let mut fx = x;
|
||||
let mut fy = y;
|
||||
let mut count = 0;
|
||||
|
||||
while grid[fx as usize][fy as usize] == 'O' {
|
||||
fx += delta.0;
|
||||
fy += delta.1;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
let mut nx = fx;
|
||||
let mut ny = fy;
|
||||
|
||||
while count > 0 && grid[nx as usize][ny as usize] == '.' {
|
||||
grid[nx as usize][ny as usize] = 'O';
|
||||
nx = fx - delta.0;
|
||||
ny = fy - delta.1;
|
||||
fx = fx - delta.0;
|
||||
fy = fy - delta.1;
|
||||
grid[fx as usize][fy as usize] = '.';
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
count == 0
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"##########
|
||||
#..O..O.O#
|
||||
#......O.#
|
||||
#.OO..O.O#
|
||||
#..O@..O.#
|
||||
#O#..O...#
|
||||
#O..O..O.#
|
||||
#.OO.O.OO#
|
||||
#....O...#
|
||||
##########
|
||||
|
||||
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
|
||||
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
|
||||
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
|
||||
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
|
||||
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
|
||||
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
|
||||
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
|
||||
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
|
||||
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
|
||||
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let (grid, moves) = input.split_once("\n\n").unwrap();
|
||||
let mut grid = grid.lines().map(|x| x.chars().collect::<Vec<char>>()).collect::<Vec<Vec<char>>>();
|
||||
let moves = moves.chars().filter(|x| !x.is_whitespace()).collect::<Vec<char>>();
|
||||
|
||||
for row in grid.iter_mut() {
|
||||
let mut new = vec![];
|
||||
|
||||
for &c in row.iter() {
|
||||
match c {
|
||||
'#' => new.extend(['#', '#'].iter()),
|
||||
'O' => new.extend(['[', ']'].iter()),
|
||||
'.' => new.extend(['.', '.'].iter()),
|
||||
'@' => new.extend(['@', '.'].iter()),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
*row = new;
|
||||
}
|
||||
|
||||
let m = grid.len();
|
||||
let n = grid[0].len();
|
||||
|
||||
let mut answer = 0;
|
||||
|
||||
let mut sx = 0;
|
||||
let mut sy = 0;
|
||||
for i in 0..m {
|
||||
for j in 0..n {
|
||||
if grid[i][j] == '@' {
|
||||
sx = i as i64;
|
||||
sy = j as i64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for mmove in moves.into_iter() {
|
||||
let (nx, ny, ndir) = match mmove {
|
||||
'^' => (sx - 1, sy, 0),
|
||||
'>' => (sx, sy + 1, 1),
|
||||
'v' => (sx + 1, sy, 2),
|
||||
'<' => (sx, sy - 1, 3),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if validate_move(&mut grid, nx, ny, ndir) {
|
||||
grid[sx as usize][sy as usize] = '.';
|
||||
grid[nx as usize][ny as usize] = '@';
|
||||
sx = nx;
|
||||
sy = ny;
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..m {
|
||||
for j in 0..n {
|
||||
if grid[i][j] != '[' {
|
||||
continue;
|
||||
}
|
||||
|
||||
answer += i as i64 * 100 + j as i64 ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
answer
|
||||
}
|
||||
|
||||
fn validate_move(grid: &mut Vec<Vec<char>>, x: i64, y: i64, direction: i64) -> bool {
|
||||
if grid[x as usize][y as usize] == '.' {
|
||||
return true;
|
||||
}
|
||||
|
||||
if grid[x as usize][y as usize] == '#' {
|
||||
return false;
|
||||
}
|
||||
|
||||
let delta = match direction {
|
||||
0 => (-1,0),
|
||||
1 => (0,1),
|
||||
2 => (1,0),
|
||||
3 => (0,-1),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let mut fx = x;
|
||||
let mut fy = y;
|
||||
let mut count = 0;
|
||||
|
||||
while grid[fx as usize][fy as usize] == '[' || grid[fx as usize][fy as usize] == ']' {
|
||||
fx += delta.0;
|
||||
fy += delta.1;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
count /= 2;
|
||||
|
||||
let mut nx = fx;
|
||||
let mut ny = fy;
|
||||
|
||||
match direction {
|
||||
1 | 3 => {
|
||||
while count > 0 && grid[nx as usize][ny as usize] == '.' {
|
||||
grid[nx as usize][ny as usize] = if direction == 1 { ']' } else { '[' };
|
||||
nx -= delta.0;
|
||||
ny -= delta.1;
|
||||
grid[nx as usize][ny as usize] = if direction == 1 { '[' } else { ']' };
|
||||
nx -= delta.0;
|
||||
ny -= delta.1;
|
||||
grid[nx as usize][ny as usize] = '.';
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
count == 0
|
||||
}
|
||||
|
||||
0 | 2 => {
|
||||
let mut seen = FxHashSet::default();
|
||||
let mut to_move = vec![];
|
||||
let starting_point = if grid[x as usize][y as usize] == '[' {
|
||||
[(x, y), (x, y+1)]
|
||||
} else if grid[x as usize][y as usize] == ']' {
|
||||
[(x, y-1), (x, y)]
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
seen.insert(starting_point);
|
||||
to_move.push(starting_point);
|
||||
|
||||
let mut last_checked = 0;
|
||||
while last_checked != to_move.len() {
|
||||
for i in last_checked..to_move.len() {
|
||||
let point = to_move[i];
|
||||
|
||||
for (cx,cy) in point {
|
||||
let cx = cx + delta.0;
|
||||
let cy = cy + delta.1;
|
||||
|
||||
let p = if grid[cx as usize][cy as usize] == '[' {
|
||||
[(cx,cy), (cx, cy+1)]
|
||||
} else if grid[cx as usize][cy as usize] == ']' {
|
||||
[(cx,cy-1), (cx,cy)]
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if seen.contains(&p) {
|
||||
continue;
|
||||
}
|
||||
to_move.push(p);
|
||||
seen.insert(p);
|
||||
}
|
||||
last_checked = i+1;
|
||||
}
|
||||
}
|
||||
|
||||
// Test if all can be moved
|
||||
let mut g = grid.clone();
|
||||
|
||||
while let Some(coord) = to_move.pop() {
|
||||
if coord.iter().any(|x| g[(x.0 + delta.0) as usize][(x.1 + delta.1) as usize] != '.') {
|
||||
to_move.push(coord);
|
||||
break;
|
||||
}
|
||||
|
||||
g[coord[0].0 as usize][coord[0].1 as usize] = '.';
|
||||
g[coord[1].0 as usize][coord[1].1 as usize] = '.';
|
||||
|
||||
g[(coord[0].0 + delta.0) as usize][(coord[0].1 + delta.1) as usize] = '[';
|
||||
g[(coord[1].0 + delta.0) as usize][(coord[1].1 + delta.1) as usize] = ']';
|
||||
}
|
||||
|
||||
if to_move.is_empty() {
|
||||
*grid = g;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"7 6 4 2 1
|
||||
1 2 7 8 9
|
||||
9 7 6 2 1
|
||||
1 3 2 4 5
|
||||
8 6 4 4 1
|
||||
1 3 6 7 9",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut safe = 0;
|
||||
|
||||
for line in input.lines().filter(|x| !x.is_empty()) {
|
||||
let nums: Vec<i64> = line.split(' ').filter(|x| !x.is_empty()).map(|x| x.parse::<i64>().unwrap()).collect();
|
||||
|
||||
let increasing = nums.windows(2).all(|nums| {
|
||||
let diff = nums[1] - nums[0];
|
||||
nums[1] > nums[0] && diff >= 1 && diff <= 3
|
||||
});
|
||||
|
||||
if increasing {
|
||||
safe += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let decreasing = nums.windows(2).all(|nums| {
|
||||
let diff = nums[0] - nums[1];
|
||||
nums[1] < nums[0] && diff >= 1 && diff <= 3
|
||||
});
|
||||
|
||||
if decreasing {
|
||||
safe += 1;
|
||||
}
|
||||
}
|
||||
|
||||
safe
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"7 6 4 2 1
|
||||
1 2 7 8 9
|
||||
9 7 6 2 1
|
||||
1 3 2 4 5
|
||||
8 6 4 4 1
|
||||
1 3 6 7 9",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut safe = 0;
|
||||
|
||||
for line in input.lines().filter(|x| !x.is_empty()) {
|
||||
let mut nums: Vec<i64> = line.split(' ').filter(|x| !x.is_empty()).map(|x| x.parse::<i64>().unwrap()).collect();
|
||||
|
||||
if test_array(&nums) {
|
||||
safe += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
for i in 0..nums.len() {
|
||||
let tmp = nums.remove(i);
|
||||
|
||||
if test_array(&nums) {
|
||||
safe += 1;
|
||||
break;
|
||||
}
|
||||
nums.insert(i, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
safe
|
||||
}
|
||||
|
||||
fn test_array(nums: &[i64]) -> bool {
|
||||
nums.windows(2).all(|nums| {
|
||||
let diff = nums[1] - nums[0];
|
||||
nums[1] > nums[0] && diff >= 1 && diff <= 3
|
||||
}) || nums.windows(2).all(|nums| {
|
||||
let diff = nums[0] - nums[1];
|
||||
nums[1] < nums[0] && diff >= 1 && diff <= 3
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(file: &str) -> u64 {
|
||||
|
||||
let mut mul_count = 0;
|
||||
let mut mul_active = false;
|
||||
let mut first_num = true;
|
||||
let mut num1 = 0;
|
||||
let mut num2 = 0;
|
||||
let mut sum = 0;
|
||||
|
||||
for c in file.chars() {
|
||||
match c {
|
||||
'm' if mul_count == 0 => {
|
||||
mul_count += 1;
|
||||
}
|
||||
'u' if mul_count == 1 => {
|
||||
mul_count += 1;
|
||||
}
|
||||
'l' if mul_count == 2 => {
|
||||
mul_count += 1;
|
||||
}
|
||||
'(' if mul_count == 3 => {
|
||||
mul_active=true;
|
||||
first_num = true;
|
||||
}
|
||||
'0'..='9' if mul_active && first_num => {
|
||||
let c = (c as u8 - b'0') as u64;
|
||||
num1 *= 10;
|
||||
num1 += c;
|
||||
}
|
||||
'0'..='9' if mul_active && !first_num => {
|
||||
let c = (c as u8 - b'0') as u64;
|
||||
num2 *= 10;
|
||||
num2 += c;
|
||||
}
|
||||
',' if mul_active => {
|
||||
first_num = false;
|
||||
}
|
||||
')' if mul_active => {
|
||||
sum += num1 * num2;
|
||||
num1 = 0;
|
||||
num2 = 0;
|
||||
mul_active = false;
|
||||
mul_count = 0 ;
|
||||
first_num = true;
|
||||
}
|
||||
_ => {
|
||||
mul_active = false;
|
||||
mul_count = 0;
|
||||
num1 = 0;
|
||||
num2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> u64 {
|
||||
|
||||
let mut mul_count = 0;
|
||||
let mut mul_active = false;
|
||||
let mut dont_active = false;
|
||||
let mut dont_count = 0;
|
||||
let mut do_count = 0;
|
||||
let mut first_num = true;
|
||||
|
||||
let mut sum = 0;
|
||||
let mut num1 = 0;
|
||||
let mut num2 = 0;
|
||||
|
||||
for c in input.chars() {
|
||||
match c {
|
||||
'd' => {
|
||||
if dont_count == 0 {
|
||||
dont_count += 1;
|
||||
}
|
||||
if do_count == 0 {
|
||||
do_count += 1 ;
|
||||
}
|
||||
mul_count = 0;
|
||||
}
|
||||
'o' => {
|
||||
if dont_count == 1 {
|
||||
dont_count += 1;
|
||||
}
|
||||
if do_count == 1 {
|
||||
do_count += 1;
|
||||
}
|
||||
mul_count = 0;
|
||||
}
|
||||
'n' if dont_count == 2 => {
|
||||
dont_count += 1;
|
||||
do_count = 0;
|
||||
mul_count = 0;
|
||||
}
|
||||
'\'' if dont_count == 3 => {
|
||||
dont_count += 1;
|
||||
do_count = 0;
|
||||
mul_count = 0;
|
||||
}
|
||||
't' if dont_count == 4 => {
|
||||
dont_count += 1;
|
||||
do_count = 0;
|
||||
mul_count = 0;
|
||||
}
|
||||
'm' if mul_count == 0 => {
|
||||
mul_count += 1;
|
||||
do_count = 0;
|
||||
dont_count = 0;
|
||||
}
|
||||
'u' if mul_count == 1 => {
|
||||
mul_count += 1;
|
||||
do_count = 0;
|
||||
dont_count = 0;
|
||||
}
|
||||
'l' if mul_count == 2 => {
|
||||
mul_count += 1;
|
||||
do_count = 0;
|
||||
dont_count = 0;
|
||||
}
|
||||
'(' if mul_count == 3 && !dont_active => {
|
||||
mul_active=true;
|
||||
first_num = true;
|
||||
}
|
||||
'(' if do_count == 2 => {
|
||||
do_count += 1;
|
||||
}
|
||||
')' if do_count == 3 => {
|
||||
dont_active = false;
|
||||
}
|
||||
'(' if dont_count == 5 => {
|
||||
dont_count += 1;
|
||||
}
|
||||
')' if dont_count == 6 => {
|
||||
dont_active = true;
|
||||
}
|
||||
'0'..='9' if mul_active && first_num => {
|
||||
let c = (c as u8 - b'0') as u64;
|
||||
num1 *= 10;
|
||||
num1 += c;
|
||||
}
|
||||
'0'..='9' if mul_active && !first_num => {
|
||||
let c = (c as u8 - b'0') as u64;
|
||||
num2 *= 10;
|
||||
num2 += c;
|
||||
}
|
||||
',' if mul_active => {
|
||||
first_num = false;
|
||||
}
|
||||
')' if mul_active => {
|
||||
sum += num1 * num2;
|
||||
num1 = 0;
|
||||
num2 = 0;
|
||||
mul_active = false;
|
||||
mul_count = 0 ;
|
||||
first_num = true;
|
||||
}
|
||||
_ => {
|
||||
mul_active = false;
|
||||
mul_count = 0;
|
||||
num1 = 0;
|
||||
num2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"47|53
|
||||
97|13
|
||||
97|61
|
||||
97|47
|
||||
75|29
|
||||
61|13
|
||||
75|53
|
||||
29|13
|
||||
97|29
|
||||
53|29
|
||||
61|53
|
||||
97|53
|
||||
61|29
|
||||
47|13
|
||||
75|47
|
||||
97|75
|
||||
47|61
|
||||
75|61
|
||||
47|29
|
||||
75|13
|
||||
53|13
|
||||
|
||||
75,47,61,53,29
|
||||
97,61,53,29,13
|
||||
75,29,13
|
||||
75,97,47,61,53
|
||||
61,13,29
|
||||
97,13,75,29,47",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
|
||||
let mut input = input.split("\n\n");
|
||||
let mut ordering = vec![vec![]; 100];
|
||||
|
||||
for order in input.next().unwrap().lines().map(|x| x.split('|').map(|x| x.parse::<i64>().unwrap()).collect::<Vec<i64>>()) {
|
||||
|
||||
let x = order[0];
|
||||
let y = order[1];
|
||||
|
||||
ordering[x as usize].push(y);
|
||||
}
|
||||
|
||||
let mut sum = 0;
|
||||
let mut count = 0;
|
||||
|
||||
for line in input.next().unwrap().lines() {
|
||||
let line = line.split(',').map(|x| x.parse::<i64>().unwrap()).collect::<Vec<i64>>();
|
||||
|
||||
if validate_order(&ordering, &line) {
|
||||
|
||||
let n = line.len();
|
||||
|
||||
sum += line[n/2];
|
||||
} else {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
println!("count = {:?}", count);
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
fn validate_order(ordering: &Vec<Vec<i64>>, line: &Vec<i64>) -> bool {
|
||||
|
||||
let mut seen = FxHashSet::default();
|
||||
|
||||
for &num in line {
|
||||
seen.insert(num);
|
||||
|
||||
let preorder = &ordering[num as usize];
|
||||
|
||||
if preorder.iter().any(|x| seen.contains(&x)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"47|53
|
||||
97|13
|
||||
97|61
|
||||
97|47
|
||||
75|29
|
||||
61|13
|
||||
75|53
|
||||
29|13
|
||||
97|29
|
||||
53|29
|
||||
61|53
|
||||
97|53
|
||||
61|29
|
||||
47|13
|
||||
75|47
|
||||
97|75
|
||||
47|61
|
||||
75|61
|
||||
47|29
|
||||
75|13
|
||||
53|13
|
||||
|
||||
75,47,61,53,29
|
||||
97,61,53,29,13
|
||||
75,29,13
|
||||
75,97,47,61,53
|
||||
61,13,29
|
||||
97,13,75,29,47",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
|
||||
let mut input = input.split("\n\n");
|
||||
let mut ordering = vec![vec![]; 100];
|
||||
|
||||
for order in input.next().unwrap().lines().map(|x| x.split('|').map(|x| x.parse::<i64>().unwrap()).collect::<Vec<i64>>()) {
|
||||
|
||||
let x = order[0];
|
||||
let y = order[1];
|
||||
|
||||
ordering[x as usize].push(y);
|
||||
}
|
||||
|
||||
let mut sum = 0;
|
||||
|
||||
for line in input.next().unwrap().lines() {
|
||||
let line = line.split(',').map(|x| x.parse::<i64>().unwrap()).collect::<Vec<i64>>();
|
||||
|
||||
if !validate_order(&ordering, &line) {
|
||||
|
||||
let line = rearrange(&ordering, line);
|
||||
|
||||
let n = line.len();
|
||||
sum += line[n/2];
|
||||
}
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
fn rearrange(ordering: &Vec<Vec<i64>>, mut line: Vec<i64>) -> Vec<i64> {
|
||||
let mut out = vec![];
|
||||
|
||||
let result = dfs(&ordering, &mut out, &mut line);
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
fn dfs(ordering: &Vec<Vec<i64>>, out: &mut Vec<i64>, nums: &mut Vec<i64>) -> bool {
|
||||
if !validate_order(&ordering, out) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if nums.is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
for i in 0..nums.len() {
|
||||
let num = nums.remove(i);
|
||||
out.push(num);
|
||||
|
||||
if dfs(ordering, out, nums) {
|
||||
return true;
|
||||
}
|
||||
out.pop();
|
||||
nums.insert(i, num);
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn validate_order(ordering: &Vec<Vec<i64>>, line: &Vec<i64>) -> bool {
|
||||
let mut seen = FxHashSet::default();
|
||||
|
||||
for &num in line {
|
||||
seen.insert(num);
|
||||
let preorder = &ordering[num as usize];
|
||||
if preorder.iter().any(|x| seen.contains(&x)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"....#.....
|
||||
.........#
|
||||
..........
|
||||
..#.......
|
||||
.......#..
|
||||
..........
|
||||
.#..^.....
|
||||
........#.
|
||||
#.........
|
||||
......#...",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let input = input.as_bytes();
|
||||
let grid: Vec<Vec<u8>> = input.split(|&x| x == b'\n').filter(|x| !x.is_empty()).map(|x| x.to_vec()).collect();
|
||||
let m = grid.len();
|
||||
let n = grid[0].len();
|
||||
|
||||
|
||||
let mut gx = 0i32;
|
||||
let mut gy = 0i32;
|
||||
|
||||
for i in 0..m {
|
||||
for j in 0..n {
|
||||
if grid[i][j] == b'^' {
|
||||
gx = i as i32;
|
||||
gy = j as i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compute(&grid, gx, gy)
|
||||
}
|
||||
|
||||
fn is_blocked(grid: &Vec<Vec<u8>>, x: i32, y: i32) -> bool {
|
||||
let m = grid.len() as i32;
|
||||
let n = grid[0].len() as i32;
|
||||
|
||||
if x < 0 || y < 0 || x >= m || y >= n {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
*grid.get_unchecked(x as usize).get_unchecked(y as usize) == b'#'
|
||||
}
|
||||
}
|
||||
|
||||
fn should_turn(grid: &Vec<Vec<u8>>, x: i32, y: i32, direction: u8) -> (bool, u8) {
|
||||
match direction {
|
||||
0 => {
|
||||
if is_blocked(&grid, x-1, y) {
|
||||
return (true, 1);
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
if is_blocked(&grid, x, y+1) {
|
||||
return (true, 2);
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
if is_blocked(&grid, x+1, y) {
|
||||
return (true, 3);
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
if is_blocked(&grid, x, y-1) {
|
||||
return (true, 0);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
return (false, direction)
|
||||
}
|
||||
|
||||
fn compute(grid: &Vec<Vec<u8>>, mut x: i32, mut y: i32) -> i64 {
|
||||
let m = grid.len();
|
||||
let n = grid[0].len();
|
||||
|
||||
let mut set = FxHashSet::default();
|
||||
let mut direction = 0;
|
||||
|
||||
while x >= 0 && y >= 0 && x < m as i32 && y < n as i32 {
|
||||
set.insert((x,y));
|
||||
|
||||
// Might need maxiumum 2 consecutive turns
|
||||
// perform those if needed
|
||||
let turn;
|
||||
(turn, direction) = should_turn(grid, x, y, direction);
|
||||
if turn {
|
||||
(_, direction) = should_turn(grid, x, y, direction);
|
||||
}
|
||||
|
||||
match direction {
|
||||
0 => x -= 1,
|
||||
1 => y += 1,
|
||||
2 => x += 1,
|
||||
3 => y -= 1,
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
set.len() as i64
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use rayon::prelude::*;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"....#.....
|
||||
.........#
|
||||
..........
|
||||
..#.......
|
||||
.......#..
|
||||
..........
|
||||
.#..^.....
|
||||
........#.
|
||||
#.........
|
||||
......#...",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let input = input.as_bytes();
|
||||
let grid: Vec<Vec<u8>> = input
|
||||
.split(|&x| x == b'\n')
|
||||
.filter(|x| !x.is_empty())
|
||||
.map(|x| x.to_vec())
|
||||
.collect();
|
||||
let m = grid.len();
|
||||
let n = grid[0].len();
|
||||
|
||||
let mut gx = 0i32;
|
||||
let mut gy = 0i32;
|
||||
|
||||
for i in 0..m {
|
||||
for j in 0..n {
|
||||
if grid[i][j] == b'^' {
|
||||
gx = i as i32;
|
||||
gy = j as i32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let answer = (0..m)
|
||||
.into_par_iter()
|
||||
.map(|i| {
|
||||
let grid = grid.clone();
|
||||
(0..n)
|
||||
.into_par_iter()
|
||||
.map(move |j| {
|
||||
if grid[i][j] != b'.' {
|
||||
return 0;
|
||||
}
|
||||
let mut grid = grid.clone();
|
||||
grid[i][j] = b'#';
|
||||
if test(&grid, gx, gy) {
|
||||
return 1;
|
||||
}
|
||||
0
|
||||
})
|
||||
.sum::<i64>()
|
||||
})
|
||||
.sum::<i64>();
|
||||
|
||||
answer
|
||||
}
|
||||
|
||||
fn is_blocked(grid: &Vec<Vec<u8>>, x: i32, y: i32) -> bool {
|
||||
let m = grid.len() as i32;
|
||||
let n = grid[0].len() as i32;
|
||||
|
||||
if x < 0 || y < 0 || x >= m || y >= n {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsafe { *grid.get_unchecked(x as usize).get_unchecked(y as usize) == b'#' }
|
||||
}
|
||||
|
||||
fn should_turn(grid: &Vec<Vec<u8>>, x: i32, y: i32, direction: i32) -> (bool, i32) {
|
||||
match direction {
|
||||
0 => {
|
||||
if is_blocked(&grid, x - 1, y) {
|
||||
return (true, 1);
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
if is_blocked(&grid, x, y + 1) {
|
||||
return (true, 2);
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
if is_blocked(&grid, x + 1, y) {
|
||||
return (true, 3);
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
if is_blocked(&grid, x, y - 1) {
|
||||
return (true, 0);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
return (false, direction);
|
||||
}
|
||||
|
||||
fn test(grid: &Vec<Vec<u8>>, mut x: i32, mut y: i32) -> bool {
|
||||
let m = grid.len();
|
||||
let n = grid[0].len();
|
||||
|
||||
let mut direction = 0;
|
||||
let limit = m * n;
|
||||
let mut steps = 0;
|
||||
let mut seen = Bitmap::new();
|
||||
|
||||
while x >= 0 && y >= 0 && x < m as i32 && y < n as i32 {
|
||||
if steps > limit {
|
||||
return true;
|
||||
}
|
||||
steps += 1;
|
||||
|
||||
if seen.get(x,y,direction) {
|
||||
return true;
|
||||
}
|
||||
|
||||
seen.set(x,y,direction);
|
||||
|
||||
// Might need maxiumum 2 consecutive turns
|
||||
// perform those if needed
|
||||
let turn;
|
||||
(turn, direction) = should_turn(grid, x, y, direction);
|
||||
if turn {
|
||||
(_, direction) = should_turn(grid, x, y, direction);
|
||||
}
|
||||
|
||||
match direction {
|
||||
0 => x -= 1,
|
||||
1 => y += 1,
|
||||
2 => x += 1,
|
||||
3 => y -= 1,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
const ROW: usize = 130;
|
||||
const COL: usize = 130;
|
||||
const WORD_SIZE: usize = 64;
|
||||
|
||||
const SIZE: usize = (4 + ROW * ROW + ROW * COL * COL) / WORD_SIZE;
|
||||
|
||||
struct Bitmap {
|
||||
inner: [u64; SIZE],
|
||||
}
|
||||
|
||||
impl Bitmap {
|
||||
#[allow(unused)]
|
||||
fn new() -> Self {
|
||||
Self { inner: [0; SIZE] }
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
const fn get(&self, x: i32, y: i32, dir: i32) -> bool {
|
||||
let offset = (dir + ROW as i32 * (x + COL as i32 * y)) as usize;
|
||||
let index = offset / WORD_SIZE;
|
||||
let bit_offset = offset % WORD_SIZE;
|
||||
|
||||
(self.inner[index] >> bit_offset & 1) == 1
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn set(&mut self, x: i32, y: i32, dir: i32) {
|
||||
let offset = (dir + ROW as i32 * (x + COL as i32 * y)) as usize;
|
||||
let index = offset / WORD_SIZE;
|
||||
let bit_offset = offset % WORD_SIZE;
|
||||
|
||||
self.inner[index] |= 1 << bit_offset;
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn count(&self) -> u32 {
|
||||
let mut count = 0;
|
||||
|
||||
for c in self.inner.iter() {
|
||||
count += c.count_ones();
|
||||
}
|
||||
count
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"190: 10 19
|
||||
3267: 81 40 27
|
||||
83: 17 5
|
||||
156: 15 6
|
||||
7290: 6 8 6 15
|
||||
161011: 16 10 13
|
||||
192: 17 8 14
|
||||
21037: 9 7 18 13
|
||||
292: 11 6 16 20",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut sum = 0;
|
||||
|
||||
for line in input.lines().filter(|x| !x.is_empty()) {
|
||||
|
||||
let (total, nums) = line.split_once(": ").unwrap();
|
||||
let total = total.parse::<i64>().unwrap();
|
||||
let nums = nums.split(' ').filter(|x| !x.is_empty()).map(|x| x.parse::<i64>().unwrap()).collect::<Vec<i64>>();
|
||||
|
||||
if test(&nums, total, 0) {
|
||||
sum += total;
|
||||
}
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
fn test(nums: &[i64], target: i64, so_far: i64) -> bool {
|
||||
if so_far == target && nums.is_empty() {
|
||||
return true;
|
||||
}
|
||||
if so_far > target || nums.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if test(&nums[1..], target, if so_far == 0 { 1 } else { so_far } * nums[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if test(&nums[1..], target, so_far + nums[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"190: 10 19
|
||||
3267: 81 40 27
|
||||
83: 17 5
|
||||
156: 15 6
|
||||
7290: 6 8 6 15
|
||||
161011: 16 10 13
|
||||
192: 17 8 14
|
||||
21037: 9 7 18 13
|
||||
292: 11 6 16 20",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let mut sum = 0;
|
||||
|
||||
for line in input.lines() {
|
||||
|
||||
let (total, nums) = line.split_once(": ").unwrap();
|
||||
let total = total.parse::<i64>().unwrap();
|
||||
let nums = nums.split(' ').map(|x| x.parse::<i64>().unwrap()).collect::<Vec<i64>>();
|
||||
|
||||
if test(&nums, total, 0) {
|
||||
sum += total;
|
||||
}
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
fn test(nums: &[i64], target: i64, so_far: i64) -> bool {
|
||||
if so_far == target && nums.is_empty() {
|
||||
return true;
|
||||
}
|
||||
if so_far > target || nums.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if test(&nums[1..], target, concat(so_far, nums[0])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if test(&nums[1..], target, if so_far == 0 { 1 } else { so_far } * nums[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if test(&nums[1..], target, so_far + nums[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
const fn concat(a: i64, b: i64) -> i64 {
|
||||
a * 10i64.pow(b.ilog(10) + 1) + b
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"............
|
||||
........0...
|
||||
.....0......
|
||||
.......0....
|
||||
....0.......
|
||||
......A.....
|
||||
............
|
||||
............
|
||||
........A...
|
||||
.........A..
|
||||
............
|
||||
............",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let input = input.as_bytes();
|
||||
let size = input.iter().position(|&x| x == b'\n').unwrap();
|
||||
|
||||
let mut map = vec![Vec::with_capacity(size); 128];
|
||||
|
||||
for i in 0..size {
|
||||
for j in 0..size {
|
||||
let c = input[i*size+j+i];
|
||||
if c == b'.' {
|
||||
continue;
|
||||
}
|
||||
map[c as usize].push((i as i32, j as i32));
|
||||
}
|
||||
}
|
||||
|
||||
let mut seen = Bitmap::new(size as i32);
|
||||
|
||||
for pos in map {
|
||||
for p in 0..pos.len() {
|
||||
let (a1,b1) = pos[p];
|
||||
|
||||
for q in p+1..pos.len() {
|
||||
let (a2,b2) = pos[q];
|
||||
|
||||
let dx = (a1 - a2).abs();
|
||||
let dy = (b1 - b2).abs();
|
||||
|
||||
let mut p1x = a1;
|
||||
let mut p1y = b1;
|
||||
let mut p2x = a2;
|
||||
let mut p2y = b2;
|
||||
|
||||
if a1 < a2 && b1 < b2 {
|
||||
p1x -= dx;
|
||||
p1y -= dy;
|
||||
p2x += dx;
|
||||
p2y += dy;
|
||||
} else if a1 < a2 && b1 > b2 {
|
||||
p1x -= dx;
|
||||
p1y += dy;
|
||||
p2x += dx;
|
||||
p2y -= dy;
|
||||
}
|
||||
|
||||
seen.set(p1x,p1y);
|
||||
seen.set(p2x,p2y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seen.count() as i64
|
||||
}
|
||||
|
||||
const WORD_SIZE: usize = 64;
|
||||
|
||||
struct Bitmap {
|
||||
inner: Vec<u64>,
|
||||
size: i32,
|
||||
}
|
||||
|
||||
impl Bitmap {
|
||||
fn new(size: i32) -> Self {
|
||||
Self { inner: vec![0; ((size * size) as usize / WORD_SIZE) + 1], size }
|
||||
}
|
||||
|
||||
fn set(&mut self, x: i32, y: i32) {
|
||||
if x < 0 || y < 0 || x >= self.size || y >= self.size {
|
||||
return;
|
||||
}
|
||||
let offset = (x * self.size + y) as usize;
|
||||
let index = offset / WORD_SIZE;
|
||||
let bit_offset = offset % WORD_SIZE;
|
||||
|
||||
self.inner[index] |= 1 << bit_offset;
|
||||
}
|
||||
|
||||
fn count(&self) -> u32 {
|
||||
let mut count = 0;
|
||||
|
||||
for c in self.inner.iter() {
|
||||
count += c.count_ones();
|
||||
}
|
||||
count
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter().take(3) {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"T.........
|
||||
...T......
|
||||
.T........
|
||||
..........
|
||||
..........
|
||||
..........
|
||||
..........
|
||||
..........
|
||||
..........
|
||||
..........",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let input = input.as_bytes();
|
||||
let size = input.iter().position(|&x| x == b'\n').unwrap();
|
||||
|
||||
let mut map = vec![Vec::with_capacity(size); 128];
|
||||
|
||||
for i in 0..size {
|
||||
for j in 0..size {
|
||||
let c = input[i*size+j+i];
|
||||
if c == b'.' {
|
||||
continue;
|
||||
}
|
||||
|
||||
map[c as usize].push((i as i32, j as i32));
|
||||
}
|
||||
}
|
||||
|
||||
let mut seen = Bitmap::new(size as i32);
|
||||
for pos in map {
|
||||
for p in 0..pos.len() {
|
||||
let (a1,b1) = pos[p];
|
||||
seen.set(a1,b1);
|
||||
|
||||
for q in p+1..pos.len() {
|
||||
let (a2,b2) = pos[q];
|
||||
|
||||
let dx = (a1 - a2).abs();
|
||||
let dy = (b1 - b2).abs();
|
||||
|
||||
let mut p1x = a1;
|
||||
let mut p1y = b1;
|
||||
let mut p2x = a2;
|
||||
let mut p2y = b2;
|
||||
|
||||
while p1x >= 0 && p1y >= 0 && p1x < size as i32 && p1y < size as i32 {
|
||||
if a1 < a2 && b1 < b2 {
|
||||
p1x -= dx;
|
||||
p1y -= dy;
|
||||
} else if a1 < a2 && b1 > b2 {
|
||||
p1x += dx;
|
||||
p1y -= dy;
|
||||
}
|
||||
|
||||
seen.set(p1x,p1y);
|
||||
}
|
||||
|
||||
while p2x >= 0 && p2y >= 0 && p2x < size as i32 && p2y < size as i32 {
|
||||
if a1 < a2 && b1 < b2 {
|
||||
p2x += dx;
|
||||
p2y += dy;
|
||||
} else if a1 < a2 && b1 > b2 {
|
||||
p2x -= dx;
|
||||
p2y += dy;
|
||||
}
|
||||
|
||||
seen.set(p2x,p2y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seen.count() as i64
|
||||
}
|
||||
|
||||
const WORD_SIZE: usize = 64;
|
||||
|
||||
struct Bitmap {
|
||||
inner: Vec<u64>,
|
||||
size: i32,
|
||||
}
|
||||
|
||||
impl Bitmap {
|
||||
fn new(size: i32) -> Self {
|
||||
Self { inner: vec![0; ((size * size) as usize / WORD_SIZE) + 1], size }
|
||||
}
|
||||
|
||||
fn set(&mut self, x: i32, y: i32) {
|
||||
if x < 0 || y < 0 || x >= self.size || y >= self.size {
|
||||
return;
|
||||
}
|
||||
let offset = (x * self.size + y) as usize;
|
||||
let index = offset / WORD_SIZE;
|
||||
let bit_offset = offset % WORD_SIZE;
|
||||
|
||||
self.inner[index] |= 1 << bit_offset;
|
||||
}
|
||||
|
||||
fn count(&self) -> u32 {
|
||||
let mut count = 0;
|
||||
|
||||
for c in self.inner.iter() {
|
||||
count += c.count_ones();
|
||||
}
|
||||
count
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"2333133121414131402",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
let input = input.as_bytes();
|
||||
let mut is_space = false;
|
||||
let mut block_id = 0;
|
||||
let mut offset = 0;
|
||||
|
||||
|
||||
let mut zeroes = VecDeque::with_capacity(input.len() / 2);
|
||||
let mut blocks = Vec::with_capacity(input.len() / 2);
|
||||
|
||||
for c in input {
|
||||
if c.is_ascii_whitespace() {
|
||||
continue;
|
||||
}
|
||||
let n = (c - b'0') as i64;
|
||||
if is_space {
|
||||
zeroes.push_back((offset, n));
|
||||
} else {
|
||||
blocks.push((block_id, offset, n));
|
||||
block_id += 1;
|
||||
}
|
||||
offset += n;
|
||||
is_space = !is_space;
|
||||
}
|
||||
|
||||
let mut answer = 0;
|
||||
|
||||
for (block_id, block_offset, mut block_len) in blocks.into_iter().rev() {
|
||||
if block_id == 0 {
|
||||
continue;
|
||||
}
|
||||
while block_len > 0 {
|
||||
let Some((zero_offset, zero_len)) = zeroes.pop_front() else {
|
||||
let sum = ((block_offset + block_len - 1) * (block_offset + block_len + 1 - 1) / 2) - ((block_offset - 1) * (block_offset + 1 - 1) / 2);
|
||||
answer += block_id * sum;
|
||||
break;
|
||||
};
|
||||
|
||||
if zero_offset > block_offset {
|
||||
let sum = ((block_offset + block_len - 1) * (block_offset + block_len + 1 - 1) / 2) - ((block_offset - 1) * (block_offset + 1 - 1) / 2);
|
||||
answer += block_id * sum;
|
||||
break;
|
||||
}
|
||||
|
||||
let moveable = std::cmp::min(block_len, zero_len);
|
||||
|
||||
let sum = ((zero_offset + moveable - 1) * (zero_offset + moveable + 1 - 1) / 2) - ((zero_offset - 1) * (zero_offset + 1 - 1) / 2);
|
||||
answer += block_id * sum;
|
||||
|
||||
if zero_len > block_len {
|
||||
zeroes.push_front((zero_offset + block_len, zero_len - block_len));
|
||||
}
|
||||
|
||||
block_len = std::cmp::max(0, block_len - zero_len);
|
||||
}
|
||||
}
|
||||
|
||||
answer as i64
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter().take(3) {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use std::collections::BinaryHeap;
|
||||
use std::cmp::Reverse;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"2333133121414131402",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> u64 {
|
||||
let input = input.as_bytes();
|
||||
let mut is_space = false;
|
||||
let mut block_id = 0;
|
||||
let mut offset = 0;
|
||||
|
||||
let mut zeroes = [const { BinaryHeap::new() }; 10];
|
||||
let mut blocks = Vec::with_capacity(input.len() / 2);
|
||||
|
||||
for c in input {
|
||||
if c.is_ascii_whitespace() {
|
||||
continue;
|
||||
}
|
||||
let n = (c - b'0') as usize;
|
||||
if is_space {
|
||||
zeroes[n].push(Reverse(offset));
|
||||
} else {
|
||||
blocks.push((block_id, offset, n));
|
||||
block_id += 1;
|
||||
}
|
||||
offset += n;
|
||||
is_space = !is_space;
|
||||
}
|
||||
|
||||
for (_, block_offset, block_len) in blocks.iter_mut().rev() {
|
||||
let mut zero_offset = std::usize::MAX;
|
||||
let mut zero_len = 0;
|
||||
|
||||
for (i, heap) in zeroes[*block_len..].iter().enumerate() {
|
||||
if let Some(&Reverse(offset)) = heap.peek() {
|
||||
if offset < zero_offset && offset < *block_offset {
|
||||
zero_offset = offset;
|
||||
zero_len = *block_len + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if zero_offset == std::usize::MAX {
|
||||
continue;
|
||||
}
|
||||
|
||||
zeroes[zero_len].pop();
|
||||
|
||||
if zero_len == *block_len {
|
||||
std::mem::swap(&mut zero_offset, block_offset);
|
||||
} else {
|
||||
*block_offset = zero_offset;
|
||||
zero_len -= *block_len;
|
||||
zero_offset += *block_len;
|
||||
|
||||
zeroes[zero_len].push(Reverse(zero_offset));
|
||||
}
|
||||
}
|
||||
|
||||
let mut sum = 0;
|
||||
for (id, offset, len) in blocks {
|
||||
let range_sum = ((offset + len - 1) * (offset + len + 1 - 1) / 2) - ((offset - 1) * (offset + 1 - 1) / 2);
|
||||
sum += id * range_sum;
|
||||
}
|
||||
|
||||
sum as u64
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
use std::{env, fs::{self, File}, io};
|
||||
use std::path::Path;
|
||||
|
||||
const AOC_TOKEN: &str = include_str!("../.aoc_token");
|
||||
|
||||
const P1_TEMPLATE: &str = r#"
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part1(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}"#;
|
||||
|
||||
|
||||
const P2_TEMPLATE: &str = r#"
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
const INPUTS: [&str; 2] = [
|
||||
"",
|
||||
include_str!("./input.txt"),
|
||||
];
|
||||
|
||||
pub fn run(input: &str) -> i64 {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in INPUTS.iter() {
|
||||
println!("answer = {}", run(input));
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn part2(b: &mut test::Bencher) {
|
||||
b.iter(|| {
|
||||
let v = run(INPUTS[1]);
|
||||
test::black_box(v);
|
||||
});
|
||||
}"#;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
assert!(args.len() == 2);
|
||||
|
||||
let day: u8 = args[1].parse::<u8>().expect("error in parsing day");
|
||||
assert!((1..=25).contains(&day));
|
||||
|
||||
let request = ureq::get(&format!("https://adventofcode.com/2024/day/{}/input", day))
|
||||
.set("Cookie", AOC_TOKEN);
|
||||
println!("{:?}", request);
|
||||
|
||||
let response = match request.call() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
eprintln!("error in fetching input for day {}: {}", day, e);
|
||||
|
||||
if let Some(v) = e.into_response() {
|
||||
eprintln!(
|
||||
"error in fetching input for day {} status code = {} response = {:?}",
|
||||
day,
|
||||
v.status(),
|
||||
v.into_string()
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Create directory
|
||||
let path = format!("./src/day{}", day);
|
||||
if !Path::new(&path).exists() {
|
||||
fs::create_dir(&path).expect("error in creating directory");
|
||||
}
|
||||
|
||||
// Create the file
|
||||
let mut file =
|
||||
File::create(format!("./{}/input.txt", path)).expect("error in creating file");
|
||||
|
||||
// Copy contents to file
|
||||
io::copy(&mut response.into_reader(), &mut file).expect("error in writing to file");
|
||||
|
||||
// Generate 1.rs and 2.rs from templates
|
||||
fs::write(format!("./{}/1.rs", path), P1_TEMPLATE).expect("error in generating template 1.rs");
|
||||
fs::write(format!("./{}/2.rs", path), P2_TEMPLATE).expect("error in generating template 1.rs");
|
||||
|
||||
println!("Saved input for day {}", day);
|
||||
}
|
||||
Reference in New Issue
Block a user