Compare commits

..

2 Commits

Author SHA1 Message Date
Alpha Chen d60889b13c [2016][rust][23.1] No inlining for profiling?
8 years ago
Alpha Chen 3ff87286de profiling
8 years ago

1
.gitignore vendored

@ -1 +0,0 @@
**/rust/target

3
.gitmodules vendored

@ -1,3 +0,0 @@
[submodule "2022/bqn/lib"]
path = 2022/bqn/lib
url = https://github.com/mlochbaum/bqn-libs.git

@ -1,17 +1,17 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
activesupport (7.0.3) activesupport (4.2.5)
concurrent-ruby (~> 1.0, >= 1.0.2) i18n (~> 0.7)
i18n (>= 1.6, < 2) json (~> 1.7, >= 1.7.7)
minitest (>= 5.1) minitest (~> 5.1)
tzinfo (~> 2.0) thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
awesome_print (1.6.1) awesome_print (1.6.1)
coderay (1.1.0) coderay (1.1.0)
colorize (0.7.7) colorize (0.7.7)
concurrent-ruby (1.1.10) i18n (0.7.0)
i18n (1.10.0) json (1.8.3)
concurrent-ruby (~> 1.0)
letters (0.4.1) letters (0.4.1)
activesupport activesupport
awesome_print awesome_print
@ -24,8 +24,9 @@ GEM
method_source (~> 0.8.1) method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
slop (3.6.0) slop (3.6.0)
tzinfo (2.0.4) thread_safe (0.3.5)
concurrent-ruby (~> 1.0) tzinfo (1.2.2)
thread_safe (~> 0.1)
xml-simple (1.1.5) xml-simple (1.1.5)
PLATFORMS PLATFORMS

107
2015/rust/Cargo.lock generated

@ -1,145 +1,146 @@
# This file is automatically @generated by Cargo. [root]
# It is not intended for manual editing. name = "advent_of_code"
version = 3 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]] [[package]]
name = "advapi32-sys" name = "advapi32-sys"
version = "0.1.2" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "307c92332867e586720c0222ee9d890bbe8431711efed8a1b06bc5b40fc66bd7"
dependencies = [ dependencies = [
"winapi", "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "advent_of_code"
version = "0.1.0"
dependencies = [
"permutohedron",
"regex",
"rust-crypto",
] ]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.18" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [ dependencies = [
"memchr", "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "gcc" name = "gcc"
version = "0.3.21" version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca10e3e1f1c8278047da19b94dc17c4397861150d5fbcea052eedb1d9847d356"
dependencies = [ dependencies = [
"advapi32-sys", "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi", "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "kernel32-sys" name = "kernel32-sys"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b5e7edf375e6d26243bde172f1d5ed1446f4a766fc9b7006e1fd27258243f1"
dependencies = [ dependencies = [
"winapi", "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.1.12" version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.4" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10569e57695cc2c91ca4214357907649c9e242dc822c9ae623d0e0b0d68aa4d9"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "permutohedron" name = "permutohedron"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf78a1e8b52782de92fc4f361362a62bcf5fd5718b5432b48cb381485740b83"
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.3.12" version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee40bdf3d293e1648490ab47e5471d9ab3e455e6b0bd48e558c454be4a015e"
dependencies = [ dependencies = [
"advapi32-sys", "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.4", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi", "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.5.5" version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr", "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax", "regex-syntax 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.26" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]] [[package]]
name = "rust-crypto" name = "rust-crypto"
version = "0.2.34" version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8672a8eb8db93d0938972e391159ba66912b415285ee5cf0ebe732df9e53b70"
dependencies = [ dependencies = [
"gcc", "gcc 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.1.12", "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rand", "rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"time", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "rustc-serialize" name = "rustc-serialize"
version = "0.3.16" version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a48546a64cae47d06885e9bccadb99d0547d877a94c5167fa451ea33a484456"
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.34" version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c4aeaa1c95974f5763c3a5ac0db95a19793589bcea5d22e161b5587e3aad029"
dependencies = [ dependencies = [
"kernel32-sys", "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.4", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi", "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.2.5" version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc3583688b861fcd83c2823d37cf2cd2446c233dd7ba3f97884d1a7302817537"
[[package]] [[package]]
name = "winapi-build" name = "winapi-build"
version = "0.1.1" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" 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"

@ -4,6 +4,6 @@ version = "0.1.0"
authors = ["Alpha Chen <alpha.chen@gmail.com>"] authors = ["Alpha Chen <alpha.chen@gmail.com>"]
[dependencies] [dependencies]
regex = "1.5" regex = "0.1"
rust-crypto = "^0.2" rust-crypto = "^0.2"
permutohedron = "0.2" permutohedron = "0.2"

@ -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.

144
2016/rust/Cargo.lock generated

@ -1,173 +1,201 @@
# This file is automatically @generated by Cargo. [root]
# It is not intended for manual editing.
version = 3
[[package]]
name = "advent_of_code_2016" name = "advent_of_code_2016"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"error-chain", "error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.18" version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [ dependencies = [
"memchr", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.0" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
dependencies = [ dependencies = [
"backtrace-sys", "backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if", "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dbghelp-sys", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc", "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle", "rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "backtrace-sys" name = "backtrace-sys"
version = "0.1.5" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3602e8d8c43336088a8505fa55cae2b3884a9be29440863a11528a42f46f6bb7"
dependencies = [ dependencies = [
"gcc", "gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)",
"libc", "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
[[package]] [[package]]
name = "dbghelp-sys" name = "dbghelp-sys"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
dependencies = [ dependencies = [
"winapi", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "error-chain" name = "error-chain"
version = "0.7.1" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd681735364a04cd5d69f01a4f6768e70473941f8d86d8c224faf6955a75799"
dependencies = [ dependencies = [
"backtrace", "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "gcc" name = "gcc"
version = "0.3.39" version = "0.3.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "771e4a97ff6f237cf0f7d5f5102f6e28bb9743814b6198d684da5c58b76c11e0"
[[package]] [[package]]
name = "kernel32-sys" name = "kernel32-sys"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
dependencies = [ dependencies = [
"winapi", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.18" version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "rand" name = "rand"
version = "0.3.15" version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
dependencies = [ dependencies = [
"libc", "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.5.5" version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax", "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]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.26" version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]] [[package]]
name = "rust-crypto" name = "rust-crypto"
version = "0.2.36" version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
dependencies = [ dependencies = [
"gcc", "gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)",
"libc", "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"rand", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize", "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)",
"time", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.3" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc"
[[package]] [[package]]
name = "rustc-serialize" name = "rustc-serialize"
version = "0.3.21" version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "time" name = "time"
version = "0.1.35" version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
dependencies = [ dependencies = [
"kernel32-sys", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc", "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi", "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]] [[package]]
name = "winapi" name = "winapi"
version = "0.2.8" version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]] [[package]]
name = "winapi-build" name = "winapi-build"
version = "0.1.1" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" 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"

@ -5,5 +5,8 @@ authors = ["Alpha Chen <alpha.chen@gmail.com>"]
[dependencies] [dependencies]
error-chain = "0.7" error-chain = "0.7"
regex = "1.5" regex = "0.1"
rust-crypto = "0.2" rust-crypto = "0.2"
[profile.release]
debug = true

@ -10,10 +10,12 @@ pub struct Assembunny {
} }
impl Assembunny { impl Assembunny {
#[inline(never)]
fn instruction(&self, i: usize) -> Option<Instruction> { fn instruction(&self, i: usize) -> Option<Instruction> {
self.instructions.get(i).cloned() self.instructions.get(i).cloned()
} }
#[inline(never)]
fn value<V: Into<Variable>>(&self, v: V) -> isize { fn value<V: Into<Variable>>(&self, v: V) -> isize {
let v: Variable = v.into(); let v: Variable = v.into();
match v { match v {
@ -22,6 +24,7 @@ impl Assembunny {
} }
} }
#[inline(never)]
fn toggle(&mut self, i: usize) { fn toggle(&mut self, i: usize) {
let instruction = match self.instruction(i) { let instruction = match self.instruction(i) {
Some(x) => x, Some(x) => x,
@ -31,9 +34,9 @@ impl Assembunny {
let replacement = match instruction { let replacement = match instruction {
Instruction::Cpy(a, b) => Instruction::Jnz(a, b), Instruction::Cpy(a, b) => Instruction::Jnz(a, b),
Instruction::Inc(x) => Instruction::Dec(x), Instruction::Inc(x) => Instruction::Dec(x),
Instruction::Dec(x) | Instruction::Dec(x) => Instruction::Inc(x),
Instruction::Tgl(x) => Instruction::Inc(x),
Instruction::Jnz(a, b) => Instruction::Cpy(a, b), Instruction::Jnz(a, b) => Instruction::Cpy(a, b),
Instruction::Tgl(x) => Instruction::Inc(x),
}; };
self.instructions[i] = replacement; self.instructions[i] = replacement;
} }
@ -42,6 +45,7 @@ impl Assembunny {
impl Iterator for Assembunny { impl Iterator for Assembunny {
type Item = Registers; type Item = Registers;
#[inline(never)]
fn next(&mut self) -> Option<Registers> { fn next(&mut self) -> Option<Registers> {
let pc = self.value(Register::PC) as usize; let pc = self.value(Register::PC) as usize;
let instruction = match self.instruction(pc) { let instruction = match self.instruction(pc) {
@ -54,7 +58,8 @@ impl Iterator for Assembunny {
self.registers[Register::PC] += 1; self.registers[Register::PC] += 1;
match instruction { match instruction {
Instruction::Cpy(v, Variable::Register(r)) => { Instruction::Cpy(v, Variable::Register(r)) => {
self.registers[r] = self.value(v); let value = self.value(v);
self.registers[r] = value;
} }
Instruction::Inc(Variable::Register(r)) => { Instruction::Inc(Variable::Register(r)) => {
self.registers[r] += 1; self.registers[r] += 1;
@ -63,8 +68,9 @@ impl Iterator for Assembunny {
self.registers[r] -= 1; self.registers[r] -= 1;
} }
Instruction::Jnz(v, delta) if self.value(v) != 0 => { Instruction::Jnz(v, delta) if self.value(v) != 0 => {
self.registers[Register::PC] -= 1; let delta = self.value(delta);
self.registers[Register::PC] += self.value(delta); let pc = self.value(Register::PC) + delta - 1;
self.registers[Register::PC] = pc;
} }
Instruction::Tgl(v) => { Instruction::Tgl(v) => {
let index = (pc as isize) + self.value(v); let index = (pc as isize) + self.value(v);
@ -84,18 +90,28 @@ impl Registers {
pub fn new() -> Self { pub fn new() -> Self {
Registers([0; 5]) Registers([0; 5])
} }
fn index(r: Register) -> usize {
match r {
Register::PC => 0,
Register::A => 1,
Register::B => 2,
Register::C => 3,
Register::D => 4,
}
}
} }
impl ops::Index<Register> for Registers { impl ops::Index<Register> for Registers {
type Output = isize; type Output = isize;
fn index(&self, _index: Register) -> &isize { fn index(&self, _index: Register) -> &isize {
self.0.index(usize::from(_index)) self.0.index(Self::index(_index))
} }
} }
impl ops::IndexMut<Register> for Registers { impl ops::IndexMut<Register> for Registers {
fn index_mut(&mut self, _index: Register) -> &mut isize { fn index_mut(&mut self, _index: Register) -> &mut isize {
self.0.index_mut(usize::from(_index)) self.0.index_mut(Self::index(_index))
} }
} }
@ -107,6 +123,18 @@ impl Instructions {
} }
} }
impl fmt::Display for Instructions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"{}",
self.0
.iter()
.map(Instruction::to_string)
.collect::<Vec<_>>()
.join("\n"))
}
}
impl ops::Index<usize> for Instructions { impl ops::Index<usize> for Instructions {
type Output = Instruction; type Output = Instruction;
@ -130,18 +158,6 @@ pub enum Register {
D, D,
} }
impl From<Register> for usize {
fn from(r: Register) -> usize {
match r {
Register::PC => 0,
Register::A => 1,
Register::B => 2,
Register::C => 3,
Register::D => 4,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum Instruction { pub enum Instruction {
Cpy(Variable, Variable), Cpy(Variable, Variable),
@ -151,61 +167,41 @@ pub enum Instruction {
Tgl(Variable), Tgl(Variable),
} }
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Variable {
Register(Register),
Value(isize),
}
impl From<Register> for Variable {
fn from(r: Register) -> Self {
Variable::Register(r)
}
}
impl From<isize> for Variable {
fn from(i: isize) -> Self {
Variable::Value(i)
}
}
// Display
impl fmt::Display for Instructions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"{}",
self.0
.iter()
.map(Instruction::to_string)
.collect::<Vec<_>>()
.join("\n"))
}
}
impl fmt::Display for Instruction { impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match self {
Instruction::Cpy(a, b) => write!(f, "cpy {} {}", a, b), &Instruction::Cpy(a, b) => write!(f, "cpy {} {}", a, b),
Instruction::Inc(a) => write!(f, "inc {}", a), &Instruction::Inc(a) => write!(f, "inc {}", a),
Instruction::Dec(a) => write!(f, "dec {}", a), &Instruction::Dec(a) => write!(f, "dec {}", a),
Instruction::Jnz(a, b) => write!(f, "jnz {} {}", a, b), &Instruction::Jnz(a, b) => write!(f, "jnz {} {}", a, b),
Instruction::Tgl(a) => write!(f, "tgl {}", a), &Instruction::Tgl(a) => write!(f, "tgl {}", a),
} }
} }
} }
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Variable {
Register(Register),
Value(isize),
}
impl fmt::Display for Variable { impl fmt::Display for Variable {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match self {
Variable::Register(r) => { &Variable::Register(r) => {
write!(f, "{}", format!("{:?}", r).to_lowercase()) write!(f, "{}", format!("{:?}", r).to_lowercase())
} }
Variable::Value(v) => write!(f, "{:?}", v), &Variable::Value(v) => write!(f, "{:?}", v),
} }
} }
} }
impl From<Register> for Variable {
fn from(r: Register) -> Self {
Variable::Register(r)
}
}
// Parsing // Parsing
impl str::FromStr for Instructions { impl str::FromStr for Instructions {

@ -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(&microchip)
});
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,10 +1,11 @@
#![feature(field_init_shorthand, inclusive_range_syntax, try_from)] #![feature(alloc_system, field_init_shorthand, inclusive_range_syntax)]
#![recursion_limit = "1024"] #![recursion_limit = "1024"]
extern crate alloc_system;
extern crate crypto;
#[macro_use] #[macro_use]
extern crate error_chain; extern crate error_chain;
extern crate regex; extern crate regex;
extern crate crypto;
mod assembunny; mod assembunny;
pub mod errors; pub mod errors;
@ -18,6 +19,5 @@ pub mod day_07;
pub mod day_08; pub mod day_08;
// pub mod day_09; // pub mod day_09;
// pub mod day_10; // pub mod day_10;
pub mod day_11;
pub mod day_12; pub mod day_12;
pub mod day_23; pub mod day_23;

@ -1,5 +1,6 @@
use std::io; use std::env;
use std::io::Read; use std::fs::File;
use std::io::prelude::*;
extern crate advent_of_code_2016; extern crate advent_of_code_2016;
use advent_of_code_2016::*; use advent_of_code_2016::*;
@ -7,10 +8,12 @@ use advent_of_code_2016::errors::*;
fn main() { fn main() {
run(|| { run(|| {
let filename = env::args().nth(1).ok_or("")?;
let mut f = File::open(filename).chain_err(|| "")?;
let mut input = String::new(); let mut input = String::new();
io::stdin().read_to_string(&mut input).ok(); f.read_to_string(&mut input).chain_err(|| "")?;
let solution = day_11::solve(&input)?; let solution = day_23::solve(&input)?;
println!("{}", solution); println!("{}", solution);
Ok(()) Ok(())

@ -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,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,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,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

247
2017/rust/Cargo.lock generated

@ -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

205
2018/rust/Cargo.lock generated

@ -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…
Cancel
Save