Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Alpha Chen | d60889b13c | 8 years ago |
Alpha Chen | 3ff87286de | 8 years ago |
@ -1 +0,0 @@
|
||||
**/rust/target
|
@ -1,3 +0,0 @@
|
||||
[submodule "2022/bqn/lib"]
|
||||
path = 2022/bqn/lib
|
||||
url = https://github.com/mlochbaum/bqn-libs.git
|
@ -1,145 +1,146 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
[root]
|
||||
name = "advent_of_code"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"permutohedron 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-crypto 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "advapi32-sys"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "307c92332867e586720c0222ee9d890bbe8431711efed8a1b06bc5b40fc66bd7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "advent_of_code"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"permutohedron",
|
||||
"regex",
|
||||
"rust-crypto",
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca10e3e1f1c8278047da19b94dc17c4397861150d5fbcea052eedb1d9847d356"
|
||||
dependencies = [
|
||||
"advapi32-sys",
|
||||
"winapi",
|
||||
"advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b5e7edf375e6d26243bde172f1d5ed1446f4a766fc9b7006e1fd27258243f1"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"winapi-build",
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10569e57695cc2c91ca4214357907649c9e242dc822c9ae623d0e0b0d68aa4d9"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
dependencies = [
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "permutohedron"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abf78a1e8b52782de92fc4f361362a62bcf5fd5718b5432b48cb381485740b83"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eee40bdf3d293e1648490ab47e5471d9ab3e455e6b0bd48e558c454be4a015e"
|
||||
dependencies = [
|
||||
"advapi32-sys",
|
||||
"libc 0.2.4",
|
||||
"winapi",
|
||||
"advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.5"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"aho-corasick 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.26"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
|
||||
|
||||
[[package]]
|
||||
name = "rust-crypto"
|
||||
version = "0.2.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8672a8eb8db93d0938972e391159ba66912b415285ee5cf0ebe732df9e53b70"
|
||||
dependencies = [
|
||||
"gcc",
|
||||
"libc 0.1.12",
|
||||
"rand",
|
||||
"rustc-serialize",
|
||||
"time",
|
||||
"gcc 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a48546a64cae47d06885e9bccadb99d0547d877a94c5167fa451ea33a484456"
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c4aeaa1c95974f5763c3a5ac0db95a19793589bcea5d22e161b5587e3aad029"
|
||||
dependencies = [
|
||||
"kernel32-sys",
|
||||
"libc 0.2.4",
|
||||
"winapi",
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc3583688b861fcd83c2823d37cf2cd2446c233dd7ba3f97884d1a7302817537"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
||||
[metadata]
|
||||
"checksum advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "307c92332867e586720c0222ee9d890bbe8431711efed8a1b06bc5b40fc66bd7"
|
||||
"checksum aho-corasick 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f36f237c490deb976b38aca6369182dceb5a7af249aabf41c0ba5a964bac5ed"
|
||||
"checksum gcc 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ca10e3e1f1c8278047da19b94dc17c4397861150d5fbcea052eedb1d9847d356"
|
||||
"checksum kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b5e7edf375e6d26243bde172f1d5ed1446f4a766fc9b7006e1fd27258243f1"
|
||||
"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
|
||||
"checksum libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "10569e57695cc2c91ca4214357907649c9e242dc822c9ae623d0e0b0d68aa4d9"
|
||||
"checksum memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dc66b0957bf6ae6590681ceac49b0df16823d43037d49aaf2ee658d483af30ab"
|
||||
"checksum permutohedron 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abf78a1e8b52782de92fc4f361362a62bcf5fd5718b5432b48cb381485740b83"
|
||||
"checksum rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5eee40bdf3d293e1648490ab47e5471d9ab3e455e6b0bd48e558c454be4a015e"
|
||||
"checksum regex 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e0940ad6bf8abf79e3210809a6a49e199fc8e00b7deafc0d9394157f56f5401e"
|
||||
"checksum regex-syntax 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fcf1e805b0a23c845be2a303136d840a1511284727bc1f1fc32d079552ef901f"
|
||||
"checksum rust-crypto 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b8672a8eb8db93d0938972e391159ba66912b415285ee5cf0ebe732df9e53b70"
|
||||
"checksum rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "1a48546a64cae47d06885e9bccadb99d0547d877a94c5167fa451ea33a484456"
|
||||
"checksum time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "8c4aeaa1c95974f5763c3a5ac0db95a19793589bcea5d22e161b5587e3aad029"
|
||||
"checksum winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dc3583688b861fcd83c2823d37cf2cd2446c233dd7ba3f97884d1a7302817537"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
@ -1,4 +0,0 @@
|
||||
The first floor contains a promethium generator and a promethium-compatible microchip.
|
||||
The second floor contains a cobalt generator, a curium generator, a ruthenium generator, and a plutonium generator.
|
||||
The third floor contains a cobalt-compatible microchip, a curium-compatible microchip, a ruthenium-compatible microchip, and a plutonium-compatible microchip.
|
||||
The fourth floor contains nothing relevant.
|
@ -1,173 +1,201 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
[root]
|
||||
name = "advent_of_code_2016"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error-chain",
|
||||
"regex",
|
||||
"rust-crypto",
|
||||
"error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
|
||||
dependencies = [
|
||||
"backtrace-sys",
|
||||
"cfg-if",
|
||||
"dbghelp-sys",
|
||||
"kernel32-sys",
|
||||
"libc",
|
||||
"rustc-demangle",
|
||||
"winapi",
|
||||
"backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3602e8d8c43336088a8505fa55cae2b3884a9be29440863a11528a42f46f6bb7"
|
||||
dependencies = [
|
||||
"gcc",
|
||||
"libc",
|
||||
"gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
|
||||
|
||||
[[package]]
|
||||
name = "dbghelp-sys"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"winapi-build",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "error-chain"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd681735364a04cd5d69f01a4f6768e70473941f8d86d8c224faf6955a75799"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "771e4a97ff6f237cf0f7d5f5102f6e28bb9743814b6198d684da5c58b76c11e0"
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"winapi-build",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
dependencies = [
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.5"
|
||||
version = "0.1.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.26"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
|
||||
|
||||
[[package]]
|
||||
name = "rust-crypto"
|
||||
version = "0.2.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
|
||||
dependencies = [
|
||||
"gcc",
|
||||
"libc",
|
||||
"rand",
|
||||
"rustc-serialize",
|
||||
"time",
|
||||
"gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bff9fc1c79f2dec76b253273d07682e94a978bd8f132ded071188122b2af9818"
|
||||
|
||||
[[package]]
|
||||
name = "thread-id"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
|
||||
dependencies = [
|
||||
"kernel32-sys",
|
||||
"libc",
|
||||
"winapi",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
|
||||
"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
|
||||
"checksum backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3602e8d8c43336088a8505fa55cae2b3884a9be29440863a11528a42f46f6bb7"
|
||||
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
|
||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||
"checksum error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cd681735364a04cd5d69f01a4f6768e70473941f8d86d8c224faf6955a75799"
|
||||
"checksum gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)" = "771e4a97ff6f237cf0f7d5f5102f6e28bb9743814b6198d684da5c58b76c11e0"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
|
||||
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
|
||||
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
|
||||
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
|
||||
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
|
||||
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
|
||||
"checksum rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc"
|
||||
"checksum rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "bff9fc1c79f2dec76b253273d07682e94a978bd8f132ded071188122b2af9818"
|
||||
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
|
||||
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
|
||||
"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
|
||||
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
@ -1,284 +0,0 @@
|
||||
use regex;
|
||||
use std::convert::TryFrom;
|
||||
use std::str;
|
||||
use errors::*;
|
||||
|
||||
// You come upon a column of four floors that have been entirely sealed off from the rest of the
|
||||
// building except for a small dedicated lobby. There are some radiation warnings and a big sign
|
||||
// which reads "Radioisotope Testing Facility".
|
||||
|
||||
struct Facility {
|
||||
floors: Vec<Floor>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct Floor {
|
||||
items: Vec<Item>,
|
||||
}
|
||||
|
||||
impl Floor {
|
||||
fn generators(&self) -> Vec<String> {
|
||||
self.items.iter().map(|item| {
|
||||
match *item {
|
||||
Item::Generator(ref s) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
}).flat_map(|x| x).cloned().collect()
|
||||
}
|
||||
|
||||
fn microchips(&self) -> Vec<String> {
|
||||
self.items.iter().map(|item| {
|
||||
match *item {
|
||||
Item::Microchip(ref s) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
}).flat_map(|x| x).cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generators_and_microchips() {
|
||||
let items = vec![
|
||||
Item::Generator("a".into()),
|
||||
Item::Microchip("b".into()),
|
||||
];
|
||||
let floor = Floor{items};
|
||||
assert_eq!(floor.generators(), vec!["a".to_string()]);
|
||||
assert_eq!(floor.microchips(), vec!["b".to_string()]);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum Item {
|
||||
Generator(String),
|
||||
Microchip(String),
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<regex::Captures<'a>> for Item {
|
||||
type Err = Error;
|
||||
fn try_from(c: regex::Captures) -> Result<Item> {
|
||||
let element = c.name("element").ok_or("missing element name")?;
|
||||
let itemtype = c.name("itemtype").ok_or("missing item type")?;
|
||||
match itemtype {
|
||||
"generator" => { Ok(Item::Generator(element.into())) },
|
||||
"microchip" => { Ok(Item::Microchip(element.into())) },
|
||||
_ => { Err(format!("invalid item type: '{}", itemtype).into()) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// According to the project status board, this facility is currently being used to experiment with
|
||||
// Radioisotope Thermoelectric Generators (RTGs, or simply "generators") that are designed to be
|
||||
// paired with specially-constructed microchips. Basically, an RTG is a highly radioactive rock
|
||||
// that generates electricity through heat.
|
||||
//
|
||||
// The experimental RTGs have poor radiation containment, so they're dangerously radioactive. The
|
||||
// chips are prototypes and don't have normal radiation shielding, but they do have the ability to
|
||||
// generate an electromagnetic radiation shield when powered. Unfortunately, they can only be
|
||||
// powered by their corresponding RTG. An RTG powering a microchip is still dangerous to other
|
||||
// microchips.
|
||||
//
|
||||
// In other words, if a chip is ever left in the same area as another RTG, and it's not connected
|
||||
// to its own RTG, the chip will be fried. Therefore, it is assumed that you will follow procedure
|
||||
// and keep chips connected to their corresponding RTG when they're in the same room, and away from
|
||||
// other RTGs otherwise.
|
||||
|
||||
impl Floor {
|
||||
fn is_safe(&self) -> bool {
|
||||
if self.generators().is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let generators = self.generators();
|
||||
let microchips = self.microchips();
|
||||
let unpaired_chips = microchips.iter().filter(|microchip| {
|
||||
!generators.contains(µchip)
|
||||
});
|
||||
unpaired_chips.count() == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_safe() {
|
||||
assert!(Floor{items: Vec::new()}.is_safe());
|
||||
assert!(Floor{items: vec![Item::Generator("".into())]}.is_safe());
|
||||
assert!(Floor{items: vec![Item::Microchip("a".into())]}.is_safe());
|
||||
|
||||
let items = vec![Item::Generator("a".into()), Item::Microchip("b".into())];
|
||||
assert!(!Floor{items}.is_safe());
|
||||
|
||||
let items = vec![
|
||||
Item::Generator("a".into()),
|
||||
Item::Microchip("a".into()),
|
||||
Item::Generator("b".into()),
|
||||
];
|
||||
assert!(Floor{items}.is_safe());
|
||||
}
|
||||
|
||||
// These microchips sound very interesting and useful to your current activities, and you'd like to
|
||||
// try to retrieve them. The fourth floor of the facility has an assembling machine which can make
|
||||
// a self-contained, shielded computer for you to take with you - that is, if you can bring it all
|
||||
// of the RTGs and microchips.
|
||||
//
|
||||
// Within the radiation-shielded part of the facility (in which it's safe to have these
|
||||
// pre-assembly RTGs), there is an elevator that can move between the four floors. Its capacity
|
||||
// rating means it can carry at most yourself and two RTGs or microchips in any combination.
|
||||
// (They're rigged to some heavy diagnostic equipment - the assembling machine will detach it for
|
||||
// you.) As a security measure, the elevator will only function if it contains at least one RTG or
|
||||
// microchip. The elevator always stops on each floor to recharge, and this takes long enough that
|
||||
// the items within it and the items on that floor can irradiate each other. (You can prevent this
|
||||
// if a Microchip and its Generator end up on the same floor in this way, as they can be connected
|
||||
// while the elevator is recharging.)
|
||||
//
|
||||
// You make some notes of the locations of each component of interest (your puzzle input). Before
|
||||
// you don a hazmat suit and start moving things around, you'd like to have an idea of what you
|
||||
// need to do.
|
||||
//
|
||||
// When you enter the containment area, you and the elevator will start on the first floor.
|
||||
//
|
||||
// For example, suppose the isolated area has the following arrangement:
|
||||
//
|
||||
// The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip.
|
||||
// The second floor contains a hydrogen generator.
|
||||
// The third floor contains a lithium generator.
|
||||
// The fourth floor contains nothing relevant.
|
||||
// As a diagram (F# for a Floor number, E for Elevator, H for Hydrogen, L for Lithium, M for Microchip, and G for Generator), the initial state looks like this:
|
||||
|
||||
impl str::FromStr for Facility {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(input: &str) -> Result<Self> {
|
||||
let floors = input.lines()
|
||||
.map(|line| line.parse::<Floor>())
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
Ok(Facility{floors})
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_facility_from_str() {
|
||||
let input = "The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip.
|
||||
The second floor contains a hydrogen generator.
|
||||
The third floor contains a lithium generator.
|
||||
The fourth floor contains nothing relevant.";
|
||||
let facility: Facility = input.parse().unwrap();
|
||||
assert_eq!(facility.floors.len(), 4);
|
||||
assert_eq!(facility.floors[1], Floor{items: vec![Item::Generator("hydrogen".into())]});
|
||||
}
|
||||
|
||||
impl str::FromStr for Floor {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(input: &str) -> Result<Self> {
|
||||
// Ok(Floor{items: Vec::new()})
|
||||
let re = regex::Regex::new(r"(?P<element>\w+)(-compatible)? (?P<itemtype>generator|microchip)").unwrap();
|
||||
re.captures_iter(input)
|
||||
.map(|captures| Item::try_from(captures))
|
||||
.collect::<Result<Vec<_>>>()
|
||||
.map(|items| Floor{items} )
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_floor_from_str() {
|
||||
let input = "The first floor contains a hydrogen-compatible microchip and \
|
||||
a lithium-compatible microchip.";
|
||||
let floor: Floor = input.parse().unwrap();
|
||||
assert_eq!(floor.items.len(), 2);
|
||||
assert!(floor.items.contains(&Item::Microchip("hydrogen".into())));
|
||||
assert!(floor.items.contains(&Item::Microchip("lithium".into())));
|
||||
|
||||
let input = "The first floor contains a hydrogen-compatible microchip and \
|
||||
a lithium generator.";
|
||||
let floor: Floor = input.parse().unwrap();
|
||||
assert_eq!(floor.items.len(), 2);
|
||||
assert!(floor.items.contains(&Item::Microchip("hydrogen".into())));
|
||||
assert!(floor.items.contains(&Item::Generator("lithium".into())));
|
||||
}
|
||||
|
||||
// F4 . . . . .
|
||||
// F3 . . . LG .
|
||||
// F2 . HG . . .
|
||||
// F1 E . HM . LM
|
||||
// Then, to get everything up to the assembling machine on the fourth floor, the following steps could be taken:
|
||||
//
|
||||
// Bring the Hydrogen-compatible Microchip to the second floor, which is safe because it can get power from the Hydrogen Generator:
|
||||
//
|
||||
// F4 . . . . .
|
||||
// F3 . . . LG .
|
||||
// F2 E HG HM . .
|
||||
// F1 . . . . LM
|
||||
// Bring both Hydrogen-related items to the third floor, which is safe because the Hydrogen-compatible microchip is getting power from its generator:
|
||||
//
|
||||
// F4 . . . . .
|
||||
// F3 E HG HM LG .
|
||||
// F2 . . . . .
|
||||
// F1 . . . . LM
|
||||
// Leave the Hydrogen Generator on floor three, but bring the Hydrogen-compatible Microchip back down with you so you can still use the elevator:
|
||||
//
|
||||
// F4 . . . . .
|
||||
// F3 . HG . LG .
|
||||
// F2 E . HM . .
|
||||
// F1 . . . . LM
|
||||
// At the first floor, grab the Lithium-compatible Microchip, which is safe because Microchips don't affect each other:
|
||||
//
|
||||
// F4 . . . . .
|
||||
// F3 . HG . LG .
|
||||
// F2 . . . . .
|
||||
// F1 E . HM . LM
|
||||
// Bring both Microchips up one floor, where there is nothing to fry them:
|
||||
//
|
||||
// F4 . . . . .
|
||||
// F3 . HG . LG .
|
||||
// F2 E . HM . LM
|
||||
// F1 . . . . .
|
||||
// Bring both Microchips up again to floor three, where they can be temporarily connected to their corresponding generators while the elevator recharges, preventing either of them from being fried:
|
||||
//
|
||||
// F4 . . . . .
|
||||
// F3 E HG HM LG LM
|
||||
// F2 . . . . .
|
||||
// F1 . . . . .
|
||||
// Bring both Microchips to the fourth floor:
|
||||
//
|
||||
// F4 E . HM . LM
|
||||
// F3 . HG . LG .
|
||||
// F2 . . . . .
|
||||
// F1 . . . . .
|
||||
// Leave the Lithium-compatible microchip on the fourth floor, but bring the Hydrogen-compatible one so you can still use the elevator; this is safe because although the Lithium Generator is on the destination floor, you can connect Hydrogen-compatible microchip to the Hydrogen Generator there:
|
||||
//
|
||||
// F4 . . . . LM
|
||||
// F3 E HG HM LG .
|
||||
// F2 . . . . .
|
||||
// F1 . . . . .
|
||||
// Bring both Generators up to the fourth floor, which is safe because you can connect the Lithium-compatible Microchip to the Lithium Generator upon arrival:
|
||||
//
|
||||
// F4 E HG . LG LM
|
||||
// F3 . . HM . .
|
||||
// F2 . . . . .
|
||||
// F1 . . . . .
|
||||
// Bring the Lithium Microchip with you to the third floor so you can use the elevator:
|
||||
//
|
||||
// F4 . HG . LG .
|
||||
// F3 E . HM . LM
|
||||
// F2 . . . . .
|
||||
// F1 . . . . .
|
||||
// Bring both Microchips to the fourth floor:
|
||||
//
|
||||
// F4 E HG HM LG LM
|
||||
// F3 . . . . .
|
||||
// F2 . . . . .
|
||||
// F1 . . . . .
|
||||
// In this arrangement, it takes 11 steps to collect all of the objects at the fourth floor for assembly. (Each elevator stop counts as one step, even if nothing is added to or removed from it.)
|
||||
//
|
||||
// In your situation, what is the minimum number of steps required to bring all of the objects to the fourth floor?
|
||||
|
||||
pub fn solve(input: &str) -> Result<String> {
|
||||
return Ok("".into())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve() {
|
||||
let input = "The first floor contains a hydrogen-compatible microchip and a lithium-compatible microchip.
|
||||
The second floor contains a hydrogen generator.
|
||||
The third floor contains a lithium generator.
|
||||
The fourth floor contains nothing relevant.";
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
3893445835429722678558456317563893861752455542588369533636585887178232467588827193173595918648538852463974393264428538856739259399322741844613957229674619566966921656443476317729968764183945899765294481327998956154956571467872487576314549468261122281384513266834769436913544431258253346374641589492728885222652146158261225296144835682556133922436438188211288458692217737145834468534829945993366314375465767468939773939978272968388546791547526366348163672162245585168892858977723516752284597322176349412485116173844733679871253985762643852151748396593275274582481295864991886985988427966155944392352248314629138972358467959614279553511247863869663526823326467571462371663396188951696286916979923587358992127741723727623235238531991996999181976664226274715591531566495345212849683589582225465555847312199122268773923175183128124556249916458878785361322713513153175157855597289482439449732469754748544437553251412476225415932478849961897299721228198262823515159848941742786272262236888514421279147329383465929358896761449135917829473321834267122759371247338155787774952626616791265889922959653887288735233291968146648533754958199821789499914763279869931218136266492627818972334549751282191883558361871277375851259751294611921756927694394977764633932938573132221389861617195291742156362494769521829599476753198422283287735888197584327719697758442462886311961723849326959213928195182293316227334998926839139915138472514686689887874559367524254175582135318545912361877139367538434683933333264146289842238921989275112323681356256979576948644489986951538689949884787173194457523474156229389465725473817651516136514446513436419126533875125645855223921197481833434658264655912731133356464193251635637423222227273192628825165993827511625956856754776849919858414375874943572889154281862749595896438581889424559988914658387293414662361364793844213298677236787998677166743945812899526292132465751582925131262933636228593134861363493849168168765261647652342891576445292462341171477487223253795935253493869317616741963486473
|
||||
|
@ -1,17 +0,0 @@
|
||||
157 564 120 495 194 520 510 618 244 443 471 473 612 149 506 138
|
||||
1469 670 47 604 1500 238 1304 1426 54 749 1218 1409 60 51 1436 598
|
||||
578 184 2760 3057 994 167 2149 191 2913 2404 213 1025 1815 588 2421 3138
|
||||
935 850 726 155 178 170 275 791 1028 75 781 138 176 621 773 688
|
||||
212 977 297 645 229 194 207 640 804 509 833 726 197 825 242 743
|
||||
131 43 324 319 64 376 231 146 382 162 464 314 178 353 123 446
|
||||
551 121 127 155 1197 288 1412 1285 557 137 145 1651 1549 1217 681 1649
|
||||
1723 1789 5525 4890 3368 188 3369 4842 3259 2502 4825 163 146 2941 126 5594
|
||||
311 2420 185 211 2659 2568 2461 231 2599 1369 821 506 2227 180 220 1372
|
||||
197 4490 141 249 3615 3314 789 4407 169 352 4383 5070 5173 3115 132 3513
|
||||
4228 2875 3717 504 114 2679 165 3568 3002 116 756 151 4027 261 4813 2760
|
||||
651 3194 2975 2591 1019 835 3007 248 3028 1382 282 3242 296 270 3224 3304
|
||||
1858 1650 1720 1848 95 313 500 1776 207 1186 72 259 281 1620 79 77
|
||||
3841 3217 440 3481 3643 940 3794 4536 1994 4040 3527 202 193 1961 230 217
|
||||
2837 2747 2856 426 72 78 2361 96 2784 2780 98 2041 2444 1267 2167 2480
|
||||
411 178 4263 4690 3653 162 3201 4702 3129 2685 3716 147 3790 4888 79 165
|
||||
|
@ -1 +0,0 @@
|
||||
361527
|
@ -1,513 +0,0 @@
|
||||
oaoe rxeq vssdqtu xrk cjv yaoqp loo
|
||||
mveua dogbam szydvri hyzk lbega abzqw xwjn wniug kwbre
|
||||
npaoy uivpxwd oynpa rcdk uixpvdw
|
||||
yserir iikzcm ieuroca iuwcfov rvb giti crdpdcv mxpps
|
||||
spyuhgo lucasl ucllsa bymnjig yflbv nxitmlf
|
||||
xlxyhwz xla mpye fvjegwg fezlfrt inetrh vhg xpvstx ydhvq
|
||||
xgue cvtmh myg ontvvyw ygm oqzrdrw
|
||||
srdfsjf dli kccb kauk kauk apa doefc cdffkhh cdffkhh
|
||||
msizb elqiov lqn epamk onmnlst baawab ncafwaf jrataml iyzhy svycuec
|
||||
wdzqpcn dkgdumv wdzqpcn qxdmwib cjsigi bgcihgh fmua
|
||||
kpvbzf kpvbzf svyq flg shwtgp
|
||||
ywrynt cesjtgk hsvitr brpiul lxgvvrl cesjtgk cesjtgk xuflpfn
|
||||
tik mrpht gkv unqp wypscc vmwiu ldrigk okbc wztc
|
||||
zpy kyzvijv bilpf etbrgk edza vuz jzgn
|
||||
yoa rgppd kzpopd cffjk murcb jmt raace iwt
|
||||
aobgkja drc ztkd qskxxbv lve lev rhhoqex bmd eolf ybxjr yiiut
|
||||
zhjcfms fpabnu aozp delsc mge yqi eovg pwefafe
|
||||
gukf iys qztqxz xhsssz pfqq slg jdbp pfqq yabztc asow ygh
|
||||
fmr ijgmjrc zbhwsmx ylgccz ycydcyx hjjset
|
||||
zybsr iqisbs hffmij ikby lwufzvg gwd
|
||||
ruk rku kur ydurp upmebe
|
||||
baqide zdijcf ezqfe ovrldez delzrov szimd irmk busim ppv zepqk mlwpl
|
||||
bxlvp dxumme byaada cgyn diz
|
||||
xlxr jhili bmcke nkl vuhqsn lxzb zmyuxgk qcqr tyxe
|
||||
wvth gyerrd yewrta kgri yewrta
|
||||
fall jpyuusu lffybb ivmtmzx alfl yjupusu
|
||||
lzvcg xwnt mjyiklh vwlz qejj mjyiklh dmcwq qejj
|
||||
vgutb smc yvnsbgd bxmjd qmhia krxz luhgg emnrp
|
||||
uuvhtia aiuutvh brstbr tsrbrb
|
||||
howd japlq lhk qtsfdq htfufj qkyywy anxxxqw jtmryw cdtajh
|
||||
pksswl jprpccl wpklss yyrbo
|
||||
furp pfru bftha iekamfc bixwmr sslovex
|
||||
nrqobo hyb byh hby
|
||||
mugix kzlbtuq hmju ysstccs hmju btsuh
|
||||
hsrlhw zilj jtvto zilj fjq
|
||||
lvol xic hqqdeo gmsug yqe wue vhmrq buj juv wxexdot
|
||||
lqeybb odpv mttm bxqy vqbqr ylbei wyjcxco urufsuz kyq
|
||||
youbiz kvrea xsfcp zaz zybiou earvk qpf
|
||||
bowsref ooobtic apiushu kplpyza
|
||||
hxfhoyy ybbe ceebt recegzz ftnlv ukaf gpvx opvd lqnvk ybbe ygnwa
|
||||
jpbgc aahm aahm aahm
|
||||
qyvheb xyb elt oaksuj dvgpmel poiowc ykgbgpz dxpit ytg
|
||||
vgsv yrjo vjss kyfvim izwo yrjo vgsv
|
||||
hkk xmqx crlki dtp nuh okef okef xomktit viia nuh tplhrx
|
||||
bmkjclx sbwe bwes bsbnqd nqbsbd
|
||||
gfwrl vocwln hsuxkz zpclb qprrvlt bkcluvs pqy sxucrla npb fensz
|
||||
adjklj nyr btmav roxv jrri vqfnis gzsab ogskmaj
|
||||
bvjm fer ztgfx mtp vvhps hptzrar wpy yhvmh qklfwpf edgrdts vmhhy
|
||||
lngra nrlga xokqu mgq
|
||||
mksdk bkkbfsq hazlai nixee vyxh hpvebeg jujoqe wkw mzpxixm
|
||||
kxrkkx qivtt xsm xsm rqvgdjl jilosjs rji
|
||||
xiqga rez igqxa odiilj izoiwf xgqia
|
||||
aepioo krcr aepioo jhigtx krcr qubkv jgo zybyvy wbsguz
|
||||
ntyscmf duwvvb kga xvaypk sfjlg daguzm kqat otj zmnki
|
||||
ggxaery jazo ggxaery zevobo zux wfnd wbyd hmhmo oaakvab jsimsw
|
||||
vqdnvgy qiex yqeweds yqvdvgn iqcukgc bvrc osi
|
||||
esjzak krwe ivbri hnbah iuvb begybsk ctxmlym gjqi lcscum
|
||||
hyxdilx tsv evckza bdbscwj jlihiqk dciuj hamd dqsm ydihxxl
|
||||
lurtwhx ygwf pwhj whxtrlu zfvywxr gcrl zvl wienpqb woto
|
||||
mfaektr ocvho ukfx ukfx old daqwotk pybjtiz kumkiq tmql lqou tmql
|
||||
guwy ceqsyvs svteymr nrovwz tesymrv rmsveyt
|
||||
pigilsu zpyiohn zpyiohn xzl pryi zpyiohn ohdz
|
||||
pziqfg hhrzdr wxl zpqigf
|
||||
psnmnxz oed edo deo
|
||||
tkdp tkdp auozn tfyo wmp jtp wjyskeh dag ojdvw gbptp deiqi
|
||||
xkr nmsbk mreiv occcvva eca bupc gvaoopu jdhr flh ptgdumz mks
|
||||
dlevn vmwzws dlevn dlevn
|
||||
qwx qnuqgc rtzc yvym sft wxq fhv fts nyvrfxz ydjvcq tnwz
|
||||
debkk pullndo ezaibw ldnloup nllupdo wiiw nij
|
||||
hng rpd aud epq opzjh jnzge
|
||||
rmtauf nwinyl nwnliy pjzahm lywnin
|
||||
cgiv omva fos irse uytiqu iqjo riplx capa dhdl echbyjw cutfam
|
||||
fqrqmi jfrj zllh gfhhq fqrqmi mmyqv
|
||||
yoepae uabuxlz jzqy yoepae sxena jzqy
|
||||
bfr jlrycal ndg xejwjdp khwg wckevqb tud xljzem ntfbazf lkr
|
||||
aomdwt sji sij jsi wlsvvva kgjzqj whhf
|
||||
ogorbil orlgiob iorlbog xapwiqs jxb
|
||||
tnn sxgdikv ynick ynick aumwthl rwhx eqxd jdbzyk kbil pmnifp dpeips
|
||||
vzeoilq son olqvh jawmny
|
||||
vsifce kcighpn mubl zkgwm
|
||||
ncagxs ilohd lyq oqhjf nfeij qmtvf qpru tfmtaj
|
||||
pfjkcpr dqrfde efqddr edqdrf
|
||||
wdyygax hscx ptmro wqko ecnfkhj ywui
|
||||
gdv nrnrzdc vyq vyq vesrj vyq jwxg
|
||||
oqhrr daoew zpoduh zwmoss nfkh vubf xza kju rhrpt fvsc
|
||||
oqp ppyq swvin mut uacwd swivn ucdaw icfj ldcujh cejl
|
||||
dar bqp ajdhuej sxwt bqp tppexrh tppexrh
|
||||
sitplaj xnb ldopp mqd gwtk uhnvozu ljz dqm ylzy qltf gwtjksx
|
||||
eqkvncb jdp pahwje avhrer awb zqnwfhx zohmcz fitbyab
|
||||
xlnel gjzviy cndpuoj jvwxs qsd kwli quisju kyoix imzg
|
||||
czqjkk evyima ixpelbv eobpd wwuxxof pbxc dgj
|
||||
czsigs lbdaynp amsexn aemsxn easnmx rsitdzf
|
||||
xdpc xfbp lrjwlo ntnnob sbe bse
|
||||
suud fws zgn kvfimsi
|
||||
wnexa diexvky oemdq uasxzhq qxa kevyixd lpw unluohs
|
||||
ylruxt beqvn vbenq ogsov mvftu sovog gshtb qriaxko vthgfr jwj
|
||||
gmz wcjb cqjlb hijz qwuluuf xdpu jybdf ajiv xizwb
|
||||
fcxos spz idg rjb uhr ert bxia urh xfxp ixba bnvxy
|
||||
uxiie eixiu wgmwbj euiix qknyd wtaojk naeqfz qmhnulk uscgwxa
|
||||
qwyxd jno xelqd isdjht qxz dbwnr bfzhewu opxmkgj igfiuck
|
||||
ljpphwc ijzic pfsemsc mfedoxy pad wsk beqjpbj gbjr imce xumhr
|
||||
causc ogypj csacu pdokc itpgjl xfx nyt yytg srhrup bontz xbalwnj
|
||||
asohjj qer pfgwo qgdw wgdq
|
||||
gpzvyhh tsnx tyu kswlgb whju zkkpdm bmh hdov
|
||||
unux lhrn unux lhrn rxr
|
||||
epq ksew pqct jib pqebafk jib pyfjy gnu pqct
|
||||
anzbbs oyhm moyh mhyo
|
||||
dpk zael zael mxots zfcum
|
||||
aehljyc wrj lfhife xbss ztszba vlg eljycah ihffle coypll
|
||||
aoqedco bogk bogk aoqedco sanwwo
|
||||
udmbz yxe dft rzolgtp nwwjpti
|
||||
efu qcls rtx mestnqt pkh ciekj scrv uswd oroowx lcztvt
|
||||
urnwt uapni ood lzce
|
||||
zjiqxt jzqxti infgde xbmi kawilp kaipwl
|
||||
lsfn kxfw zgzdfq meqwql zpqqu otert
|
||||
taajsho gbeoguv bpi nxeuy
|
||||
dpoyzi rqlzx rqlzx udhuwjm qnu bnuma udhuwjm gfezx cbjpfp woir
|
||||
mjbv isni ixjtjue fwsk ncgwpn vqnmq pivz jbmv qoakqou argval dacvksc
|
||||
xxjcn amdgdhh iup hlk xxjcn elx
|
||||
gyhocay ofqosv nldfqay aqu dsrz lmekze bus lmekze gfoq lmekze vkor
|
||||
xidyqq bimvxu zrkg rpcdca ymg nmxkkqu gygcmp euemr
|
||||
gvd ywog ywog gvd hwjzzq
|
||||
byu ggpwrl lpexjcf hgy jee febgcae valcgc tcfwicu texqi lxfjepc qeraxcs
|
||||
lkjejsb eonp jtsbps pfvlos neop ikwnb avzxnk
|
||||
big pjgttfb eetr jobjfae odvl jheh tuz ystrh tuz tuz ige
|
||||
czubaxq czubaxq pbxgs jhuopn snmhhc qwmcka xdhxfuz jhuopn eummw
|
||||
xdwduc sqcano zopaco ozbbc bczob eas cbbzo
|
||||
oanpgo tiav bbssup ttzchih tpb xmfnqwa ghdx uepmz fzqbx
|
||||
ahha zsbdq jggv zfcjdp dzcfpj dkew jxmelbf jgsohj oghsjj
|
||||
awdy plulzw gdi jiiq lod rog mrf uihaz sebk guvb
|
||||
tlhwro sapaws ovlbbfh xctruk spzpzm latyy
|
||||
ligaot xfhacs jvk xbnpu yuanx yvvi gjek
|
||||
nfwuug nxccj dxpfvfq pvxcvy ayss lfwz wwole ewowl xceybeb efs zfwl
|
||||
lzowlql armo yrlgfg kbl vudahci yav evdi ofak ysmfjk upe
|
||||
qtmmqrl gxi rrhbi pydbopp yvevlq ovwwdrt mrppov lzzs yjyrxh srzo
|
||||
hytkyas wpuqvf fftiso fftiso
|
||||
yutais qjdbzo kewsi opy ysl zyvyoty wkp
|
||||
qtbad bxfjkwa stcdk lyre tabdq yler
|
||||
friyh ivp hshy ksmanzq mzdbbub ncbx mhzki friyh vyjk hshy
|
||||
ijeysr aww evn ttqvshg xkd zjy honvuqy zyj quvyohn gphcir
|
||||
okft smja fkto etb
|
||||
pbi zhyy kyjdho mqsuyic vegocmw gdkskg kgavjag dbqh wamfijz ktihnrg
|
||||
csqix soz ingra gvslgk
|
||||
ugxgzqt pdn hiynufo lpfabmi rmwj uhsqoo pmlzad ferdup guzqtxg voxd
|
||||
wkixiq vck vck sylv ttqcbwv ywqta vblz mhohx frv
|
||||
phns ozeghgm dfodkyv iyc psnh tedotyz xqz gqbyj ydttezo kxgju mvip
|
||||
chc jdjo pyq usyn vtrbnq ohnx dsxpdzn mgbc ysun mlalmu mqemyuw
|
||||
qrkosx wcwcv brvbwo nvxwg bvrwob
|
||||
bovt gpb rwm gpb pitttl rwm rvfzn tbo
|
||||
zczkb tmpwtj kackkx yzqkzso rsg ema ereo jptvfd jptvfd flbjfii
|
||||
fcdyetv jqelvx jlevqx cfvetyd
|
||||
dtyp wfh rxtpwr nolbro iozrs mnshu tkesvyk pkmkf
|
||||
lvecoh ohpb brlqwx immgqe dzfac bwlrxq hng clxmpd qodfyv
|
||||
sjbc dsoqk dqosk iyla lqzrsgi tjgt mfxshtd ztmc
|
||||
nxveg vmxf jwnub kujji aqkonjl xtit xitt
|
||||
jsft pmojruo vtvjox wimrlhj rezqi rnv hjnvdka
|
||||
vnl vzgltnl mry kkqf fekwjw knsrvt nct kqy infvys
|
||||
jbvm igq gvcl crry ylia nbqcq ouduen jklepay
|
||||
ermsf emrsf uksuvz zrnlun
|
||||
ecksf dkydasw wddasky pmfhi yltmedt bdovedg vfnyoze ufcki civrjs ohozga
|
||||
hvf gfqgc adbeykt jdz zmgonhi yua kifxyoy umsza ivnbvoc whnpi gtbinze
|
||||
nmy fsdu myn iiw
|
||||
yrkwca jkxc yrkwca yrkwca kxqtvqh
|
||||
ildxc taopx spykdz dzbpcxp wzgka cbyr xpvrzbk
|
||||
qqp axdmvo cmppp shx
|
||||
uldyu luyud uduly rgcmugh
|
||||
woc vjdpyq cwshqq tlh fzyuz cbwgp egpy sfw
|
||||
adyv cnrn bhaxvx ofdbkn yxrtir cnrn
|
||||
ycz ednsydc bqsdcpx adnq bydb tqy tqy vqzpy erdcnv
|
||||
mouv ouiy gld stdv gwr lxlfq gdl ldg
|
||||
gtx bbvr fxytm veofwp bvbr opefvw
|
||||
pcf scu ovso rawtjxs kzxgnuy ifcn tvibap
|
||||
ugcbob xkjgtx ugcbob ilkkx dikca wpxyq retqhlu ugcbob ylmt tigcmmm
|
||||
gmnde ool qeuwc ctux
|
||||
wpajwn gooy fedmjur pxiq xkyniyp xtgi eyfpc gjx
|
||||
uaivt kvfyn mpsya qxu kvnyf wvoeaz mbt fkyvn
|
||||
jth awxbprn kpcodj qxegybo
|
||||
sfvitld mdzczg pdptzm fmz himb eutpyi mgrde gubsta tfsldvi dfistvl
|
||||
piabmr fckmhrv twnlnka jyb selqflm iwcutk pvvann
|
||||
uxjfm rmleg ochuj ruiq aobxbb tpuusot uhwjojw tutopus
|
||||
dzj qdyxzk oan rtpz ona qkdzyx nkunr
|
||||
urjydh dfreifg tmbetd aakc vdr dkdkldw xgvtfsa ivv doadb axgvstf
|
||||
fdjhr ujgbj ulkm dfzh tmhx zfdh ckt ortg
|
||||
obe ywwge rgqmt cfcnyt atn fdkdrwz lmb zwpe sqfoc yllxs akdlsso
|
||||
ckhbu jfqhkml abenw ckp xvjy wsyhxox jzsz hqksq
|
||||
tjx zlh zgyrjpe bdorry uofh hgkzl ezixges kaxlkjw ztijupu hlgkz
|
||||
belj ipbygk dxe cqoyukw jnncelh ihvom qstbowu rocqsz ifiztlf fjrf nsit
|
||||
vyswalv reaqae hzoqyun lbci ibqfljz cgjflqf kos
|
||||
njrzfvu nxw nxw bdsgnxp
|
||||
gxlgn qrx nspbvl pzuob nggxl ipak wjr lggxn zas
|
||||
xkd sooef fsayaob tfsiyl
|
||||
ecldvh jugto ghfpbev xzlc
|
||||
rpyattn spb ajdplq eaorgi ackirxg knrap cobdeu qca pkp zkc
|
||||
bhh tczwffg bhh bhh hrjx jwyu gry kkgghnx
|
||||
zsav frsakbr bvzd gafr homzjw frsakbr yasgz homzjw kqa
|
||||
nbd mekhfif mekhfif keuoag nbd
|
||||
mzv vzm utuxhuf uufuhtx
|
||||
siy tdbii qtu yrxar ruubale yrxar lsvnr yqxq ruubale
|
||||
wstykuz fxnuszr tgmkw eovvrd ohheh raf degh hzoeun tiou wpt cqnw
|
||||
dzbyhrv vzlbvn ncoa xfglcye ncoa sykfps ghi
|
||||
lvi ilv xalhd ztejzb
|
||||
zaeu diz zaeu gtdjsz fmoxgju diz uvh
|
||||
zef lmkqlcs jnhgqww qsm fuatcq ixfa
|
||||
wgp gvu rpmxrjh yokepvc yokepvc lywdl bbvvbf yokepvc
|
||||
etjfs gjh tvmxb agovg yihn rmmh nue jfil
|
||||
zgcco slios jbfodb wpthe ydvit regizw regizw qosou slios cto jfz
|
||||
kmmq lnafaha ddos hrsjtxk zjch rfynx eovks
|
||||
ezeuzu jfpv oinrstv vsw naoz enrcy svw jfvp kgmfwf cfisxzo
|
||||
ljtv watps equf ljtv equf
|
||||
axijki zotolsi ryqujrm xmhug fhz lkgaw umzokxh ktr jsdsfat trk iosoztl
|
||||
vpqvvvn ydjz tcqc asffcxr rxb fyt vyham fys
|
||||
agxrcxl obcncq htod ved ozesk obcncq iwqmksk fsijtg iidyy lxu ozesk
|
||||
orsyqt otqrys pnaax qtrsoy
|
||||
oyisc chu ahdp abhbtry kjsqve tkpux tkpux sxzu sxzu
|
||||
wquw umlbwf mxzdbvb upp fopxe aub bau eritni punrpfc esnkyg
|
||||
jjlzy hozskgo jjlzy aiq jjlzy sgfyhsd
|
||||
ejghc ejghc ejghc igacslu
|
||||
unzmg fugzotb nxkdlds ewn hydj fbr iuly oiwwkbg scnozau sfi dsishk
|
||||
xuhjduu hfloaga xhuuduj mbavfkd nrnl ral erc mntev elpoqgq
|
||||
seydro onpi qjey skgkiox fbdgyt xhr rhvz dpsjcj tfzd spjdcj btqn
|
||||
difyxz cdm jlzsz oycm txyssd wckqshu ihya yjyb
|
||||
nmrhlif wcreso chtqfov qcftvoh lqp egd erc myep plq cjdh
|
||||
hcnwgkq kkrpxxj gwe xqgea kkrpxxj nxz mumqbw kwxhlz kkrpxxj otqy
|
||||
rxbioyf cszah mhu mhu mhu
|
||||
qpbrf jzink ojy idt nrjykzu
|
||||
omnrq kkol dex eaqdmej dnpaum ynnntw ddwewsh ztcenhc zqdrq hmi
|
||||
ngmqpu owmcuz gop gdbsfc nyott cdsflq ngmqpu
|
||||
srus lrexy aqgkqvm tiyjm
|
||||
wxa qopky glaaekv ykopq lna gyxvpx xwa hly dbvo
|
||||
vqf sqrqw phxn xiw gejyzip ugg gghhugl zyqae
|
||||
ylj cyolrx giim yrchuu yrchuu ylj
|
||||
rixa yfusuqn yfusuqn yfusuqn
|
||||
lpm gboakz ylyv gje yxu ahokxb ixwnpu hlcka cndhbbm nkmvts xdtqbc
|
||||
veul zjvz regtyp njwfpm
|
||||
pdlyjbn edawa xbcmyew gme yuk yek nfknzgn ehjz
|
||||
rcgun ulv ntbwnvg ptf givapv bych gmxxxf iajqpb gwh ipavvg
|
||||
qvpwk grbb gptdgrh sij vunv hsb uegsmt uos vkxdd
|
||||
iun aagzlj elqcq vkrk awl yyt dxfhkwq hbkeht
|
||||
cgf omofuz zddgwef iyosk hmou
|
||||
mvjorn zseyo wpfjlac kpxb dlh ggo zgxoso txzuy jfbmv lacjpwf vha
|
||||
twrsrw pxv iklzg rtfcl kfbcjix uyvowpa kfbcjix ofnsf adqm
|
||||
qvi ivr plxfrg awugjh fxbv ztlljk qvi jdkfts xyq jdkfts uqwgdr
|
||||
phs eimuuf lmxq wmp
|
||||
laf gmuowr rplgkh orentm whor lkrhgp mjwr zapz mdqtqyq ttkfkf
|
||||
fxk wdbl fjh ojqxp yvs fkx ysv ngksb
|
||||
oclyxqu tpajqun vvmj twin zclk
|
||||
srcwxs xiduxd tqpfc sbqybp sdtzw gizfn bpji kaolpuy
|
||||
pfkmk olmsaz uffy uyff
|
||||
crpazh pcrzha lew lkhcjij stfxq
|
||||
nkbb rnlo icnzg rnlo ejanu mofx ujblud
|
||||
abte xnjfo boz fnxzid nqfhifm jmnmsgh
|
||||
lvck nfll szdgrxc nghig szdgrxc oytahh cibk szdgrxc
|
||||
sduf jgv rrt spxw fdus
|
||||
gplutjv ufep fuzrnj tmko zzpj cpd mvtrzq
|
||||
ycdiav qvr ycdiav tjngezs mphk oykgcei ycdiav
|
||||
egbkscg ksgcbeg qmw jdbj
|
||||
kbgx otnfyc agouh iai lyhqd yzihyq ouagh snzhxa xyxrgz
|
||||
kdpqljx rin dlxms ukdzedc duezdkc ikgplm ffk vdmie qziajdf ftfwl
|
||||
prrzhj okffaot tlrxpjd aquc dbonaef enfdoab nwbtuh
|
||||
vyzf ijo cdhek bvlgxt kvldmp kvldmp vfvg
|
||||
zhijgyb yfkkal utb brew vfj ztiftq
|
||||
kodsuol ubnbdv iozwfum ayqxgnj qkp yiiv wbkgi psi wnfa epw
|
||||
iok mecjsp lccn nrb kobca wkznctc afjjlrt
|
||||
yrw yhsva hgx nxjfbb
|
||||
dbdj vef xjssylt hjlld bqbmx ihfmz uhij zoh opzrmy mfq
|
||||
wqhcq usyfuc wqhcq pmf aryq nhvtkh
|
||||
nkviwge snpfdza nadzfsp evvdnrl qled ekqs qumle myhky
|
||||
rgljws kjuk txgeein ajmph pjhdy pmvr upae yfh
|
||||
vmepn wekgc qfwybl midbac vmepn ddqmbu vmepn uhfccp yuh zzz gnx
|
||||
hyqv fud xdc bssziiv mwo xfrsn xqehs mwo
|
||||
djhr qxhfy vdjs ueoi mbmwa lkeumzd hyxfq krbyy ywvcstf wdkum xfqyh
|
||||
heprtex wgxpign lvm vlm ypswfxr ggxipwn hdszz blrv ppy
|
||||
fwalim sbqj zewxcaf qjsb cjgujwr uclxro wceu wmaifl rnd
|
||||
gmivd spncot jxeycn notspc nzb wie ceyjxn xlam
|
||||
cfujai hfvux hhtwe hfvux oputz oam
|
||||
gmwu xwthnkp xwthnkp mdxa xwthnkp
|
||||
shfqzi hdq uyyqjrd wczfvy wciko hdq nuywebl
|
||||
dtkq qnb uzmo ypxfja cekqe cekqe tnaibc uzmo pmtnb
|
||||
apdz exdze pop pvm pce hywvftx jrjezgd jkajq jcdjli
|
||||
satq czv cfhyca cshnyh cshnyh rcu cshnyh
|
||||
mxp ujq fmrnzxx xqv mxp
|
||||
nel whnnxak lwzlre mrxq kpo pko bsa gimtzwb
|
||||
okssco iuke vcnv okssco liawwc vcnv aztl
|
||||
kjvq rye eawplkw qzxt jkqv bxbfyv
|
||||
bphssax ylemih wsm jnpxce jgh repsyj ieypbz asx
|
||||
dwivit ptcwt qwectqk ttwcp bklpa ivditw
|
||||
ies knj zemmcto mczotme yanr kjdrwr mcry ndols
|
||||
dqzdpg adb ulsv ulsv qux ppmoru sjcn dpihqz
|
||||
akazkk kssdguo cgigktm indfh wwh kevuhv dclpjv kgtd ehjxous
|
||||
spogxy jyzhag qumd brk cbu akbpjxb spie
|
||||
jgyn cxbar axtkwh hktgcm cfsla xll rpauwl cgpziuh dyc brcxa
|
||||
dodey dysnjxe kzmyytw tzddd cnupwmv
|
||||
nqab whxkb kvc kvc jcjhywy mbbpfwj fxozlt whxkb qwz
|
||||
ihmif xhjc lmfk yjrsioo uvtd qvtqsgt dqd
|
||||
uvzedxd afli hkrigd lkzkzu ncki toam hoaefui
|
||||
zmvywjv jsjf nrbrgt mbs yog eexuo
|
||||
ukzab euwb qnkanyt lgeqf qefgl ewub
|
||||
zbol bolz ilncu ciunl
|
||||
hjryu qyl ajwju rplplr skbdsl xvto
|
||||
ojfotbx zvta jofxtbo ejjnhi jyeiz yzeij
|
||||
ivr pvrwef ivr zgnm jscgaoq hfjuzju cea hfjuzju ehszaz
|
||||
yikp gul ugbniac jehm fwqxb hqbhi hlfr iyuuf vacrao fwqxb
|
||||
plsjh efu napxwe jfxfjz efacqcp sythfxc sythfxc napxwe qncqc
|
||||
meuf rcjzf mhluz kbrk tzjrcn omoiprl khs oyzad yuzbz
|
||||
exvzzuc ckqfivf uoyidkg mwztyf wxtg uzrls gudioyk wfihpzn tdmwhf
|
||||
qoovwqm bldswvy xkb yqrcluk qyrclku cluqyrk qgakbv urclhse
|
||||
rmmymgg ytpqtuq ibt tmedibz tmbsdg ytpqtuq cxbnng
|
||||
qkyeo frjjht vkpt ikztq avzqon diw noqzva dvkhwdt
|
||||
opz usos kdqseyb cdxvve nahjc hbr rhsfm hcjna wnczls kky
|
||||
sgeml uyaoe ked utxab hxqa glems wbdo kzrjsq
|
||||
isp bmebt becira ixoz yeakj fmueu
|
||||
jrd qyys cik bmaief zxllza rsu swvodiv ivvdsow ikpvwaj jdr qte
|
||||
gzjjre tkjhdn lrqmvw gues ositymc xhfiutm
|
||||
kcnble oxoh zggvo zjz auub kunoj snil zggvo lgql
|
||||
yyfmd wbwmizs vmb clba bpzzjz nlt wgukoe hedlp osxz
|
||||
skic mgcr chkj eiiy kdhch gcanziz dpecug fccp
|
||||
jhnejy akpwbj mhrunvm wjzwyhe lwxostl gfe niuhj iuf bewur
|
||||
nuursk gehzvck szm fllr bfaq ijpjp gehzvck bfaq
|
||||
ecx etrsadp lyekp lxf flx tadreps
|
||||
gbo wzkner hky ggoqu
|
||||
yiitvf tyvifi xpnbk iiytfv
|
||||
okpjxyq mmxcha pujgv ltgfdk wpporh bfle tuupth ukyyjgv vlnwhz
|
||||
phbs qtpolnh udito ukx kjqsi jbwf sgkkwgm udito mwwb wihg
|
||||
mces dhc qccy sxyilmb qmki dyqnr qsh aigaemz oofdw hbifiz
|
||||
yyben jjklnz whwswg tox vgytp noijcv jjsa ybney eyrvg htjl vxli
|
||||
detb tus rloz zymvmg zpe
|
||||
usvkehi kxgvo rna scnaljd jmowud ipfkkf rxvpie nxysvj pvquagf fjhsvef
|
||||
ytosun puwdoix oyc qdufuw ysunot
|
||||
htw biy htw oxot oxot
|
||||
xgzi nbq lxxtmt nbq lxxtmt fnzmmno
|
||||
lko bdbj kcqvc torg enbfbj sbooco afjbclm dendwq
|
||||
cgih ikmfn lyhzhxd ubq ixrori tofbo
|
||||
glfhfzs gihsccj yic mlci slne
|
||||
wdiu lhl hdlhzo voo yhqckcy axnz yqyi fyss qhvtsbc
|
||||
aotbk zfokegh uax myhehay terwus hmzic fdwojh wjuwlp
|
||||
ucbiex eigq qqe ifqw sxakwl xkwsal qeq
|
||||
pknvybh qkrwi povvd phairw qst inklob yrryv bcuv dolvr okwe iexrpbw
|
||||
kkah qrt dihygsm nly rblqvrm sxguxj yspmre
|
||||
gzhhkjt uimif bssle vdiaa wkohq nrgboi htkojiw
|
||||
aeb xihgva vwcjbjh lri nlwbxun sargiey uyekrc
|
||||
fnnwfbj yyccaxu fhqb nlmwhc ymbqky ooljix mfijg ryykirn womn rygezi qsdwgpw
|
||||
itfs udfr sitf gml
|
||||
gknztly vay ypy jpid pyy mbpfmwz pfmzbwm qqec
|
||||
bbhmw uus xffgd xcjzrlk kyecv zcerxe
|
||||
ncpc otqzotf godtu yhcpsyw ncpc fbs
|
||||
ggoiqm ofk pryqt kqdbo ktek kklhlju iqgmgo gqoimg flscx
|
||||
gsgmvy tktzj kgi ikyz pthtk hxt gik
|
||||
bunvugy fefqpkk juwk aent
|
||||
atm tma dzyret jmuqke xbayiit jumqke
|
||||
dilfw qws ldwfi lnujld ywrogk kjh adaj khmlb hkbml
|
||||
veaemc xugf udpphf mydi jbvebgp ngyhly pufdph vbgepbj
|
||||
vyd tisntn qmc yzal
|
||||
uxdlc piw mwjnk qiar xwpspf sxktemh jmw
|
||||
qhhvar pox aed bgwq doe uyktv pox vriy ndel pzx aed
|
||||
tswei dtfb yhj krxu yqio wtzpm wtzpm yqio
|
||||
bjzp zzp qdzdfv tzkbl nggbfqs vquqds xiud xgrkb
|
||||
ffvjfwp jbzslqo ffvjfwp pchzrqv ffvjfwp pkd nlav
|
||||
czepixn yurmsw ucckih qqlnxjj exipznc
|
||||
xeu llc jnmp dmz pnmj stqzao
|
||||
fzvu uscqp xerkzkg roivhri fzvu yiwae xguz ajpg
|
||||
qdzk uyyoi cspmnc qdzk nwknfx fnngvla cbl
|
||||
acg utwrv cahupdm xgat elb aemkf wmkdzj kfmae ahlrwu yxfcj
|
||||
vdumh rcd rgc hpqk qeum fpgva qkhmuji rjxpuzk ommk
|
||||
ztvm ntxkav ajv avj ippodg sukg bivcslu tes gdlrbnt bdlkaye xpgslef
|
||||
aygsym pwq owxmx xjw
|
||||
dkhykf pfqeyo lfq saoewy qldrky sdgrrcr frdqn tkfezop doo saoewy
|
||||
cwof mqlscm iqxhb nnkex nxx glgpbn
|
||||
noq zikmeyx yodahj ssu qqmifa plcbv rsahsd
|
||||
nvc fuwiyq myv hjn rtuoq zoyp rqnt xchlrg
|
||||
dziscfa nbzsuvp rbnrban cjdprp dkj zcry ckxtm
|
||||
stpm ifcbmmw dpkpzo sot ydpeydw nusp nkciqa psnr
|
||||
udikjfr foqnxl whq ojuspzz ddyz emdktzb gfio mnd hyb
|
||||
vchdphx zkrtky ucyifqx ryzl txdixd cip aid cip
|
||||
wcz ywzwpp viswpsm qfus uzopaq mhps sidjky kipvjg
|
||||
wehhc rzujn urprwzw gkwzhk rhrpph xkzzl rzujn yddlb
|
||||
wlhif foh rpvylg gruiqdv daih yflhbr coe yflhbr hvluddj
|
||||
hfzi ffjntj fdth crkrzdr nyel nlxm cawze bfjz neixnw uygqvmw zayf
|
||||
guthfwn kcinec glhaiqv rfgbi cbrm
|
||||
mvqv lszqu eyjn suq lavyjbh ujivbza aianl wik noy zth
|
||||
zkn ren ncoyj fppsy dwgtgqz til
|
||||
ybxepr hrzcrxs zhrscxr uvpxxl eprxby vzgg
|
||||
xhi zess zet mtpcu ibz nkwq cbzb etz kjjcns
|
||||
kvmu rxgw xboplw enlqcxi uxysl xboplw kvmu oqxislh xeg qwhdc spsddge
|
||||
dxaao ltjjn cpsvnxe core aojgu pbss nudwi
|
||||
llro yoy tixzyc beim qirnb lffcr gzm
|
||||
quxetbf gfpll gqyav dckhp xbfetqu xaebz xuqfteb
|
||||
fblkc hsydxqt bvmwujr rak
|
||||
epeohq olrwyft cmrvov fbdyxbg
|
||||
uzqk pkhizw jbrnlvx aqkq mtmjmy gpcln gaqt rinrz gwis gpcln
|
||||
ttkcu ttkcu mcq xao lhnxdph djj ylet atdln xao
|
||||
pmwn svqktkm isopar krrfbna knrw kbm zsohxrk xlsmm knrw cmoikq etqeggc
|
||||
undrw issrttk mcoe pvufl bwjwqkx jdz undrw vje
|
||||
kfzqbb djpcjv ixctsvb rqsntv fcqz
|
||||
agezraf ezrfaga pftdwrk slsxu axw
|
||||
ezvkn smwko utdlu nizby
|
||||
ygl dwtrpsh qzz cuntrr hdrn lujcx iwc bll qvjhg
|
||||
jrdrvj ledrjp noqx igodve odgiev
|
||||
zonvzgy ujnzj ujnzj zonvzgy ckzd
|
||||
rmg lmib fdn nfd gfobw wrc iro nsz
|
||||
acgxvh sdn zcef sdn jvgnmhi xitkqgy tbascbh
|
||||
ykuzk ovp mikolx xxgpylt secuf yrtilra wnoypy mty lmnagx
|
||||
wwmlins mxwye kjntv sadc wnvyoov rzdawl
|
||||
ali ncsrq tcbjzpu oiw iimxlbp mwi hdvdl dqnicf lxit
|
||||
sql vywv vycj nprzb tdqe qwvljm myhpvxy hdixbk ywqpn xvue vrno
|
||||
etncz etncz czqw moz uaxbtm axlslow fhephy moz
|
||||
wsriuaj umjkx mhxau luzf wmo kyx jidl ufuoz cbk
|
||||
msfrvbt bxnd msfrvbt yut qwbx
|
||||
rhag vfkqf rekoz buw qffvk wxs ghra
|
||||
meignx dhdu xacg hmiqkd nrijc gcxa gwap lov ybtyr vol
|
||||
qoqns swib mlegyjn ojdtt tvdrrhg oetg xdret nzpq
|
||||
ntc zowllt dwiyht ztdeifx velaumx jfxxsqt uefmb gwn
|
||||
bgykxl bykan tvvgcpa wdcsj coonage hpocfz sqmihw pnagv uozsh
|
||||
wass vve ngyd yyvxmsq rsaypsa newxyc adqmbm xqsvymy ygdn idysq
|
||||
ybo vpjcf tsbpc hcdszr qrxwjqr bzz tgjhkpu hgtxkt stpbc woro
|
||||
ogszrg rszt owufa cohmv msygfw fud fzi lhts sfiy dfu gxsuj
|
||||
fclumcq ejuj jkbu hbsv ythmpoo xdzg dkvrdue
|
||||
rbf sunzzl sokgih rngqli xndnuj rbf smiea mqzpzb fwpcx smiea
|
||||
uuuxchs uuuxchs fzna qlj tcjnv oghk fzna
|
||||
zuiyk tbn nqma wptoecs xndgbqm mqan wmcahvm qpir
|
||||
ztexf pqsc icxqsuf tkgr itnn yorg oyvqaj yoxggqk lep
|
||||
ehm hysd jfv iugyt jyvh
|
||||
fenjp zjtvvhb xfe dgxoah ljn ixvdyi fenjp odnlr
|
||||
uosxyy euicgp lrsc euicgp mcszotm kvxrpk jfo oxu xyeiv fhdwl wbw
|
||||
tsmdp gshgm kpb tlx kfznsu gglefv pkb gcnydo eavgrc rgd lgefvg
|
||||
xuq svh cmzt bxxlvfm rtblxpu imuexhl lbre hqyedxa hwkgaak
|
||||
hhlfj mlrdv dlsn zgcy hciiuzw uwciihz iizhcwu gwx
|
||||
ukqoj kjqou hlk nfyz lusf kebvmrw ccaj ewmicq useba
|
||||
jlnnl jsmox vnw ucr ggithr usqe allzc pfumkkm jlnnl
|
||||
mswpbk lffjwq icc kef zlba uolrrl fqlfwj tbc
|
||||
bfmra hdgczrw dgmnod afbmr fnczx
|
||||
dcqrso cgbymsg jbx ofpbp rmtygip syly
|
||||
yrmn wzkt lqys tzkw sqyl fxoc
|
||||
wal zgjy cwnqyaf bhz dbpft owx
|
||||
xnrautk dlsyot nzbohog xmzsbh soec wyy
|
||||
kde jpkvbs eyzw ukgiv ggrtzcd vikgu mxqy jyh crdtgzg ebzet
|
||||
psg jsykdw drpqzl qzqbge ldqpzr wsdykj lmhbldv hbognjp nqej fmxoq guuf
|
||||
ueo ncedaju ijasprn rvxb mxkddl qvgdlbx bpj bpf pxewuf chvo lvrq
|
||||
zlmg eciyqi xfbeoq pupyrc bfqexo ituqab pycrpu
|
||||
jsk clo vqxzl aja jfbce ldov
|
||||
muss tzg iksvdej zpw fxwhrv eeye fxwhrv
|
||||
kjjd dzf zkppx qdwlx irudds kjgd pdrz rgogy qdwlx egx rjxldp
|
||||
szjpf aouvl ehxq exqh
|
||||
nzweop qlkje welkfs jqmvqi coc
|
||||
ivmjzk usk auvmc vvcnwn qubihx vkms fbt udn uyto jjt kxqy
|
||||
rayw ijaklcr ywra qkj qytxeh pmnfh qffvsft tyxheq
|
||||
pea cqy tkg qidvx qidvx pea skgrndq
|
||||
iijm xgwq zzpskl qtjezqt yqjwy dhbq
|
||||
dfuv iqw iejb bjei iwq
|
||||
ogrmldp xdc dcx cqhbwlp
|
||||
wzwb xrjl keciql ckky litdr bmurdk anjs nyggesn ygwt svmee
|
||||
bvkkzj rcr lozrw mgpwkm lwm yecsr ykl tzny aeus jmq mchopp
|
||||
rsnvaa oikce angqn rnvsaa mhc
|
||||
hsiov kxqpxtc rzh vjrqlx xxtkpqc wiunol qckxtpx
|
||||
aosek lhi ruqgd rmr
|
||||
agqvlao pvhcgz esw kwnpefs qsrvxz hgkgrs mpx odaiqi
|
||||
dvqkrzf dawioo jtaco oeutol ravp apvr frjunad
|
||||
wss nahhsh pfwgcfr rvvvq uqxxmhq qax vtrkfou medfj
|
||||
imdyfc sez gve kgtryl kmqklg
|
||||
crmg yhkpa bsfouax kyttpa who mcrbzaj kcsktxe yfv
|
||||
zpw zlab pzw pwz okb
|
||||
fgqlb byhkhfn qglfb ladle ifa
|
||||
skr zwwjnr iub wekt biu jnrwwz
|
||||
mpvt mpvt havn ztf
|
||||
odqhd uxrswp ppj eztyj nxzwm fvxyadn tostwy odo abyp meqdm ktqkvh
|
||||
fgufup uabd vhxem imto imto vhxem
|
||||
vrpxxhi kii zwatqg nokg wesxju xplc sumte muwjj
|
||||
nsse iquhoc giuv pxaa qpqn zrfk kywjr spz kgzc lfa
|
||||
cjjgarr psvwoap ivijyt nfbxu ktiuy jajrgrc goyc
|
||||
yrfzf wyxda gsslsy oeyve jczghf cbuwf iwnu izyrtho dyoup toizyhr vzzrr
|
||||
bwqgxsr ufy cnouypd qwxbgsr efdkfe rwsblis bhvyws oodh
|
||||
piqpez yhqahjp oxu qtomld
|
||||
vjvpnwy kajjaim lcxmbyd fkdy ywvvnjp xcn nbwlklo
|
||||
qghq mihdp vuv ocrzsw mlmkn rgnbfcm qgufcks btlulb effsrih
|
||||
psazbfo vbpr efcspj yrjl pqjrfe relxjc nzzvb yviuhc
|
||||
tbbhdbm uxhawtk bmdhtbb rqxrr pspjzx krtmf pnaz srcej rsjec
|
||||
owikzec glvbqy jhknyuz jkaxu ldhnlpx wdp
|
||||
qvuv wteohr daynue nehs gzqu porzrsk cqokye zzsbqox rqh ogxtn pskorrz
|
||||
gnm grlfoon lxid isxa
|
||||
jes iixswl umgbg qfixa xnecpns asm nopsmo axaopsm qahwpqd
|
||||
orr auvlruu mqq uurlvua urauuvl fjrcuo mqht tkdgps tdvnhvq iezdv
|
||||
txwyzy zzwk bzi etfg gtef
|
||||
qyydr lllgosq qyydr lllgosq
|
||||
xqm uyl ldpowm pxhi ievvvez hmhzwmr ldpowm jaw
|
||||
qlvfq efgivhr rfhhu gvw bxgsrp sgbnjh ekgbp cyof rvghph nxfekia xym
|
||||
lgladv ogj cir jxx msz fshf ayheu wpmke zckng vgrlv lxgmge
|
||||
fcmp aabxdp hpxbb bblpy mpcf eju pnkv jxwoy hmv fgynps pbdxaa
|
||||
jcrh dgg lzyiv ojop vhk vdb uinoetv
|
||||
utlzcf ziizdo njffmxe uhyjxdb cztluf yjdhbxu
|
||||
ubl cgz tyg nljl
|
||||
slwe qaos ybcwdoh ogazkj tqh opggnzt ffrscl opggnzt izeh
|
||||
evitfwb jpivmn dpnxzuf gdkx zprogl xehb
|
||||
dktt kpnkizb rreq gjmosa iekdtpj rcxk eweawk qrre olv
|
||||
cmcw vmw mujx mujx ypqfz
|
||||
nzxcl fzwa ftcrc immendi tmxzzi hslye eibc tmxzzi
|
||||
abfc jdqvk lichxx uiomtz tlq
|
||||
mnkthoj nohjktm eued izmcjj
|
||||
ullh wju bxfsif icnrmmj qnufw zubcnmo yewz phovhv
|
||||
ndfvd gcyt wnm badaww twm jahlat ndfdv mtw xrq bechxx dnp
|
||||
ceg gcxgu gnudeib utsynwx dpg wpsnp ahbbvkt wpsnp iou
|
||||
wutcg congyz erkj ibtcics
|
||||
xsbq lyycse qbsx ppgutls lroo tyor
|
||||
hfiwoy hclhl gcwgqox ogo hlqr ultkaz yke iwohyf oog
|
||||
bcl nemims udwkmlm nokck tkwny ulkihcu knwty pngamqg yxtphkn kuihlcu
|
||||
nwsr enrutc eqcfb uxmdgju rfnzhsn tzk vysc
|
||||
wbtki vjmkk kvjkm ibwkt sckvbv
|
||||
xjxnow tli woxldj rotrtz nfkhcz ibh mla ybxldg
|
||||
cwtpkhr oxywg qpwrgfm dfjpfuc kpcopa
|
||||
byczby tbfkonk ytlczzf bbyczy
|
||||
khuvrne rnamlgt akjtu qlx odr git xmiazr icwsxsq
|
||||
jfm bneh tkdzuad bsr oruvmqq uauw zjlp gwov hot jkjbex
|
||||
jjo uvk vlpy lpxd irntb uvk ehhsqv fxhvt jjo fpa
|
||||
qrwu mgnw hvflf ytspp mco ikvbqg fflvh wts cbbf
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,2 +0,0 @@
|
||||
4 10 4 1 8 4 9 14 5 1 14 15 0 15 3 5
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
147,37,249,1,31,2,226,0,161,71,254,243,183,255,30,70
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -1,44 +0,0 @@
|
||||
0: 3
|
||||
1: 2
|
||||
2: 4
|
||||
4: 8
|
||||
6: 5
|
||||
8: 6
|
||||
10: 6
|
||||
12: 4
|
||||
14: 6
|
||||
16: 6
|
||||
18: 17
|
||||
20: 8
|
||||
22: 8
|
||||
24: 8
|
||||
26: 9
|
||||
28: 8
|
||||
30: 12
|
||||
32: 12
|
||||
34: 10
|
||||
36: 12
|
||||
38: 12
|
||||
40: 8
|
||||
42: 12
|
||||
44: 12
|
||||
46: 10
|
||||
48: 12
|
||||
50: 12
|
||||
52: 14
|
||||
54: 14
|
||||
56: 12
|
||||
58: 14
|
||||
60: 14
|
||||
62: 14
|
||||
64: 14
|
||||
66: 14
|
||||
68: 12
|
||||
70: 14
|
||||
72: 14
|
||||
74: 14
|
||||
76: 14
|
||||
80: 18
|
||||
82: 14
|
||||
90: 18
|
||||
|
@ -1 +0,0 @@
|
||||
xlqgujun
|
@ -1,3 +0,0 @@
|
||||
Generator A starts with 679
|
||||
Generator B starts with 771
|
||||
|
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
328
|
@ -1,202 +0,0 @@
|
||||
|
|
||||
+---------------------------------------------------------------------------+ +---------------------+ +---+ +-------------------------------------+
|
||||
| | | | | | | | |
|
||||
+---------------+ +---------------+ +-------|-------------------------------------+ | | | | +-----------+ +-----+
|
||||
| | | | | | | | | | | | | | | | |
|
||||
+---+ | | +-------+ | | +-----------------------------|-------------------------------------------|-----------+ | | | | | | +-----------+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
+-----------+ | +-|-----------|-----------+ | +---+ | | | +-----------------------|-|---------------|-------|-----------|-----------------------+ |
|
||||
| | | | | | | | | | | | | | | | | M | | | | | | | | |
|
||||
| | | +-|-----------|---------------------|-----+ | | | | | +---------+ +-+ +---------------|-----------|---------------+ | +-+ |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | +-------------------------|---------------|---------------|-------|-------+ | | +-----+ +-----+ | | | | | | | +---+ +-+ | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +---|-+ | +---+ | +---------------------------------------|-------------|---------------------------|-----|-|---|-------|---------------------|-|-|---------+ |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +---+ | | | | | | | | +-------|-------|-------|---|-|-----|---------------|-----------|-------------|-|-----------|---|-|-|-|---+ | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | +-----------------------------|---------------------|---|-|-------------------|-|-----------|---|-|-|-|-------|-|---+
|
||||
| | | | C | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +-|---|-----|-|-----------|-------|-----------------------------|-------------+ | | | | | | +-------------|-|---|-|-|---|---+ | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +-|---|-----|-------------|-------|-----------------------------|---------------|-------------------|-------|-----|---------|---|-+ | | | | | | | | | +-|---|---|-----|-+ |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| +---+ | | | | | | | | +-+ | +---------------------|---+ | | | | | | | +-|-----|-|-------------|-----------+ | | | | | | | | +---+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | P |
|
||||
| | | | | | | | | | | | | +-+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | +---|-+ | +---|-|-----|-----------|-+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | +---|---------+ | | +---|-|-|---|---------|-----------|-+ +-+ | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | +-------+ | | | | | | | | | | +-------+ | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +---|---|---|---------|-----+ +-----|-|-----|-------------------|-----|-------------|-|-------|-----------|-|-----|-------------------|-------|---------|---|-----------|-----------+ | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-------+ | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | +---+ | | | | | | | | | | | | | | | | | | | | | | | +-|-+ Y +-|-|-----+ | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | +-+ | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | +-|-------|-----|-|-----|-------------------|-------------|---------------|---------------------|-----|-|---------|-|---|-|-|-------|---|-------+ | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | +-----|---------|-------------|---------------|---|---|-|-|-----|-+ | | +-------|-+ +---|---|-------+ | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | +-------------------|-------|-------------|---+ | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | +-|-------------------|---|-----+ | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | +-----|-----|---------|-------|---|-|-------------------|---------------------------------------------|-|-----|---+ | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-|-+ | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | +-----|---|-|-|-----|-----|-+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | +-------|-|-----|-----|-+ | | +---+ | +---------|-------|---------|-|---|-----|-|-|-+ | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | +---|-|---------------|-|---|-|-----|-------------|-+ | | | +-----------|-------------|---------+ | | | | | +-----+ | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | +-------|---------------------------|---|-------|---+ +-------|---+ | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | +-+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | +-----|---------------|-|-----------|-|-----|-----|-|---|---|-----------------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | Q | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-----+ | | | | | | | | | +-+ | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | +-----------|---|---------|-|-----------------------+ | | | | | | | | | | | | | | | | +---------------------|-|-|-----------|----------E------+ | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | +---------|-|---|-----------|-|-|---+ | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | +---|-------|---|-+ | | +-|-------------|-|-----------|-----|---|-----+ | | +-+ | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | +-----------------|-|---|-----|-----------|---|-|---------------|-----|-------------------|-|-|-----|---------------+ | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | +---|-|---|-------|---|-----|---|-----------|---------------|-----|-------|---|-----|-----------------+ | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | +-------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | +---------------|-+ | | +-|-|-------------------|-----------|-----|-|-|-|---------------|-|-----------|-----|-|-|---------------------|-------------|-|-|-|-----|-|-+ | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | +-|---+ | | | | | | | | | | | | | | | +-|---|-----+ | +---|---|-|---+ | | | +-------|-|-------|---|-|---|-------|-----+ | +-------|-----+ | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +-+ | | | | | | | | | | +-----------|-|-|---|---|-------|---|---|---------------|-|-|---------+ | | +-|---|---------|-|-----------|-------|-------|-----|-----|-----|---+ | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-------|-|-+ | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | H | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | +-|---|-----+ | | | | | | | | | | | | | | | | +-|-------|---|-|-----------|-----------|-|---+ | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-----|-|-------|-|-----|---|-----|-------------------|-------|-+ | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-|-----+ | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | +---|-|---|-|---|-----------|---|-----|-|---------|---|-------------|-|-----|-----|-------|-------|-------|---|---|-|-|-|-----------------------------------|-------------+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | +-|-------|---+ | | | | | | | | | | | | | | | | | | | | | | | | | +-----|-+ | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | +-------|---|-------|---------------|-|---------|-----|---|-----------|---|-|-|-|-----------------------------|-------|-|---------+ | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | +-+ | | | | | +---|-----|-----------------|-|-------+ | | | | | | | +-|-------+ | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +---|---|-------|-|---|-----------------+ | | | | +---+ | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | +-------|-|-|-|-------|---------|-|-------------|-|---|-|-----|-|-------------------|-------|-|-------|-------------+ | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | +-----+ | | | | | | | | | | | | +---------|-----+ | +-+ | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | +-|-----------|---|-|---|-------+ +-------|-----------+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-|-----+ | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | +---|-|---------|-|---------------+ | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | +---|---------|---|---------------|---|---|-----|---------|-------|---------------------|---|-------|-|-|-----+ | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | +-|-+ | | | | | | | | | | | | | | | | | | | | | | | | +-|---------|-------------------|-----------|---|-----|-------|-----|---------|-+ | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-----|-----+ | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +-|---|-|---|-|-----|---|-|---|-|-+ +---|-+ | | | | | | | +-------|-----+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +---+ | | | | | | | | | | | | | | | | | | | | | | | | | +---|-----|-------|-|-----------------|-|-|-|-|---|-|---|-|-|-|-------------------|-------|---|-----+ | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | +-----|---+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-------|---------|-------|-|-|-------|-----|-|-|-|---------|-----|-----+ | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | +-|-+ | +-------------|---|---|---------|-------------|-|---------|-------|---|-|-|-------|-|-|---------|-------|-|---|-----------|-----+ | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | +-----|-----|---------|-+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +-----+ | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | +-------|-----------|-------|-|-------|-----+ | | | | | +---|-|-|---|-|-|-+ | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | S | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | +---|-------|---------------------------------|---------|-----------------|---|-|---|-|---+ | | | +---------|-----|---------+ | | | | +-|-+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
+-----|-|---|-|---|-----------|-----|-|---|-----|---------|---+ | | | | | +-------|-+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | +---|-----|---------|-----|---|-|-|-|-----|-------|-------|---|-----|-------+ +-|-|-------|-|---------------------|-|-|-------------------|-|-+ | | +-|---+ | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
+-------------|-|-|-|-----|---------|-----|-|-----|-|---------------------|---|-----|---------|-|-|-|-------|---------+ | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +-|-----|-|---|-|-----|---------------|---|---|---|---|-------|-------|-------|-----+ | | | | | | | | | | | | | +---|-+ | | | | | | | | | | | | | +-+ | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +---|---|-|-----------|---|-------|-------|---+ | | | | +-----------------------|---|-------|---+ +---------------|-----+ | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | +---+ | +-|---|-+ +-----|-----|-+ +-+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | +-|-----------|-|---|---+ | +-------|-+ | | | | | | | | | +---|-+ | | | | | | +-|-|-----|-----+ | | | | +---+ | +-+ | +-+ | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| +-----|-|V------|-|---|-|---------|-|-------|-----|-----------------|-------------------------|---------|-----|---------------------------+ | | | | +-|-+ | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +-|-|-----|-|-|-|---------------------|-|-------|---------------|---|-------|-------------|---------|-|-----------+ | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +-----+ | | | | | | +---|-----------|-|---------------|-------|---|-|-----------------------|---|-----------------|-----|-------|-|---|-|---|---+ | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +---------|-|---|-|-|-----------------|-|-------------------|-------|---|-------------------|---------|---------------------|-|-----|-------|---|-|---|-------------------|-|-----|---|-|-----+ |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| +-|-----|-----+ +---|---|-----------------|---+ | | | | | | | | | | | | | +-----------+ | | | | | | | | | | +-|---|-----|-----+ | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
+-|-|-----|---------|-|-+ | +-----|-|-+ | | | | | | | | | | | | | +-----------|---+ | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
+---------|---------|-|-----------------|-+ | | | +---|-------|---|---|---|---------------+ | | | | | +-|-------+ | | | | | | | | +---------------------|-+ | +-----+ |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | +---|---------+ +-+ | | | | | +---------|---------------+ | +-|---------------|-------|-----|---------------|-|-----|-------|-------|---------------------|-|---+ | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | +---+ | | +---|-----------|---|-----------|-----------|-|---------|-|-----------|-----------|-|---|-|-------------------------|-----|-------------+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | +-------|-|-+ | | | | | | | | | | | | | +-----------|-----+ | +---+ | | | | | | | +---------------------+ +-------|-------+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | +-----|-----|-+ | | +-|-----------|---|-----------------|---+ | | | +-----+ | +-------|-----------+ | | | | | +-------------|-------------+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | +---------|---|---|---|-------|-|-|-----------|-|-|---------|-------------------+ | +---|-------------+ +-------------|-----+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | +-----------|-----|-----------+ | | +-----|-|-|-------------------------|-----------+ +-|-|-|-------------+ |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +---------------------|-----|-------|-|---------|-----|-----------|-|-----|---|-+ +-------+ | +-|-|-+ | | | +---------------------------------+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +-|-|---------|---|-------|---------|---|-|---------------|-------|---------|---------|-|-|-|---------|---------------------|-------|---------+ | | +-+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | +-------|-----|-----------|---|---|---+ | | | | | | +-+ +---------|---------------+ | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | +---+ | | | | | | | | | | | | | +---------|-|-|-------|---------+ | | +---------|-----+ +-+ | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | +---------|-+ | | | | | +-----+ | +-----|-------+ +-+ +---------------+ | | | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | | | | | +---------|-------|---------|---|---|-----|-----------|---------------------------------------------|-------+ +-------------------------------------|---------------+
|
||||
| | | | | | | | | | | | | | | | | | | | | | | |
|
||||
| | | +---------+ | +-------------|-----------|---------|---|-------------|-------------------------------------------------+ | | | | |
|
||||
| | | | | | | | | | | | | | | | | | | |
|
||||
| | | | +---------+ +---------|---+ +---|---------+ +-+ +---------------------------------------------+ | | | | |
|
||||
| | | | | | | | | | | | | | | | | |
|
||||
+-+ +-------------------------|-----------+ +-+ +---|---+ | +---------------------------------------------------------------+ +-----+ | +-------------+
|
||||
| | | | | |
|
||||
+-----+ +-------+ +--------------------------------------------B----------------------------------------------------------------------+
|
||||
|
||||
|
@ -1,5 +0,0 @@
|
||||
# p ARGF.read.strip.chars.map(&:to_i).each_cons(2).select {|a,b| a == b }.map(&:first).sum
|
||||
|
||||
a = ARGF.read.strip.chars.map(&:to_i)
|
||||
b = a.rotate(a.size/2)
|
||||
p a.zip(b).select {|a,b| a == b }.map(&:first).sum
|
@ -1,5 +0,0 @@
|
||||
p ARGF.read.strip.split("\n")
|
||||
.map {|line| line.split("\t").map(&:to_i) }
|
||||
.map {|row| row.combination(2).map(&:sort).map(&:reverse).find {|a,b| (a.to_f / b.to_f) * 10 % 10 == 0 }}
|
||||
.map {|a,b| a / b}
|
||||
.sum
|
@ -1,100 +0,0 @@
|
||||
require "minitest"
|
||||
|
||||
class Spiral
|
||||
def initialize
|
||||
@state = [0,0]
|
||||
end
|
||||
|
||||
def each
|
||||
return enum_for(__method__) unless block_given?
|
||||
|
||||
(1..Float::INFINITY).lazy
|
||||
.flat_map {|i| [i, i] }
|
||||
.zip(%i[r u l d].cycle)
|
||||
.flat_map {|n,d| Array.new(n, d) }
|
||||
.each do |dir|
|
||||
|
||||
yield @state
|
||||
@state = @state.zip(
|
||||
case dir
|
||||
when :r
|
||||
[1, 0]
|
||||
when :u
|
||||
[0, 1]
|
||||
when :l
|
||||
[-1, 0]
|
||||
when :d
|
||||
[0, -1]
|
||||
end
|
||||
).map {|a,b| a + b }
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Grid
|
||||
def initialize
|
||||
@grid = Hash.new {|h,(x,y)|
|
||||
neighbors = [[-1, 1], [0, 1], [1, 1],
|
||||
[-1, 0], [1, 0],
|
||||
[-1,-1], [0,-1], [1,-1]]
|
||||
h[[x,y]] = neighbors
|
||||
.map {|i,j| [x+i,y+j] }
|
||||
.select {|i,j| h.has_key?([i,j]) }
|
||||
.map {|i,j| h[[i,j]] }
|
||||
.sum
|
||||
}
|
||||
@grid[[0,0]] = 1
|
||||
end
|
||||
|
||||
def [](x,y)
|
||||
@grid[[x,y]]
|
||||
end
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
case ARGV.shift
|
||||
when "test"
|
||||
require "minitest/autorun"
|
||||
when "0"
|
||||
input = ARGF.read.to_i
|
||||
p Spiral.new.each.with_index.find {|_,i| i == input - 1 }.first.sum
|
||||
when "1"
|
||||
input = ARGF.read.to_i
|
||||
grid = Grid.new
|
||||
p Spiral.new.each.lazy.map {|x,y| grid[x,y] }.find {|value| value > input }
|
||||
end
|
||||
end
|
||||
|
||||
class TestSpiral < Minitest::Test
|
||||
def test_spiral
|
||||
spiral = Spiral.new
|
||||
e = spiral.each
|
||||
assert_equal [0,0], e.next
|
||||
assert_equal [1,0], e.next
|
||||
assert_equal [1,1], e.next
|
||||
assert_equal [0,1], e.next
|
||||
assert_equal [-1,1], e.next
|
||||
assert_equal [-1,0], e.next
|
||||
assert_equal [-1,-1], e.next
|
||||
assert_equal [0,-1], e.next
|
||||
assert_equal [1,-1], e.next
|
||||
assert_equal [2,-1], e.next
|
||||
|
||||
spiral = Spiral.new
|
||||
assert_equal [0,-2], spiral.each.with_index.find {|_,i| i == 22 }.first
|
||||
end
|
||||
end
|
||||
|
||||
class TestGrid < Minitest::Test
|
||||
def test_grid
|
||||
grid = Grid.new
|
||||
assert_equal 1, grid[0,0]
|
||||
assert_equal 1, grid[1,0]
|
||||
assert_equal 2, grid[1,1]
|
||||
assert_equal 4, grid[0,1]
|
||||
assert_equal 5, grid[-1,1]
|
||||
assert_equal 10, grid[-1,0]
|
||||
end
|
||||
end
|
@ -1,30 +0,0 @@
|
||||
class Passphrase
|
||||
def initialize(raw)
|
||||
@raw = raw
|
||||
end
|
||||
|
||||
def valid?
|
||||
words = @raw.split(/\s+/).map {|word| word.split(//).sort.join }
|
||||
words.uniq.size == words.size
|
||||
end
|
||||
end
|
||||
|
||||
# require "minitest/autorun"
|
||||
if $0 == __FILE__
|
||||
p ARGF.read.split("\n").map {|line| Passphrase.new(line) }.select(&:valid?).size
|
||||
end
|
||||
|
||||
require "minitest"
|
||||
class TestPassphrase < Minitest::Test
|
||||
def test_valid
|
||||
# assert Passphrase.new("aa bb cc dd ee").valid?
|
||||
# refute Passphrase.new("aa bb cc dd aa").valid?
|
||||
# assert Passphrase.new("aa bb cc dd aaa").valid?
|
||||
|
||||
assert Passphrase.new("abcde fghij").valid?
|
||||
refute Passphrase.new("abcde xyz ecdab").valid?
|
||||
assert Passphrase.new("a ab abc abd abf abj").valid?
|
||||
assert Passphrase.new("iiii oiii ooii oooi oooo").valid?
|
||||
refute Passphrase.new("oiii ioii iioi iiio").valid?
|
||||
end
|
||||
end
|
@ -1,14 +0,0 @@
|
||||
instructions = ARGF.read.strip.split("\n").map(&:to_i)
|
||||
pc = 0
|
||||
count = 0
|
||||
while (0...instructions.size).cover?(pc)
|
||||
offset = instructions[pc]
|
||||
if offset >= 3
|
||||
instructions[pc] -= 1
|
||||
else
|
||||
instructions[pc] += 1
|
||||
end
|
||||
pc += offset
|
||||
count += 1
|
||||
end
|
||||
p count
|
@ -1,36 +0,0 @@
|
||||
require "set"
|
||||
|
||||
class Day6
|
||||
def initialize(banks)
|
||||
@banks = banks
|
||||
end
|
||||
|
||||
def each
|
||||
return enum_for(__method__) unless block_given?
|
||||
|
||||
loop do
|
||||
yield @banks.dup
|
||||
|
||||
value, i = @banks.map.with_index.max_by(&:first)
|
||||
@banks[i] = 0
|
||||
value.times do |offset|
|
||||
@banks[(i+offset+1) % @banks.size] += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
banks = ARGF.read.strip.split("\t").map(&:to_i)
|
||||
day6 = Day6.new(banks).each.lazy
|
||||
seen = Set.new
|
||||
needle, i = day6.with_index.find {|config,_|
|
||||
if seen.include?(config)
|
||||
true
|
||||
else
|
||||
seen << config
|
||||
false
|
||||
end
|
||||
}
|
||||
|
||||
p i
|
||||
p day6.with_index.drop(1).find {|config,_| config == needle }.last
|
@ -1,20 +0,0 @@
|
||||
Program = Struct.new(:name, :weight, :disc)
|
||||
|
||||
programs = {}
|
||||
ARGF.read.strip.split("\n").each do |line|
|
||||
name, weight, above = line.scan(/(.+) \((\d+)\)(?: -> (.+))?/)[0]
|
||||
programs[name] = Program.new(name, weight.to_i, (above || "").split(", "))
|
||||
end
|
||||
|
||||
disc_weights = Hash.new {|h,k|
|
||||
program = programs[k]
|
||||
h[k] = if program.disc.empty?
|
||||
program.weight
|
||||
else
|
||||
program.weight + program.disc.map {|x| h[programs[x].name] }.sum
|
||||
end
|
||||
}
|
||||
|
||||
root = "mkxke"
|
||||
p programs[root].disc.map {|n| [n, disc_weights[n]] }
|
||||
require "pry"; binding.pry
|
@ -1,20 +0,0 @@
|
||||
instructions = ARGF.read.strip.scan(/(\w+) (dec|inc) (-?\d+) if (\w+) ([!<=>]+) (-?\d+)/m)
|
||||
max = 0
|
||||
registers = Hash.new(0)
|
||||
instructions.each do |instruction|
|
||||
condition_value = registers[instruction[-3]]
|
||||
if eval("#{condition_value} #{instruction[-2]} #{instruction[-1]}")
|
||||
value = registers[instruction[0]]
|
||||
case instruction[1]
|
||||
when "inc"
|
||||
value += instruction[2].to_i
|
||||
when "dec"
|
||||
value -= instruction[2].to_i
|
||||
else
|
||||
raise instruction
|
||||
end
|
||||
registers[instruction[0]] = value
|
||||
max = [value, max].max
|
||||
end
|
||||
end
|
||||
p max
|
@ -1,25 +0,0 @@
|
||||
require "strscan"
|
||||
|
||||
input = ARGF.read.strip
|
||||
input = input.gsub(/!./, "")
|
||||
|
||||
p input.scan(/<[^>]*>/).map {|g| g.size - 2 }.sum
|
||||
|
||||
input = input.gsub(/<[^>]*>/, "")
|
||||
.gsub(?,, "")
|
||||
|
||||
ss = StringScanner.new(input)
|
||||
score = 0
|
||||
group = 0
|
||||
until ss.eos?
|
||||
case
|
||||
when ss.scan(/\{/)
|
||||
group += 1
|
||||
when ss.scan(/\}/)
|
||||
score += group
|
||||
group -= 1
|
||||
else
|
||||
raise "omg!"
|
||||
end
|
||||
end
|
||||
p score
|
@ -1,33 +0,0 @@
|
||||
list = (0..255).to_a
|
||||
current = 0
|
||||
# lengths = ARGF.read.strip.split(?,).map(&:to_i)
|
||||
input = ARGF.read.strip
|
||||
p input
|
||||
lengths = input.split(//).map(&:ord)
|
||||
p lengths
|
||||
lengths.concat([17, 31, 73, 47, 23])
|
||||
skip = 0
|
||||
|
||||
# list = (0..4).to_a
|
||||
# lengths = [3,4,1,5]
|
||||
|
||||
64.times do
|
||||
lengths.each do |length|
|
||||
list[0, length] = list[0, length].reverse
|
||||
list = list.rotate(length + skip)
|
||||
current += length + skip
|
||||
current %= list.size
|
||||
skip += 1
|
||||
|
||||
# p list.rotate(list.size - current)
|
||||
end
|
||||
end
|
||||
|
||||
list = list.rotate(list.size - current)
|
||||
p list
|
||||
dense = list.each_slice(16).map {|slice| slice.inject(&:^) }
|
||||
p dense
|
||||
p hex = dense.map {|n| n.to_s(16).rjust(2, ?0) }.join
|
||||
|
||||
# list = list.rotate(list.size - current)
|
||||
# p list[0] * list[1]
|
@ -1,26 +0,0 @@
|
||||
dirs = ARGF.read.strip.split(?,)
|
||||
current = [0, 0, 0]
|
||||
max = 0
|
||||
dirs.each do |dir|
|
||||
delta = case dir
|
||||
when "nw"
|
||||
[-1, 1, 0]
|
||||
when "n"
|
||||
[0, 1, -1]
|
||||
when "ne"
|
||||
[1, 0, -1]
|
||||
when "sw"
|
||||
[-1, 0, 1]
|
||||
when "s"
|
||||
[0, -1, 1]
|
||||
when "se"
|
||||
[1, -1, 0]
|
||||
else
|
||||
raise "omg!"
|
||||
end
|
||||
current = current.zip(delta).map {|a,b| a + b }
|
||||
max = [max, current.map(&:abs).sum / 2].max
|
||||
end
|
||||
p current
|
||||
p current.map(&:abs).sum / 2
|
||||
p max
|
@ -1,31 +0,0 @@
|
||||
require "set"
|
||||
|
||||
@programs = Hash[
|
||||
ARGF.read.strip
|
||||
.lines
|
||||
.map {|line| line.scan(/\d+/).map(&:to_i) }
|
||||
.map {|x| [x.shift, x] }
|
||||
]
|
||||
|
||||
def group(id)
|
||||
group = Set.new
|
||||
queue = [id]
|
||||
until queue.empty?
|
||||
program = queue.shift
|
||||
next if group.include?(program)
|
||||
group << program
|
||||
queue = queue.concat(@programs[program])
|
||||
end
|
||||
group
|
||||
end
|
||||
|
||||
p group(0).size
|
||||
|
||||
count = 0
|
||||
until @programs.empty?
|
||||
group(@programs.keys.first).each do |program|
|
||||
@programs.delete(program)
|
||||
end
|
||||
count += 1
|
||||
end
|
||||
p count
|
@ -1,11 +0,0 @@
|
||||
firewall = Hash[ARGF.read.strip.scan(/(\d+): (\d+)/).map {|x| x.map(&:to_i) }]
|
||||
|
||||
def caught?(time, range)
|
||||
(time % (2 * (range - 1))).zero?
|
||||
end
|
||||
|
||||
p firewall.select {|depth, range| caught?(depth, range) }.map {|d,r| d * r }.sum
|
||||
|
||||
p (1..Float::INFINITY).find {|delay|
|
||||
firewall.none? {|depth, range| caught?(delay+depth, range) }
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
input = ARGF.read.strip
|
||||
|
||||
def knot_hash(input)
|
||||
list = (0..255).to_a
|
||||
current = 0
|
||||
lengths = input.split(//).map(&:ord)
|
||||
lengths.concat([17, 31, 73, 47, 23])
|
||||
skip = 0
|
||||
64.times do
|
||||
lengths.each do |length|
|
||||
list[0, length] = list[0, length].reverse
|
||||
list = list.rotate(length + skip)
|
||||
current += length + skip
|
||||
current %= list.size
|
||||
skip += 1
|
||||
end
|
||||
end
|
||||
|
||||
list = list.rotate(list.size - current)
|
||||
dense = list.each_slice(16).map {|slice| slice.inject(&:^) }
|
||||
hex = dense.map {|n| n.to_s(16).rjust(2, ?0) }.join
|
||||
hex.hex.to_s(2).rjust(128, ?0)
|
||||
end
|
||||
|
||||
# p (0..127).map {|i| "#{input}-#{i}" }.map {|row| knot_hash(row) }.join.split(//).select {|c| c == ?1 }.count
|
||||
|
||||
# input = "flqrgnkx"
|
||||
grid = (0..127).map {|i| "#{input}-#{i}" }.map {|row| knot_hash(row).split(//) }
|
||||
|
||||
regions = 0
|
||||
queue = []
|
||||
(0..127).each do |y|
|
||||
(0..127).each do |x|
|
||||
if grid[y][x] == ?1
|
||||
regions += 1
|
||||
grid[y][x] = ?0
|
||||
queue << [x, y]
|
||||
until queue.empty?
|
||||
xx,yy = queue.shift
|
||||
[[0, 1], [0, -1], [1, 0], [-1, 0]].each do |dx, dy|
|
||||
xxx = xx + dx
|
||||
yyy = yy + dy
|
||||
if (0..127).cover?(xxx) && (0..127).cover?(yyy) && grid[yyy][xxx] == ?1
|
||||
grid[yyy][xxx] = ?0
|
||||
queue << [xxx, yyy]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
p regions
|
@ -1,28 +0,0 @@
|
||||
start_a, start_b = ARGF.read.strip.scan(/\d+/).map(&:to_i)
|
||||
|
||||
class Generator
|
||||
def initialize(start, factor)
|
||||
@value = start
|
||||
@factor = factor
|
||||
end
|
||||
|
||||
def each
|
||||
return enum_for(__method__) unless block_given?
|
||||
|
||||
loop do
|
||||
@value *= @factor
|
||||
@value %= 2147483647
|
||||
yield @value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# start_a, start_b = 65, 8921
|
||||
a = Generator.new(start_a, 16807).each.lazy
|
||||
b = Generator.new(start_b, 48271).each.lazy
|
||||
|
||||
p a.zip(b).take(40_000_000).with_index.count {|(a,b),i|
|
||||
p i if i % 1_000_000 == 0
|
||||
# a.to_s(2)[-16,16] == b.to_s(2)[-16,16]
|
||||
a & 0b1111111111111111 == b & 0b1111111111111111
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
require "strscan"
|
||||
|
||||
@dance = ARGF.read.strip
|
||||
@programs = (?a..?p).to_a
|
||||
|
||||
def run
|
||||
ss = StringScanner.new(@dance)
|
||||
until ss.eos?
|
||||
case
|
||||
when ss.scan(/s(\d+)/)
|
||||
@programs.rotate!(@programs.size - ss[1].to_i)
|
||||
when ss.scan(/x(\d+)\/(\d+)/)
|
||||
a, b = ss[1].to_i, ss[2].to_i
|
||||
@programs[a], @programs[b] = @programs[b], @programs[a]
|
||||
when ss.scan(/p(\w)\/(\w)/)
|
||||
a, b = @programs.index(ss[1]), @programs.index(ss[2])
|
||||
@programs[a], @programs[b] = @programs[b], @programs[a]
|
||||
when ss.scan(/,/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@memoized = {}
|
||||
count = 0
|
||||
until @memoized.has_key?(@programs.join)
|
||||
@memoized[@programs.join] = count
|
||||
run
|
||||
count += 1
|
||||
end
|
||||
|
||||
mod = 1_000_000_000 % count
|
||||
p @memoized.find {|_,v| v == mod }.first
|
@ -1,21 +0,0 @@
|
||||
input = ARGF.read.strip.to_i
|
||||
# input = 3
|
||||
|
||||
# buffer = [0]
|
||||
pos = 0
|
||||
50_000_000.times do |i|
|
||||
# 10.times do |i|
|
||||
pos += input + 1
|
||||
# pos %= buffer.size
|
||||
pos %= i + 1
|
||||
|
||||
p i+1 if pos.zero?
|
||||
|
||||
# buffer = (buffer[0..pos] << i+1).concat(buffer[pos+1..-1])
|
||||
end
|
||||
|
||||
# index = buffer.index(0)
|
||||
# p buffer[index+1]
|
||||
|
||||
# So 0 is always element 0...
|
||||
# So we just need to know when something is inserted at element 1?
|
@ -1,36 +0,0 @@
|
||||
diagram = ARGF.read.split("\n").map(&:chars)
|
||||
|
||||
dir = [0, 1]
|
||||
y = 0
|
||||
x = diagram[y].index(?|)
|
||||
|
||||
begin
|
||||
steps = 0
|
||||
loop do
|
||||
case diagram[y][x]
|
||||
when ?+
|
||||
dir = if dir[0] == 0 # going vertically
|
||||
if (diagram[y][x-1] || " ") != " "
|
||||
[-1, 0]
|
||||
else
|
||||
[1, 0]
|
||||
end
|
||||
else # going horizontally
|
||||
if (diagram[y-1][x] || " ") != " "
|
||||
[0, -1]
|
||||
else
|
||||
[0, 1]
|
||||
end
|
||||
end
|
||||
when /[a-z]/i
|
||||
# print diagram[y][x]
|
||||
when /\||\+|-/
|
||||
else
|
||||
raise diagram[y][x]
|
||||
end
|
||||
x,y = [x,y].zip(dir).map {|a,b| a + b}
|
||||
steps += 1
|
||||
end
|
||||
rescue
|
||||
puts steps
|
||||
end
|
@ -1 +0,0 @@
|
||||
target
|
@ -1,247 +0,0 @@
|
||||
[[package]]
|
||||
name = "advent_of_code_2017"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "dbghelp-sys"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
|
||||
"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e"
|
||||
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
|
||||
"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||
"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
|
||||
"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||
"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
|
||||
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
|
||||
"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322"
|
||||
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
|
||||
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
@ -1,10 +0,0 @@
|
||||
[package]
|
||||
name = "advent_of_code_2017"
|
||||
version = "0.1.0"
|
||||
authors = ["Alpha Chen <alpha.chen@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
failure = "0.1"
|
||||
lazy_static = "1.0"
|
||||
regex = "0.2"
|
||||
time = ""
|
@ -1,32 +0,0 @@
|
||||
use failure::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn solve(input: &str) -> Result<String, Error> {
|
||||
let input: Vec<u32> = input
|
||||
.trim()
|
||||
.chars()
|
||||
.map(|x| x.to_digit(10).ok_or_else(|| err_msg("")))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
// 1
|
||||
// let offset = 1;
|
||||
let offset = input.len() / 2;
|
||||
|
||||
let offset_iter = input.iter().cycle().skip(offset);
|
||||
Ok(input
|
||||
.iter()
|
||||
.zip(offset_iter)
|
||||
.filter(|&a| a.0 == a.1)
|
||||
.map(|a| a.0)
|
||||
.sum::<u32>()
|
||||
.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part_two() {
|
||||
assert_eq!(solve("1212").unwrap(), "6".to_string());
|
||||
assert_eq!(solve("1221").unwrap(), "0".to_string());
|
||||
assert_eq!(solve("123425").unwrap(), "4".to_string());
|
||||
assert_eq!(solve("123123").unwrap(), "12".to_string());
|
||||
assert_eq!(solve("12131415").unwrap(), "4".to_string());
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
use failure::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn solve(input: &str) -> Result<String, Error> {
|
||||
Ok(input
|
||||
.trim()
|
||||
.split('\n')
|
||||
.map(|row| {
|
||||
row.split('\t')
|
||||
.map(|x| x.parse::<usize>().unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.map(|row| checksum(&row))
|
||||
.sum::<usize>()
|
||||
.to_string())
|
||||
}
|
||||
|
||||
fn checksum(row: &[usize]) -> usize {
|
||||
// 1
|
||||
// let min = row.iter().min().unwrap();
|
||||
// let max = row.iter().max().unwrap();
|
||||
// max - min
|
||||
|
||||
row.iter()
|
||||
.flat_map(|x| row.iter().map(|y| (x, y)).collect::<Vec<_>>())
|
||||
.filter(|&(a, b)| a != b)
|
||||
.filter(|&(&a, &b)| (a as f64) % (b as f64) == 0.0)
|
||||
.map(|(&a, &b)| a / b)
|
||||
.next()
|
||||
.unwrap()
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::iter;
|
||||
use failure::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn solve(input: &str) -> Result<String, Error> {
|
||||
let input: usize = input.trim().parse()?;
|
||||
|
||||
// 1
|
||||
// spiral()
|
||||
// .zip(1..)
|
||||
// .find(|&(_, i)| i == (square - 1))
|
||||
// .map(|(coord, _)| (coord.0 + coord.1).to_string())
|
||||
// .ok_or_else(|| format_err!(""))
|
||||
|
||||
// 2
|
||||
let mut grid = HashMap::new();
|
||||
grid.insert(Coord(0, 0), 1);
|
||||
spiral()
|
||||
.map(|coord| {
|
||||
let sum = coord.neighbors().iter().filter_map(|x| grid.get(x)).sum();
|
||||
grid.insert(coord, sum);
|
||||
sum
|
||||
})
|
||||
.find(|value| value > &input)
|
||||
.map(|value| value.to_string())
|
||||
.ok_or_else(|| err_msg(""))
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
struct Coord(isize, isize);
|
||||
|
||||
impl Coord {
|
||||
#[allow(dead_code)]
|
||||
fn neighbors(&self) -> Vec<Coord> {
|
||||
vec![
|
||||
[-1, 1],
|
||||
[0, 1],
|
||||
[1, 1],
|
||||
[-1, 0],
|
||||
[1, 0],
|
||||
[-1, -1],
|
||||
[0, -1],
|
||||
[1, -1],
|
||||
].iter()
|
||||
.map(|delta| Coord(self.0 + delta[0], self.1 + delta[1]))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
enum Dir {
|
||||
Right,
|
||||
Up,
|
||||
Left,
|
||||
Down,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
lazy_static! {
|
||||
static ref DIRS: Vec<Dir> = vec![Dir::Right, Dir::Up, Dir::Left, Dir::Down];
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn spiral() -> impl Iterator<Item = Coord> {
|
||||
(1..)
|
||||
.flat_map(|x| iter::repeat(x).take(2))
|
||||
.zip(DIRS.iter().cycle())
|
||||
.flat_map(|(steps, dir)| iter::repeat(dir).take(steps))
|
||||
.scan(Coord(0, 0), |state, &dir| {
|
||||
*state = match dir {
|
||||
Dir::Right => Coord(state.0 + 1, state.1),
|
||||
Dir::Up => Coord(state.0, state.1 + 1),
|
||||
Dir::Left => Coord(state.0 - 1, state.1),
|
||||
Dir::Down => Coord(state.0, state.1 - 1),
|
||||
};
|
||||
Some(*state)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_coords() {
|
||||
let mut spiral = spiral();
|
||||
assert_eq!(spiral.next(), Some(Coord(1, 0)));
|
||||
assert_eq!(spiral.next(), Some(Coord(1, 1)));
|
||||
assert_eq!(spiral.next(), Some(Coord(0, 1)));
|
||||
assert_eq!(spiral.next(), Some(Coord(-1, 1)));
|
||||
assert_eq!(spiral.next(), Some(Coord(-1, 0)));
|
||||
assert_eq!(spiral.next(), Some(Coord(-1, -1)));
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
use std::collections::HashSet;
|
||||
use failure::Error;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn solve(input: &str) -> Result<String, Error> {
|
||||
Ok(input
|
||||
.trim()
|
||||
.lines()
|
||||
.map(|line| Passphrase { words: line.into() })
|
||||
.filter(Passphrase::is_valid)
|
||||
.count()
|
||||
.to_string())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct Passphrase {
|
||||
words: String,
|
||||
}
|
||||
|
||||
impl Passphrase {
|
||||
#[allow(dead_code)]
|
||||
fn is_valid(&self) -> bool {
|
||||
let mut words = HashSet::new();
|
||||
!self.words
|
||||
.split_whitespace()
|
||||
.map(|word| {
|
||||
let mut chars: Vec<String> = word.chars().map(|x| x.to_string()).collect();
|
||||
chars.sort();
|
||||
chars.as_slice().join("")
|
||||
})
|
||||
.any(|word| {
|
||||
if words.contains(&word) {
|
||||
return true;
|
||||
}
|
||||
words.insert(word);
|
||||
false
|
||||
})
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use failure::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn solve(input: &str) -> Result<String, Error> {
|
||||
let mut jumps: HashMap<isize, isize> = input
|
||||
.trim()
|
||||
.lines()
|
||||
.enumerate()
|
||||
.map(|(i, x)| x.parse().map(|x| (i as isize, x)))
|
||||
.collect::<Result<_, _>>()?;
|
||||
let mut pc = 0;
|
||||
let mut steps = 0;
|
||||
while let Entry::Occupied(mut entry) = jumps.entry(pc) {
|
||||
let offset = entry.get_mut();
|
||||
pc += *offset;
|
||||
if *offset >= 3 {
|
||||
*offset -= 1;
|
||||
} else {
|
||||
*offset += 1;
|
||||
}
|
||||
steps += 1;
|
||||
}
|
||||
Ok(steps.to_string())
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
use std::collections::HashSet;
|
||||
use failure::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn solve(input: &str) -> Result<String, Error> {
|
||||
let banks: Vec<_> = input
|
||||
.split_whitespace()
|
||||
.map(str::parse)
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
let mut reallocation = Reallocation {
|
||||
banks: banks.clone(),
|
||||
};
|
||||
let cycles = unique_cycles(reallocation);
|
||||
|
||||
reallocation = Reallocation { banks };
|
||||
Ok((unique_cycles(reallocation.skip(cycles - 1)) - 1).to_string())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn unique_cycles<R: Iterator<Item = Vec<usize>>>(reallocation: R) -> usize {
|
||||
let mut seen = HashSet::new();
|
||||
for (i, banks) in reallocation.enumerate() {
|
||||
if seen.contains(&banks) {
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
seen.insert(banks.clone());
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_one() {
|
||||
let reallocation = Reallocation {
|
||||
banks: vec![0, 2, 7, 0],
|
||||
};
|
||||
assert_eq!(unique_cycles(reallocation), 5);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct Reallocation {
|
||||
banks: Vec<usize>,
|
||||
}
|
||||
|
||||
impl Iterator for Reallocation {
|
||||
type Item = Vec<usize>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let banks = self.banks.clone();
|
||||
let mut banks: Vec<_> = banks.iter().enumerate().collect();
|
||||
banks.reverse();
|
||||
let (start, max) = banks
|
||||
.iter()
|
||||
.max_by_key(|&&(_, x)| x)
|
||||
.map(|&(i, x)| (i, *x))?;
|
||||
|
||||
let len = self.banks.len();
|
||||
self.banks[start] = 0;
|
||||
for i in 1..=max {
|
||||
self.banks[(start + i) % len] += 1;
|
||||
}
|
||||
|
||||
Some(self.banks.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reallocation() {
|
||||
let mut r = Reallocation {
|
||||
banks: vec![0, 2, 7, 0],
|
||||
};
|
||||
assert_eq!(r.next(), Some(vec![2, 4, 1, 2]));
|
||||
assert_eq!(r.next(), Some(vec![3, 1, 2, 3]));
|
||||
assert_eq!(r.next(), Some(vec![0, 2, 3, 4]));
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
use failure::*;
|
||||
use regex::Regex;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn solve(input: &str) -> Result<String, Error> {
|
||||
let re: Regex = Regex::new(r"\d+")?;
|
||||
let matches: Vec<_> = re.find_iter(input)
|
||||
.map(|x| x.as_str())
|
||||
.map(str::parse)
|
||||
.collect::<Result<_, _>>()?;
|
||||
let a_start = matches[0];
|
||||
let b_start = matches[1];
|
||||
// let a_start = 679;
|
||||
// let b_start = 771;
|
||||
|
||||
let a = Generator {
|
||||
value: a_start,
|
||||
factor: 16_807,
|
||||
};
|
||||
let b = Generator {
|
||||
value: b_start,
|
||||
factor: 48_271,
|
||||
};
|
||||
|
||||
let answer = a.filter(|a| a % 4 == 0)
|
||||
.zip(b.filter(|b| b % 8 == 0))
|
||||
.take(5_000_000)
|
||||
.filter(|&(a, b)| a & 0b1111_1111_1111_1111 == b & 0b1111_1111_1111_1111)
|
||||
.count();
|
||||
Ok(answer.to_string())
|
||||
}
|
||||
|
||||
struct Generator {
|
||||
value: usize,
|
||||
factor: usize,
|
||||
}
|
||||
|
||||
impl Iterator for Generator {
|
||||
type Item = usize;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.value *= self.factor;
|
||||
self.value %= 2_147_483_647;
|
||||
Some(self.value)
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use failure::*;
|
||||
use regex::Regex;
|
||||
|
||||
pub fn solve(input: &str) -> Result<String, Error> {
|
||||
// let input = "s1,x3/4,pe/b";
|
||||
let moves = input
|
||||
.split(',')
|
||||
.map(Move::try_from)
|
||||
.collect::<Result<_, _>>()?;
|
||||
let programs = (b'a'..=b'p').map(|c| c as char).collect();
|
||||
let dance = Dance { moves, programs };
|
||||
|
||||
// dance.next();
|
||||
// Ok(dance.next().unwrap().iter().collect::<String>())
|
||||
|
||||
let history = dance
|
||||
.enumerate()
|
||||
.scan(HashMap::new(), |state, (i, programs)| {
|
||||
if state.contains_key(&programs) {
|
||||
None
|
||||
} else {
|
||||
state.insert(programs, i);
|
||||
Some(state.clone())
|
||||
}
|
||||
})
|
||||
.last()
|
||||
.unwrap();
|
||||
let index = 1_000_000_000 % history.len();
|
||||
Ok(history
|
||||
.iter()
|
||||
.find(|(_, &v)| v == &index)
|
||||
.map(|(k, _)| k)
|
||||
.unwrap()
|
||||
.iter()
|
||||
.collect())
|
||||
}
|
||||
|
||||
struct Dance {
|
||||
moves: Vec<Move>,
|
||||
programs: Vec<char>,
|
||||
}
|
||||
|
||||
impl Iterator for Dance {
|
||||
type Item = Vec<char>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let item = self.programs.clone();
|
||||
|
||||
for m in &self.moves {
|
||||
match m {
|
||||
Move::Spin(size) => {
|
||||
let len = self.programs.len();
|
||||
self.programs.rotate(len - size);
|
||||
}
|
||||
Move::Exchange(a, b) => {
|
||||
self.programs.swap(*a, *b);
|
||||
}
|
||||
Move::Partner(a, b) => {
|
||||
let a = self.programs.iter().position(|x| x == a).unwrap();
|
||||
let b = self.programs.iter().position(|x| x == b).unwrap();
|
||||
self.programs.swap(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(item)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dance() {
|
||||
let moves = vec![Move::Spin(1), Move::Exchange(3, 4), Move::Partner('e', 'b')];
|
||||
let programs = (b'a'..=b'e').map(|c| c as char).collect();
|
||||
let mut dance = Dance { moves, programs };
|
||||
|
||||
assert_eq!(dance.next().unwrap(), vec!['a', 'b', 'c', 'd', 'e']);
|
||||
assert_eq!(dance.next().unwrap(), vec!['b', 'a', 'e', 'd', 'c']);
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
enum Move {
|
||||
Spin(usize),
|
||||
Exchange(usize, usize),
|
||||
Partner(char, char),
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref RE_S: Regex = { Regex::new(r"s(\d+)").unwrap() };
|
||||
static ref RE_X: Regex = { Regex::new(r"x(\d+)/(\d+)").unwrap() };
|
||||
static ref RE_P: Regex = { Regex::new(r"p(\w)/(\w)").unwrap() };
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a str> for Move {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
RE_S.captures(value)
|
||||
.and_then(|c| {
|
||||
let size = c.get(1).unwrap().as_str().parse().ok()?;
|
||||
Some(Move::Spin(size))
|
||||
})
|
||||
.or_else(|| {
|
||||
RE_X.captures(value).and_then(|c| {
|
||||
let a = c.get(1).unwrap().as_str().parse().ok()?;
|
||||
let b = c.get(2).unwrap().as_str().parse().ok()?;
|
||||
Some(Move::Exchange(a, b))
|
||||
})
|
||||
})
|
||||
.or_else(|| {
|
||||
RE_P.captures(value).and_then(|c| {
|
||||
let a = c.get(1).unwrap().as_str().chars().next()?;
|
||||
let b = c.get(2).unwrap().as_str().chars().next()?;
|
||||
Some(Move::Partner(a, b))
|
||||
})
|
||||
})
|
||||
.ok_or_else(|| format_err!("invalid move: {}", value))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_move_try_from() {
|
||||
assert_eq!(Move::try_from("s1").unwrap(), Move::Spin(1));
|
||||
assert_eq!(Move::try_from("x3/4").unwrap(), Move::Exchange(3, 4));
|
||||
assert_eq!(Move::try_from("pe/b").unwrap(), Move::Partner('e', 'b'));
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#![feature(conservative_impl_trait, inclusive_range_syntax, match_default_bindings, slice_rotate,
|
||||
try_from)]
|
||||
|
||||
extern crate failure;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate regex;
|
||||
extern crate time;
|
||||
|
||||
use std::io::{self, Read};
|
||||
|
||||
use failure::Error;
|
||||
|
||||
mod day_01;
|
||||
mod day_02;
|
||||
mod day_03;
|
||||
mod day_04;
|
||||
mod day_05;
|
||||
mod day_06;
|
||||
mod day_15;
|
||||
mod day_16;
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = run() {
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
fn run() -> Result<(), Error> {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input)?;
|
||||
|
||||
let solution = day_16::solve(&input)?;
|
||||
println!("{}", solution);
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
||||
|
||||
gem "minitest"
|
||||
gem "pry"
|
@ -1,19 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
coderay (1.1.2)
|
||||
method_source (0.9.2)
|
||||
minitest (5.11.3)
|
||||
pry (0.12.2)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
minitest
|
||||
pry
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.1
|
@ -1,8 +0,0 @@
|
||||
require "set"
|
||||
|
||||
seen = Set.new
|
||||
ARGF.read.lines.map(&:to_i).cycle.each.with_object([0]) do |i,n|
|
||||
n[0] += i
|
||||
p n[0] and exit if seen.include?(n[0])
|
||||
seen << n[0]
|
||||
end
|
@ -1,11 +0,0 @@
|
||||
a = ARGF.read.lines.map(&:chomp).map(&:chars)
|
||||
# two = a.count {|i| i.any? {|x| i.count(x) == 2} }
|
||||
# three = a.count {|i| i.any? {|x| i.count(x) == 3} }
|
||||
# puts two * three
|
||||
x,y = a.flat_map {|i|
|
||||
a.select {|j|
|
||||
i.zip(j).select {|a,b| a != b }.count == 1
|
||||
}
|
||||
}.map(&:join)
|
||||
|
||||
p x.chars.zip(y.chars).select {|a,b| a == b }.map(&:first).join
|
@ -1,27 +0,0 @@
|
||||
claims, fabric = ARGF
|
||||
.read
|
||||
.lines
|
||||
.map(&:chomp)
|
||||
.reject(&:empty?)
|
||||
.each
|
||||
.with_object([[], Hash.new {|h,k| h[k] = []}]) { |line, (claims, fabric)|
|
||||
line =~ /^#(\d+) @ (\d+),(\d+): (\d+)x(\d+)$/
|
||||
claim = $1.to_i
|
||||
x = $2.to_i
|
||||
y = $3.to_i
|
||||
width = $4.to_i
|
||||
height = $5.to_i
|
||||
|
||||
claims << claim
|
||||
width.times {|dx|
|
||||
height.times {|dy|
|
||||
fabric[[y+dy, x+dx]] << claim
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p claims.reject {|claim|
|
||||
fabric.any? {|_,v|
|
||||
v.length > 1 && v.include?(claim)
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
records = ARGF.read.chomp.lines.map(&:chomp).sort
|
||||
# puts records
|
||||
|
||||
stats = Hash.new {|h,k| h[k] = [] }
|
||||
|
||||
guard = nil
|
||||
fell_asleep_at = nil
|
||||
records.each do |record|
|
||||
if record =~ /\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}\] Guard \#(\d+) begins shift/
|
||||
guard = $1.to_i
|
||||
elsif record =~ /\[\d{4}-\d{2}-\d{2} \d{2}:(\d{2})\] falls asleep/
|
||||
fell_asleep_at = $1.to_i
|
||||
elsif record =~ /\[\d{4}-\d{2}-\d{2} \d{2}:(\d{2})\] wakes up/
|
||||
stats[guard].concat((fell_asleep_at...$1.to_i).to_a)
|
||||
else
|
||||
p record
|
||||
end
|
||||
end
|
||||
|
||||
stats.transform_values! {|v| v.group_by(&:itself).transform_values(&:count) }
|
||||
|
||||
# Part One
|
||||
guard, minutes = stats.max_by {|_,v| v.values.sum }
|
||||
minute = minutes.max_by(&:last).first
|
||||
p guard * minute
|
||||
|
||||
# Part Two
|
||||
guard, (minute, _) = stats.map {|k,v| [k, v.max_by(&:last)] }.max_by {|_,(_,v)| v }
|
||||
p guard * minute
|
@ -1,29 +0,0 @@
|
||||
input = ARGF.read.chomp
|
||||
|
||||
REGEX = Regexp.new(
|
||||
(?a..?z)
|
||||
.map {|x| [x, x.upcase] }
|
||||
.flat_map(&:permutation)
|
||||
.flat_map(&:to_a)
|
||||
.map(&:join)
|
||||
.join(?|)
|
||||
)
|
||||
|
||||
def react(polymer)
|
||||
last = nil
|
||||
until polymer == last
|
||||
last = polymer
|
||||
polymer = polymer.gsub(REGEX, "")
|
||||
end
|
||||
polymer
|
||||
end
|
||||
|
||||
# Part One
|
||||
# p react(input).size
|
||||
|
||||
# Part Two
|
||||
p (?a..?z)
|
||||
.map {|unit| input.gsub(/#{unit}/i, "") }
|
||||
.map {|polymer| react(polymer) }
|
||||
.map {|reacted| reacted.size }
|
||||
.min
|
@ -1,49 +0,0 @@
|
||||
require "set"
|
||||
|
||||
coords = ARGF.read.chomp.lines.map(&:chomp).map {|line| line.split(", ").map(&:to_i) }
|
||||
|
||||
x_min = coords.map(&:first).min
|
||||
x_max = coords.map(&:first).max
|
||||
y_min = coords.map(&:last).min
|
||||
y_max = coords.map(&:last).max
|
||||
|
||||
coords = coords.map.with_index {|c,i| [i, c] }
|
||||
|
||||
p coords
|
||||
|
||||
p x_min, x_max, y_min, y_max
|
||||
|
||||
def manhattan_distance(a, b)
|
||||
(a[0] - b[0]).abs + (a[1] - b[1]).abs
|
||||
end
|
||||
|
||||
grid = {}
|
||||
(x_min..x_max).each do |x|
|
||||
(y_min..y_max).each do |y|
|
||||
# Part One
|
||||
# distances = coords.map {|id, coord|
|
||||
# [id, manhattan_distance(coord, [x,y])]
|
||||
# }
|
||||
# min_distance = distances.map(&:last).min
|
||||
# closests = distances.select {|_,distance| distance == min_distance }
|
||||
# grid[[x,y]] = closests.length > 1 ? nil : closests.first.first
|
||||
|
||||
# Part Two
|
||||
total_distance = coords.map {|_,coord| manhattan_distance(coord, [x,y]) }.sum
|
||||
grid[[x,y]] = true if total_distance < 10000
|
||||
end
|
||||
end
|
||||
|
||||
# Part One
|
||||
# infinites = Set.new
|
||||
# (x_min..x_max).each do |x|
|
||||
# infinites << grid[[x,y_min]]
|
||||
# infinites << grid[[x,y_max]]
|
||||
# end
|
||||
# (y_min..y_max).each do |y|
|
||||
# infinites << grid[[x_min,y]]
|
||||
# infinites << grid[[x_max,y]]
|
||||
# end
|
||||
# p grid.values.group_by(&:itself).transform_values(&:count).reject {|k,_| infinites.include?(k) }.max_by(&:last)
|
||||
|
||||
p grid.size
|
@ -1,33 +0,0 @@
|
||||
class Node
|
||||
def self.from(raw)
|
||||
child_count = raw.shift
|
||||
metadata_count = raw.shift
|
||||
|
||||
children = child_count.times.map { Node.from(raw) }
|
||||
metadata = metadata_count.times.map { raw.shift }
|
||||
|
||||
Node.new(children, metadata)
|
||||
end
|
||||
|
||||
def initialize(children, metadata)
|
||||
@children, @metadata = children, metadata
|
||||
end
|
||||
|
||||
def checksum
|
||||
@metadata.sum + @children.map(&:checksum).sum
|
||||
end
|
||||
|
||||
def value
|
||||
if @children.empty?
|
||||
@metadata.sum
|
||||
else
|
||||
@metadata.flat_map {|index|
|
||||
@children.fetch(index-1, [])
|
||||
}.map(&:value).sum
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
raw = ARGF.read.chomp.split(/\s+/).map(&:to_i)
|
||||
root = Node.from(raw)
|
||||
p root.value
|
@ -1,45 +0,0 @@
|
||||
Node = Struct.new(*%i[ value next prev ]) do
|
||||
def to_s
|
||||
out = [value]
|
||||
current = self
|
||||
loop do
|
||||
current = current.next
|
||||
break if current == self
|
||||
out << current.value
|
||||
end
|
||||
out.join(" ")
|
||||
end
|
||||
end
|
||||
|
||||
ARGF.read.chomp =~ /(\d+) players; last marble is worth (\d+) points/
|
||||
num_players = $1.to_i
|
||||
num_marbles = $2.to_i * 100
|
||||
|
||||
current = Node.new(0, nil, nil)
|
||||
current.next = current.prev = current
|
||||
|
||||
current_player = 0
|
||||
scores = Array.new(num_players, 0)
|
||||
|
||||
(1...num_marbles).each do |marble|
|
||||
if marble % 23 == 0
|
||||
scores[current_player] += marble
|
||||
7.times { current = current.prev }
|
||||
scores[current_player] += current.value
|
||||
current.next.prev = current.prev
|
||||
current.prev.next = current.next
|
||||
current = current.next
|
||||
else
|
||||
current = current.next
|
||||
current.next = Node.new(marble, current.next, current)
|
||||
current = current.next
|
||||
current.next.prev = current
|
||||
end
|
||||
|
||||
# puts "[#{current_player + 1}] #{current}"
|
||||
puts marble if marble % 100000 == 0
|
||||
|
||||
current_player = (current_player + 1) % num_players
|
||||
end
|
||||
|
||||
p scores.max
|
@ -1,379 +0,0 @@
|
||||
Point = Struct.new(*%i[position velocity])
|
||||
|
||||
points = <<~POINTS
|
||||
position=< 21992, -10766> velocity=<-2, 1>
|
||||
position=<-43366, -21661> velocity=< 4, 2>
|
||||
position=<-10714, -21661> velocity=< 1, 2>
|
||||
position=< 21993, 32773> velocity=<-2, -3>
|
||||
position=< 43745, 32772> velocity=<-4, -3>
|
||||
position=< 43742, 43664> velocity=<-4, -4>
|
||||
position=<-43327, 43662> velocity=< 4, -4>
|
||||
position=<-43373, 43655> velocity=< 4, -4>
|
||||
position=<-10677, 32773> velocity=< 1, -3>
|
||||
position=<-43324, 43664> velocity=< 4, -4>
|
||||
position=<-32447, 43664> velocity=< 3, -4>
|
||||
position=< 21946, -54317> velocity=<-2, 5>
|
||||
position=< 11051, -10772> velocity=<-1, 1>
|
||||
position=< 32824, -21652> velocity=<-3, 2>
|
||||
position=< 11092, -21655> velocity=<-1, 2>
|
||||
position=< 32863, 11002> velocity=<-3, -1>
|
||||
position=<-21562, 10997> velocity=< 2, -1>
|
||||
position=<-10725, 43662> velocity=< 1, -4>
|
||||
position=< 11074, 11006> velocity=<-1, -1>
|
||||
position=<-54209, -10768> velocity=< 5, 1>
|
||||
position=< 43710, -10774> velocity=<-4, 1>
|
||||
position=< 54615, 54544> velocity=<-5, -5>
|
||||
position=< 32859, -21659> velocity=<-3, 2>
|
||||
position=< 11052, 10997> velocity=<-1, -1>
|
||||
position=< 21957, -32542> velocity=<-2, 3>
|
||||
position=<-10714, 10997> velocity=< 1, -1>
|
||||
position=< 32847, -21652> velocity=<-3, 2>
|
||||
position=<-21561, -32547> velocity=< 2, 3>
|
||||
position=< 11074, 21887> velocity=<-1, -2>
|
||||
position=<-43339, -21656> velocity=< 4, 2>
|
||||
position=< 54643, 54541> velocity=<-5, -5>
|
||||
position=<-32477, -32547> velocity=< 3, 3>
|
||||
position=<-21571, 11005> velocity=< 2, -1>
|
||||
position=<-10701, -54314> velocity=< 1, 5>
|
||||
position=<-21584, -43429> velocity=< 2, 4>
|
||||
position=<-21595, -32542> velocity=< 2, 3>
|
||||
position=< 54594, 21887> velocity=<-5, -2>
|
||||
position=< 21970, 32774> velocity=<-2, -3>
|
||||
position=<-54237, -43425> velocity=< 5, 4>
|
||||
position=< 43732, -54319> velocity=<-4, 5>
|
||||
position=<-32488, -10766> velocity=< 3, 1>
|
||||
position=<-32473, -43433> velocity=< 3, 4>
|
||||
position=<-43370, 10998> velocity=< 4, -1>
|
||||
position=<-43347, 32777> velocity=< 4, -3>
|
||||
position=<-32460, 11002> velocity=< 3, -1>
|
||||
position=< 21962, -21659> velocity=<-2, 2>
|
||||
position=< 21981, 21889> velocity=<-2, -2>
|
||||
position=<-32437, -21656> velocity=< 3, 2>
|
||||
position=<-43347, -21653> velocity=< 4, 2>
|
||||
position=< 54652, 54541> velocity=<-5, -5>
|
||||
position=<-21606, -54319> velocity=< 2, 5>
|
||||
position=< 11055, 54549> velocity=<-1, -5>
|
||||
position=<-54259, 21892> velocity=< 5, -2>
|
||||
position=< 54636, 32777> velocity=<-5, -3>
|
||||
position=<-54224, 11006> velocity=< 5, -1>
|
||||
position=<-10723, -54310> velocity=< 1, 5>
|
||||
position=< 32856, 54547> velocity=<-3, -5>
|
||||
position=< 11052, 11006> velocity=<-1, -1>
|
||||
position=<-10674, -54319> velocity=< 1, 5>
|
||||
position=< 11071, -54317> velocity=<-1, 5>
|
||||
position=< 11075, 54541> velocity=<-1, -5>
|
||||
position=<-54226, 21888> velocity=< 5, -2>
|
||||
position=< 21962, 32774> velocity=<-2, -3>
|
||||
position=<-54251, 21883> velocity=< 5, -2>
|
||||
position=< 54628, -32540> velocity=<-5, 3>
|
||||
position=< 11087, 32770> velocity=<-1, -3>
|
||||
position=< 54594, 43659> velocity=<-5, -4>
|
||||
position=< 43748, 32778> velocity=<-4, -3>
|
||||
position=< 32854, 32778> velocity=<-3, -3>
|
||||
position=< 54639, -32542> velocity=<-5, 3>
|
||||
position=<-43367, -43425> velocity=< 4, 4>
|
||||
position=< 54651, -21660> velocity=<-5, 2>
|
||||
position=< 11087, 10999> velocity=<-1, -1>
|
||||
position=<-43379, 32778> velocity=< 4, -3>
|
||||
position=< 43737, -32543> velocity=<-4, 3>
|
||||
position=<-43382, 43655> velocity=< 4, -4>
|
||||
position=<-10684, -43433> velocity=< 1, 4>
|
||||
position=<-54250, 54550> velocity=< 5, -5>
|
||||
position=< 11095, -21657> velocity=<-1, 2>
|
||||
position=< 32836, 10997> velocity=<-3, -1>
|
||||
position=<-54209, -32540> velocity=< 5, 3>
|
||||
position=< 11050, 21892> velocity=<-1, -2>
|
||||
position=<-21587, 10999> velocity=< 2, -1>
|
||||
position=< 43725, 54550> velocity=<-4, -5>
|
||||
position=<-54221, 32771> velocity=< 5, -3>
|
||||
position=< 11087, 54546> velocity=<-1, -5>
|
||||
position=< 11088, -32538> velocity=<-1, 3>
|
||||
position=< 21986, -10774> velocity=<-2, 1>
|
||||
position=< 11071, 10998> velocity=<-1, -1>
|
||||
position=< 54631, 43661> velocity=<-5, -4>
|
||||
position=<-32462, 21892> velocity=< 3, -2>
|
||||
position=<-32464, -43433> velocity=< 3, 4>
|
||||
position=<-32485, -10772> velocity=< 3, 1>
|
||||
position=< 43707, 21888> velocity=<-4, -2>
|
||||
position=< 54602, -32538> velocity=<-5, 3>
|
||||
position=<-43335, -32546> velocity=< 4, 3>
|
||||
position=< 54639, -10769> velocity=<-5, 1>
|
||||
position=<-21551, -21656> velocity=< 2, 2>
|
||||
position=<-43323, -21658> velocity=< 4, 2>
|
||||
position=< 43718, 32770> velocity=<-4, -3>
|
||||
position=<-10709, 43662> velocity=< 1, -4>
|
||||
position=< 43749, 10997> velocity=<-4, -1>
|
||||
position=< 32859, 11002> velocity=<-3, -1>
|
||||
position=< 32839, -43433> velocity=<-3, 4>
|
||||
position=< 21975, -10775> velocity=<-2, 1>
|
||||
position=< 11088, 11006> velocity=<-1, -1>
|
||||
position=<-10716, 21892> velocity=< 1, -2>
|
||||
position=<-21560, -32538> velocity=< 2, 3>
|
||||
position=<-21591, 54541> velocity=< 2, -5>
|
||||
position=< 21968, -21661> velocity=<-2, 2>
|
||||
position=<-21579, -32545> velocity=< 2, 3>
|
||||
position=<-10721, -32547> velocity=< 1, 3>
|
||||
position=<-32468, -43430> velocity=< 3, 4>
|
||||
position=<-54260, -43427> velocity=< 5, 4>
|
||||
position=<-43333, 10997> velocity=< 4, -1>
|
||||
position=<-21579, 21884> velocity=< 2, -2>
|
||||
position=<-43343, 54545> velocity=< 4, -5>
|
||||
position=<-10708, -43424> velocity=< 1, 4>
|
||||
position=< 54601, -21661> velocity=<-5, 2>
|
||||
position=<-32460, -21654> velocity=< 3, 2>
|
||||
position=< 32848, -10770> velocity=<-3, 1>
|
||||
position=<-54209, 21886> velocity=< 5, -2>
|
||||
position=< 32844, 32773> velocity=<-3, -3>
|
||||
position=< 32839, 32778> velocity=<-3, -3>
|
||||
position=<-43374, -43427> velocity=< 4, 4>
|
||||
position=< 32827, 43662> velocity=<-3, -4>
|
||||
position=<-21583, -43433> velocity=< 2, 4>
|
||||
position=< 32819, -54311> velocity=<-3, 5>
|
||||
position=<-43371, 43655> velocity=< 4, -4>
|
||||
position=<-32437, 10997> velocity=< 3, -1>
|
||||
position=<-21566, 43664> velocity=< 2, -4>
|
||||
position=<-43371, -21658> velocity=< 4, 2>
|
||||
position=< 43707, -32542> velocity=<-4, 3>
|
||||
position=<-21551, 11003> velocity=< 2, -1>
|
||||
position=<-21599, 11006> velocity=< 2, -1>
|
||||
position=< 11057, 43660> velocity=<-1, -4>
|
||||
position=<-21571, -10773> velocity=< 2, 1>
|
||||
position=< 54609, -43424> velocity=<-5, 4>
|
||||
position=<-32473, -54311> velocity=< 3, 5>
|
||||
position=<-21587, -54310> velocity=< 2, 5>
|
||||
position=<-43370, -54310> velocity=< 4, 5>
|
||||
position=< 54627, 21883> velocity=<-5, -2>
|
||||
position=< 54620, 32777> velocity=<-5, -3>
|
||||
position=<-32473, -54316> velocity=< 3, 5>
|
||||
position=< 54615, 21892> velocity=<-5, -2>
|
||||
position=<-21579, -54313> velocity=< 2, 5>
|
||||
position=<-43370, -21652> velocity=< 4, 2>
|
||||
position=<-10709, -54313> velocity=< 1, 5>
|
||||
position=< 43737, 32777> velocity=<-4, -3>
|
||||
position=< 32843, 11000> velocity=<-3, -1>
|
||||
position=<-43383, -32547> velocity=< 4, 3>
|
||||
position=<-43359, 43661> velocity=< 4, -4>
|
||||
position=<-10720, -43433> velocity=< 1, 4>
|
||||
position=< 54620, 32772> velocity=<-5, -3>
|
||||
position=< 43739, 21892> velocity=<-4, -2>
|
||||
position=< 54615, 43656> velocity=<-5, -4>
|
||||
position=<-32471, 32769> velocity=< 3, -3>
|
||||
position=<-54232, 21884> velocity=< 5, -2>
|
||||
position=< 11107, -10769> velocity=<-1, 1>
|
||||
position=<-43383, 21890> velocity=< 4, -2>
|
||||
position=< 21951, 54550> velocity=<-2, -5>
|
||||
position=< 43747, -21661> velocity=<-4, 2>
|
||||
position=<-32494, -43433> velocity=< 3, 4>
|
||||
position=<-21563, -54316> velocity=< 2, 5>
|
||||
position=<-54224, 11002> velocity=< 5, -1>
|
||||
position=<-43372, -32538> velocity=< 4, 3>
|
||||
position=<-43342, -21652> velocity=< 4, 2>
|
||||
position=< 11079, 54548> velocity=<-1, -5>
|
||||
position=< 11106, -32538> velocity=<-1, 3>
|
||||
position=<-32488, -54310> velocity=< 3, 5>
|
||||
position=< 43748, 43664> velocity=<-4, -4>
|
||||
position=< 11063, 43658> velocity=<-1, -4>
|
||||
position=<-54240, 54543> velocity=< 5, -5>
|
||||
position=< 21983, 43655> velocity=<-2, -4>
|
||||
position=<-21551, 32773> velocity=< 2, -3>
|
||||
position=<-21607, -32547> velocity=< 2, 3>
|
||||
position=<-10709, -54315> velocity=< 1, 5>
|
||||
position=< 21978, 32775> velocity=<-2, -3>
|
||||
position=< 32864, -21653> velocity=<-3, 2>
|
||||
position=<-32464, 43655> velocity=< 3, -4>
|
||||
position=< 32848, -54312> velocity=<-3, 5>
|
||||
position=< 54639, 32772> velocity=<-5, -3>
|
||||
position=<-43380, -21657> velocity=< 4, 2>
|
||||
position=<-43371, 54544> velocity=< 4, -5>
|
||||
position=< 11079, -43429> velocity=<-1, 4>
|
||||
position=< 11099, 43664> velocity=<-1, -4>
|
||||
position=< 54591, -21653> velocity=<-5, 2>
|
||||
position=<-10715, -54310> velocity=< 1, 5>
|
||||
position=< 21949, -10768> velocity=<-2, 1>
|
||||
position=<-21606, 43657> velocity=< 2, -4>
|
||||
position=<-54256, -21660> velocity=< 5, 2>
|
||||
position=<-54242, -54319> velocity=< 5, 5>
|
||||
position=< 21985, -21661> velocity=<-2, 2>
|
||||
position=<-32465, -32542> velocity=< 3, 3>
|
||||
position=<-54250, -43433> velocity=< 5, 4>
|
||||
position=< 43742, 11005> velocity=<-4, -1>
|
||||
position=<-32494, -10775> velocity=< 3, 1>
|
||||
position=< 32843, 11004> velocity=<-3, -1>
|
||||
position=<-21586, 43664> velocity=< 2, -4>
|
||||
position=<-10723, 21883> velocity=< 1, -2>
|
||||
position=<-21552, -43433> velocity=< 2, 4>
|
||||
position=<-43358, -10775> velocity=< 4, 1>
|
||||
position=< 32872, -10774> velocity=<-3, 1>
|
||||
position=<-10680, -54312> velocity=< 1, 5>
|
||||
position=<-54237, -32545> velocity=< 5, 3>
|
||||
position=< 54651, 10997> velocity=<-5, -1>
|
||||
position=<-32489, -43425> velocity=< 3, 4>
|
||||
position=<-54243, -43429> velocity=< 5, 4>
|
||||
position=< 54626, -54314> velocity=<-5, 5>
|
||||
position=< 11107, -21656> velocity=<-1, 2>
|
||||
position=<-21575, 10997> velocity=< 2, -1>
|
||||
position=< 43716, 11001> velocity=<-4, -1>
|
||||
position=<-10720, 32771> velocity=< 1, -3>
|
||||
position=< 11092, 43660> velocity=<-1, -4>
|
||||
position=< 54631, -21658> velocity=<-5, 2>
|
||||
position=< 11068, 11005> velocity=<-1, -1>
|
||||
position=< 43708, -21652> velocity=<-4, 2>
|
||||
position=<-10674, -32538> velocity=< 1, 3>
|
||||
position=< 11051, 11006> velocity=<-1, -1>
|
||||
position=< 11063, -54316> velocity=<-1, 5>
|
||||
position=< 11056, 32769> velocity=<-1, -3>
|
||||
position=<-21587, 21884> velocity=< 2, -2>
|
||||
position=< 11082, 43660> velocity=<-1, -4>
|
||||
position=< 43726, 43663> velocity=<-4, -4>
|
||||
position=< 54633, 54550> velocity=<-5, -5>
|
||||
position=< 11071, 43663> velocity=<-1, -4>
|
||||
position=<-43367, 43660> velocity=< 4, -4>
|
||||
position=<-21563, 11004> velocity=< 2, -1>
|
||||
position=< 54639, 54542> velocity=<-5, -5>
|
||||
position=< 32848, -32541> velocity=<-3, 3>
|
||||
position=<-54209, 54543> velocity=< 5, -5>
|
||||
position=<-43370, 21892> velocity=< 4, -2>
|
||||
position=< 54627, -21661> velocity=<-5, 2>
|
||||
position=< 54612, 54542> velocity=<-5, -5>
|
||||
position=< 11103, 43663> velocity=<-1, -4>
|
||||
position=< 32876, 21892> velocity=<-3, -2>
|
||||
position=< 21978, -21660> velocity=<-2, 2>
|
||||
position=< 54592, 54547> velocity=<-5, -5>
|
||||
position=<-43354, -43428> velocity=< 4, 4>
|
||||
position=< 54615, 11001> velocity=<-5, -1>
|
||||
position=<-10665, -43430> velocity=< 1, 4>
|
||||
position=<-21566, -10766> velocity=< 2, 1>
|
||||
position=< 43753, -43431> velocity=<-4, 4>
|
||||
position=< 43739, -32547> velocity=<-4, 3>
|
||||
position=<-43354, -43425> velocity=< 4, 4>
|
||||
position=<-10669, -21654> velocity=< 1, 2>
|
||||
position=< 54644, -10767> velocity=<-5, 1>
|
||||
position=< 54612, -43432> velocity=<-5, 4>
|
||||
position=< 32829, 54546> velocity=<-3, -5>
|
||||
position=< 54594, -10766> velocity=<-5, 1>
|
||||
position=< 54626, -32547> velocity=<-5, 3>
|
||||
position=<-32441, 11004> velocity=< 3, -1>
|
||||
position=< 43738, 11006> velocity=<-4, -1>
|
||||
position=<-43351, -32541> velocity=< 4, 3>
|
||||
position=< 43732, -10766> velocity=<-4, 1>
|
||||
position=< 43749, 32777> velocity=<-4, -3>
|
||||
position=<-32460, -21656> velocity=< 3, 2>
|
||||
position=< 54628, 10998> velocity=<-5, -1>
|
||||
position=< 21949, 32777> velocity=<-2, -3>
|
||||
position=<-43370, -21661> velocity=< 4, 2>
|
||||
position=<-10682, -43433> velocity=< 1, 4>
|
||||
position=<-32441, -10767> velocity=< 3, 1>
|
||||
position=< 21973, 21888> velocity=<-2, -2>
|
||||
position=< 21973, 11000> velocity=<-2, -1>
|
||||
position=< 11107, -10771> velocity=<-1, 1>
|
||||
position=<-10680, -10769> velocity=< 1, 1>
|
||||
position=< 32867, 54542> velocity=<-3, -5>
|
||||
position=<-10701, 21887> velocity=< 1, -2>
|
||||
position=<-54250, -10775> velocity=< 5, 1>
|
||||
position=< 54615, -10768> velocity=<-5, 1>
|
||||
position=<-21550, 21883> velocity=< 2, -2>
|
||||
position=<-43346, 21890> velocity=< 4, -2>
|
||||
position=<-54216, -54318> velocity=< 5, 5>
|
||||
position=<-43357, 11006> velocity=< 4, -1>
|
||||
position=<-10692, -10766> velocity=< 1, 1>
|
||||
position=< 21944, 21892> velocity=<-2, -2>
|
||||
position=< 54623, -10772> velocity=<-5, 1>
|
||||
position=< 43749, 43663> velocity=<-4, -4>
|
||||
position=< 43740, 21888> velocity=<-4, -2>
|
||||
position=<-54224, 32776> velocity=< 5, -3>
|
||||
position=<-54240, 43657> velocity=< 5, -4>
|
||||
position=<-21592, -54310> velocity=< 2, 5>
|
||||
position=< 54599, 21883> velocity=<-5, -2>
|
||||
position=< 32830, -10771> velocity=<-3, 1>
|
||||
position=< 21961, 54550> velocity=<-2, -5>
|
||||
position=<-54258, -32543> velocity=< 5, 3>
|
||||
position=< 11047, -10768> velocity=<-1, 1>
|
||||
position=< 11047, -21653> velocity=<-1, 2>
|
||||
position=< 43709, 21883> velocity=<-4, -2>
|
||||
position=< 43729, -10766> velocity=<-4, 1>
|
||||
position=<-32481, -54317> velocity=< 3, 5>
|
||||
position=<-32481, -54318> velocity=< 3, 5>
|
||||
position=< 43750, -54311> velocity=<-4, 5>
|
||||
position=<-43325, 11006> velocity=< 4, -1>
|
||||
position=<-43331, 21892> velocity=< 4, -2>
|
||||
position=< 32867, -54311> velocity=<-3, 5>
|
||||
position=< 32847, -10771> velocity=<-3, 1>
|
||||
position=< 43731, 43664> velocity=<-4, -4>
|
||||
position=< 21965, -10770> velocity=<-2, 1>
|
||||
position=<-43362, 21884> velocity=< 4, -2>
|
||||
position=< 43742, 43663> velocity=<-4, -4>
|
||||
position=< 54634, 54541> velocity=<-5, -5>
|
||||
position=<-32437, 10999> velocity=< 3, -1>
|
||||
position=< 54631, -21654> velocity=<-5, 2>
|
||||
position=<-54220, 11006> velocity=< 5, -1>
|
||||
position=< 54607, 54546> velocity=<-5, -5>
|
||||
position=<-43342, 43655> velocity=< 4, -4>
|
||||
position=< 21973, 32773> velocity=<-2, -3>
|
||||
position=<-32496, -32538> velocity=< 3, 3>
|
||||
position=< 54599, -21652> velocity=<-5, 2>
|
||||
position=<-54267, 54541> velocity=< 5, -5>
|
||||
position=< 21949, -10768> velocity=<-2, 1>
|
||||
position=< 11071, -10773> velocity=<-1, 1>
|
||||
position=< 32879, 54549> velocity=<-3, -5>
|
||||
position=<-43351, -54316> velocity=< 4, 5>
|
||||
position=<-54237, 10999> velocity=< 5, -1>
|
||||
position=<-54245, 32774> velocity=< 5, -3>
|
||||
position=<-43375, 54549> velocity=< 4, -5>
|
||||
position=< 54623, -21658> velocity=<-5, 2>
|
||||
position=<-43375, 32778> velocity=< 4, -3>
|
||||
position=<-21551, -21660> velocity=< 2, 2>
|
||||
position=< 43741, -21656> velocity=<-4, 2>
|
||||
position=<-54240, 32775> velocity=< 5, -3>
|
||||
position=< 21984, -10766> velocity=<-2, 1>
|
||||
position=<-10720, -21659> velocity=< 1, 2>
|
||||
position=< 32824, 32770> velocity=<-3, -3>
|
||||
position=< 11057, 32774> velocity=<-1, -3>
|
||||
position=<-21561, 54550> velocity=< 2, -5>
|
||||
position=< 11071, -21653> velocity=<-1, 2>
|
||||
position=<-32497, -54310> velocity=< 3, 5>
|
||||
position=< 32871, 43655> velocity=<-3, -4>
|
||||
position=<-43371, 32778> velocity=< 4, -3>
|
||||
position=<-21582, -54318> velocity=< 2, 5>
|
||||
position=< 11076, -21658> velocity=<-1, 2>
|
||||
position=< 43749, 43655> velocity=<-4, -4>
|
||||
position=< 43754, -54319> velocity=<-4, 5>
|
||||
POINTS
|
||||
|
||||
points = points.chomp.lines.map(&:chomp).map {|line|
|
||||
line =~ /position=<\s*(-?\d+),\s*(-?\d+)> velocity=<\s*(-?\d+),\s*(-?\d+)>/
|
||||
Point.new([$1, $2].map(&:to_i), [$3, $4].map(&:to_i))
|
||||
}
|
||||
|
||||
def print_points(points)
|
||||
min_x = points.map(&:position).map(&:first).min
|
||||
max_x = points.map(&:position).map(&:first).max
|
||||
min_y = points.map(&:position).map(&:last).min
|
||||
max_y = points.map(&:position).map(&:last).max
|
||||
|
||||
# return if max_x - min_x > 500
|
||||
return if max_y - min_y > 10
|
||||
|
||||
h = points.each.with_object(Hash.new(?.)) {|point, h|
|
||||
h[point.position] = ?#
|
||||
}
|
||||
|
||||
(min_y..max_y).each {|y|
|
||||
(min_x..max_x).each {|x|
|
||||
print h[[x,y]]
|
||||
}
|
||||
puts
|
||||
}
|
||||
|
||||
gets
|
||||
end
|
||||
|
||||
i = 0
|
||||
loop do
|
||||
print_points(points)
|
||||
puts i
|
||||
points.each {|point|
|
||||
point.position[0] += point.velocity[0]
|
||||
point.position[1] += point.velocity[1]
|
||||
}
|
||||
i += 1
|
||||
end
|
@ -1,38 +0,0 @@
|
||||
INPUT = ARGF.read.chomp.to_i
|
||||
|
||||
FuelCell = Struct.new(*%i[ x y ]) do
|
||||
def rack_id
|
||||
x + 10
|
||||
end
|
||||
|
||||
def power_level
|
||||
power_level = rack_id * y
|
||||
power_level += INPUT
|
||||
power_level *= rack_id
|
||||
power_level = power_level / 100 % 10
|
||||
power_level -= 5
|
||||
|
||||
power_level
|
||||
end
|
||||
end
|
||||
|
||||
grid = Hash.new(0)
|
||||
(1..300).each do |x|
|
||||
(1..300).each do |y|
|
||||
grid[[x,y]] = FuelCell.new(x, y).power_level
|
||||
end
|
||||
end
|
||||
|
||||
squares = Hash.new(0)
|
||||
(1..300).each do |size|
|
||||
(1..(300-size+1)).each {|x|
|
||||
(1..(300-size+1)).each {|y|
|
||||
deltas = (0...size).flat_map {|d| [[size-1, d], [d, size-1]] }
|
||||
squares[[x,y,size]] = squares[[x,y,size-1]] + deltas.map {|(dx,dy)| grid[[x+dx, y+dy]] }.sum - grid[[x+size-1, y+size-1]]
|
||||
}
|
||||
}
|
||||
|
||||
puts "#{size}: #{squares.max_by(&:last)}"
|
||||
squares.delete_if {|(_,_,s)| s < size }
|
||||
end
|
||||
|
@ -1,123 +0,0 @@
|
||||
Cart = Struct.new(*%i[ x y dir turns ])
|
||||
map = ARGF.read.chomp.lines.map(&:chomp).map(&:chars)
|
||||
|
||||
carts = []
|
||||
map.each.with_index {|row,y|
|
||||
row.each.with_index {|i,x|
|
||||
carts << Cart.new(x, y, i, 0) if %w[ ^ v < > ].include?(i)
|
||||
}
|
||||
}
|
||||
|
||||
loop do
|
||||
carts.sort_by {|cart|
|
||||
[cart.y, cart.x]
|
||||
}.each do |cart|
|
||||
case cart.dir
|
||||
when ?^
|
||||
cart.y -= 1
|
||||
crashes = carts.select {|candidate| candidate.x == cart.x && candidate.y == cart.y }
|
||||
carts.delete_if {|candidate| crashes.include?(candidate) } if crashes.size > 1
|
||||
case map[cart.y][cart.x]
|
||||
when ?\\
|
||||
cart.dir = ?<
|
||||
when ?/
|
||||
cart.dir = ?>
|
||||
when ?+
|
||||
case cart.turns % 3
|
||||
when 0
|
||||
cart.dir = ?<
|
||||
when 1
|
||||
when 2
|
||||
cart.dir = ?>
|
||||
end
|
||||
cart.turns += 1
|
||||
end
|
||||
when ?v
|
||||
cart.y += 1
|
||||
crashes = carts.select {|candidate| candidate.x == cart.x && candidate.y == cart.y }
|
||||
carts.delete_if {|candidate| crashes.include?(candidate) } if crashes.size > 1
|
||||
case map[cart.y][cart.x]
|
||||
when ?\\
|
||||
cart.dir = ?>
|
||||
when ?/
|
||||
cart.dir = ?<
|
||||
when ?+
|
||||
case cart.turns % 3
|
||||
when 0
|
||||
cart.dir = ?>
|
||||
when 1
|
||||
when 2
|
||||
cart.dir = ?<
|
||||
end
|
||||
cart.turns += 1
|
||||
end
|
||||
when ?<
|
||||
cart.x -= 1
|
||||
crashes = carts.select {|candidate| candidate.x == cart.x && candidate.y == cart.y }
|
||||
carts.delete_if {|candidate| crashes.include?(candidate) } if crashes.size > 1
|
||||
case map[cart.y][cart.x]
|
||||
when ?\\
|
||||
cart.dir = ?^
|
||||
when ?/
|
||||
cart.dir = ?v
|
||||
when ?+
|
||||
case cart.turns % 3
|
||||
when 0
|
||||
cart.dir = ?v
|
||||
when 1
|
||||
when 2
|
||||
cart.dir = ?^
|
||||
end
|
||||
cart.turns += 1
|
||||
end
|
||||
when ?>
|
||||
cart.x += 1
|
||||
crashes = carts.select {|candidate| candidate.x == cart.x && candidate.y == cart.y }
|
||||
carts.delete_if {|candidate| crashes.include?(candidate) } if crashes.size > 1
|
||||
case map[cart.y][cart.x]
|
||||
when ?\\
|
||||
cart.dir = ?v
|
||||
when ?/
|
||||
cart.dir = ?^
|
||||
when ?+
|
||||
case cart.turns % 3
|
||||
when 0
|
||||
cart.dir = ?^
|
||||
when 1
|
||||
when 2
|
||||
cart.dir = ?v
|
||||
end
|
||||
cart.turns += 1
|
||||
end
|
||||
end
|
||||
|
||||
# puts map.map.with_index {|row,y|
|
||||
# row.map.with_index {|i,x|
|
||||
# cart = carts.find {|cart| cart.x == x && cart.y == y }
|
||||
# cart ? cart.dir : i
|
||||
# }.join
|
||||
# }.join("\n")
|
||||
# puts
|
||||
|
||||
# crashes = Hash.new(0)
|
||||
# carts.each {|cart| crashes[[cart.x, cart.y]] += 1 }
|
||||
# crashes = crashes.select {|_,v| v > 1 }.map(&:first)
|
||||
# crashes.each do |(x,y)|
|
||||
# p x
|
||||
# p y
|
||||
# carts.delete_if {|cart| cart.x == x && cart.y == y }
|
||||
# end
|
||||
# if crashes.values.any? {|v| v > 1 }
|
||||
# p crashes.find {|_,v| v > 1 }
|
||||
# exit
|
||||
# end
|
||||
end
|
||||
|
||||
if carts.size == 1
|
||||
p carts
|
||||
exit
|
||||
end
|
||||
|
||||
# p carts
|
||||
# sleep 1
|
||||
end
|
@ -1,522 +0,0 @@
|
||||
require "set"
|
||||
|
||||
require "minitest"
|
||||
require "minitest/pride"
|
||||
|
||||
class EndCombat < StandardError; end
|
||||
|
||||
class Combat
|
||||
def initialize(map, elf_attack)
|
||||
@map = map
|
||||
@attack = {
|
||||
Elf => elf_attack,
|
||||
Goblin => 3,
|
||||
}
|
||||
end
|
||||
|
||||
def fight
|
||||
return enum_for(__method__) unless block_given?
|
||||
|
||||
yield @map
|
||||
|
||||
loop do
|
||||
turn_order.each do |pos|
|
||||
next if @map[pos].nil? # don't take a turn for units that just died
|
||||
|
||||
turn = Turn.new(@map, pos)
|
||||
|
||||
if move = turn.move
|
||||
unit = @map.delete(pos)
|
||||
@map[move] = unit
|
||||
turn.pos = move
|
||||
end
|
||||
|
||||
if attack = turn.attack
|
||||
unit = @map.fetch(turn.pos)
|
||||
target = @map.fetch(attack)
|
||||
target.hp -= @attack.fetch(unit.class)
|
||||
@map.delete(attack) if target.hp <= 0
|
||||
end
|
||||
end
|
||||
|
||||
yield @map
|
||||
end
|
||||
rescue EndCombat
|
||||
# yield @map
|
||||
end
|
||||
|
||||
def turn_order
|
||||
@map.units.keys.sort
|
||||
end
|
||||
end
|
||||
|
||||
class TestCombat < Minitest::Test
|
||||
def test_move
|
||||
map = Map.parse(<<~MAP)
|
||||
#########
|
||||
#G..G..G#
|
||||
#.......#
|
||||
#.......#
|
||||
#G..E..G#
|
||||
#.......#
|
||||
#.......#
|
||||
#G..G..G#
|
||||
#########
|
||||
MAP
|
||||
combat = Combat.new(map, 3)
|
||||
rounds = combat.fight
|
||||
rounds.next # skip the first round
|
||||
|
||||
assert_equal <<~MAP.chomp, rounds.next.to_s
|
||||
#########
|
||||
#.G...G.#
|
||||
#...G...#
|
||||
#...E..G#
|
||||
#.G.....#
|
||||
#.......#
|
||||
#G..G..G#
|
||||
#.......#
|
||||
#########
|
||||
MAP
|
||||
|
||||
assert_equal <<~MAP.chomp, rounds.next.to_s
|
||||
#########
|
||||
#..G.G..#
|
||||
#...G...#
|
||||
#.G.E.G.#
|
||||
#.......#
|
||||
#G..G..G#
|
||||
#.......#
|
||||
#.......#
|
||||
#########
|
||||
MAP
|
||||
|
||||
assert_equal <<~MAP.chomp, rounds.next.to_s
|
||||
#########
|
||||
#.......#
|
||||
#..GGG..#
|
||||
#..GEG..#
|
||||
#G..G...#
|
||||
#......G#
|
||||
#.......#
|
||||
#.......#
|
||||
#########
|
||||
MAP
|
||||
end
|
||||
|
||||
def test_fight
|
||||
map = Map.parse(<<~MAP)
|
||||
#######
|
||||
#.G...#
|
||||
#...EG#
|
||||
#.#.#G#
|
||||
#..G#E#
|
||||
#.....#
|
||||
#######
|
||||
MAP
|
||||
combat = Combat.new(map, 3)
|
||||
rounds = combat.fight
|
||||
rounds.next # skip the initial state
|
||||
rounds.next # skip the first found
|
||||
|
||||
map = rounds.next # second round
|
||||
assert_equal 188, map.fetch(Position[2,4]).hp
|
||||
|
||||
20.times { rounds.next }
|
||||
assert_equal <<~MAP.chomp, rounds.next.to_s
|
||||
#######
|
||||
#...G.#
|
||||
#..G.G#
|
||||
#.#.#G#
|
||||
#...#E#
|
||||
#.....#
|
||||
#######
|
||||
MAP
|
||||
end
|
||||
|
||||
def test_turn_order
|
||||
map = Map.parse(<<~MAP)
|
||||
#######
|
||||
#.G.E.#
|
||||
#E.G.E#
|
||||
#.G.E.#
|
||||
#######
|
||||
MAP
|
||||
combat = Combat.new(map, 3)
|
||||
|
||||
expected = [[1,2], [1,4], [2,1], [2,3], [2,5], [3,2], [3,4]].map {|pos| Position[*pos]}
|
||||
assert_equal expected, combat.turn_order
|
||||
end
|
||||
end
|
||||
|
||||
class Turn
|
||||
attr_accessor :pos
|
||||
|
||||
def initialize(map, pos)
|
||||
@map, @pos = map, pos
|
||||
@unit = @map.fetch(@pos)
|
||||
end
|
||||
|
||||
def move
|
||||
raise EndCombat if targets.empty?
|
||||
return if can_attack?
|
||||
return if nearest.empty?
|
||||
|
||||
chosen = nearest.min
|
||||
haystack = @map.in_range(@pos)
|
||||
dijkstra(chosen)
|
||||
.select {|pos,_| haystack.include?(pos) }
|
||||
.min_by {|pos,distance| [distance, pos] }
|
||||
.first
|
||||
end
|
||||
|
||||
def attack
|
||||
attackable.min_by {|pos, target| [target.hp, pos] }&.first
|
||||
end
|
||||
|
||||
def targets
|
||||
@map.units.select {|_, other| other.is_a?(@unit.enemy) }
|
||||
end
|
||||
|
||||
def attackable
|
||||
targets.select {|pos, _| @pos.adjacent.include?(pos) }
|
||||
end
|
||||
|
||||
def can_attack?
|
||||
!attackable.empty?
|
||||
end
|
||||
|
||||
def in_range
|
||||
targets.flat_map {|pos, _| @map.in_range(pos) }.uniq
|
||||
end
|
||||
|
||||
def reachable
|
||||
dijkstra(@pos).select {|pos,_| in_range.include?(pos) }
|
||||
end
|
||||
|
||||
def nearest
|
||||
nearest = Hash.new {|h,k| h[k] = [] }
|
||||
reachable.each do |pos, distance|
|
||||
nearest[distance] << pos
|
||||
end
|
||||
|
||||
return [] if nearest.empty?
|
||||
nearest.min_by(&:first).last
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def dijkstra(pos)
|
||||
distances = { pos => 0 }
|
||||
queue = [ pos ]
|
||||
while pos = queue.shift
|
||||
distance = distances.fetch(pos) + 1
|
||||
@map.in_range(pos).reject {|pos| distances.has_key?(pos) }.each do |pos|
|
||||
distances[pos] = distance
|
||||
queue << pos
|
||||
end
|
||||
end
|
||||
distances
|
||||
end
|
||||
end
|
||||
|
||||
class TestTurn < Minitest::Test
|
||||
def setup
|
||||
map = Map.parse(<<~MAP)
|
||||
#######
|
||||
#E..G.#
|
||||
#...#.#
|
||||
#.G.#G#
|
||||
#######
|
||||
MAP
|
||||
@turn = Turn.new(map, Position[1,1])
|
||||
end
|
||||
|
||||
def test_targets
|
||||
assert_equal [[1,4], [3,2], [3,5]].to_set, @turn.targets.keys.map(&:to_a).to_set
|
||||
end
|
||||
|
||||
def test_in_range
|
||||
assert_equal [[1,3], [1,5], [2,2], [2,5], [3,1], [3,3]].to_set, @turn.in_range.map(&:to_a).to_set
|
||||
end
|
||||
|
||||
def test_reachable
|
||||
assert_equal [[1,3], [2,2], [3,1], [3,3]].to_set, @turn.reachable.keys.map(&:to_a).to_set
|
||||
end
|
||||
|
||||
def test_nearest
|
||||
assert_equal [[1,3], [2,2], [3,1]].to_set, @turn.nearest.map(&:to_a).to_set
|
||||
end
|
||||
|
||||
def test_move
|
||||
assert_equal Position[1,2], @turn.move
|
||||
|
||||
turn = Turn.new(Map.parse(<<~MAP), Position[1,2])
|
||||
#######
|
||||
#.E...#
|
||||
#.....#
|
||||
#...G.#
|
||||
#######
|
||||
MAP
|
||||
assert_equal Position[1,3], turn.move
|
||||
end
|
||||
end
|
||||
|
||||
class Map
|
||||
def self.parse(s)
|
||||
occupied = {}
|
||||
s.chomp.lines.each.with_index do |row, y|
|
||||
row.chomp.chars.each.with_index do |square, x|
|
||||
case square
|
||||
when ?#
|
||||
occupied[Position[y, x]] = Wall.new
|
||||
when ?E
|
||||
occupied[Position[y, x]] = Elf.new
|
||||
when ?G
|
||||
occupied[Position[y, x]] = Goblin.new
|
||||
when ?.
|
||||
else
|
||||
fail "Invalid character: #{square.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
self.new(occupied)
|
||||
end
|
||||
|
||||
def initialize(occupied)
|
||||
@occupied = occupied
|
||||
end
|
||||
|
||||
def [](pos)
|
||||
@occupied[pos]
|
||||
end
|
||||
|
||||
def []=(pos, square)
|
||||
@occupied[pos] = square
|
||||
end
|
||||
|
||||
def fetch(pos)
|
||||
@occupied.fetch(pos)
|
||||
end
|
||||
|
||||
def delete(pos)
|
||||
@occupied.delete(pos)
|
||||
end
|
||||
|
||||
def units
|
||||
@occupied.select {|_, sq| sq.is_a?(Unit) }
|
||||
end
|
||||
|
||||
def in_range(pos)
|
||||
pos
|
||||
.adjacent
|
||||
.reject {|pos| @occupied.has_key?(pos) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
max_y = @occupied.keys.map(&:y).max
|
||||
max_x = @occupied.keys.map(&:x).max
|
||||
(0..max_y).map {|y|
|
||||
(0..max_x).map {|x|
|
||||
case @occupied[Position[y, x]]
|
||||
when Wall
|
||||
?#
|
||||
when Elf
|
||||
?E
|
||||
when Goblin
|
||||
?G
|
||||
when nil
|
||||
?.
|
||||
else
|
||||
fail "Unexpected object: #{@occupied[Position[y, x]]}"
|
||||
end
|
||||
}.join
|
||||
}.join(?\n)
|
||||
end
|
||||
end
|
||||
|
||||
class TestMap < Minitest::Test
|
||||
def test_parse
|
||||
map = Map.parse(<<~MAP)
|
||||
#######
|
||||
#E..G.#
|
||||
#...#.#
|
||||
#.G.#G#
|
||||
#######
|
||||
MAP
|
||||
|
||||
assert_instance_of Wall, map[Position[0,0]]
|
||||
assert_instance_of Wall, map[Position[2,4]]
|
||||
assert_instance_of Wall, map[Position[4,6]]
|
||||
|
||||
assert_instance_of Elf, map[Position[1,1]]
|
||||
|
||||
assert_instance_of Goblin, map[Position[1,4]]
|
||||
assert_instance_of Goblin, map[Position[3,5]]
|
||||
|
||||
assert_nil map[Position[1,2]]
|
||||
assert_nil map[Position[2,5]]
|
||||
end
|
||||
|
||||
def test_units
|
||||
map = Map.parse(<<~MAP)
|
||||
#######
|
||||
#E..G.#
|
||||
#...#.#
|
||||
#.G.#G#
|
||||
#######
|
||||
MAP
|
||||
|
||||
assert_equal 4, map.units.length
|
||||
end
|
||||
end
|
||||
|
||||
Position = Struct.new(:y, :x) do
|
||||
def self.[](y, x)
|
||||
self.new(y, x)
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
[self.y, self.x] <=> [other.y, other.x]
|
||||
end
|
||||
|
||||
def adjacent
|
||||
[-1, 1]
|
||||
.flat_map {|d| [[y, x+d], [y+d, x]] }
|
||||
.map {|pos| Position[*pos] }
|
||||
end
|
||||
|
||||
def to_a
|
||||
[y, x]
|
||||
end
|
||||
|
||||
def to_s
|
||||
to_a.to_s
|
||||
end
|
||||
end
|
||||
|
||||
class Unit
|
||||
attr_accessor :hp
|
||||
|
||||
def initialize
|
||||
@hp = 200
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{self.class.name.chars.first}(#{hp})"
|
||||
end
|
||||
end
|
||||
|
||||
class Wall
|
||||
end
|
||||
|
||||
class Elf < Unit
|
||||
def enemy
|
||||
Goblin
|
||||
end
|
||||
end
|
||||
|
||||
class Goblin < Unit
|
||||
def enemy
|
||||
Elf
|
||||
end
|
||||
end
|
||||
|
||||
def solve(input)
|
||||
(3..Float::INFINITY).each do |elf_attack|
|
||||
map = Map.parse(input)
|
||||
outcome = simulate(map, elf_attack)
|
||||
next if outcome.nil?
|
||||
return outcome
|
||||
end
|
||||
end
|
||||
|
||||
def simulate(map, elf_attack)
|
||||
elf_count = map.units.count {|_, unit| unit.is_a?(Elf) }
|
||||
combat = Combat.new(map, elf_attack)
|
||||
map, count = combat.fight.map.with_index
|
||||
.inject(nil) {|last,(map,count)|
|
||||
return if map.units.count {|_, unit| unit.is_a?(Elf) } < elf_count
|
||||
# puts map, map.units.values.map(&:to_s).inspect
|
||||
[map, count]
|
||||
}
|
||||
return if map.units.count {|_, unit| unit.is_a?(Elf) } < elf_count
|
||||
map.units.values.map(&:hp).sum * count
|
||||
end
|
||||
|
||||
class TestSolve < Minitest::Test
|
||||
def test_solve
|
||||
# assert_equal 27730, solve(<<~INPUT)
|
||||
assert_equal 4988, solve(<<~INPUT)
|
||||
#######
|
||||
#.G...#
|
||||
#...EG#
|
||||
#.#.#G#
|
||||
#..G#E#
|
||||
#.....#
|
||||
#######
|
||||
INPUT
|
||||
|
||||
# assert_equal 36334, solve(<<~INPUT)
|
||||
########
|
||||
##G..#E#
|
||||
##E#E.E#
|
||||
##G.##.#
|
||||
##...#E#
|
||||
##...E.#
|
||||
########
|
||||
#INPUT
|
||||
|
||||
# assert_equal 39514, solve(<<~INPUT)
|
||||
assert_equal 31284, solve(<<~INPUT)
|
||||
#######
|
||||
#E..EG#
|
||||
#.#G.E#
|
||||
#E.##E#
|
||||
#G..#.#
|
||||
#..E#.#
|
||||
#######
|
||||
INPUT
|
||||
|
||||
# assert_equal 27755, solve(<<~INPUT)
|
||||
assert_equal 3478, solve(<<~INPUT)
|
||||
#######
|
||||
#E.G#.#
|
||||
#.#G..#
|
||||
#G.#.G#
|
||||
#G..#.#
|
||||
#...E.#
|
||||
#######
|
||||
INPUT
|
||||
|
||||
# assert_equal 28944, solve(<<~INPUT)
|
||||
assert_equal 6474, solve(<<~INPUT)
|
||||
#######
|
||||
#.E...#
|
||||
#.#..G#
|
||||
#.###.#
|
||||
#E#G#G#
|
||||
#...#G#
|
||||
#######
|
||||
INPUT
|
||||
|
||||
# assert_equal 18740, solve(<<~INPUT)
|
||||
assert_equal 1140, solve(<<~INPUT)
|
||||
#########
|
||||
#G......#
|
||||
#.E.#...#
|
||||
#..##..G#
|
||||
#...##..#
|
||||
#...#...#
|
||||
#.G...G.#
|
||||
#.....G.#
|
||||
#########
|
||||
INPUT
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
require "minitest/autorun" and exit if ENV["TEST"]
|
||||
|
||||
puts solve(ARGF.read)
|
||||
end
|
@ -1,99 +0,0 @@
|
||||
require "minitest"
|
||||
require "minitest/pride"
|
||||
|
||||
OPCODES = {
|
||||
addr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + registers[b] } },
|
||||
addi: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + b } },
|
||||
mulr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * registers[b] } },
|
||||
muli: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * b } },
|
||||
banr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & registers[b] } },
|
||||
bani: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & b } },
|
||||
borr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | registers[b] } },
|
||||
bori: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | b } },
|
||||
setr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] } },
|
||||
seti: ->(a, b, c) { ->(registers) { registers[c] = a } },
|
||||
gtir: ->(a, b, c) { ->(registers) { registers[c] = (a > registers[b]) ? 1 : 0 } },
|
||||
gtri: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > b) ? 1 : 0 } },
|
||||
gtrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > registers[b]) ? 1 : 0 } },
|
||||
eqir: ->(a, b, c) { ->(registers) { registers[c] = (a == registers[b]) ? 1 : 0 } },
|
||||
eqri: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == b) ? 1 : 0 } },
|
||||
eqrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == registers[b]) ? 1 : 0 } },
|
||||
}
|
||||
|
||||
class TestOpcodes < Minitest::Test
|
||||
def test_mulr
|
||||
registers = [3, 2, 1, 1]
|
||||
|
||||
OPCODES[:mulr].call(2, 1, 2).call(registers)
|
||||
|
||||
assert_equal [3, 2, 2, 1], registers
|
||||
end
|
||||
|
||||
def test_addi
|
||||
registers = [3, 2, 1, 1]
|
||||
|
||||
OPCODES[:addi].call(2, 1, 2).call(registers)
|
||||
|
||||
assert_equal [3, 2, 2, 1], registers
|
||||
end
|
||||
|
||||
def test_seti
|
||||
registers = [3, 2, 1, 1]
|
||||
|
||||
OPCODES[:seti].call(2, 1, 2).call(registers)
|
||||
|
||||
assert_equal [3, 2, 2, 1], registers
|
||||
end
|
||||
end
|
||||
|
||||
def solve(input)
|
||||
samples = input.scan(/
|
||||
Before:\s*((?~\n))\n
|
||||
((?~\n))\n
|
||||
After:\s*((?~\n))\n
|
||||
/mx)
|
||||
|
||||
valid_opcodes = samples.map do |sample|
|
||||
before = sample[0].scan(/\d+/).map(&:to_i)
|
||||
instruction = sample[1].scan(/\d+/).map(&:to_i)
|
||||
after = sample[2].scan(/\d+/).map(&:to_i)
|
||||
opcode, *args = instruction
|
||||
|
||||
opcodes = OPCODES.select {|_, instruction|
|
||||
registers = before.dup
|
||||
instruction[*args][registers]
|
||||
registers == after
|
||||
}.map(&:first)
|
||||
[opcode, opcodes]
|
||||
end
|
||||
|
||||
# Part One
|
||||
# return valid_opcodes.count {|_,opcodes| opcodes.length >= 3 }
|
||||
|
||||
opcode_map = {}
|
||||
until opcode_map.length == OPCODES.length
|
||||
number, opcodes = valid_opcodes.find {|_,opcodes| opcodes.length == 1 }
|
||||
opcode = opcodes[0]
|
||||
opcode_map[number] = opcode
|
||||
|
||||
valid_opcodes.delete_if {|n,_| n == number }
|
||||
valid_opcodes.each do |_,opcodes|
|
||||
opcodes.delete(opcode)
|
||||
end
|
||||
end
|
||||
|
||||
program = input[/[\d\s]+\Z/].lines.map {|line| line.scan(/\d+/).map(&:to_i) }.reject(&:empty?)
|
||||
registers = [0, 0, 0, 0]
|
||||
program.each do |instruction|
|
||||
number, *args = instruction
|
||||
opcode = opcode_map.fetch(number)
|
||||
OPCODES.fetch(opcode)[*args][registers]
|
||||
end
|
||||
registers[0]
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
require "minitest/autorun" and exit if ENV["TEST"]
|
||||
|
||||
puts solve(ARGF.read)
|
||||
end
|
@ -1,261 +0,0 @@
|
||||
require "set"
|
||||
|
||||
require "minitest"
|
||||
require "minitest/pride"
|
||||
|
||||
class Slice
|
||||
def self.parse(s)
|
||||
squares = {}
|
||||
s.scan(/^(x|y)=(\d+), (?:x|y)=(\d+)..(\d+)$/m).each do |xy, i, min, max|
|
||||
i, min, max = [i, min, max].map(&:to_i)
|
||||
(min..max).map {|j| xy == ?x ? [i, j] : [j, i] }.each do |pos|
|
||||
squares[pos] = ?#
|
||||
end
|
||||
end
|
||||
new(squares)
|
||||
end
|
||||
|
||||
attr_reader :squares
|
||||
|
||||
def initialize(squares)
|
||||
@squares = squares
|
||||
@squares[[500, 0]] = ?+
|
||||
@active = Set[[500, 0]]
|
||||
end
|
||||
|
||||
def simulate
|
||||
return enum_for(__method__) unless block_given?
|
||||
|
||||
max_y = @squares.keys.map(&:last).max
|
||||
|
||||
loop do
|
||||
@active.to_a.each do |pos|
|
||||
@active.delete(pos)
|
||||
x, y = pos
|
||||
case @squares.fetch(pos)
|
||||
when ?+
|
||||
@squares[[x, y+1]] = ?|
|
||||
@active << [x, y+1]
|
||||
when ?|
|
||||
next if y+1 > max_y
|
||||
|
||||
if @squares[[x, y+1]].nil?
|
||||
@squares[[x, y+1]] = ?|
|
||||
@active << [x, y+1]
|
||||
else
|
||||
if @squares[[x-1, y]].nil?
|
||||
@squares[[x-1, y]] = ?|
|
||||
@active << [x-1, y]
|
||||
end
|
||||
|
||||
if @squares[[x+1, y]].nil?
|
||||
@squares[[x+1, y]] = ?|
|
||||
@active << [x+1, y]
|
||||
end
|
||||
|
||||
left_x = x-1
|
||||
left_x -= 1 until @squares[[left_x, y]] != ?|
|
||||
right_x = x+1
|
||||
right_x += 1 until @squares[[right_x, y]] != ?|
|
||||
if @squares[[left_x, y]] == ?# && @squares[[right_x, y]] == ?#
|
||||
(left_x+1..right_x-1).each do |x|
|
||||
@squares[[x, y]] = ?~
|
||||
@active << [x, y-1] if @squares[[x, y-1]] == ?|
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return if @active.empty?
|
||||
|
||||
yield self
|
||||
end
|
||||
end
|
||||
|
||||
def water
|
||||
@squares.select {|_, s| %w[ | ~ ].include?(s) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
min_x, max_x = @squares.keys.map(&:first).minmax
|
||||
min_y, max_y = @squares.keys.map(&:last).minmax
|
||||
min_y = [0, min_y].min
|
||||
(min_y..max_y).map {|y| (min_x-1..max_x+1).map {|x| @squares.fetch([x, y]) { ?. } }.join }.join(?\n)
|
||||
end
|
||||
end
|
||||
|
||||
class TestSlice < Minitest::Test
|
||||
def setup
|
||||
@slice = Slice.parse(<<~SLICE)
|
||||
x=495, y=2..7
|
||||
y=7, x=495..501
|
||||
x=501, y=3..7
|
||||
x=498, y=2..4
|
||||
x=506, y=1..2
|
||||
x=498, y=10..13
|
||||
x=504, y=10..13
|
||||
y=13, x=498..504
|
||||
SLICE
|
||||
end
|
||||
|
||||
def test_parse_to_s
|
||||
assert_equal <<~SLICE.chomp, @slice.to_s
|
||||
......+.......
|
||||
............#.
|
||||
.#..#.......#.
|
||||
.#..#..#......
|
||||
.#..#..#......
|
||||
.#.....#......
|
||||
.#.....#......
|
||||
.#######......
|
||||
..............
|
||||
..............
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#######...
|
||||
SLICE
|
||||
end
|
||||
|
||||
def test_simulate
|
||||
simulation = @slice.simulate
|
||||
|
||||
5.times { simulation.next }
|
||||
assert_equal <<~SLICE.chomp, @slice.to_s
|
||||
......+.......
|
||||
......|.....#.
|
||||
.#..#.|.....#.
|
||||
.#..#.|#......
|
||||
.#..#.|#......
|
||||
.#....|#......
|
||||
.#.....#......
|
||||
.#######......
|
||||
..............
|
||||
..............
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#######...
|
||||
SLICE
|
||||
|
||||
5.times { simulation.next }
|
||||
assert_equal <<~SLICE.chomp, @slice.to_s
|
||||
......+.......
|
||||
......|.....#.
|
||||
.#..#.|.....#.
|
||||
.#..#.|#......
|
||||
.#..#.|#......
|
||||
.#....|#......
|
||||
.#~~~~~#......
|
||||
.#######......
|
||||
..............
|
||||
..............
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#######...
|
||||
SLICE
|
||||
|
||||
4.times { simulation.next }
|
||||
assert_equal <<~SLICE.chomp, @slice.to_s
|
||||
......+.......
|
||||
......|.....#.
|
||||
.#..#.|.....#.
|
||||
.#..#.|#......
|
||||
.#..#.|#......
|
||||
.#~~~~~#......
|
||||
.#~~~~~#......
|
||||
.#######......
|
||||
..............
|
||||
..............
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#######...
|
||||
SLICE
|
||||
|
||||
2.times { simulation.next }
|
||||
assert_equal <<~SLICE.chomp, @slice.to_s
|
||||
......+.......
|
||||
......|.....#.
|
||||
.#..#.|.....#.
|
||||
.#..#~~#......
|
||||
.#..#~~#......
|
||||
.#~~~~~#......
|
||||
.#~~~~~#......
|
||||
.#######......
|
||||
..............
|
||||
..............
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#.....#...
|
||||
....#######...
|
||||
SLICE
|
||||
|
||||
21.times { simulation.next }
|
||||
assert_equal <<~SLICE.chomp, @slice.to_s
|
||||
......+.......
|
||||
......|.....#.
|
||||
.#..#||||...#.
|
||||
.#..#~~#|.....
|
||||
.#..#~~#|.....
|
||||
.#~~~~~#|.....
|
||||
.#~~~~~#|.....
|
||||
.#######|.....
|
||||
........|.....
|
||||
........|.....
|
||||
....#~~~~~#...
|
||||
....#~~~~~#...
|
||||
....#~~~~~#...
|
||||
....#######...
|
||||
SLICE
|
||||
|
||||
9.times { simulation.next }
|
||||
assert_equal <<~SLICE.chomp, @slice.to_s
|
||||
......+.......
|
||||
......|.....#.
|
||||
.#..#||||...#.
|
||||
.#..#~~#|.....
|
||||
.#..#~~#|.....
|
||||
.#~~~~~#|.....
|
||||
.#~~~~~#|.....
|
||||
.#######|.....
|
||||
........|.....
|
||||
...|||||||||..
|
||||
...|#~~~~~#|..
|
||||
...|#~~~~~#|..
|
||||
...|#~~~~~#|..
|
||||
...|#######|..
|
||||
SLICE
|
||||
|
||||
assert_equal 57, @slice.water.count
|
||||
end
|
||||
end
|
||||
|
||||
def solve(input)
|
||||
slice = Slice.parse(input)
|
||||
min_y = slice.squares.select {|_,s| s == ?# }.map(&:first).map(&:last).min
|
||||
simulation = slice.simulate
|
||||
|
||||
loop do
|
||||
simulation.next
|
||||
end
|
||||
|
||||
# puts
|
||||
# min_x, max_x = slice.water.map(&:first).minmax
|
||||
# min_y, max_y = slice.water.map(&:last).minmax
|
||||
# min_y = [0, min_y].min
|
||||
# puts (min_y..max_y).map {|y| (min_x-1..max_x+1).map {|x| slice.squares.fetch([x, y]) { ?. } }.join }.join(?\n)
|
||||
|
||||
# Part One
|
||||
# slice.water.count {|(_,y),_| y >= min_y }
|
||||
|
||||
slice.water.count {|_,s| s == ?~ }
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
require "minitest/autorun" and exit if ENV["TEST"]
|
||||
|
||||
puts solve(ARGF.read)
|
||||
end
|
@ -1,280 +0,0 @@
|
||||
require "minitest"
|
||||
require "minitest/pride"
|
||||
|
||||
class Area
|
||||
def self.parse(input)
|
||||
acres = input.chomp.lines.map {|row| row.chomp.chars.to_a }
|
||||
new(acres)
|
||||
end
|
||||
|
||||
attr_reader :acres
|
||||
|
||||
def initialize(acres)
|
||||
@acres = acres
|
||||
end
|
||||
|
||||
def changes
|
||||
return enum_for(__method__) unless block_given?
|
||||
|
||||
loop do
|
||||
yield self
|
||||
|
||||
acres = @acres.map.with_index {|row, y|
|
||||
row.map.with_index {|acre, x|
|
||||
adjacent = self.adjacent(x, y)
|
||||
case self[x, y]
|
||||
when ?.
|
||||
(adjacent.count(?|) >= 3) ? ?| : ?.
|
||||
when ?|
|
||||
(adjacent.count(?#) >= 3) ? ?# : ?|
|
||||
when ?#
|
||||
(adjacent.count(?#) >= 1 && adjacent.count(?|) >= 1) ? ?# : ?.
|
||||
else
|
||||
fail "Unexpected acre: #{self[x, y]}"
|
||||
end
|
||||
}
|
||||
}
|
||||
@acres = acres
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
@acres.map {|row| row.join }.join(?\n)
|
||||
end
|
||||
|
||||
def [](x, y)
|
||||
@acres.fetch(y).fetch(x)
|
||||
end
|
||||
|
||||
def adjacent(x, y)
|
||||
(-1..1).flat_map {|dx| (-1..1).map {|dy| [dx, dy] } }
|
||||
.reject {|dx,dy| dx == 0 && dy == 0 }
|
||||
.map {|dx, dy| [x+dx, y+dy] }
|
||||
.reject {|x, y| x < 0 || y < 0 }
|
||||
.map {|x, y|
|
||||
@acres.fetch(y) { [] }.fetch(x) { nil }
|
||||
}.compact
|
||||
end
|
||||
end
|
||||
|
||||
class TestArea < Minitest::Test
|
||||
def test_area
|
||||
area = Area.parse(<<~AREA)
|
||||
.#.#...|#.
|
||||
.....#|##|
|
||||
.|..|...#.
|
||||
..|#.....#
|
||||
#.#|||#|#|
|
||||
...#.||...
|
||||
.|....|...
|
||||
||...#|.#|
|
||||
|.||||..|.
|
||||
...#.|..|.
|
||||
AREA
|
||||
changes = area.changes
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
.#.#...|#.
|
||||
.....#|##|
|
||||
.|..|...#.
|
||||
..|#.....#
|
||||
#.#|||#|#|
|
||||
...#.||...
|
||||
.|....|...
|
||||
||...#|.#|
|
||||
|.||||..|.
|
||||
...#.|..|.
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
.......##.
|
||||
......|###
|
||||
.|..|...#.
|
||||
..|#||...#
|
||||
..##||.|#|
|
||||
...#||||..
|
||||
||...|||..
|
||||
|||||.||.|
|
||||
||||||||||
|
||||
....||..|.
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
.......#..
|
||||
......|#..
|
||||
.|.|||....
|
||||
..##|||..#
|
||||
..###|||#|
|
||||
...#|||||.
|
||||
|||||||||.
|
||||
||||||||||
|
||||
||||||||||
|
||||
.|||||||||
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
.......#..
|
||||
....|||#..
|
||||
.|.||||...
|
||||
..###|||.#
|
||||
...##|||#|
|
||||
.||##|||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
.....|.#..
|
||||
...||||#..
|
||||
.|.#||||..
|
||||
..###||||#
|
||||
...###||#|
|
||||
|||##|||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
....|||#..
|
||||
...||||#..
|
||||
.|.##||||.
|
||||
..####|||#
|
||||
.|.###||#|
|
||||
|||###||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
...||||#..
|
||||
...||||#..
|
||||
.|.###|||.
|
||||
..#.##|||#
|
||||
|||#.##|#|
|
||||
|||###||||
|
||||
||||#|||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
...||||#..
|
||||
..||#|##..
|
||||
.|.####||.
|
||||
||#..##||#
|
||||
||##.##|#|
|
||||
|||####|||
|
||||
|||###||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
..||||##..
|
||||
..|#####..
|
||||
|||#####|.
|
||||
||#...##|#
|
||||
||##..###|
|
||||
||##.###||
|
||||
|||####|||
|
||||
||||#|||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
..||###...
|
||||
.||#####..
|
||||
||##...##.
|
||||
||#....###
|
||||
|##....##|
|
||||
||##..###|
|
||||
||######||
|
||||
|||###||||
|
||||
||||||||||
|
||||
||||||||||
|
||||
AREA
|
||||
|
||||
assert_equal <<~AREA.chomp, changes.next.to_s
|
||||
.||##.....
|
||||
||###.....
|
||||
||##......
|
||||
|##.....##
|
||||
|##.....##
|
||||
|##....##|
|
||||
||##.####|
|
||||
||#####|||
|
||||
||||#|||||
|
||||
||||||||||
|
||||
AREA
|
||||
end
|
||||
end
|
||||
|
||||
def solve(input)
|
||||
area = Area.parse(input)
|
||||
changes = area.changes
|
||||
|
||||
# Part One
|
||||
# 11.times do |i|
|
||||
1000000001.times do |i|
|
||||
changes.next
|
||||
|
||||
wooded = area.acres.flat_map(&:itself).count(?|)
|
||||
lumberyards = area.acres.flat_map(&:itself).count(?#)
|
||||
|
||||
puts "#{i}: #{wooded * lumberyards}"
|
||||
end
|
||||
|
||||
wooded = area.acres.flat_map(&:itself).count(?|)
|
||||
lumberyards = area.acres.flat_map(&:itself).count(?#)
|
||||
wooded * lumberyards
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
require "minitest/autorun" and exit if ENV["TEST"]
|
||||
|
||||
puts solve(ARGF.read)
|
||||
end
|
||||
|
||||
__END__
|
||||
Here's the cycle, 28 minutes long:
|
||||
|
||||
1000000000 % 28 = 552 % 28
|
||||
552 % 28 = 20
|
||||
|
||||
540: 223468
|
||||
541: 227744
|
||||
542: 226338
|
||||
543: 221697
|
||||
544: 214775
|
||||
545: 206150
|
||||
546: 200326
|
||||
547: 197380
|
||||
548: 177364
|
||||
549: 177834
|
||||
550: 176960
|
||||
551: 176490
|
||||
552: 174584
|
||||
553: 177683
|
||||
554: 176808
|
||||
555: 176715
|
||||
556: 177784
|
||||
557: 182016
|
||||
558: 182479
|
||||
559: 188256
|
||||
560: 194892
|
||||
561: 199864
|
||||
562: 206720
|
||||
563: 210330
|
||||
564: 212102
|
||||
565: 212310
|
||||
566: 215306
|
||||
567: 217260
|
@ -1,118 +0,0 @@
|
||||
require "minitest"
|
||||
require "minitest/pride"
|
||||
|
||||
OPCODES = {
|
||||
addr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + registers[b] } },
|
||||
addi: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + b } },
|
||||
mulr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * registers[b] } },
|
||||
muli: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * b } },
|
||||
banr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & registers[b] } },
|
||||
bani: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & b } },
|
||||
borr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | registers[b] } },
|
||||
bori: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | b } },
|
||||
setr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] } },
|
||||
seti: ->(a, b, c) { ->(registers) { registers[c] = a } },
|
||||
gtir: ->(a, b, c) { ->(registers) { registers[c] = (a > registers[b]) ? 1 : 0 } },
|
||||
gtri: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > b) ? 1 : 0 } },
|
||||
gtrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > registers[b]) ? 1 : 0 } },
|
||||
eqir: ->(a, b, c) { ->(registers) { registers[c] = (a == registers[b]) ? 1 : 0 } },
|
||||
eqri: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == b) ? 1 : 0 } },
|
||||
eqrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == registers[b]) ? 1 : 0 } },
|
||||
}
|
||||
|
||||
class TestOpcodes < Minitest::Test
|
||||
def test_mulr
|
||||
registers = [3, 2, 1, 1]
|
||||
|
||||
OPCODES[:mulr].call(2, 1, 2).call(registers)
|
||||
|
||||
assert_equal [3, 2, 2, 1], registers
|
||||
end
|
||||
|
||||
def test_addi
|
||||
registers = [3, 2, 1, 1]
|
||||
|
||||
OPCODES[:addi].call(2, 1, 2).call(registers)
|
||||
|
||||
assert_equal [3, 2, 2, 1], registers
|
||||
end
|
||||
|
||||
def test_seti
|
||||
registers = [3, 2, 1, 1]
|
||||
|
||||
OPCODES[:seti].call(2, 1, 2).call(registers)
|
||||
|
||||
assert_equal [3, 2, 2, 1], registers
|
||||
end
|
||||
end
|
||||
|
||||
Instruction = Struct.new(:opcode, :args)
|
||||
|
||||
class Program
|
||||
def self.parse(input)
|
||||
lines = input.lines
|
||||
ip = lines.shift[/^#ip (\d)+$/, 1].to_i
|
||||
instructions = lines.map {|line|
|
||||
opcode, *args = line.split
|
||||
opcode = opcode.to_sym
|
||||
args = args.map(&:to_i)
|
||||
Instruction.new(opcode, args)
|
||||
}
|
||||
new(ip, instructions)
|
||||
end
|
||||
|
||||
attr_reader :registers
|
||||
|
||||
def initialize(ip, instructions)
|
||||
@ip, @instructions = ip, instructions
|
||||
@registers = Array.new(6, 0)
|
||||
end
|
||||
|
||||
def run
|
||||
return enum_for(__method__) unless block_given?
|
||||
|
||||
while (0...@instructions.length).cover?(@registers[@ip])
|
||||
instruction = @instructions.fetch(@registers[@ip])
|
||||
OPCODES.fetch(instruction.opcode)[*instruction.args][@registers]
|
||||
yield self
|
||||
@registers[@ip] += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class TestProgram < Minitest::Test
|
||||
def test_program
|
||||
program = Program.parse(<<~PROGRAM)
|
||||
#ip 0
|
||||
seti 5 0 1
|
||||
seti 6 0 2
|
||||
addi 0 1 0
|
||||
addr 1 2 3
|
||||
setr 1 0 0
|
||||
seti 8 0 4
|
||||
seti 9 0 5
|
||||
PROGRAM
|
||||
|
||||
run = program.run
|
||||
loop do
|
||||
run.next
|
||||
end
|
||||
|
||||
assert_equal [7, 5, 6, 0, 0, 9], program.registers
|
||||
end
|
||||
end
|
||||
|
||||
def solve(input)
|
||||
program = Program.parse(input)
|
||||
run = program.run
|
||||
loop do
|
||||
run.next
|
||||
end
|
||||
program.registers[0]
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
require "minitest/autorun" and exit if ENV["TEST"]
|
||||
|
||||
puts solve(ARGF.read)
|
||||
end
|
@ -1,205 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "advent_of_code"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"byte-tools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d00328cedcac5e81c683e5620ca6a30756fc23027ebf9bff405c0e8da1fbb7e"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a677051ad923732bb5c70f2d45f8985a96e3eee2e2bff86697e3b11b0c3fcfde"
|
||||
dependencies = [
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b76f477146419bc539a63f4ef40e902166cb43b3e51cecc71d9136fd12c567e7"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ebee4e9680be4fd162e6f3394ae4192a6b60b1e4d17d845e631f0c68d1a3386"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f6d5f6f0e6082578c86af197d780dc38328e3f768cec06aac9bc46d714e8221"
|
||||
dependencies = [
|
||||
"maplit",
|
||||
"pest",
|
||||
"sha-1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"byte-tools",
|
||||
"digest",
|
||||
"fake-simd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.14.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
@ -1,11 +0,0 @@
|
||||
[package]
|
||||
name = "advent_of_code"
|
||||
version = "0.1.0"
|
||||
authors = ["Alpha Chen <alpha.chen@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.2.0"
|
||||
pest = "2.0"
|
||||
pest_derive = "2.0"
|
||||
regex = "1"
|
@ -1,64 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::io::{self, Read};
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input)?;
|
||||
|
||||
let output = solve_1(&input, "\n");
|
||||
println!("{}", output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn solve_0(input: &str, delimiter: &str) -> String {
|
||||
let sum: i32 = input
|
||||
.trim()
|
||||
.split(delimiter)
|
||||
.map(|change| change.parse::<i32>().unwrap())
|
||||
.sum();
|
||||
sum.to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve_0() {
|
||||
assert_eq!(solve_0("+1, -2, +3, +1", ", "), "3");
|
||||
}
|
||||
|
||||
fn solve_1(input: &str, delimiter: &str) -> String {
|
||||
vec![0 as i32] // Start with 0 frequency
|
||||
.into_iter()
|
||||
.chain(
|
||||
input
|
||||
.trim()
|
||||
.split(delimiter)
|
||||
.map(|change| change.parse::<i32>().unwrap())
|
||||
.cycle(),
|
||||
)
|
||||
.scan(0, |freq, change| {
|
||||
*freq += change;
|
||||
Some(*freq)
|
||||
})
|
||||
.scan(HashMap::new(), |history, freq| {
|
||||
let count = history.entry(freq).or_insert(0);
|
||||
*count += 1;
|
||||
|
||||
Some((freq, *count))
|
||||
})
|
||||
.filter(|(_, count)| *count > 1)
|
||||
.map(|(freq, _)| freq)
|
||||
.next()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve_1() {
|
||||
assert_eq!(solve_1("+1, -2, +3, +1", ", "), "2");
|
||||
assert_eq!(solve_1("+1, -1", ", "), "0");
|
||||
assert_eq!(solve_1("+3, +3, +4, -2, -4", ", "), "10");
|
||||
assert_eq!(solve_1("-6, +3, +8, +5, -6", ", "), "5");
|
||||
assert_eq!(solve_1("+7, +7, -2, -7, -4", ", "), "14");
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
use std::error::Error;
|
||||
use std::io::{self, Read};
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input)?;
|
||||
|
||||
let output = solve(&input);
|
||||
println!("{}", output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn solve(input: &str) -> String {
|
||||
let box_ids: Vec<_> = input.lines().map(BoxId::new).collect();
|
||||
|
||||
let two_count = box_ids.iter().filter(|&x| x.is_two()).count();
|
||||
let three_count = box_ids.iter().filter(|&x| x.is_three()).count();
|
||||
|
||||
(two_count * three_count).to_string()
|
||||
}
|
||||
|
||||
struct BoxId(String);
|
||||
|
||||
impl BoxId {
|
||||
fn new(s: &str) -> Self {
|
||||
BoxId(s.into())
|
||||
}
|
||||
|
||||
fn is_two(&self) -> bool {
|
||||
self.is_n(2)
|
||||
}
|
||||
|
||||
fn is_three(&self) -> bool {
|
||||
self.is_n(3)
|
||||
}
|
||||
|
||||
fn is_n(&self, n: usize) -> bool {
|
||||
self.0
|
||||
.chars()
|
||||
.any(|x| self.0.chars().filter(|&y| x == y).count() == n)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_two() {
|
||||
assert_eq!(BoxId::new("abcdef").is_two(), false);
|
||||
assert_eq!(BoxId::new("bababc").is_two(), true);
|
||||
assert_eq!(BoxId::new("abbcde").is_two(), true);
|
||||
assert_eq!(BoxId::new("abcccd").is_two(), false);
|
||||
assert_eq!(BoxId::new("aabcdd").is_two(), true);
|
||||
assert_eq!(BoxId::new("abcdee").is_two(), true);
|
||||
assert_eq!(BoxId::new("ababab").is_two(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_three() {
|
||||
assert_eq!(BoxId::new("abcdef").is_three(), false);
|
||||
assert_eq!(BoxId::new("bababc").is_three(), true);
|
||||
assert_eq!(BoxId::new("abbcde").is_three(), false);
|
||||
assert_eq!(BoxId::new("abcccd").is_three(), true);
|
||||
assert_eq!(BoxId::new("aabcdd").is_three(), false);
|
||||
assert_eq!(BoxId::new("abcdee").is_three(), false);
|
||||
assert_eq!(BoxId::new("ababab").is_three(), true);
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::io::{self, Read};
|
||||
use std::str::FromStr;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input)?;
|
||||
|
||||
let output = solve(&input)?;
|
||||
println!("{}", output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||
let claims: Vec<_> = input
|
||||
.lines()
|
||||
.map(str::trim)
|
||||
.map(Claim::from_str)
|
||||
.collect::<Result<_, _>>()?;
|
||||
let fabric = claims.iter().fold(
|
||||
HashMap::new(),
|
||||
|mut fabric: HashMap<(usize, usize), Vec<usize>>, claim| {
|
||||
for square_inch in claim.square_inches() {
|
||||
fabric
|
||||
.entry(square_inch)
|
||||
.and_modify(|ids| ids.push(claim.id))
|
||||
.or_insert_with(|| vec![claim.id]);
|
||||
}
|
||||
fabric
|
||||
},
|
||||
);
|
||||
let values: Vec<_> = fabric.values().collect();
|
||||
let output = values
|
||||
.iter()
|
||||
.map(|ids| ids[0])
|
||||
.find(|id| !values.iter().any(|ids| ids.len() > 1 && ids.contains(id)))
|
||||
.unwrap()
|
||||
.to_string();
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve() {
|
||||
let input = r"
|
||||
#1 @ 1,3: 4x4
|
||||
#2 @ 3,1: 4x4
|
||||
#3 @ 5,5: 2x2
|
||||
"
|
||||
.trim();
|
||||
|
||||
assert_eq!(&solve(input).unwrap(), "3");
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Claim {
|
||||
id: usize,
|
||||
x: usize,
|
||||
y: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
}
|
||||
|
||||
impl Claim {
|
||||
fn square_inches(&self) -> impl Iterator<Item = (usize, usize)> + '_ {
|
||||
(self.x..self.x + self.width)
|
||||
.flat_map(move |x| (self.y..self.y + self.height).map(move |y| (x, y)))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_claim_square_inches() {
|
||||
let claim = Claim {
|
||||
id: 1,
|
||||
x: 2,
|
||||
y: 3,
|
||||
width: 4,
|
||||
height: 4,
|
||||
};
|
||||
let square_inches: Vec<_> = claim.square_inches().collect();
|
||||
assert_eq!(square_inches.len(), 16);
|
||||
assert!(square_inches.contains(&(2, 3)));
|
||||
assert!(square_inches.contains(&(5, 3)));
|
||||
assert!(square_inches.contains(&(5, 6)));
|
||||
assert!(square_inches.contains(&(2, 6)));
|
||||
}
|
||||
|
||||
impl FromStr for Claim {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let re =
|
||||
Regex::new(r"^#(?P<id>\d+) @ (?P<x>\d+),(?P<y>\d+): (?P<width>\d+)x(?P<height>\d+)$")
|
||||
.unwrap();
|
||||
|
||||
let captures = re.captures(s).unwrap();
|
||||
let id = captures.name("id").unwrap().as_str().parse()?;
|
||||
let x = captures.name("x").unwrap().as_str().parse()?;
|
||||
let y = captures.name("y").unwrap().as_str().parse()?;
|
||||
let width = captures.name("width").unwrap().as_str().parse()?;
|
||||
let height = captures.name("height").unwrap().as_str().parse()?;
|
||||
|
||||
Ok(Claim {
|
||||
id,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_claim_from_str() {
|
||||
let claim = Claim::from_str("#1 @ 1,3: 4x4").unwrap();
|
||||
assert_eq!(
|
||||
claim,
|
||||
Claim {
|
||||
id: 1,
|
||||
x: 1,
|
||||
y: 3,
|
||||
width: 4,
|
||||
height: 4
|
||||
}
|
||||
);
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::io::{self, Read};
|
||||
use std::ops::Range;
|
||||
|
||||
use pest::iterators::Pair;
|
||||
use pest::Parser;
|
||||
use pest_derive::Parser;
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input)?;
|
||||
|
||||
let output = solve(&input)?;
|
||||
println!("{}", output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||
let records = Record::parse(input)?;
|
||||
|
||||
let mut stats = HashMap::new();
|
||||
for record in records {
|
||||
let minute_stats = stats.entry(record.guard_id).or_insert_with(HashMap::new);
|
||||
let minutes: Vec<_> = record
|
||||
.sleep_ranges
|
||||
.into_iter()
|
||||
.flat_map(|x| x.collect::<Vec<_>>())
|
||||
.collect();
|
||||
for minute in minutes {
|
||||
let count = minute_stats.entry(minute).or_insert(0);
|
||||
*count += 1
|
||||
}
|
||||
}
|
||||
|
||||
// Part One
|
||||
// let (guard, minute_stats) = stats
|
||||
// .iter()
|
||||
// .max_by_key::<usize, _>(|(_, v)| v.iter().map(|(_, v)| v).sum())
|
||||
// .unwrap();
|
||||
// let (minute, _) = minute_stats.iter().max_by_key(|(_, &v)| v).unwrap();
|
||||
|
||||
// Part Two
|
||||
let (guard, (minute, _)) = stats
|
||||
.iter()
|
||||
.flat_map(|(k, minute_counts)| minute_counts.iter().max_by_key(|(_, &v)| v).map(|v| (k, v)))
|
||||
.max_by_key(|(_, (_, &v))| v)
|
||||
.unwrap();
|
||||
|
||||
Ok((guard * minute).to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve() {
|
||||
let input = r"
|
||||
[1518-11-01 00:00] Guard #10 begins shift
|
||||
[1518-11-01 00:05] falls asleep
|
||||
[1518-11-01 00:25] wakes up
|
||||
[1518-11-01 00:30] falls asleep
|
||||
[1518-11-01 00:55] wakes up
|
||||
[1518-11-01 23:58] Guard #99 begins shift
|
||||
[1518-11-02 00:40] falls asleep
|
||||
[1518-11-02 00:50] wakes up
|
||||
[1518-11-03 00:05] Guard #10 begins shift
|
||||
[1518-11-03 00:24] falls asleep
|
||||
[1518-11-03 00:29] wakes up
|
||||
[1518-11-04 00:02] Guard #99 begins shift
|
||||
[1518-11-04 00:36] falls asleep
|
||||
[1518-11-04 00:46] wakes up
|
||||
[1518-11-05 00:03] Guard #99 begins shift
|
||||
[1518-11-05 00:45] falls asleep
|
||||
[1518-11-05 00:55] wakes up
|
||||
"
|
||||
.trim();
|
||||
|
||||
let output = solve(input).unwrap();
|
||||
|
||||
// Part One
|
||||
// assert_eq!(output, "240".to_string());
|
||||
|
||||
// Part Two
|
||||
assert_eq!(output, "4455".to_string());
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Record {
|
||||
guard_id: usize,
|
||||
sleep_ranges: Vec<Range<usize>>,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
fn parse(s: &str) -> Result<Vec<Record>, Box<Error>> {
|
||||
let mut records: Vec<_> = s.lines().collect();
|
||||
records.sort();
|
||||
let input = records.join("\n");
|
||||
|
||||
let mut parsed = RecordsParser::parse(Rule::records, &input)?;
|
||||
let records: Vec<Record> = parsed
|
||||
.next()
|
||||
.unwrap()
|
||||
.into_inner()
|
||||
.flat_map(|record| match record.as_rule() {
|
||||
Rule::record => Some(record.into()),
|
||||
Rule::EOI => None,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
fn parse_sleep_range(pair: Pair<Rule>) -> Range<usize> {
|
||||
let mut sleep_range = pair.into_inner();
|
||||
let falls_asleep: usize = Self::parse_minute(sleep_range.next().unwrap());
|
||||
let wakes_up: usize = Self::parse_minute(sleep_range.next().unwrap());
|
||||
(falls_asleep..wakes_up)
|
||||
}
|
||||
|
||||
fn parse_minute(pair: Pair<Rule>) -> usize {
|
||||
pair.into_inner().next().unwrap().as_str().parse().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parsing() {
|
||||
let input = r"
|
||||
[1518-11-01 00:00] Guard #10 begins shift
|
||||
[1518-11-01 00:05] falls asleep
|
||||
[1518-11-01 00:25] wakes up
|
||||
[1518-11-01 00:30] falls asleep
|
||||
[1518-11-01 00:55] wakes up
|
||||
[1518-11-01 23:58] Guard #99 begins shift
|
||||
[1518-11-02 00:40] falls asleep
|
||||
[1518-11-02 00:50] wakes up
|
||||
[1518-11-03 00:05] Guard #10 begins shift
|
||||
[1518-11-03 00:24] falls asleep
|
||||
[1518-11-03 00:29] wakes up
|
||||
[1518-11-04 00:02] Guard #99 begins shift
|
||||
[1518-11-04 00:36] falls asleep
|
||||
[1518-11-04 00:46] wakes up
|
||||
[1518-11-05 00:03] Guard #99 begins shift
|
||||
[1518-11-05 00:45] falls asleep
|
||||
[1518-11-05 00:55] wakes up
|
||||
"
|
||||
.trim();
|
||||
|
||||
let records = Record::parse(input).unwrap();
|
||||
assert_eq!(records.len(), 5);
|
||||
let record = &records[0];
|
||||
assert_eq!(record.guard_id, 10);
|
||||
assert_eq!(record.sleep_ranges, vec![(5..25), (30..55)]);
|
||||
}
|
||||
|
||||
impl<'a> From<Pair<'a, Rule>> for Record {
|
||||
fn from(pair: Pair<Rule>) -> Self {
|
||||
let mut record = pair.into_inner();
|
||||
let guard_id = record
|
||||
.next()
|
||||
.unwrap()
|
||||
.into_inner()
|
||||
.nth(1) // skip the minute
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.parse()
|
||||
.unwrap();
|
||||
let sleep_ranges: Vec<_> = record
|
||||
.next()
|
||||
.unwrap()
|
||||
.into_inner()
|
||||
.map(Self::parse_sleep_range)
|
||||
.collect();
|
||||
|
||||
Record {
|
||||
guard_id,
|
||||
sleep_ranges,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[grammar = "day_04.pest"]
|
||||
#[allow(dead_code)]
|
||||
struct RecordsParser;
|
@ -1,103 +0,0 @@
|
||||
use std::error::Error;
|
||||
use std::io::{self, Read};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input)?;
|
||||
|
||||
let output = solve(&input)?;
|
||||
println!("{}", output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||
let polymer = input.trim();
|
||||
|
||||
// Part One
|
||||
// let reaction = Reaction {
|
||||
// polymer: polymer.into()
|
||||
// };
|
||||
// Ok(reaction.last().map(|x| x.len().to_string()).unwrap())
|
||||
|
||||
// Part Two
|
||||
let output = (b'a'..=b'z')
|
||||
.map(|x| x as char)
|
||||
.map(|x| {
|
||||
polymer
|
||||
.replace(x, "")
|
||||
.replace(&x.to_uppercase().to_string(), "")
|
||||
})
|
||||
.map(|polymer| Reaction { polymer })
|
||||
.flat_map(|reaction| reaction.last())
|
||||
.map(|polymer| polymer.len())
|
||||
.min();
|
||||
Ok(output.unwrap().to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve() {
|
||||
let input = "dabAcCaCBAcCcaDA";
|
||||
|
||||
let output = solve(input).unwrap();
|
||||
|
||||
// Part One
|
||||
// assert_eq!(output, "10".to_string());
|
||||
|
||||
// Part Two
|
||||
assert_eq!(output, "4".to_string());
|
||||
}
|
||||
|
||||
struct Reaction {
|
||||
polymer: String,
|
||||
}
|
||||
|
||||
impl Iterator for Reaction {
|
||||
type Item = String;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = {
|
||||
let re: String = (b'a'..=b'z')
|
||||
.map(|x| x as char)
|
||||
.flat_map(|x| {
|
||||
vec![
|
||||
format!("{}{}", x, x.to_uppercase()),
|
||||
format!("{}{}", x.to_uppercase(), x),
|
||||
]
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("|");
|
||||
Regex::new(&re).unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
let current = self.polymer.clone();
|
||||
self.polymer = RE.replace(&self.polymer, "").into();
|
||||
if self.polymer == current {
|
||||
None
|
||||
} else {
|
||||
Some(self.polymer.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reaction() {
|
||||
let polymer = "dabAcCaCBAcCcaDA".into();
|
||||
let mut reaction = Reaction { polymer };
|
||||
|
||||
let polymer = reaction.next().unwrap();
|
||||
assert_eq!(polymer, "dabAaCBAcCcaDA".to_string());
|
||||
|
||||
let polymer = reaction.next().unwrap();
|
||||
assert_eq!(polymer, "dabCBAcCcaDA".to_string());
|
||||
|
||||
let polymer = reaction.next().unwrap();
|
||||
assert_eq!(polymer, "dabCBAcaDA".to_string());
|
||||
|
||||
assert_eq!(reaction.next(), Option::None);
|
||||
}
|
@ -1,287 +0,0 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::error::Error;
|
||||
use std::hash::Hash;
|
||||
use std::io::{self, Read};
|
||||
use std::str::FromStr;
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input)?;
|
||||
|
||||
let output = part_two(&input, 10_000)?;
|
||||
println!("{}", output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn part_two(input: &str, max_distance: usize) -> Result<String, Box<Error>> {
|
||||
let coords = Coords::from_str(input)?;
|
||||
|
||||
let min_x = coords.0.iter().map(|c| c.x).min().unwrap();
|
||||
let max_x = coords.0.iter().map(|c| c.x).max().unwrap();
|
||||
let min_y = coords.0.iter().map(|c| c.y).min().unwrap();
|
||||
let max_y = coords.0.iter().map(|c| c.y).max().unwrap();
|
||||
let top_left = Coord { x: min_x, y: min_y };
|
||||
let bottom_right = Coord { x: max_x, y: max_y };
|
||||
|
||||
let grid = Grid::new(top_left, bottom_right, |coord| {
|
||||
coords.total_distance(*coord)
|
||||
});
|
||||
|
||||
let area = grid
|
||||
.locations
|
||||
.values()
|
||||
.filter(|&&x| x < max_distance)
|
||||
.count();
|
||||
Ok(area.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_two() {
|
||||
let input = r"
|
||||
1, 1
|
||||
1, 6
|
||||
8, 3
|
||||
3, 4
|
||||
5, 5
|
||||
8, 9
|
||||
";
|
||||
|
||||
let output = part_two(&input, 32).unwrap();
|
||||
assert_eq!(output, "16".to_string());
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn part_one(input: &str) -> Result<String, Box<Error>> {
|
||||
let coords = Coords::from_str(input)?;
|
||||
|
||||
let min_x = coords.0.iter().map(|c| c.x).min().unwrap();
|
||||
let max_x = coords.0.iter().map(|c| c.x).max().unwrap();
|
||||
let min_y = coords.0.iter().map(|c| c.y).min().unwrap();
|
||||
let max_y = coords.0.iter().map(|c| c.y).max().unwrap();
|
||||
let top_left = Coord { x: min_x, y: min_y };
|
||||
let bottom_right = Coord { x: max_x, y: max_y };
|
||||
|
||||
let coord_names: HashMap<_, _> = coords
|
||||
.0
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, c)| (c, (i + 65) as u8 as char))
|
||||
.collect();
|
||||
|
||||
let grid = Grid::new(top_left, bottom_right, |coord| {
|
||||
coords
|
||||
.closest(*coord)
|
||||
.and_then(|closest| coord_names.get(&closest))
|
||||
});
|
||||
let edges: HashSet<_> = grid.edges().iter().flat_map(|&x| x).collect();
|
||||
|
||||
let mut area_sizes = HashMap::new();
|
||||
grid.locations
|
||||
.values()
|
||||
.flat_map(|x| x)
|
||||
.filter(|x| !edges.contains(x))
|
||||
.for_each(|x| {
|
||||
let count = area_sizes.entry(x).or_insert(0);
|
||||
*count += 1;
|
||||
});
|
||||
|
||||
let max_area = area_sizes.iter().map(|(_, v)| v).max().unwrap();
|
||||
Ok(max_area.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_one() {
|
||||
let input = r"
|
||||
1, 1
|
||||
1, 6
|
||||
8, 3
|
||||
3, 4
|
||||
5, 5
|
||||
8, 9
|
||||
";
|
||||
|
||||
let output = part_one(&input).unwrap();
|
||||
assert_eq!(output, "17".to_string());
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Grid<T> {
|
||||
top_left: Coord,
|
||||
bottom_right: Coord,
|
||||
locations: HashMap<Coord, T>,
|
||||
}
|
||||
|
||||
impl<T> Grid<T> {
|
||||
fn new<C: Into<Coord>, F: Fn(&Coord) -> T>(top_left: C, bottom_right: C, f: F) -> Self {
|
||||
let top_left = top_left.into();
|
||||
let bottom_right = bottom_right.into();
|
||||
let mut locations = HashMap::new();
|
||||
|
||||
for coord in top_left.grid(&bottom_right) {
|
||||
locations.insert(coord, f(&coord));
|
||||
}
|
||||
|
||||
Grid {
|
||||
top_left,
|
||||
bottom_right,
|
||||
locations,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq + Hash> Grid<T> {
|
||||
fn edges(&self) -> HashSet<&T> {
|
||||
let mut edges = HashSet::new();
|
||||
|
||||
for x in self.top_left.x..=self.bottom_right.x {
|
||||
for &y in &[self.top_left.y, self.bottom_right.y] {
|
||||
if let Some(t) = self.locations.get(&Coord { x, y }) {
|
||||
edges.insert(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for y in self.top_left.y..=self.bottom_right.y {
|
||||
for &x in &[self.top_left.x, self.bottom_right.x] {
|
||||
if let Some(t) = self.locations.get(&Coord { x, y }) {
|
||||
edges.insert(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edges
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edges() {
|
||||
let top_left = Coord { x: 0, y: 0 };
|
||||
let bottom_right = Coord { x: 2, y: 2 };
|
||||
let grid = Grid::new(top_left, bottom_right, |coord| coord.y * 3 + coord.x);
|
||||
let expected: HashSet<_> = vec![0, 1, 2, 3, 5, 6, 7, 8]
|
||||
.iter()
|
||||
.map(|&x| x as isize)
|
||||
.collect();
|
||||
assert_eq!(grid.edges(), expected.iter().collect());
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Coords(Vec<Coord>);
|
||||
|
||||
impl Coords {
|
||||
fn closest<C: Into<Coord>>(&self, c: C) -> Option<Coord> {
|
||||
let c = c.into();
|
||||
|
||||
let mut distances = HashMap::new();
|
||||
for coord in &self.0 {
|
||||
let distance = coord.distance(c);
|
||||
let v = distances.entry(distance).or_insert_with(Vec::new);
|
||||
v.push(coord);
|
||||
}
|
||||
|
||||
let (_, closest_coords) = distances.iter().min_by_key(|(&k, _)| k)?;
|
||||
if closest_coords.len() == 1 {
|
||||
Some(*closest_coords[0])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn total_distance<C: Into<Coord>>(&self, c: C) -> usize {
|
||||
let c = c.into();
|
||||
self.0.iter().map(|x| x.distance(c) as usize).sum()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_closest() {
|
||||
let coords = Coords::from_str(
|
||||
r"
|
||||
1, 1
|
||||
1, 6
|
||||
8, 3
|
||||
3, 4
|
||||
5, 5
|
||||
8, 9
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(coords.closest((0, 0)), Some(Coord::from((1, 1))));
|
||||
assert_eq!(coords.closest((3, 2)), Some(Coord::from((3, 4))));
|
||||
assert_eq!(coords.closest((5, 0)), None);
|
||||
assert_eq!(coords.closest((0, 4)), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_total_distance() {
|
||||
let coords = Coords::from_str(
|
||||
r"
|
||||
1, 1
|
||||
1, 6
|
||||
8, 3
|
||||
3, 4
|
||||
5, 5
|
||||
8, 9
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(coords.total_distance((4, 3)), 30);
|
||||
}
|
||||
|
||||
impl FromStr for Coords {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let coords = s
|
||||
.trim()
|
||||
.lines()
|
||||
.map(Coord::from_str)
|
||||
.collect::<Result<_, _>>()?;
|
||||
Ok(Coords(coords))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
struct Coord {
|
||||
x: isize,
|
||||
y: isize,
|
||||
}
|
||||
|
||||
impl Coord {
|
||||
fn distance<C: Into<Self>>(&self, other: C) -> isize {
|
||||
let other = other.into();
|
||||
(self.x - other.x).abs() + (self.y - other.y).abs()
|
||||
}
|
||||
|
||||
fn grid(&self, to: &Self) -> impl Iterator<Item = Coord> + '_ {
|
||||
let to = *to;
|
||||
(self.x..=to.x).flat_map(move |x| (self.y..=to.y).map(move |y| (x, y).into()))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_distance() {
|
||||
let coord = Coord { x: 4, y: 3 };
|
||||
assert_eq!(coord.distance((1, 1)), 5);
|
||||
assert_eq!(coord.distance((8, 9)), 10);
|
||||
}
|
||||
|
||||
impl From<(isize, isize)> for Coord {
|
||||
fn from((x, y): (isize, isize)) -> Self {
|
||||
Coord { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Coord {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut xy = s.split(", ");
|
||||
let x = xy.next().unwrap().parse()?;
|
||||
let y = xy.next().unwrap().parse()?;
|
||||
Ok(Coord { x, y })
|
||||
}
|
||||
}
|
@ -1,254 +0,0 @@
|
||||
#![feature(vec_remove_item)]
|
||||
|
||||
use std::cmp::{Ord, Ordering};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::error::Error;
|
||||
use std::str::FromStr;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use advent_of_code::main;
|
||||
|
||||
main!();
|
||||
|
||||
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||
let assembly: Assembly = input.parse()?;
|
||||
let output = part_two(assembly, 5, |x| (x as usize) - ('A' as usize) + 61);
|
||||
Ok(output.to_string())
|
||||
}
|
||||
|
||||
fn part_two<F: Fn(char) -> usize>(assembly: Assembly, worker_count: usize, step_time: F) -> usize {
|
||||
let workers = Workers(vec![None; worker_count]);
|
||||
PartTwo {
|
||||
assembly,
|
||||
workers,
|
||||
step_time,
|
||||
}
|
||||
.count()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_two() {
|
||||
let input = r"
|
||||
Step C must be finished before step A can begin.
|
||||
Step C must be finished before step F can begin.
|
||||
Step A must be finished before step B can begin.
|
||||
Step A must be finished before step D can begin.
|
||||
Step B must be finished before step E can begin.
|
||||
Step D must be finished before step E can begin.
|
||||
Step F must be finished before step E can begin.
|
||||
";
|
||||
|
||||
let assembly: Assembly = input.parse().unwrap();
|
||||
let output = part_two(assembly, 2, |x| (x as usize) - ('A' as usize) + 1);
|
||||
assert_eq!(output, 15);
|
||||
}
|
||||
|
||||
struct PartTwo<F> {
|
||||
assembly: Assembly,
|
||||
workers: Workers,
|
||||
step_time: F,
|
||||
}
|
||||
|
||||
impl<F: Fn(char) -> usize> Iterator for PartTwo<F> {
|
||||
type Item = Vec<Option<char>>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.assembly.is_done() {
|
||||
return None;
|
||||
}
|
||||
|
||||
for (worker, step_id) in self
|
||||
.workers
|
||||
.available()
|
||||
.iter_mut()
|
||||
.zip(self.assembly.available())
|
||||
{
|
||||
worker.replace((step_id, (self.step_time)(step_id)));
|
||||
self.assembly.start(step_id);
|
||||
}
|
||||
|
||||
let done = self.workers.tick();
|
||||
for step_id in done {
|
||||
self.assembly.finish(step_id);
|
||||
}
|
||||
|
||||
Some(self.workers.0.iter().map(|x| x.map(|x| x.0)).collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Workers(Vec<Option<(char, usize)>>);
|
||||
|
||||
impl Workers {
|
||||
fn available(&mut self) -> Vec<&mut Option<(char, usize)>> {
|
||||
self.0.iter_mut().filter(|x| x.is_none()).collect()
|
||||
}
|
||||
|
||||
fn tick(&mut self) -> Vec<char> {
|
||||
let mut done = Vec::new();
|
||||
for maybe_work in self.0.iter_mut() {
|
||||
if let Some((step, mut time)) = maybe_work.take() {
|
||||
time -= 1;
|
||||
if time > 0 {
|
||||
maybe_work.replace((step, time));
|
||||
} else {
|
||||
done.push(step);
|
||||
}
|
||||
}
|
||||
}
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_workers() {
|
||||
let mut workers = Workers(vec![None; 5]);
|
||||
|
||||
let steps = workers.tick();
|
||||
assert!(steps.is_empty());
|
||||
|
||||
let worker = &mut workers.available()[0];
|
||||
worker.replace(('a', 5));
|
||||
assert_eq!(workers.0[0], Some(('a', 5)));
|
||||
|
||||
let worker = &mut workers.available()[0];
|
||||
worker.replace(('b', 1));
|
||||
assert_eq!(workers.0[1], Some(('b', 1)));
|
||||
|
||||
let steps = workers.tick();
|
||||
assert_eq!(workers.0[0], Some(('a', 4)));
|
||||
assert_eq!(steps, vec!['b']);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn part_one(assembly: &mut Assembly) -> Vec<char> {
|
||||
let mut output = Vec::new();
|
||||
while !assembly.is_done() {
|
||||
let done = assembly.available()[0];
|
||||
|
||||
output.push(done);
|
||||
|
||||
assembly.finish(done);
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part_one() {
|
||||
let input = r"
|
||||
Step C must be finished before step A can begin.
|
||||
Step C must be finished before step F can begin.
|
||||
Step A must be finished before step B can begin.
|
||||
Step A must be finished before step D can begin.
|
||||
Step B must be finished before step E can begin.
|
||||
Step D must be finished before step E can begin.
|
||||
Step F must be finished before step E can begin.
|
||||
";
|
||||
|
||||
let mut assembly: Assembly = input.parse().unwrap();
|
||||
let output = part_one(&mut assembly);
|
||||
assert_eq!(output, vec!['C', 'A', 'B', 'D', 'F', 'E']);
|
||||
}
|
||||
|
||||
struct Assembly(Vec<Step>);
|
||||
|
||||
impl Assembly {
|
||||
fn is_done(&self) -> bool {
|
||||
self.0.iter().all(|x| x.state == State::Finished)
|
||||
}
|
||||
|
||||
fn available(&self) -> Vec<char> {
|
||||
let finished = self.finished();
|
||||
let mut available: Vec<_> = self
|
||||
.0
|
||||
.iter()
|
||||
.filter(|x| x.state == State::Unstarted)
|
||||
.filter(|x| x.deps.iter().all(|x| finished.contains(x)))
|
||||
.map(|x| x.id)
|
||||
.collect();
|
||||
available.sort();
|
||||
available
|
||||
}
|
||||
|
||||
fn finished(&self) -> Vec<char> {
|
||||
self.0
|
||||
.iter()
|
||||
.filter(|x| x.state == State::Finished)
|
||||
.map(|x| x.id)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn start(&mut self, step_id: char) {
|
||||
if let Some(step) = self.0.iter_mut().find(|x| x.id == step_id) {
|
||||
step.state = State::InProgress;
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(&mut self, step_id: char) {
|
||||
if let Some(step) = self.0.iter_mut().find(|x| x.id == step_id) {
|
||||
step.state = State::Finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Assembly {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let re = Regex::new(r"^Step (\w).*step (\w)").unwrap();
|
||||
|
||||
let mut steps = HashMap::new();
|
||||
s.trim()
|
||||
.lines()
|
||||
.flat_map(|x| re.captures(x))
|
||||
.map(|x| {
|
||||
x.iter()
|
||||
.flat_map(|x| x)
|
||||
.map(|x| x.as_str().chars().next().unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.map(|x| (x[1], x[2]))
|
||||
.for_each(|(x, y)| {
|
||||
steps.entry(x).or_insert_with(HashSet::new);
|
||||
let entry = steps.entry(y).or_insert_with(HashSet::new);
|
||||
entry.insert(x);
|
||||
});
|
||||
let steps = steps
|
||||
.into_iter()
|
||||
.map(|(id, deps)| {
|
||||
let state = State::Unstarted;
|
||||
Step { id, deps, state }
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(Assembly(steps))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
struct Step {
|
||||
id: char,
|
||||
deps: HashSet<char>,
|
||||
state: State,
|
||||
}
|
||||
|
||||
impl PartialOrd for Step {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Step {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.id.cmp(&other.id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
enum State {
|
||||
Unstarted,
|
||||
InProgress,
|
||||
Finished,
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
use std::error::Error;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use advent_of_code::main;
|
||||
|
||||
main!();
|
||||
|
||||
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||
let re = Regex::new(r"(?P<players>\d+) players; last marble is worth (?P<points>\d+) points")
|
||||
.unwrap();
|
||||
let caps = re.captures(input).unwrap();
|
||||
let player_count = caps.name("players").unwrap().as_str().parse()?;
|
||||
let marble_count: usize = caps.name("points").unwrap().as_str().parse()?;
|
||||
let high_score = play(player_count, marble_count * 100);
|
||||
Ok(high_score.to_string())
|
||||
}
|
||||
|
||||
fn play(player_count: usize, marble_count: usize) -> usize {
|
||||
let mut scores = vec![0; player_count];
|
||||
let mut circle = vec![Marble {
|
||||
value: 0,
|
||||
next: 0,
|
||||
prev: 0,
|
||||
}];
|
||||
|
||||
let mut current_player = 0;
|
||||
let mut current_index: usize = 0;
|
||||
|
||||
for value in 1..=marble_count {
|
||||
if value % 23 == 0 {
|
||||
scores[current_player] += value;
|
||||
for _ in 0..7 {
|
||||
current_index = circle[current_index].prev;
|
||||
}
|
||||
let marble = &circle[current_index];
|
||||
scores[current_player] += marble.value;
|
||||
let prev = marble.prev;
|
||||
let next = marble.next;
|
||||
circle[prev].next = next;
|
||||
circle[next].prev = prev;
|
||||
current_index = next;
|
||||
} else {
|
||||
current_index = circle[current_index].next;
|
||||
let current_marble = &circle[current_index];
|
||||
let next = current_marble.next;
|
||||
let prev = current_index;
|
||||
let marble = Marble { value, next, prev };
|
||||
circle.push(marble);
|
||||
current_index = circle.len() - 1;
|
||||
circle[prev].next = current_index;
|
||||
circle[next].prev = current_index;
|
||||
}
|
||||
|
||||
// if current_index % 100000 == 0 {
|
||||
// println!("{}", current_index);
|
||||
// }
|
||||
// println!("[{}] {:?}", current_player + 1, circle_to_string(&circle));
|
||||
|
||||
current_player += 1;
|
||||
current_player %= player_count;
|
||||
}
|
||||
|
||||
*scores.iter().max().unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_play() {
|
||||
assert_eq!(play(9, 25), 32);
|
||||
assert_eq!(play(10, 1618), 8317);
|
||||
assert_eq!(play(13, 7999), 146373);
|
||||
assert_eq!(play(17, 1104), 2764);
|
||||
assert_eq!(play(21, 6111), 54718);
|
||||
assert_eq!(play(30, 5807), 37305);
|
||||
}
|
||||
|
||||
// fn circle_to_string(circle: &Vec<Marble>) -> String {
|
||||
// let mut i = 0;
|
||||
// let mut v = Vec::new();
|
||||
// loop {
|
||||
// v.push(circle[i].value);
|
||||
// i = circle[i].next;
|
||||
// if i == 0 {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// format!("{:?}", v)
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Marble {
|
||||
value: usize,
|
||||
next: usize,
|
||||
prev: usize,
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use advent_of_code::main;
|
||||
|
||||
main!();
|
||||
|
||||
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||
let mut generation: Generation = input.parse()?;
|
||||
for _ in 0..19 {
|
||||
generation.next();
|
||||
}
|
||||
|
||||
let pots = generation.next().unwrap();
|
||||
let indices: Vec<_> = pots.iter().filter(|(_, &v)| v).map(|(&k, _)| k).collect();
|
||||
let output: isize = indices.iter().sum();
|
||||
|
||||
Ok(output.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve() {
|
||||
let input = r"
|
||||
initial state: #..#.#..##......###...###
|
||||
|
||||
...## => #
|
||||
..#.. => #
|
||||
.#... => #
|
||||
.#.#. => #
|
||||
.#.## => #
|
||||
.##.. => #
|
||||
.#### => #
|
||||
#.#.# => #
|
||||
#.### => #
|
||||
##.#. => #
|
||||
##.## => #
|
||||
###.. => #
|
||||
###.# => #
|
||||
####. => #
|
||||
";
|
||||
|
||||
assert_eq!(solve(&input).unwrap(), 325.to_string());
|
||||
}
|
||||
|
||||
struct Generation {
|
||||
pots: HashMap<isize, bool>,
|
||||
notes: HashMap<String, bool>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Generation {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let plants: Vec<_> = self
|
||||
.pots
|
||||
.iter()
|
||||
.filter(|(_, &v)| v)
|
||||
.map(|(&k, _)| k)
|
||||
.collect();
|
||||
let min = *plants.iter().min().unwrap();
|
||||
let max = *plants.iter().max().unwrap();
|
||||
let s: String = (min..=max)
|
||||
.map(|x| self.pots.get(&x).unwrap_or_else(|| &false))
|
||||
.map(|&x| if x { '#' } else { '.' })
|
||||
.collect();
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Generation {
|
||||
type Item = HashMap<isize, bool>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let plants: Vec<_> = self
|
||||
.pots
|
||||
.iter()
|
||||
.filter(|(_, &v)| v)
|
||||
.map(|(&k, _)| k)
|
||||
.collect();
|
||||
let min = *plants.iter().min().unwrap() - 2;
|
||||
let max = *plants.iter().max().unwrap() + 2;
|
||||
self.pots = (min..=max)
|
||||
.map(|i| {
|
||||
let key: String = ((i - 2)..=(i + 2))
|
||||
.map(|x| self.pots.get(&x).unwrap_or_else(|| &false))
|
||||
.map(|&x| if x { '#' } else { '.' })
|
||||
.collect();
|
||||
let value = *self.notes.get(&key).unwrap_or_else(|| &false);
|
||||
(i, value)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Some(self.pots.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generation() {
|
||||
let input = r"
|
||||
initial state: #..#.#..##......###...###
|
||||
|
||||
...## => #
|
||||
..#.. => #
|
||||
.#... => #
|
||||
.#.#. => #
|
||||
.#.## => #
|
||||
.##.. => #
|
||||
.#### => #
|
||||
#.#.# => #
|
||||
#.### => #
|
||||
##.#. => #
|
||||
##.## => #
|
||||
###.. => #
|
||||
###.# => #
|
||||
####. => #
|
||||
";
|
||||
let mut generation: Generation = input.parse().unwrap();
|
||||
let pots = generation.pots.clone();
|
||||
assert!(pots.get(&0).unwrap());
|
||||
assert!(pots.get(&3).unwrap());
|
||||
assert!(!pots.get(&4).unwrap());
|
||||
|
||||
let pots = generation.next().unwrap();
|
||||
assert!(pots.get(&0).unwrap());
|
||||
assert!(!pots.get(&3).unwrap());
|
||||
assert!(pots.get(&4).unwrap());
|
||||
}
|
||||
|
||||
impl FromStr for Generation {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut lines = s.trim().lines();
|
||||
|
||||
let initial_state = lines.next().unwrap();
|
||||
let pots = Regex::new(r"[.#]+")
|
||||
.ok()
|
||||
.and_then(|re| re.find(initial_state))
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.chars()
|
||||
.enumerate()
|
||||
.map(|(i, c)| (i as isize, c == '#'))
|
||||
.collect();
|
||||
|
||||
lines.next(); // skip blank line
|
||||
|
||||
let notes = lines
|
||||
.map(|line| {
|
||||
let mut note = line.split(" => ");
|
||||
let key = note.next().unwrap();
|
||||
let value = note.next().unwrap() == "#";
|
||||
(key.into(), value)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(Generation { pots, notes })
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
use std::error::Error;
|
||||
|
||||
use advent_of_code::main;
|
||||
|
||||
main!();
|
||||
|
||||
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||
let elves = vec![0, 1];
|
||||
let recipes = "37".into();
|
||||
let scoreboard = Scoreboard { elves, recipes };
|
||||
|
||||
let needle = input;
|
||||
// let recipes = scoreboard.find(|x| x.len() > n + 9).unwrap();
|
||||
// let score: String = recipes[n..n + 10].iter().map(|&x| x.to_string()).collect();
|
||||
|
||||
let n = scoreboard
|
||||
.scan(0, |n, recipes| {
|
||||
let seen = *n;
|
||||
*n = recipes
|
||||
.len()
|
||||
.checked_sub(needle.len() - 1)
|
||||
.unwrap_or_else(|| 0);
|
||||
Some((seen, recipes[seen..recipes.len()].to_string()))
|
||||
})
|
||||
// .inspect(|x| println!("{:?}", x))
|
||||
.flat_map(|(n, x)| x.find(needle).map(|i| n + i))
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
Ok(n.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve() {
|
||||
// Part Two
|
||||
assert_eq!(&solve("51589").unwrap(), "9");
|
||||
assert_eq!(&solve("01245").unwrap(), "5");
|
||||
assert_eq!(&solve("92510").unwrap(), "18");
|
||||
assert_eq!(&solve("59414").unwrap(), "2018");
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Scoreboard {
|
||||
elves: Vec<usize>,
|
||||
recipes: String,
|
||||
}
|
||||
|
||||
impl Iterator for Scoreboard {
|
||||
type Item = String;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.recipes.push_str(
|
||||
&self
|
||||
.elves
|
||||
.iter()
|
||||
.map(|&x| self.recipes[x..=x].parse::<usize>().unwrap())
|
||||
.sum::<usize>()
|
||||
.to_string(),
|
||||
);
|
||||
self.elves = self
|
||||
.elves
|
||||
.iter()
|
||||
.map(|&x| (1 + self.recipes[x..=x].parse::<usize>().unwrap() + x) % self.recipes.len())
|
||||
.collect();
|
||||
|
||||
Some(self.recipes.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scoreboard() {
|
||||
let elves = vec![0, 1];
|
||||
let recipes = "37".into();
|
||||
let mut scoreboard = Scoreboard { elves, recipes };
|
||||
|
||||
let recipes = scoreboard.next().unwrap();
|
||||
assert_eq!(recipes, "3710");
|
||||
}
|
@ -1,467 +0,0 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BinaryHeap, HashMap, HashSet};
|
||||
use std::error::Error;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
use advent_of_code::main;
|
||||
|
||||
main!();
|
||||
|
||||
fn solve(_input: &str) -> Result<String, Box<Error>> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
struct Combat {
|
||||
map: Map,
|
||||
}
|
||||
|
||||
impl Combat {
|
||||
fn initiative(&self) -> Vec<(Square, Unit)> {
|
||||
let mut initiative: Vec<_> = self.map.units.iter().map(|(&k, &v)| (k, v)).collect();
|
||||
initiative.sort_by_key(|(x, _)| *x);
|
||||
initiative
|
||||
}
|
||||
|
||||
fn move_unit(&mut self, from: &Square, to: &Square) {
|
||||
let unit = self.map.units.remove(from).unwrap();
|
||||
self.map.units.insert(*to, unit);
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Combat {
|
||||
type Item = Map;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
for (square, unit) in self.initiative() {
|
||||
if let Some(next_step) = unit.next_step(&square, &self.map) {
|
||||
println!("{:?} -> {:?}", square, next_step);
|
||||
self.move_unit(&square, &next_step);
|
||||
}
|
||||
}
|
||||
|
||||
Some(self.map.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_combat() {
|
||||
let map: Map = r"
|
||||
#########
|
||||
#G..G..G#
|
||||
#.......#
|
||||
#.......#
|
||||
#G..E..G#
|
||||
#.......#
|
||||
#.......#
|
||||
#G..G..G#
|
||||
#########
|
||||
"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let mut combat = Combat { map };
|
||||
|
||||
let map = combat.next().unwrap();
|
||||
assert_eq!(
|
||||
format!("{}", map),
|
||||
r"
|
||||
#########
|
||||
#.G...G.#
|
||||
#...G...#
|
||||
#...E..G#
|
||||
#.G.....#
|
||||
#.......#
|
||||
#G..G..G#
|
||||
#.......#
|
||||
#########
|
||||
"
|
||||
.trim()
|
||||
.to_string()
|
||||
);
|
||||
|
||||
let map = combat.next().unwrap();
|
||||
assert_eq!(
|
||||
format!("{}", map),
|
||||
r"
|
||||
#########
|
||||
#..G.G..#
|
||||
#...G...#
|
||||
#.G.E.G.#
|
||||
#.......#
|
||||
#G..G..G#
|
||||
#.......#
|
||||
#.......#
|
||||
#########
|
||||
"
|
||||
.trim()
|
||||
.to_string()
|
||||
);
|
||||
|
||||
let map = combat.next().unwrap();
|
||||
assert_eq!(
|
||||
format!("{}", map),
|
||||
r"
|
||||
#########
|
||||
#.......#
|
||||
#..GGG..#
|
||||
#..GEG..#
|
||||
#G..G...#
|
||||
#......G#
|
||||
#.......#
|
||||
#.......#
|
||||
#########
|
||||
"
|
||||
.trim()
|
||||
.to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Map {
|
||||
walls: HashSet<Square>,
|
||||
units: HashMap<Square, Unit>,
|
||||
}
|
||||
|
||||
impl Map {
|
||||
fn squares(&self) -> impl Iterator<Item = &Square> {
|
||||
self.walls.iter().chain(self.units.keys())
|
||||
}
|
||||
|
||||
fn is_open(&self, square: &Square) -> bool {
|
||||
!self.walls.contains(&square) && !self.units.contains_key(&square)
|
||||
}
|
||||
|
||||
fn open_neighbors(&self, square: &Square) -> HashSet<Square> {
|
||||
square
|
||||
.neighbors()
|
||||
.into_iter()
|
||||
.filter(|x| self.is_open(x))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn distances(&self, from: &Square) -> HashMap<Square, usize> {
|
||||
#[derive(Eq, PartialEq)]
|
||||
struct State {
|
||||
distance: usize,
|
||||
square: Square,
|
||||
}
|
||||
|
||||
impl Ord for State {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
other.distance.cmp(&self.distance)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for State {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
let mut distances = HashMap::new();
|
||||
let mut queue = BinaryHeap::new();
|
||||
queue.push(State {
|
||||
distance: 0,
|
||||
square: *from,
|
||||
});
|
||||
|
||||
while let Some(State { distance, square }) = queue.pop() {
|
||||
distances.entry(square).or_insert(distance);
|
||||
|
||||
self.open_neighbors(&square)
|
||||
.iter()
|
||||
.filter(|x| !distances.contains_key(x))
|
||||
.map(|&x| State {
|
||||
distance: distance + 1,
|
||||
square: x,
|
||||
})
|
||||
.for_each(|x| queue.push(x));
|
||||
}
|
||||
|
||||
distances
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Map {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||
let min_y = self.squares().map(|x| (x.0).0).min().unwrap();
|
||||
let max_y = self.squares().map(|x| (x.0).0).max().unwrap();
|
||||
let min_x = self.squares().map(|x| (x.0).1).min().unwrap();
|
||||
let max_x = self.squares().map(|x| (x.0).1).max().unwrap();
|
||||
let mut out = String::new();
|
||||
for y in min_y..=max_y {
|
||||
for x in min_x..=max_x {
|
||||
let square = Square((y, x));
|
||||
out.push(if self.walls.contains(&square) {
|
||||
'#'
|
||||
} else if let Some(Unit { race, .. }) = self.units.get(&square) {
|
||||
match race {
|
||||
Race::Elf => 'E',
|
||||
Race::Goblin => 'G',
|
||||
}
|
||||
} else {
|
||||
'.'
|
||||
})
|
||||
}
|
||||
out.push('\n');
|
||||
}
|
||||
write!(f, "{}", out.trim())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Map {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut walls = HashSet::new();
|
||||
let mut units = HashMap::new();
|
||||
s.trim()
|
||||
.lines()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| {
|
||||
line.chars()
|
||||
.enumerate()
|
||||
.map(move |(x, c)| (Square((y, x)), c))
|
||||
})
|
||||
.for_each(|(square, c)| {
|
||||
match c {
|
||||
'#' => {
|
||||
walls.insert(square);
|
||||
}
|
||||
'G' => {
|
||||
units.insert(square, Unit::new(Race::Goblin));
|
||||
}
|
||||
'E' => {
|
||||
units.insert(square, Unit::new(Race::Elf));
|
||||
}
|
||||
'.' => {}
|
||||
_ => panic!(),
|
||||
};
|
||||
});
|
||||
|
||||
Ok(Self { walls, units })
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_distances() {
|
||||
let map: Map = r"
|
||||
#######
|
||||
#E..G.#
|
||||
#...#.#
|
||||
#.G.#G#
|
||||
#######
|
||||
"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let distances = map.distances(&Square((1, 1)));
|
||||
assert!(!distances.contains_key(&Square((0, 0))));
|
||||
assert!(!distances.contains_key(&Square((1, 4))));
|
||||
assert!(!distances.contains_key(&Square((1, 5))));
|
||||
assert_eq!(distances.get(&Square((2, 2))).unwrap(), &2);
|
||||
assert_eq!(distances.get(&Square((1, 3))).unwrap(), &2);
|
||||
assert_eq!(distances.get(&Square((3, 3))).unwrap(), &4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_from_str() {
|
||||
let input = r"
|
||||
#######
|
||||
#.G.E.#
|
||||
#E.G.E#
|
||||
#.G.E.#
|
||||
#######
|
||||
";
|
||||
|
||||
let map: Map = input.parse().unwrap();
|
||||
|
||||
assert!(map.walls.contains(&Square((0, 0))));
|
||||
assert!(!map.walls.contains(&Square((1, 1))));
|
||||
|
||||
assert_eq!(map.units.get(&Square((1, 2))).unwrap().race, Race::Goblin);
|
||||
assert_eq!(map.units.get(&Square((1, 4))).unwrap().race, Race::Elf);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
struct Square((usize, usize));
|
||||
|
||||
impl Square {
|
||||
fn neighbors(&self) -> HashSet<Self> {
|
||||
let (y, x) = self.0;
|
||||
let mut set = HashSet::new();
|
||||
set.insert(Square((y - 1, x)));
|
||||
set.insert(Square((y + 1, x)));
|
||||
set.insert(Square((y, x - 1)));
|
||||
set.insert(Square((y, x + 1)));
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Square {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.0.cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Square {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_square_ord() {
|
||||
let mut squares: Vec<Square> = vec![(1, 2), (1, 4), (2, 1), (2, 3), (2, 5), (3, 2), (3, 4)]
|
||||
.iter()
|
||||
.map(|&x| Square(x))
|
||||
.collect();
|
||||
squares.sort();
|
||||
assert_eq!(
|
||||
squares.iter().map(|x| x.0).collect::<Vec<_>>(),
|
||||
vec![(1, 2), (1, 4), (2, 1), (2, 3), (2, 5), (3, 2), (3, 4)]
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Unit {
|
||||
race: Race,
|
||||
hp: usize,
|
||||
}
|
||||
|
||||
impl Unit {
|
||||
fn new(race: Race) -> Self {
|
||||
let hp = 200;
|
||||
Unit { race, hp }
|
||||
}
|
||||
|
||||
fn targets(&self, map: &Map) -> HashSet<Square> {
|
||||
map.units
|
||||
.iter()
|
||||
.filter(|(_, x)| x.race == self.race.enemy())
|
||||
.map(|(&x, _)| x)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn in_range(&self, square: &Square, map: &Map) -> HashSet<Square> {
|
||||
let targets = self.targets(&map);
|
||||
if square.neighbors().iter().any(|x| targets.contains(x)) {
|
||||
return HashSet::new();
|
||||
}
|
||||
|
||||
targets.iter().flat_map(|x| map.open_neighbors(x)).collect()
|
||||
}
|
||||
|
||||
fn reachable(&self, square: &Square, map: &Map) -> HashMap<Square, usize> {
|
||||
let in_range = self.in_range(square, map);
|
||||
map.distances(square)
|
||||
.into_iter()
|
||||
.filter(|(x, _)| in_range.contains(x))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn chosen(&self, square: &Square, map: &Map) -> Option<Square> {
|
||||
self.reachable(&square, &map)
|
||||
.into_iter()
|
||||
.fold(HashMap::new(), |mut m, (s, d)| {
|
||||
let v = m.entry(d).or_insert_with(Vec::new);
|
||||
v.push(s);
|
||||
m
|
||||
})
|
||||
.iter()
|
||||
.min_by_key(|(&x, _)| x)
|
||||
.and_then(|(_, x)| x.iter().min().cloned()) // Is there a way to avoid this clone?
|
||||
}
|
||||
|
||||
fn next_step(&self, square: &Square, map: &Map) -> Option<Square> {
|
||||
self.chosen(square, map).as_ref().and_then(|x| {
|
||||
let distances = map.distances(x);
|
||||
map.open_neighbors(square)
|
||||
.into_iter()
|
||||
.fold(HashMap::new(), |mut m, x| {
|
||||
if let Some(distance) = distances.get(&x) {
|
||||
let v = m.entry(distance).or_insert_with(Vec::new);
|
||||
v.push(x);
|
||||
}
|
||||
m
|
||||
})
|
||||
.iter()
|
||||
.min_by_key(|(&x, _)| x)
|
||||
.and_then(|(_, x)| x.iter().min().cloned()) // Is there a way to avoid this clone?
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unit() {
|
||||
let map: Map = r"
|
||||
#######
|
||||
#E..G.#
|
||||
#...#.#
|
||||
#.G.#G#
|
||||
#######
|
||||
"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let square = Square((1, 1));
|
||||
let unit = map.units.get(&square).unwrap();
|
||||
|
||||
let targets = unit.targets(&map);
|
||||
assert_eq!(targets.len(), 3);
|
||||
assert!(vec![(1, 4), (3, 2), (3, 5)]
|
||||
.iter()
|
||||
.map(|&x| Square(x))
|
||||
.all(|x| targets.contains(&x)));
|
||||
|
||||
let in_range = unit.in_range(&square, &map);
|
||||
assert_eq!(in_range.len(), 6);
|
||||
assert!(vec![(1, 3), (1, 5), (2, 2), (2, 5), (3, 1), (3, 3)]
|
||||
.iter()
|
||||
.map(|&x| Square(x))
|
||||
.all(|x| in_range.contains(&x)));
|
||||
|
||||
let reachable = unit.reachable(&square, &map);
|
||||
assert_eq!(reachable.len(), 4);
|
||||
assert!(vec![(1, 3), (2, 2), (3, 1), (3, 3)]
|
||||
.iter()
|
||||
.map(|&x| Square(x))
|
||||
.all(|x| reachable.contains_key(&x)));
|
||||
|
||||
let chosen = unit.chosen(&square, &map);
|
||||
assert_eq!(chosen.unwrap().0, (1, 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unit_next_step() {
|
||||
let map: Map = r"
|
||||
#######
|
||||
#.E...#
|
||||
#.....#
|
||||
#...G.#
|
||||
#######
|
||||
"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let square = Square((1, 2));
|
||||
let unit = map.units.get(&square).unwrap();
|
||||
|
||||
let next_step = unit.next_step(&square, &map);
|
||||
assert_eq!(next_step.unwrap().0, (1, 3));
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum Race {
|
||||
Elf,
|
||||
Goblin,
|
||||
}
|
||||
|
||||
impl Race {
|
||||
fn enemy(self) -> Race {
|
||||
match self {
|
||||
Race::Elf => Race::Goblin,
|
||||
Race::Goblin => Race::Elf,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
use std::error::Error;
|
||||
use std::str::FromStr;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use advent_of_code::main;
|
||||
|
||||
main!();
|
||||
|
||||
fn solve(input: &str) -> Result<String, Box<Error>> {
|
||||
let mut program: Program = input.parse()?;
|
||||
program.registers[0] = 1;
|
||||
let registers = program.last().unwrap();
|
||||
let output = registers[0].to_string();
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
type Registers = [usize; 6];
|
||||
|
||||
struct Program {
|
||||
ip: usize,
|
||||
instructions: Vec<Instruction>,
|
||||
registers: Registers,
|
||||
}
|
||||
|
||||
impl Program {
|
||||
fn execute(&mut self, i: &Instruction) {
|
||||
match i.opcode {
|
||||
Opcode::Addr => self.registers[i.c] = self.registers[i.a] + self.registers[i.b],
|
||||
Opcode::Addi => self.registers[i.c] = self.registers[i.a] + i.b,
|
||||
Opcode::Mulr => self.registers[i.c] = self.registers[i.a] * self.registers[i.b],
|
||||
Opcode::Muli => self.registers[i.c] = self.registers[i.a] * i.b,
|
||||
Opcode::Banr => self.registers[i.c] = self.registers[i.a] & self.registers[i.b],
|
||||
Opcode::Bani => self.registers[i.c] = self.registers[i.a] & i.b,
|
||||
Opcode::Borr => self.registers[i.c] = self.registers[i.a] | self.registers[i.b],
|
||||
Opcode::Bori => self.registers[i.c] = self.registers[i.a] | i.b,
|
||||
Opcode::Setr => self.registers[i.c] = self.registers[i.a],
|
||||
Opcode::Seti => self.registers[i.c] = i.a,
|
||||
Opcode::Gtir => self.registers[i.c] = if i.a > self.registers[i.b] { 1 } else { 0 },
|
||||
Opcode::Gtri => self.registers[i.c] = if self.registers[i.a] > i.b { 1 } else { 0 },
|
||||
Opcode::Gtrr => {
|
||||
self.registers[i.c] = if self.registers[i.a] > self.registers[i.b] {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
Opcode::Eqir => self.registers[i.c] = if i.a == self.registers[i.b] { 1 } else { 0 },
|
||||
Opcode::Eqri => self.registers[i.c] = if self.registers[i.a] == i.b { 1 } else { 0 },
|
||||
Opcode::Eqrr => {
|
||||
self.registers[i.c] = if self.registers[i.a] == self.registers[i.b] {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Program {
|
||||
type Item = Registers;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let ins = *self.instructions.get(self.registers[self.ip])?;
|
||||
self.execute(&ins);
|
||||
self.registers[self.ip] += 1;
|
||||
Some(self.registers)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_program() {
|
||||
let mut program: Program = r"
|
||||
#ip 0
|
||||
seti 5 0 1
|
||||
seti 6 0 2
|
||||
addi 0 1 0
|
||||
addr 1 2 3
|
||||
setr 1 0 0
|
||||
seti 8 0 4
|
||||
seti 9 0 5
|
||||
"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(program.next().unwrap(), [1, 5, 0, 0, 0, 0]);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Instruction {
|
||||
opcode: Opcode,
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Opcode {
|
||||
Addr,
|
||||
Addi,
|
||||
Mulr,
|
||||
Muli,
|
||||
Banr,
|
||||
Bani,
|
||||
Borr,
|
||||
Bori,
|
||||
Setr,
|
||||
Seti,
|
||||
Gtir,
|
||||
Gtri,
|
||||
Gtrr,
|
||||
Eqir,
|
||||
Eqri,
|
||||
Eqrr,
|
||||
}
|
||||
|
||||
impl FromStr for Program {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut lines = s.trim().lines();
|
||||
let ip_re = Regex::new(r"^#ip (\d+)$").unwrap();
|
||||
let ip = lines
|
||||
.next()
|
||||
.and_then(|l| ip_re.captures(l))
|
||||
.and_then(|c| c.get(1))
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.parse()?;
|
||||
|
||||
let instructions = lines.map(|l| l.parse()).collect::<Result<_, _>>()?;
|
||||
|
||||
let registers = [0; 6];
|
||||
|
||||
Ok(Program {
|
||||
ip,
|
||||
instructions,
|
||||
registers,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Instruction {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut s = s.split_whitespace();
|
||||
let opcode = s.next().unwrap().parse()?;
|
||||
let a = s.next().unwrap().parse()?;
|
||||
let b = s.next().unwrap().parse()?;
|
||||
let c = s.next().unwrap().parse()?;
|
||||
Ok(Instruction { opcode, a, b, c })
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Opcode {
|
||||
type Err = Box<Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let opcode = match s {
|
||||
"addr" => Opcode::Addr,
|
||||
"addi" => Opcode::Addi,
|
||||
"mulr" => Opcode::Mulr,
|
||||
"muli" => Opcode::Muli,
|
||||
"banr" => Opcode::Banr,
|
||||
"bani" => Opcode::Bani,
|
||||
"borr" => Opcode::Borr,
|
||||
"bori" => Opcode::Bori,
|
||||
"setr" => Opcode::Setr,
|
||||
"seti" => Opcode::Seti,
|
||||
"gtir" => Opcode::Gtir,
|
||||
"gtri" => Opcode::Gtri,
|
||||
"gtrr" => Opcode::Gtrr,
|
||||
"eqir" => Opcode::Eqir,
|
||||
"eqri" => Opcode::Eqri,
|
||||
"eqrr" => Opcode::Eqrr,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Ok(opcode)
|
||||
}
|
||||
}
|
||||
|
||||
// OPCODES = {
|
||||
// addr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + registers[b] } },
|
||||
// addi: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + b } },
|
||||
// mulr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * registers[b] } },
|
||||
// muli: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * b } },
|
||||
// banr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & registers[b] } },
|
||||
// bani: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & b } },
|
||||
// borr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | registers[b] } },
|
||||
// bori: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | b } },
|
||||
// setr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] } },
|
||||
// seti: ->(a, b, c) { ->(registers) { registers[c] = a } },
|
||||
// gtir: ->(a, b, c) { ->(registers) { registers[c] = (a > registers[b]) ? 1 : 0 } },
|
||||
// gtri: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > b) ? 1 : 0 } },
|
||||
// gtrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > registers[b]) ? 1 : 0 } },
|
||||
// eqir: ->(a, b, c) { ->(registers) { registers[c] = (a == registers[b]) ? 1 : 0 } },
|
||||
// eqri: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == b) ? 1 : 0 } },
|
||||
// eqrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == registers[b]) ? 1 : 0 } },
|
||||
// }
|
@ -1,21 +0,0 @@
|
||||
records = { SOI ~ record* ~ EOI }
|
||||
record = { begins_shift ~ sleep_ranges }
|
||||
|
||||
begins_shift = { date ~ " Guard #" ~ guard_id ~ " begins shift" ~ eol }
|
||||
guard_id = { digit+ }
|
||||
sleep_ranges = { sleep_range* }
|
||||
sleep_range = { falls_asleep ~ wakes_up }
|
||||
|
||||
falls_asleep = { date ~ " falls asleep" ~ eol }
|
||||
wakes_up = { date ~ " wakes up" ~ eol }
|
||||
|
||||
date = _{ "[" ~ year ~ "-" ~ month ~ "-" ~ day ~ " " ~ hour ~ ":" ~ minute ~ "]" }
|
||||
|
||||
year = _{ digit{4} }
|
||||
month = _{ digit{2} }
|
||||
day = _{ digit{2} }
|
||||
hour = _{ digit{2} }
|
||||
minute = { digit{2} }
|
||||
|
||||
digit = _{ '0'..'9' }
|
||||
eol = _{ "\n" | EOI }
|
@ -1,16 +0,0 @@
|
||||
#[macro_export]
|
||||
macro_rules! main {
|
||||
() => {
|
||||
fn main() -> Result<(), Box<std::error::Error>> {
|
||||
use std::io::{self, Read};
|
||||
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input)?;
|
||||
|
||||
let output = solve(&input)?;
|
||||
println!("{}", output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
||||
|
||||
gem "minitest"
|
||||
gem "pry"
|
||||
gem "sorbet"
|
||||
gem "sorbet-runtime"
|
@ -1,25 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
coderay (1.1.2)
|
||||
method_source (0.9.2)
|
||||
minitest (5.13.0)
|
||||
pry (0.12.2)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
sorbet (0.4.5109)
|
||||
sorbet-static (= 0.4.5109)
|
||||
sorbet-runtime (0.4.5109)
|
||||
sorbet-static (0.4.5109-universal-darwin-14)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
minitest
|
||||
pry
|
||||
sorbet
|
||||
sorbet-runtime
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.0.pre.3
|
@ -1,13 +0,0 @@
|
||||
require "rake/testtask"
|
||||
|
||||
task default: [:test, :srb]
|
||||
|
||||
Rake::TestTask.new do |t|
|
||||
t.libs << "test"
|
||||
t.test_files = FileList["test_*.rb"]
|
||||
t.verbose = true
|
||||
end
|
||||
|
||||
task :srb do
|
||||
sh "srb tc"
|
||||
end
|
@ -1,154 +0,0 @@
|
||||
# typed: strict
|
||||
|
||||
require "stringio"
|
||||
|
||||
require "sorbet-runtime"
|
||||
|
||||
AnyIO = T.type_alias { T.any(IO, StringIO) }
|
||||
Memory = T.type_alias { T::Array[T.nilable(Integer)] }
|
||||
|
||||
class Mode < T::Enum
|
||||
enums do
|
||||
Position = new
|
||||
Immediate = new
|
||||
Relative = new
|
||||
end
|
||||
|
||||
extend T::Sig
|
||||
|
||||
sig {params(value: String).returns(Mode)}
|
||||
def self.from(value)
|
||||
case value
|
||||
when ?0 then Mode::Position
|
||||
when ?1 then Mode::Immediate
|
||||
when ?2 then Mode::Relative
|
||||
else fail "unexpected mode: #{value}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
OPCODES = T.let({
|
||||
1 => ->(x, _, _, a, b, c) { x[c] = x[a] + x[b] }, # add
|
||||
2 => ->(x, _, _, a, b, c) { x[c] = x[a] * x[b] }, # multiply
|
||||
3 => ->(x, i, _, a) { x[a] = i.gets.to_i }, # input
|
||||
4 => ->(x, _, o, a) { o.puts(x[a]) }, # output
|
||||
5 => ->(x, _, _, a, b) { x.pc = x[b] if x[a].nonzero? }, # jump-if-true
|
||||
6 => ->(x, _, _, a, b) { x.pc = x[b] if x[a].zero? }, # jump-if-false
|
||||
7 => ->(x, _, _, a, b, c) { x[c] = (x[a] < x[b]) ? 1 : 0 }, # less than
|
||||
8 => ->(x, _, _, a, b, c) { x[c] = (x[a] == x[b]) ? 1 : 0 }, # equals
|
||||
9 => ->(x, _, _, a) { x.rb += x[a] }, # adjust relative base
|
||||
99 => ->(*) { throw :halt }, # halt
|
||||
}, T::Hash[Integer, T.untyped])
|
||||
|
||||
class Parameter
|
||||
extend T::Sig
|
||||
|
||||
sig {params(value: T.any(Parameter, Integer)).returns(Parameter)}
|
||||
def self.from(value)
|
||||
case value
|
||||
when Parameter then value
|
||||
when Integer then new(Mode::Position, value)
|
||||
else T.absurd(value)
|
||||
end
|
||||
end
|
||||
|
||||
sig {returns(Mode)}
|
||||
attr_reader :mode
|
||||
|
||||
sig {returns(Integer)}
|
||||
attr_reader :value
|
||||
|
||||
sig {params(mode: Mode, value: Integer).void}
|
||||
def initialize(mode, value)
|
||||
@mode = T.let(mode, Mode)
|
||||
@value = T.let(value, Integer)
|
||||
end
|
||||
end
|
||||
|
||||
class Computer
|
||||
extend T::Sig
|
||||
|
||||
sig {params(input: String).returns(Computer)}
|
||||
def self.from(input)
|
||||
new(input.split(?,).map(&:to_i))
|
||||
end
|
||||
|
||||
sig {returns(Integer)}
|
||||
attr_accessor :pc, :rb
|
||||
|
||||
sig {params(program: Memory).void}
|
||||
def initialize(program)
|
||||
@memory = T.let(program.dup, Memory)
|
||||
@pc = T.let(0, Integer)
|
||||
@rb = T.let(0, Integer)
|
||||
end
|
||||
|
||||
sig {params(input: T.untyped, output: AnyIO).returns(Memory)}
|
||||
def run(input=STDIN, output=STDOUT)
|
||||
each(input, output).inject(nil) {|_,i| i }
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
input: T.untyped,
|
||||
output: AnyIO,
|
||||
blk: T.nilable(T.proc.params(m: Memory).returns(T.nilable(Integer)))
|
||||
).returns(T::Enumerator[Memory])
|
||||
}
|
||||
def each(input, output, &blk)
|
||||
return enum_for(T.must(__method__), input, output) unless block_given?
|
||||
|
||||
catch(:halt) do
|
||||
loop do
|
||||
instruction = @memory[pc].to_s.rjust(5, ?0)
|
||||
opcode = OPCODES.fetch(instruction[-2..-1].to_i)
|
||||
self.pc += 1
|
||||
|
||||
n = opcode.arity - 3 # subtract the computer, input, and output params
|
||||
args = (0...n).map {|i|
|
||||
mode = Mode.from(T.must(instruction[2-i]))
|
||||
value = @memory[pc + i] || 0
|
||||
Parameter.new(mode, value)
|
||||
}
|
||||
self.pc += n
|
||||
|
||||
opcode.call(self, input, output, *args)
|
||||
|
||||
yield @memory
|
||||
end
|
||||
end
|
||||
|
||||
# Satisfy sorbet:
|
||||
# https://sorbet-ruby.slack.com/archives/CHN2L03NH/p1575648549254600
|
||||
Enumerator.new {}
|
||||
end
|
||||
|
||||
sig {params(parameter: Parameter).returns(Integer)}
|
||||
def [](parameter)
|
||||
parameter = Parameter.from(parameter)
|
||||
mode = parameter.mode
|
||||
case mode
|
||||
when Mode::Position then @memory[parameter.value] || 0
|
||||
when Mode::Immediate then parameter.value
|
||||
when Mode::Relative then @memory[rb + parameter.value] || 0
|
||||
else T.absurd(mode)
|
||||
end
|
||||
end
|
||||
alias_method :fetch, :[]
|
||||
|
||||
sig {params(parameter: Parameter, value: Integer).void}
|
||||
def []=(parameter, value)
|
||||
|
||||
mode = parameter.mode
|
||||
case mode
|
||||
when Mode::Position then @memory[parameter.value] = value
|
||||
when Mode::Immediate then raise "writes should never be in immediate mode"
|
||||
when Mode::Relative then @memory[rb + parameter.value] = value
|
||||
else T.absurd(mode)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
Computer.from(T.cast(ARGF, IO).read || "").run
|
||||
end
|
@ -1,16 +0,0 @@
|
||||
# typed: false
|
||||
# puts ARGF.read.lines.map(&:to_i).map {|mass|
|
||||
# (mass / 3.0).floor - 2
|
||||
# }.sum
|
||||
|
||||
fuel = ->(mass) {
|
||||
total = 0
|
||||
loop do
|
||||
mass = (mass / 3.0).floor - 2
|
||||
break if mass <= 0
|
||||
total += mass
|
||||
end
|
||||
total
|
||||
}
|
||||
|
||||
puts ARGF.read.lines.map(&:to_i).map(&fuel).sum
|
@ -1,21 +0,0 @@
|
||||
# typed: false
|
||||
require_relative "computer"
|
||||
|
||||
program = ARGF.read.split(?,).map(&:to_i)
|
||||
|
||||
# modified = program.dup
|
||||
# modified[1] = 12
|
||||
# modified[2] = 2
|
||||
# c = Computer.new(modified)
|
||||
# puts c.each.inject(nil) {|_,i| i }.fetch(0)
|
||||
|
||||
noun, verb = (0..99).flat_map {|noun| (0..99).map {|verb| [noun, verb] } }
|
||||
.find {|(noun, verb)|
|
||||
modified = program.dup
|
||||
modified[1] = noun
|
||||
modified[2] = verb
|
||||
c = Computer.new(modified)
|
||||
final = c.run
|
||||
final.fetch(0) == 19690720
|
||||
}
|
||||
puts 100 * noun + verb
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue