Compare commits

...

175 Commits
master ... main

Author SHA1 Message Date
Alpha Chen babaaebb45
mu
6 months ago
Alpha Chen 2364abf76a
[2023][ruby][19.1]
10 months ago
Alpha Chen 48b7acdcea
[2023][ruby][18.x]
10 months ago
Alpha Chen 6f332e48d1
[2023][ruby][17.2]
10 months ago
Alpha Chen 51c91ab2f2
[2023][ruby][17.1]
10 months ago
Alpha Chen 2ac1c6069a
[2023][ruby][16.x] golfing
10 months ago
Alpha Chen efda4ecb16
[2023][ruby][16.2] shameless green
10 months ago
Alpha Chen b7a02fda85
[2023][ruby][16.1] shameless green
10 months ago
Alpha Chen 957435a8ca
[2023][uiua][15] @\0 = @\x00
10 months ago
Alpha Chen af98c2abc5
[2023][uiua][15.1]
10 months ago
Alpha Chen 10da9e80a0
[2023][ruby][15.2]
10 months ago
Alpha Chen 5bbeb5d969
[2023][ruby][15.1]
10 months ago
Alpha Chen 4fa0141f5f
[2023][uiua][14.1]
10 months ago
Alpha Chen 16677ad6a4
[2023][ruby][14.x] clean up part one
10 months ago
Alpha Chen 74bf4a5213
[2023][ruby][14.2]
10 months ago
Alpha Chen cba5517ee9
[2023][ruby][14.1]
10 months ago
Alpha Chen 06068a3114
[2023][ruby][13.2]
10 months ago
Alpha Chen 21e4174051
[2023][ruby][13.1]
10 months ago
Alpha Chen 31afd41329
[2023][ruby][12.2]
10 months ago
Alpha Chen 2928c03ce0
[2023][ruby][12.1]
10 months ago
Alpha Chen eeb3633702
[2023][uiua][11.x] shortening
10 months ago
Alpha Chen 0da7444be5
[2023][uiua][11.x]
10 months ago
Alpha Chen 28e35196f5
[2023][ruby][11.2]
10 months ago
Alpha Chen 1118280a6e
[2023][ruby][11.1]
10 months ago
Alpha Chen 47ca37d8c2
[2023][ruby][8.x] remove unnecessary require
10 months ago
Alpha Chen ed02032839
[2023][ruby][10.x] one more comment
10 months ago
Alpha Chen a3706096c3
[2023][ruby][10.x] lol
10 months ago
Alpha Chen 95a6798f7f
[2023][ruby][10.x]
10 months ago
Alpha Chen b5bfbcff0b
[2023][ruby][9.x] dry
10 months ago
Alpha Chen 7f25d2bde6
[2023][ruby][9.x]
10 months ago
Alpha Chen ca65631b37
[2023][ruby][8.2] til about Integer#lcm
10 months ago
Alpha Chen 5d7fc5b308
[2023][ruby][8.2]
10 months ago
Alpha Chen 794e3db35a
[2023][ruby][8.1]
10 months ago
Alpha Chen ee07a6130e
[2023][ruby][7.x] refactoring
10 months ago
Alpha Chen 8b21d78e9a
[2023][ruby][6.x] perf
10 months ago
Alpha Chen 8a81e989da
[2023][ruby][7.x] remove unnecessary lexographic sorting
11 months ago
Alpha Chen cc41e835ac
[2023][ruby][7.x] refactoring
11 months ago
Alpha Chen 9b6dd4cc53
[2023][ruby][7.x]
11 months ago
Alpha Chen c87d7854bf
uiua
11 months ago
Alpha Chen b8cd0faa3e
[2023][ruby][6.x]
11 months ago
Alpha Chen 1931b227df
[2023][ruby][5.x] remove more duplicate code
11 months ago
Alpha Chen 5525e8b7e5
[2023][ruby][5.x] remove duplicate code
11 months ago
Alpha Chen 1815ec7b1a
[2023][ruby][5.x]
11 months ago
Alpha Chen eb21642bf4
[2023][ruby][4.2] cleanup
11 months ago
Alpha Chen 0d0cc439b0
[2023][ruby][4.*]
11 months ago
Alpha Chen e6ae06a605
[2023][ruby][3.*] clean up parsing
11 months ago
Alpha Chen 8c72adad6d
[2023][ruby][3.*] remove hack
11 months ago
Alpha Chen fc5821b277
[2023][ruby][3.2]
11 months ago
Alpha Chen 6581325e8f
[2023][ruby][3.1]
11 months ago
Alpha Chen 5e542d90aa
[2023][ruby][2.*]
11 months ago
Alpha Chen 8677078287
[2023][uiua][01.1]
11 months ago
Alpha Chen 37ac8ad85b
[2023][ruby][1.*]
11 months ago
Alpha Chen 5c2f1eb45f
mu
11 months ago
Alpha Chen 6db3326726
[2022][ruby][16.2]
2 years ago
Alpha Chen b32bf143f9
[2022][ruby][16.1]
2 years ago
Alpha Chen 5c4b1cb37e
[2022][ruby][25.1]
2 years ago
Alpha Chen a0a54eefff
[2022][ruby] update Gemfile
2 years ago
Alpha Chen a3bded6091
[2022][ruby][21.x] use z3 for part two
2 years ago
Alpha Chen b62bf80b86
[2022][ruby][23.x]
2 years ago
Alpha Chen 6fb92a59ab
[2022][ruby][21.x]
2 years ago
Alpha Chen 7ced4db4a4
[2022][ruby][20.x]
2 years ago
Alpha Chen ce623e16d1
[2022][ruby][18.x]
2 years ago
Alpha Chen da36d561b8
[2022][ruby][15.x]
2 years ago
Alpha Chen 4129a82f26
[2022][ruby][14.x] refactored
2 years ago
Alpha Chen adff292d00
[2022][ruby][14.x]
2 years ago
Alpha Chen c5846c52e9
[2022][ruby][13.x] refactored
2 years ago
Alpha Chen d246206681
[2022][ruby][13.x]
2 years ago
Alpha Chen c3c34b998c
[2022][ruby][12.x] refactoring
2 years ago
Alpha Chen 220c8853de
[2022][ruby][12.x] backwards
2 years ago
Alpha Chen e12d4d7c63
[2022][ruby][12.x] refactored
2 years ago
Alpha Chen 44936f2906
[2022][ruby][12.x]
2 years ago
Alpha Chen 7e89a0122f
[2022][ruby][11.x] parslet
2 years ago
Alpha Chen 38b2c310a8
[2022][ruby][11.x] clean up parsing
2 years ago
Alpha Chen b8a4ca01b4
[2022][ruby][11.x]
2 years ago
Alpha Chen 762e65126a
[2022][ruby][10.x] refactor
2 years ago
Alpha Chen f871f28d27
[2022][ruby][10.x]
2 years ago
Alpha Chen 88c3c73d2f
[2022][bqn][6.x] refactor
2 years ago
Alpha Chen cdbcffdda5
[2022][ruby][9.x] refactoring
2 years ago
Alpha Chen 3782908dbb
[2022][ruby][9.2]
2 years ago
Alpha Chen caaa3da525
[2022][ruby][9.1]
2 years ago
Alpha Chen ea26a19bc0
[2022][ruby][8.x] refactored
2 years ago
Alpha Chen f67bc7bd27
[2022][ruby][8.x]
2 years ago
Alpha Chen 1fa98d82d6
[2022][ruby][7.x] refactoring
2 years ago
Alpha Chen fac81cb212
[2022][ruby][7.x]
2 years ago
Alpha Chen f8a61202fc
[2022][bqn][5.0] parsing only
2 years ago
Alpha Chen e666ab9344
[2022][bqn][6.x]
2 years ago
Alpha Chen 34ce71c8b6
[2022][ruby][6.x]
2 years ago
Alpha Chen c92d5a4346
[2022][ruby][5.x] refactor
2 years ago
Alpha Chen a8f19091f7
[2022][ruby][5.x]
2 years ago
Alpha Chen e9093934cf
[2022][ruby][4.x] cleanup
2 years ago
Alpha Chen 74d3bef510
[2022][ruby][3.x,4.x]
2 years ago
Alpha Chen ccdfedbbb6
[2022][ruby][3.x]
2 years ago
Alpha Chen e1016ab913
mu
2 years ago
Alpha Chen 049eedabf4
mu
2 years ago
dependabot[bot] b61b268c6e Bump i18n from 0.7.0 to 1.10.0 in /2015/ruby
2 years ago
dependabot[bot] 7b145e68f7 Bump regex from 1.1.0 to 1.5.5 in /2018/rust
2 years ago
dependabot[bot] b8a3ca273b Bump regex from 0.1.44 to 1.5.5 in /2015/rust
2 years ago
dependabot[bot] 31a381eb5d Bump regex from 0.1.80 to 1.5.5 in /2016/rust
2 years ago
dependabot[bot] e8eeea82d4 Bump generic-array from 0.9.0 to 0.9.1 in /2018/rust
2 years ago
Alpha Chen 1fb181e7d2 [2021][ruby][22.x]
3 years ago
Alpha Chen 76266b5bf3 [2021][ruby][21.x]
3 years ago
Alpha Chen a0ff324262 [2021][ruby][20.x]
3 years ago
Alpha Chen 289d452904 [2021][ruby][18.x] small refactoring
3 years ago
Alpha Chen 2196242eea [2021][ruby][18.x]
3 years ago
Alpha Chen 169491113a [2021][ruby][17.x] a bit of refactoring
3 years ago
Alpha Chen 8c5c67ae24 [2021][ruby][17.x]
3 years ago
Alpha Chen 28d2d2ca0c [2021][ruby][16.x] refactor
3 years ago
Alpha Chen f274c589c0 [2021][ruby][16.x]
3 years ago
Alpha Chen cd8a8345b3 [2021][ruby][15.x] use a Set for a minor speedup
3 years ago
Alpha Chen f23af95c02 [2021][ruby][15.x]
3 years ago
Alpha Chen 8e38040c04 [2021][ruby][14.x]
3 years ago
Alpha Chen b7e00339a3 [2021][ruby][13.x] clean up getting the dir index
3 years ago
Alpha Chen 4d7ad2055f [2021][ruby][13.x] refactor
3 years ago
Alpha Chen 963a61b14e [2021][ruby][13.x]
3 years ago
Alpha Chen 8f7c9985a5 [2021][ruby][12.x] tweak
3 years ago
Alpha Chen d40179f8c1 [2021][ruby][12.x]
3 years ago
Alpha Chen d29ae63a86 [2021][ruby][11.x] tweak loop
3 years ago
Alpha Chen 212ef6a381 [2021][ruby][11.x]
3 years ago
Alpha Chen 5145a17ba2 [2021][ruby][10.x] result type?
3 years ago
Alpha Chen aa66d3ed86 [2021][ruby][10.x] refactoring?
3 years ago
Alpha Chen 96072c90c3 [2021][ruby][10.x]
3 years ago
Alpha Chen 1a3d489be8 [2021][ruby][8.2] clean up minizinc solver
3 years ago
Alpha Chen 038495b353 [2021][ruby][9.x]
3 years ago
Alpha Chen 1aeb80d0eb [2021][ruby][8.2] minizinc
3 years ago
Alpha Chen 63778c56b7 [2021][ruby][8.x]
3 years ago
Alpha Chen 0c92ce7de7 [2021][ruby][7.x]
3 years ago
Alpha Chen ff6f142e2b [2021][ruby][6.x]
3 years ago
Alpha Chen 367a35f400 [2021][ruby][4.x..=5.x]
3 years ago
Alpha Chen c6e95f860f [2021][ruby][3.x]
3 years ago
Alpha Chen ea42e4bbc8 [2021][ruby][2.x]
3 years ago
Alpha Chen 86cd480264 [2021][ruby][01.x]
3 years ago
Alpha Chen ce57cc41da [2020][ruby] set ruby version to 3
4 years ago
Alpha Chen 24a173d106 [2020][ruby][20] remove unused code
4 years ago
Alpha Chen bb763d6644 [2020][ruby][25]
4 years ago
Alpha Chen 1a30bb23a1 [2020][ruby][24.x] use axial coordinates
4 years ago
Alpha Chen 319dd0129b [2020][ruby][24.x] refactor
4 years ago
Alpha Chen a9797560cf [2020][ruby][24.x]
4 years ago
Alpha Chen f057404538 [2020][ruby][23.2]
4 years ago
Alpha Chen 45212a6916 [2020][ruby][23.1]
4 years ago
Alpha Chen 5bcd40bef6 [2020][ruby][18] refactor
4 years ago
Alpha Chen 5ecce65bb5 [2020][ruby][18] playing around
4 years ago
Alpha Chen 969f06d4d0 [2020][ruby][16] removed commented out code
4 years ago
Alpha Chen f40f2356d3 [2020][ruby][22.x]
4 years ago
Alpha Chen 2c8cff45b0 [2020][ruby][20.x] refactor
4 years ago
Alpha Chen e1d1092a8b [2020][ruby][20.2]
4 years ago
Alpha Chen 35b1015882 [2020][ruby][21.2]
4 years ago
Alpha Chen 9919db1887 [2020][ruby][21.1]
4 years ago
Alpha Chen 1f6f3b62f6 [2020][ruby][20.1]
4 years ago
Alpha Chen be245847a2 [2020][ruby][19.x]
4 years ago
Alpha Chen 019d9eae12 [2020][ruby][18.x]
4 years ago
Alpha Chen 5949372ee0 [2020][ruby][17.x] refactor
4 years ago
Alpha Chen f668b8256d [2020][ruby][17.x]
4 years ago
Alpha Chen b727f41bd0 [2020][ruby][16.x]
4 years ago
Alpha Chen c9ad797075 [2020][ruby][15.x]
4 years ago
Alpha Chen 900a3e13b2 [2020][ruby][14.x] refactor
4 years ago
Alpha Chen a17445636d [2020][ruby][14.x]
4 years ago
Alpha Chen ffcf15c67e [2020][ruby][13.x]
4 years ago
Alpha Chen ad8fb67c6c [2020][ruby][12.x]
4 years ago
Alpha Chen 47b07ceb34 [2020][ruby][11.x] refactor
4 years ago
Alpha Chen 77256e1bf8 [2020][ruby][11.x]
4 years ago
Alpha Chen 771ad5c052 [2020][ruby][10.x] refactor
4 years ago
Alpha Chen 074fbc54d6 [2020][ruby][10.x] refactor
4 years ago
Alpha Chen 231f971888 [2020][ruby][10.x]
4 years ago
Alpha Chen 7521f3c9d4 [2020][ruby][9.x] refactor
4 years ago
Alpha Chen 7f46f39d8d [2020][ruby][9.x] refactor
4 years ago
Alpha Chen 95b912211d [2020][ruby][9.x]
4 years ago
Alpha Chen 8d30b0713c [2020][ruby][8.x] refactor
4 years ago
Alpha Chen 73ca0bca60 [2020][ruby][8.x]
4 years ago
Alpha Chen 7a2dee465d [2020][ruby][7.x]
4 years ago
Alpha Chen e49d6c4bef [2020][ruby][6.x] refactor
4 years ago
Alpha Chen 5fa382329f [2020] move input files to root dir
4 years ago
Alpha Chen f5660e8938 [2020][ruby][6.x]
4 years ago
Alpha Chen cccdf1e45e [2020][ruby][5.x] too clever
4 years ago
Alpha Chen a369ffb751 [2020][ruby][5.x]
4 years ago
Alpha Chen eea91b1ed5 [2020][ruby][4.x]
4 years ago

3
.gitmodules vendored

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

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

107
2015/rust/Cargo.lock generated

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

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

144
2016/rust/Cargo.lock generated

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

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

175
2018/rust/Cargo.lock generated

@ -1,252 +1,205 @@
# 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 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static",
"pest",
"pest_derive",
"regex",
]
[[package]]
name = "aho-corasick"
version = "0.6.9"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"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 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayref",
"byte-tools",
]
[[package]]
name = "byte-tools"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.6"
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 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"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.0"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d00328cedcac5e81c683e5620ca6a30756fc23027ebf9bff405c0e8da1fbb7e"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum",
]
[[package]]
name = "lazy_static"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.44"
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.1.1"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (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 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b76f477146419bc539a63f4ef40e902166cb43b3e51cecc71d9136fd12c567e7"
dependencies = [
"pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_generator 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"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 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_meta 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
"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 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"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 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid",
]
[[package]]
name = "quote"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.1.0"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [
"aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.4"
version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.3 (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 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"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 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"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"
[[package]]
name = "ucd-util"
version = "0.1.3"
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"
[[package]]
name = "utf8-ranges"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
"checksum pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a677051ad923732bb5c70f2d45f8985a96e3eee2e2bff86697e3b11b0c3fcfde"
"checksum pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b76f477146419bc539a63f4ef40e902166cb43b3e51cecc71d9136fd12c567e7"
"checksum pest_generator 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebee4e9680be4fd162e6f3394ae4192a6b60b1e4d17d845e631f0c68d1a3386"
"checksum pest_meta 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f6d5f6f0e6082578c86af197d780dc38328e3f768cec06aac9bc46d714e8221"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"

@ -0,0 +1,25 @@
FIELDS = {
byr: ->(s) { s =~ /^\d{4}$/ && (1920..2002).cover?(s.to_i) },
iyr: ->(s) { s =~ /^\d{4}$/ && (2010..2020).cover?(s.to_i) },
eyr: ->(s) { s =~ /^\d{4}$/ && (2020..2030).cover?(s.to_i) },
hgt: ->(s) {
s =~ /^(\d+)(cm|in)$/
case $2
when "cm"
(150..193).cover?($1.to_i)
when "in"
(59..76).cover?($1.to_i)
else
false
end
},
hcl: ->(s) { s =~ /^#[0-9a-f]{6}$/ },
ecl: ->(s) { s =~ /^(amb|blu|brn|gry|grn|hzl|oth)$/ },
pid: ->(s) { s =~ /^\d{9}$/ },
cid: ->(s) { true },
}
puts ARGF.read.split("\n\n").map {|line| line.scan(/(\w+):(\S+)/).to_h }
.count {|passport|
FIELDS.map {|k,v| v[passport.fetch(k.to_s, "")] }.all?
}

@ -0,0 +1,6 @@
seats = ARGF.read.split("\n")
.map {|pass| pass.tr("FB", "01").tr("LR", "01") }
.map {|pass| pass.to_i(2) }
p seats.max # day 1
p (0b1000..).find {|id| !seats.include?(id) }

@ -0,0 +1,6 @@
p ARGF.read.split("\n\n").map {|group|
group.split("\n").map(&:chars)
}.map {|group|
# group.inject(&:|)
group.inject(&:&)
}.map(&:size).sum

@ -0,0 +1,16 @@
require "set"
rules = ARGF.read.split("\n")
.map {|line| line.split(" bags contain") }.to_h
.transform_values {|v| v.scan(/(\d+) ([\w ]+) bags?/).map(&:reverse).to_h }
# bags = rules.select {|_,v| v.has_key?("shiny gold") }.map(&:first).to_set
# while true
# bags.merge(bags.flat_map {|bag| rules.select {|_,v| v.has_key?(bag) }.map(&:first) })
# p bags.size
# end
bags = Hash.new {|h,k|
h[k] = rules.fetch(k).map {|k,v| v.to_i + h[k] * v.to_i }.sum
}
p bags["shiny gold"]

@ -0,0 +1,55 @@
require "set"
execute = ->(r, op, arg) {
delta = case op
when :acc
{ acc: arg, pc: 1 }
when :jmp
{ pc: arg }
when :nop
{ pc: 1 }
else
fail
end
r.merge(delta) {|_, old, new| old + new }
}
# part 1
seen = Set.new
detect_loop = ->(r, op, arg) {
throw :halt if seen.include?(r[:pc])
seen << r[:pc]
execute[r, op, arg]
}
instructions = ARGF.read.scan(/(\w+) ([-+]\d+)/).map {|op,arg| [op.to_sym, arg.to_i] }
registers = Hash.new(0)
swaps = { nop: :jmp, jmp: :nop }
candidates = instructions.filter_map.with_index {|(op, arg), i|
swap = swaps[op]
if swap.nil?
nil
else
[i, [swap, arg]]
end
}.map {|i, swap|
candidate = instructions.clone
candidate[i] = swap
candidate
}
candidates.each do |candidate|
seen = Set.new
registers = Hash.new(0)
catch(:halt) do
while instruction = candidate[registers[:pc]]
registers = detect_loop[registers, *instruction]
end
end
break if registers[:pc] == candidate.size
end
p registers[:acc]

@ -0,0 +1,18 @@
N = 25
data = ARGF.read.scan(/\d+/).map(&:to_i)
invalid = data.each_cons(N+1).filter_map {|range|
n = range.pop
range.combination(2).map(&:sum).include?(n) ? nil : n
}.first
weakness = (0..).lazy.flat_map {|start|
(2..data.size-start-1).map {|len|
data[start, len]
}
}.find {|range|
range.sum == invalid
}.minmax.sum
p weakness

@ -0,0 +1,29 @@
adapters = ARGF.read.scan(/\d+/).map(&:to_i)
outlet = 0
device = adapters.max + 3
dist = (adapters + [outlet, device]).sort.each_cons(2).map {|a,b| b - a }
# part 1
# tally = dist.tally
# p dist[1] * dist[3]
# programmatically figuring out the arrangements
# arrangements = Hash.new {|h,k|
# h[k] = (0..k-1).flat_map {|n| (2..k).to_a.combination(n).to_a }
# .reject {|c| (c << 1 << k+1).sort.each_cons(2).any? {|a,b| b-a > 3 }}
# .count
# }
# tribonacci
arrangements = Hash.new {|h,k| h[k] = h[k-1] + h[k-2] + h[k-3] }
arrangements[0] = 1
arrangements[1] = 1
arrangements[2] = 2
p dist
.slice_when {|a,b| a != b }
.select {|run| run.first == 1 }
.map {|run| arrangements[run.size] }
.inject(&:*)

@ -0,0 +1,90 @@
class Layout
def self.from(raw, &logic)
seats = Hash.new
raw.split("\n").each.with_index do |row,y|
row.chars.each.with_index do |pos,x|
seats[[y,x]] = false if pos == ?L
end
end
self.new(seats, &logic)
end
attr_reader :seats, :y_max, :x_max
def initialize(seats, &logic)
@seats, @logic = seats, logic
@y_max = @seats.keys.map(&:first).max
@x_max = @seats.keys.map(&:last).max
end
def [](yx)
@seats[yx]
end
def each
return enum_for(__method__) unless block_given?
loop do
yield self
seats = tick(&@logic)
break if seats == @seats
@seats = seats
end
end
def tick
@seats.keys.map {|yx|
[yx, @logic[self, yx]]
}.to_h
end
def to_s
(0..@y_max).map {|y|
(0..@x_max).map {|x|
case @seats[[y,x]]
when true then ?#
when false then ?L
when nil then ?.
else fail
end
}.join
}.join("\n")
end
end
NEIGHBORS = (-1..1).flat_map {|y| (-1..1).map {|x| [y, x] }} - [[0, 0]]
day1 = ->(layout, yx) {
y, x = yx
occupied_neighbors = NEIGHBORS.filter_map {|dy,dx| layout[[y+dy, x+dx]] }
if !layout[yx] && occupied_neighbors.empty?
true
elsif layout[yx] && occupied_neighbors.size >= 4
false
else
layout[yx]
end
}
day2 = ->(layout, yx) {
y, x = yx
occupied_neighbors = NEIGHBORS.filter_map {|dy,dx|
(1..).lazy
.map {|i| [y+dy*i, x+dx*i] }
.find {|y,x|
!(0..layout.y_max).cover?(y) ||
!(0..layout.x_max).cover?(x) ||
layout.seats.has_key?([y, x])
}
}.filter_map {|yx| layout[yx] }
if !layout[yx] && occupied_neighbors.empty?
true
elsif layout[yx] && occupied_neighbors.size >= 5
false
else
layout[yx]
end
}
layout = Layout.from(ARGF.read, &day2)
layout.each.take_while(&:itself).last
puts layout.seats.count(&:last)

@ -0,0 +1,54 @@
actions = ARGF.read.scan(/(\w)(\d+)/).map {|a,v| [a, v.to_i] }
dir = 0
pos = [0, 0]
way = [10, 1]
actions.each do |a,v|
# delta = case a
# when ?N
# [ 0, v]
# when ?S
# [ 0, -v]
# when ?E
# [ v, 0]
# when ?W
# [-v, 0]
# when ?L
# dir += v
# [0, 0]
# when ?R
# dir -= v
# [0, 0]
# when ?F
# rad = dir * Math::PI / 180.0
# [v * Math.cos(rad), v * Math.sin(rad)].map(&:round)
# else
# fail
# end
case a
when ?N
way[1] += v
when ?S
way[1] -= v
when ?E
way[0] += v
when ?W
way[0] -= v
when ?L
rad = Math.atan2(*way.reverse)
dis = Math.sqrt(way.map {|x| x**2 }.sum)
rad += v * Math::PI / 180
way = [dis * Math.cos(rad), dis * Math.sin(rad)].map(&:round)
when ?R
rad = Math.atan2(*way.reverse)
dis = Math.sqrt(way.map {|x| x**2 }.sum)
rad -= v * Math::PI / 180
way = [dis * Math.cos(rad), dis * Math.sin(rad)].map(&:round)
when ?F
delta = way.map {|i| v * i }
pos = pos.zip(delta).map {|a,b| a + b }
else
fail
end
end
p pos.map(&:abs).sum

@ -0,0 +1,42 @@
input = ARGF.read.split("\n")
depart_time = input.shift.to_i
buses = input.shift.split(?,).map {|b| b != ?x ? b.to_i : nil }
# p buses.compact.map {|bus|
# d = bus * ((depart_time / bus) + 1)
# [bus, d - depart_time]
# }.min_by(&:last).inject {|a,b| a * b }
# shamelessly copied from https://rosettacode.org/wiki/Chinese_remainder_theorem#Ruby
def extended_gcd(a, b)
last_remainder, remainder = a.abs, b.abs
x, last_x, y, last_y = 0, 1, 1, 0
while remainder != 0
last_remainder, (quotient, remainder) = remainder, last_remainder.divmod(remainder)
x, last_x = last_x - quotient*x, x
y, last_y = last_y - quotient*y, y
end
return last_remainder, last_x * (a < 0 ? -1 : 1)
end
def invmod(e, et)
g, x = extended_gcd(e, et)
if g != 1
raise 'Multiplicative inverse modulo does not exist!'
end
x % et
end
def chinese_remainder(mods, remainders)
max = mods.inject( :* ) # product of all moduli
series = remainders.zip(mods).map{ |r,m| (r * max * invmod(max/m, m) / m) }
series.inject( :+ ) % max
end
buses = buses.map.with_index.select {|b,_| b }
# p 0.step(by: buses[0][0]).lazy.find {|depart_time|
# buses.all? {|b,i| (depart_time + i) % b == 0 }
# }
mods, remainders = buses.map {|b,i| [b, b-i] }.transpose
p chinese_remainder(mods, remainders)

@ -0,0 +1,37 @@
require "strscan"
mem = Hash.new(0)
mask = nil
ss = StringScanner.new(ARGF.read)
until ss.eos?
case
when ss.scan(/mask = ([10X]+)\n/)
mask = ss.captures.fetch(0)
when ss.scan(/mem\[(\d+)\] = (\d+)\n/)
addr, value = ss.captures.map(&:to_i)
# part 1
# value &= mask.gsub(?X, ?1).to_i(2)
# value |= mask.gsub(?X, ?0).to_i(2)
# mem[addr] = value
masked = ("%036b" % addr).chars.zip(mask.chars).map {|a,m|
case m
when ?X then ?X
when ?1 then ?1
when ?0 then a
else fail
end
}.join
floating = masked.count(?X)
(0...2**floating).map {|i| i.to_s(2).chars }.each do |i|
floated = masked.gsub(?X) { i.pop || "0" }.to_i(2)
mem[floated] = value
end
else
fail
end
end
p mem.values.sum

@ -0,0 +1,31 @@
# turns = ARGF.read.scan(/\d+/).map(&:to_i)
# until turns.size == 2020
# turns << if turns.count(turns.last) == 1
# 0
# else
# a, b = turns.filter_map.with_index {|x,i|
# x == turns.last ? i : nil
# }[-2,2]
# b - a
# end
# end
start = ARGF.read.scan(/\d+/).map(&:to_i)
turns = Hash.new
last = start.pop
start.each.with_index do |x,i|
turns[x] = i+1
end
(start.size+1...30000000).each do |turn|
if n = turns[last]
turns[last] = turn
last = turn - n
else
turns[last] = turn
last = 0
end
end
p last

@ -0,0 +1,52 @@
require "strscan"
ss = StringScanner.new(ARGF.read)
rules = {}
mine = []
nearby = []
while ss.scan(/([\w\s]+): (\d+)-(\d+) or (\d+)-(\d+)\n/)
c = ss.captures
field = c.shift
rules[field] = c.map(&:to_i).each_slice(2).map {|a,b| a..b }
end
ss.scan(/\n/)
ss.scan(/your ticket:\n/)
mine = ss.scan(/(?~\n)\n/).scan(/\d+/).map(&:to_i)
ss.scan(/\nnearby tickets:\n/)
nearby = ss.rest.split("\n").map {|line| line.split(?,).map(&:to_i) }
# part one
# p nearby.flat_map {|fields|
# fields.reject {|field|
# rules.values.any? {|values| values.any? {|range| range.cover?(field) }}
# }
# }.sum
nearby.select! {|fields|
fields.all? {|field|
rules.values.any? {|values| values.any? {|range| range.cover?(field) }}
}
}
valid = (0...mine.size).map {|i|
rules.select {|name, ranges|
nearby.map {|n| n[i] }.all? {|n| ranges.any? {|range| range.cover?(n) }}
}
}.map.with_index {|v,i| [i, v.keys] }.to_h
order = {}
until valid.values.all?(&:empty?)
k, f = valid.find {|_,v| v.size == 1 }
order[k] = f[0]
valid.transform_values! {|v| v - f }
end
p order
.select {|_,v| v.start_with?("departure") }
.map(&:first)
.map {|i| mine[i] }
.inject(&:*)

@ -0,0 +1,33 @@
DIMENSIONS = 4
state = ARGF.read.strip.split("\n").flat_map.with_index {|line,y|
line.chars.map.with_index {|c,x|
[[x,y].fill(0, 2, DIMENSIONS-2), c == "#"]
}
}.to_h
NEIGHBORS = (0...3**DIMENSIONS)
.reject {|n| n == 3**DIMENSIONS / 2 }
.map {|n| n.digits(3) }
.map {|n| (0...DIMENSIONS).map {|x| n.fetch(x, 0) - 1 }}
def tick(state)
actives = state.select {|_,c| c }.keys
minmaxes = actives
.transpose.map(&:minmax)
.map {|min,max| (min-1..max+1).to_a }
coords = minmaxes.inject {|n,x|
n.flat_map {|nn| x.map {|xx| [nn, xx] }}
}.map(&:flatten)
coords.map {|coord|
active_neighbors = NEIGHBORS.count {|delta| state[coord.zip(delta).map {|a,b| a + b }] }
[ coord,
state[coord] ? (2..3).cover?(active_neighbors) : active_neighbors == 3
]
}.to_h
end
6.times do
state = tick(state)
end
p state.values.count(&:itself)

@ -0,0 +1,58 @@
require "strscan"
# def evaluate(input)
# while input.include?(?()
# input = input.gsub(/\((?~[()])+\)/) {|m| evaluate(m[1..-2]) }
# end
# # part one
# # ss = StringScanner.new(input)
# # n = ss.scan(/\d+/).to_i
# # until ss.eos?
# # case
# # when ss.scan(/\s*\+\s*(\d+)/)
# # n += ss.captures[0].to_i
# # when ss.scan(/\s*\*\s*(\d+)/)
# # n *= ss.captures[0].to_i
# # else
# # fail
# # end
# # end
# # n
# while input.include?(?+)
# input = input.gsub(/\d+\s*\+\s*\d+/) {|m| eval(m) }
# end
# while input.include?(?*)
# input = input.gsub(/\d+\s*\*\s*\d+/) {|m| eval(m) }
# end
# input.to_i
# end
def evaluate(input)
stack = [->(x) { x }]
ss = StringScanner.new(input)
until ss.eos?
ss.scan(/\s*/)
stack << case
when n = ss.scan(/\d+/)
stack.pop[n.to_i]
when ss.scan(/\+/)
->(x) { stack.pop + x }
when ss.scan(/\*/)
->(x) { stack.pop * x }
when ss.scan(/\(/)
->(x) { x }
when ss.scan(/\)/)
n = stack.pop
stack.pop[n]
else
fail
end
end
stack.pop
end
p ARGF.read.split("\n").map {|line| evaluate(line) }.sum

@ -0,0 +1,67 @@
# require "bundler/inline"
# gemfile do
# source "https://rubygems.org"
# gem "parslet"
# end
rules, messages = ARGF.read.split("\n\n")
# class Day19 < Parslet::Parser
# root(:rule_0)
# end
# rules = rules.split("\n").map {|rule| rule.split(": ") }.to_h
# rules["8"] = "42 | 42 8"
# rules["11"] = "42 31 | 42 11 31"
# rules.each do |rule, sub_rules|
# sub_rules = sub_rules.split(" | ").map {|sub_rule|
# sub_rule.split(/\s+/).map {|sub_sub_rule|
# sub_sub_rule =~ /^\d+$/ ? "rule_#{sub_sub_rule}" : "str(#{sub_sub_rule})"
# }.join(" >> ")
# }.join(" | ")
# rule = "rule(:rule_#{rule}) { #{sub_rules} }"
# p rule
# Day19.class_eval(rule)
# end
# PARSER = Day19.new
# def parsable?(input)
# !!PARSER.parse(input)
# rescue
# false
# end
# puts messages.split("\n").select {|line| parsable?(line) }
# begin
# p PARSER.parse("bbbbbbbaaaabbbbaaabbabaaa")
# rescue Parslet::ParseFailed => failure
# puts failure.parse_failure_cause.ascii_tree
# end
rules = rules.split("\n").map {|line|
line.split(": ")
}.to_h
rule = rules["0"]
while rule =~ /\d/
rule.gsub!(/\d+/) {|r|
case r
when "8"
"(?:42)+"
when "11"
"(?:#{(1..5).map {|i| (Array.new(i, "42") + Array.new(i, "31")).join(" ") }.join(" | ")})"
else
value = rules.fetch(r)
value = value[1..-2] if value =~ /^"\w+"$/
"(?:#{value})"
end
}
end
rule.gsub!(" ", "")
while rule =~ /\(\?:\w+\)/
rule.gsub!(/\(\?:(\w+)\)/, '\1')
end
p messages.split("\n").count {|m| m =~ /^#{rule}$/ }

@ -0,0 +1,107 @@
# all rotations are clockwise
# all flips are vertical
class Tile
attr_reader :id, :raw
def initialize(id, raw)
@id, @raw = id, raw
end
def [](y, x)
@raw.fetch(y).fetch(x)
end
def edge_keys
{
top: @raw.first,
down: @raw.last,
left: @raw.transpose.first,
right: @raw.transpose.last,
}.transform_values(&:join)
end
def permutations
(0..3).map {|i|
i.times.inject(self) {|x,_| x.rotated }
}.flat_map {|x| [x, x.flipped] }
end
def rotated
self.class.new(@id, @raw.reverse.transpose)
end
def flipped
self.class.new(@id, @raw.reverse)
end
def to_s
@raw.map(&:join).join("\n")
end
end
tiles = ARGF.read
.scan(/Tile (\d+):\n((?:[.#]+\n)+)/m)
.to_h
.transform_values {|v| v.split("\n").map {|row| row.chars } }
.map {|k,v| [k, Tile.new(k, v)] }
.to_h
keys_to_tiles = Hash.new {|h,k| h[k] = [] }
tiles.values.each do |tile|
tile.edge_keys.values.each do |key|
keys_to_tiles[key] << tile.id
keys_to_tiles[key.reverse] << tile.id
end
end
start_corner = tiles.values.find {|tile|
tile.edge_keys.values_at(:left, :top).all? {|key| keys_to_tiles.fetch(key).size == 1 }
}
image = [[start_corner]]
until image.map(&:size).sum == tiles.size
current = image.last.last
right_key = current.edge_keys.fetch(:right)
if right_id = keys_to_tiles.fetch(right_key, nil).find {|id| id != current.id }
right_tile = tiles.fetch(right_id).permutations.find {|p| p.edge_keys.fetch(:left) == right_key }
image.last << right_tile
else
current = image.last.first
down_key = current.edge_keys.fetch(:down)
break unless down_id = keys_to_tiles.fetch(down_key).find {|id| id != current.id }
down_tile = tiles.fetch(down_id).permutations.find {|p| p.edge_keys.fetch(:top) == down_key }
image << [down_tile]
end
end
full_raw = image.map {|row| row.map {|tile|
tile.raw[1..-2].map {|row| row[1..-2] }
}}.flat_map {|row| row.inject(&:zip).map(&:flatten) }
full_tile = Tile.new(nil, full_raw)
sea_monster = <<~SEA_MONSTER.split("\n").map(&:chars)
#
# ## ## ###
# # # # # #
SEA_MONSTER
needle = sea_monster.flat_map.with_index {|row,y|
row.filter_map.with_index {|c,x|
c == ?# ? [y,x] : nil
}
}
num_monsters = full_tile.permutations.map {|tile|
needle_maxes = needle.transpose.map(&:max)
haystack = (0...tile.raw.size-needle_maxes.first).flat_map {|y|
(0...tile.raw.first.size-needle_maxes.last).map {|x|
[y, x]
}
}
haystack.count {|y,x|
needle.all? {|dy,dx| tile[y+dy, x+dx] == ?# }
}
}.sum
puts full_tile.raw.map {|row| row.count(?#) }.sum - (num_monsters * needle.size)

@ -0,0 +1,39 @@
require "set"
Food = Struct.new(:id, :ingredients, :allergens)
foods = ARGF.read
.scan(/(.+) \(contains (.+)\)/)
.map.with_index {|(ingredients, allergens), i|
ingredients, allergens = [ ingredients.split(" "), allergens.split(", ") ].map {|x| Set.new(x) }
Food.new(i, ingredients, allergens)
}
all_ingredients = foods.map(&:ingredients).inject(&:|)
all_allergens = foods.map(&:allergens).inject(&:|)
no_allergens = all_ingredients.select {|ingredient|
possible_allergens = foods
.select {|food| food.ingredients.include?(ingredient) }
.map(&:allergens)
.inject(&:|)
possible_allergens.none? {|allergen|
foods_with_allergen = foods.select {|f| f.allergens.include?(allergen) }
foods_with_allergen.all? {|f| f.ingredients.include?(ingredient) }
}
}
# part one
# p foods.map {|f| f.ingredients.count {|i| no_allergens.include?(i) }}.sum
known, unknown = all_allergens.map {|a|
[a, foods.select {|f| f.allergens.include?(a) }.map(&:ingredients).inject(&:&) ]
}.to_h.partition {|_,v| v.size == 1 }.map(&:to_h)
until unknown.empty?
unknown.transform_values! {|v| v - known.values.inject(&:|) }
new_known, unknown = unknown.partition {|_,v| v.size == 1 }.map(&:to_h)
known.merge!(new_known)
end
p known.transform_values {|v| v.to_a.first }.sort_by(&:first).map(&:last).join(?,)

@ -0,0 +1,46 @@
require "set"
decks = ARGF.read.split("\n\n").map {|players| players.split("\n")[1..].map(&:to_i) }
# part one
# until decks.any?(&:empty?)
# p decks
# top_cards = decks.map(&:shift)
# fail if top_cards.tally.size == 1
# if top_cards.first > top_cards.last
# decks.first.concat(top_cards)
# else
# decks.last.concat(top_cards.reverse)
# end
# end
SEEN = Set.new
def recursive_combat!(decks)
until decks.any?(&:empty?)
return 0 if SEEN.include?(decks)
SEEN << decks
top_cards = decks.map(&:shift)
winner = if decks.zip(top_cards).all? {|d,tc| d.size >= tc }
recursive_combat!(decks.zip(top_cards).map {|d,tc| d[0,tc] })
elsif top_cards.first > top_cards.last
0
else
1
end
if winner == 0
decks.first.concat(top_cards)
else
decks.last.concat(top_cards.reverse)
end
end
decks.index {|d| !d.empty? }
end
recursive_combat!(decks)
p decks.flatten.reverse.map.with_index {|v,i| v * (i+1) }.sum

@ -0,0 +1,32 @@
cups = Hash.new {|h,k|
fail if k > 1000000
h[k] = k + 1
}
cup_values = ARGF.read.chars.map(&:to_i)
current = cup_values.first
cup_values = [1_000_000, *cup_values, cup_values.max + 1]
cup_values.each_cons(2) do |a,b|
cups[a] = b
end
cups_range = Range.new(*cups.keys.minmax)
10_000_000.times do |i|
pickup = 2.times.inject([cups[current]]) {|p,_| p << cups[p.last] }
cups[current] = cups[pickup.last]
dest_value = current - 1
loop do
dest_value = cups_range.max if dest_value == 0
break unless pickup.include?(dest_value)
dest_value -= 1
end
cups[pickup.last] = cups[dest_value]
cups[dest_value] = pickup.first
current = cups[current]
end
p 1.times.inject([cups[1]]) {|p,_| p << cups[p.last] }.inject(&:*)

@ -0,0 +1,55 @@
require "set"
require "strscan"
def parse(line)
deltas = []
ss = StringScanner.new(line)
until ss.eos?
deltas << case
when ss.scan(/e/) then [ 1, 0]
when ss.scan(/se/) then [ 0, 1]
when ss.scan(/sw/) then [-1, 1]
when ss.scan(/w/) then [-1, 0]
when ss.scan(/nw/) then [ 0, -1]
when ss.scan(/ne/) then [ 1, -1]
else fail
end
end
deltas.inject {|c,d| c.zip(d).map {|c,d| c+d }}
end
NEIGHBORS = %w[ e se sw w nw ne ].map {|dir| parse(dir) }
def tick(tiles)
coords = Set.new(tiles.flat_map {|coord|
[
coord,
*NEIGHBORS.map {|n| coord.zip(n).map {|c,d| c+d }},
]
})
Set.new(coords.select {|coord|
live_neighbors = NEIGHBORS.map {|n| coord.zip(n).map {|c,d| c+d }}.count {|c| tiles.include?(c) }
if tiles.include?(coord)
(1..2).cover?(live_neighbors)
else
live_neighbors == 2
end
})
end
tiles = Set.new
ARGF.read.split("\n").each do |line|
tile = parse(line)
if tiles.include?(tile)
tiles.delete(tile)
else
tiles << tile
end
end
100.times do |i|
tiles = tick(tiles)
end
p tiles.size

@ -0,0 +1,17 @@
def transform(subject_number)
return enum_for(__method__, subject_number) unless block_given?
value = 1
(0..).each do |loop_size|
yield [loop_size, value]
value *= subject_number
value %= 20201227
end
end
public_keys = ARGF.read.scan(/\d+/).map(&:to_i)
loop_size, _ = transform(7).find {|_,v| v == public_keys.first }
_, encryption_key = transform(public_keys.last).find {|i,_| i == loop_size }
p encryption_key

@ -0,0 +1,4 @@
#!/usr/bin/env jconsole
echo stdin
exit''

@ -0,0 +1,2 @@
p ARGF.read.split("\n").map(&:to_i).each_cons(2).count {|x,y| x < y }
p ARGF.read.split("\n").map(&:to_i).each_cons(3).map(&:sum).each_cons(2).count {|x,y| x < y }

@ -0,0 +1,35 @@
# h = 0
# d = 0
# ARGF.read.split("\n").map(&:split).each do |dir, n|
# n = n.to_i
# case dir
# when "forward"
# h += n
# when "down"
# d += n
# when "up"
# d -= n
# else
# fail dir
# end
# end
# p h, d, h*d
h = 0
d = 0
aim = 0
ARGF.read.split("\n").map(&:split).each do |dir, n|
n = n.to_i
case dir
when "forward"
h += n
d += aim * n
when "down"
aim += n
when "up"
aim -= n
else
fail dir
end
end
p h, d, h*d

@ -0,0 +1,23 @@
bits = ARGF.read.split("\n").map(&:chars)
gamma = bits.transpose.map {|a| a.tally.max_by(&:last).first }.join
epsilon = bits.transpose.map {|a| a.tally.min_by(&:last).first }.join
p gamma.to_i(2) * epsilon.to_i(2)
oxy = bits.clone
(0..oxy.first.length).each do |i|
b = oxy.transpose.map {|a| a.tally.sort.reverse.max_by(&:last).first }[i]
oxy.select! {|x| x[i] == b }
break if oxy.length == 1
end
oxy = oxy.join.to_i(2)
co2 = bits.clone
(0..co2.first.length).each do |i|
b = co2.transpose.map {|a| a.tally.sort.min_by(&:last).first }[i]
co2.select! {|x| x[i] == b }
break if co2.length == 1
end
co2 = co2.join.to_i(2)
p oxy * co2

@ -0,0 +1,29 @@
input = ARGF.read
numbers, *cards = input.split("\n\n")
numbers = numbers.split(?,).map(&:to_i)
cards = cards.map {|c| c.split("\n").map {|r| r.split(/\s+/).reject(&:empty?).map(&:to_i) }}
def win?(card, drawn)
return true if card.any? {|row| row.all? {|c| drawn.include?(c) }}
return true if card.transpose.any? {|col| col.all? {|c| drawn.include?(c) }}
# return true if (0..4).all? {|x| drawn.include?(card.fetch(x).fetch(x)) }
# return true if (0..4).all? {|x| drawn.include?(card.fetch(x).fetch(4-x)) }
return false
end
(0..numbers.length).each do |i|
drawn = numbers[0..i]
# winning_card = cards.find {|c| win?(c, drawn) }
# if winning_card
# p winning_card.flatten.reject {|x| drawn.include?(x) }.sum * drawn.last
# exit
# end
if cards.length == 1 && winning_card = cards.find {|c| win?(c, drawn) }
p winning_card.flatten.reject {|x| drawn.include?(x) }.sum * drawn.last
exit
else
cards = cards.reject {|c| win?(c, drawn) }
end
end

@ -0,0 +1,29 @@
vents = ARGF.read.split("\n").map {|l| l.split(" -> ").map {|x| x.split(?,).map(&:to_i) }}
straights = vents.select {|(x1,y1),(x2,y2)| x1 == x2 || y1 == y2 }
points = Hash.new(0)
straights.each do |(x1,y1),(x2,y2)|
x = [x1, x2].minmax
y = [y1, y2].minmax
(x[0]..x[1]).each do |x|
(y[0]..y[1]).each do |y|
points[[x,y]] += 1
end
end
end
diagonals = vents - straights
diagonals.each do |(x1,y1),(x2,y2)|
if x1 > x2
x1,x2 = x2,x1
y1,y2 = y2,y1
end
sign = (y1 < y2) ? 1 : -1
(x1..x2).each.with_index do |x,i|
delta = i * sign
points[[x,y1+delta]] += 1
end
end
p points.count {|_,v| v > 1 }

@ -0,0 +1,22 @@
ages = ARGF.read.split(?,).map(&:to_i)
# 80.times do
# new_fish = 0
# ages.map! {|age|
# if age.zero?
# new_fish += 1
# 6
# else
# age - 1
# end
# }
# ages.concat(Array.new(new_fish) { 8 })
# end
# p ages.count
DURATION = 256
DESCENDANTS = Hash.new {|h,k|
children = (k...DURATION).step(7)
h[k] = children.count + children.map {|d| d + 9 }.select {|d| d < DURATION }.sum {|d| h[d] }
}
p ages.count + ages.sum {|age| DESCENDANTS[age] }

@ -0,0 +1,9 @@
positions = ARGF.read.split(?,).map(&:to_i)
min, max = positions.minmax
pos = (min..max).min_by {|i|
# positions.sum {|p| (p - i).abs }
positions.sum {|p| n = (p - i).abs; (n * (n + 1)) / 2 }
}
# p positions.sum {|p| (p - pos).abs }
p positions.sum {|p| n = (p - pos).abs; (n * (n + 1)) / 2 }

@ -0,0 +1,38 @@
include "globals.mzn";
enum Signals = { A, B, C, D, E, F, G };
set of Signals: Zero = { A, B, C, E, F, G };
set of Signals: One = { C, F };
set of Signals: Two = { A, C, D, E, G };
set of Signals: Three = { A, C, D, F, G };
set of Signals: Four = { B, C, D, F };
set of Signals: Five = { A, B, D, F, G };
set of Signals: Six = { A, B, D, E, F, G };
set of Signals: Seven = { A, C, F };
set of Signals: Eight = { A, B, C, D, E, F, G };
set of Signals: Nine = { A, B, C, D, F, G };
array[1..10] of set of Signals: AllSignals = [ Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine ];
array[1..10] of set of Signals: Patterns;
% Patterns = [
% { A, C, E, D, G, F, B },
% { C, D, F, B, E },
% { G, C, D, F, A },
% { F, B, C, A, D },
% { D, A, B },
% { C, E, F, A, B, D },
% { C, D, F, G, E, B },
% { E, A, F, B },
% { C, A, G, E, D, B },
% { A, B },
% ];
array [Signals] of var Signals: Map;
constraint alldifferent(Map);
constraint forall(pattern in [ { Map[x] | x in pattern } | pattern in Patterns])(
exists(digit in AllSignals)(pattern = digit)
);
output [show(Map)];

@ -0,0 +1,51 @@
require "set"
input = ARGF.read.split("\n").map {|x| x.split(/\s+\|\s+/).map {|x| x.split(/\s+/) } }
# output = input.map(&:last)
# p output.flatten.count {|x| [2, 4, 3, 7].include?(x.length) }
MAP = {
%w[ a b c e f g ] => 0,
%w[ c f ] => 1,
%w[ a c d e g ] => 2,
%w[ a c d f g ] => 3,
%w[ b c d f ] => 4,
%w[ a b d f g ] => 5,
%w[ a b d e f g ] => 6,
%w[ a c f ] => 7,
%w[ a b c d e f g ] => 8,
%w[ a b c d f g ] => 9,
# 8 6 8 7 4 9 7
}.transform_keys(&:to_set)
# # My original solution to part two
# def solve(signals, output)
# all = signals + output
# one = all.find {|x| x.length == 2 }
# four = all.find {|x| x.length == 4 }
# seven = all.find {|x| x.length == 3 }
# eight = all.find {|x| x.length == 7 }
# b = (?a..?g).find {|x| signals.count {|s| s.include?(x) } == 6 }
# e = (?a..?g).find {|x| signals.count {|s| s.include?(x) } == 4 }
# f = (?a..?g).find {|x| signals.count {|s| s.include?(x) } == 9 }
# a = (seven.chars - one.chars)[0]
# c = (one.chars - [f])[0]
# d = (four.chars - [b, c, f])[0]
# g = (eight.chars - [a, b, c, d, e, f])[0]
# map = { a: a, b: b, c: c, d: d, e: e, f: f, g: g }.invert
# output.map {|x| MAP.fetch(x.chars.map {|c| map.fetch(c).to_s }.to_set) }.join.to_i
# end
# Here it is with a solver, but much, much slower!
def solve(signals, output)
data = "Patterns = [ #{signals.map { "{ #{_1.upcase.chars.join(" ,")} }" }.join(", ")} ]"
solution = `minizinc --cmdline-data "#{data}" day_08.mzn`.scan(/[A-G]/)
map = (?a..?g).zip(solution.map(&:downcase)).to_h
output.map {|x| MAP.fetch(x.chars.map {|c| map.fetch(c).to_s }.to_set) }.join.to_i
end
p input.sum {|x| solve(*x) }

@ -0,0 +1,31 @@
require "set"
INPUT = ARGF.read.split("\n").map {|l| l.chars.map(&:to_i) }
NEIGHBORS = [[0,-1], [-1, 0], [1, 0], [0, 1]]
def neighbors(y,x)
NEIGHBORS
.map {|dy,dx| [y+dy, x+dx] }
.select {|y,x| (0...INPUT.size).cover?(y) && (0...INPUT[0].size).cover?(x) }
end
all = (0...INPUT.size).flat_map {|y| (0...INPUT[0].size).map {|x| [y, x]}}
lows = all.select {|y,x| neighbors(y,x).all? {|yy,xx| INPUT[yy][xx] > INPUT[y][x] }}
# p lows.sum {|y,x| INPUT[y][x] + 1 }
def fill_basin(low)
basin = Set.new([low])
stack = [low]
until stack.empty?
y,x = stack.shift
new_neighbors = neighbors(y,x).reject {|y,x| basin.include?([y,x]) || INPUT[y][x] == 9 }
stack.concat(new_neighbors)
basin.merge(new_neighbors)
end
basin
end
p lows.map { fill_basin(_1) }.map(&:size).sort[-3, 3].inject(:*)

@ -0,0 +1,51 @@
input = ARGF.read.split("\n")
COMPLEMENTS = %w[ () [] {} <> ].map(&:chars).to_h
OPENING_REGEXP = Regexp.new("[#{Regexp.escape(COMPLEMENTS.keys.join)}]")
CLOSING_REGEXP = Regexp.new("[#{Regexp.escape(COMPLEMENTS.values.join)}]")
def parse(line)
stack = []
s = line.chars
until s.empty?
case char = s.shift
when OPENING_REGEXP
stack << char
when CLOSING_REGEXP
return { err: char } unless stack.pop == COMPLEMENTS.invert.fetch(char)
end
end
{ ok: stack }
end
# points = {
# ?) => 3,
# ?] => 57,
# ?} => 1197,
# ?> => 25137,
# }
# p input.sum {|line|
# case parse(line)
# in { ok: } then 0
# in { err: } then points.fetch(err)
# else fail
# end
# }
def score(closing) = closing
.map { COMPLEMENTS.values.index(_1) + 1 }
.inject(0) {|n,i| n*5 + i }
scores = input
.filter_map {|line|
case parse(line)
in { ok: } then ok
in { err: } then nil
else fail
end
}
.map {|remaining| remaining.reverse.map { COMPLEMENTS.fetch(_1) }}
.map { score(_1) }
p scores.sort.fetch(scores.length / 2)

@ -0,0 +1,36 @@
input = ARGF.read.split("\n").map { _1.chars.map(&:to_i) }
ys = (0...input.size)
xs = (0...input.fetch(0).size)
coords = ys.flat_map {|y| xs.map {|x| [y,x] }}
octopuses = coords.to_h {|y,x| [[y,x], input.fetch(y).fetch(x)] }
deltas = (-1..1).flat_map {|dy| (-1..1).map {|dx| [dy, dx] }}.reject { _1 == [0, 0] }
neighbors = ->(y, x) {
deltas
.map {|dy,dx| [y+dy, x+dx] }
.select {|y,x| ys.cover?(y) && xs.cover?(x) }
}
# flashes = 0
# 100.times do
(1..).each do |i|
octopuses.transform_values! { _1 + 1 }
until (flashing = octopuses.select { _2 == 10 }).empty?
flashing.each do |(y,x),_|
octopuses[[y,x]] += 1
neighbors.(y,x)
.select {|y,x| octopuses.fetch([y,x]) < 10 }
.each do |y,x|
octopuses[[y,x]] += 1
end
end
end
if octopuses.values.all? { _1 > 9 }
puts i
exit
end
# flashes += octopuses.count { _2 > 9 }
octopuses.transform_values! { _1 > 10 ? 0 : _1 }
end
# p flashes

@ -0,0 +1,25 @@
cave = Hash.new {|h,k| h[k] = [] }
ARGF.read.scan(/(\w+)-(\w+)/).each do
cave[_1] << _2
cave[_2] << _1
end
paths = [ %w[start] ]
loop do
closed, open = paths.partition { _1.last == "end" }
break if open.empty?
paths = closed + open.flat_map {|path|
cave.fetch(path.last)
# .reject { _1 =~ /^[a-z]+$/ && path.include?(_1) }
.reject { _1 == "start" }
.reject {|cave|
smalls = path.tally.select { _1 =~ /^[a-z]+$/ }
smalls.fetch(cave, 0) > (smalls.any? { _2 > 1 } ? 0 : 1)
}
.map { path + [_1] }
}
end
p paths.count

@ -0,0 +1,18 @@
dots, folds = ARGF.read.split("\n\n")
dots = dots.scan(/(\d+),(\d+)/).map { _1.map(&:to_i) }
folds = folds.scan(/(x|y)=(\d+)/).map { [_1, _2.to_i] }
dirs = { ?x => 0, ?y => 1 }
folds.each do |dir, axis|
index = dirs.fetch(dir)
dots.select { _1[index] > axis }.each do |dot|
dot[index] = axis - (dot[index] - axis)
end
dots.uniq!
# p dots.size or exit
end
xx = Range.new(*dots.map(&:first).minmax)
yy = Range.new(*dots.map(&:last).minmax)
puts yy.map {|y| xx.map {|x| dots.include?([x,y]) ? "" : " " }.join }.join("\n")

@ -0,0 +1,41 @@
template, rules = ARGF.read.split("\n\n")
template = template.chars
rules = rules.scan(/(\w{2}) -> (\w)/).to_h
# polymer = template
# 10.times do
# polymer = polymer.each_cons(2).flat_map {|a,b|
# [a, rules.fetch("#{a}#{b}")]
# } << polymer.last
# end
# min, max = polymer.tally.values.minmax
# p max - min
tally = Hash.new {|h,k|
polymer, steps = k
new_elements = polymer.each_cons(2).map(&:join).map { rules.fetch(_1) }
h[k] = case steps
when 1
(polymer + new_elements).tally
when (2..)
initial = new_elements.tally.transform_values { -_1 }
polymer.zip(new_elements)
.flatten[0..-2]
.each_cons(2)
.map { h[[_1, steps-1]] }
.inject(initial) {|final,tally| final.merge(tally) { _2 + _3 } }
else
fail
end
}
final = tally[[template, 40]]
# correct for internal elements being double-counted
template[1..-2].each do
final[_1] -= 1
end
min, max = final.values.minmax
p max - min

@ -0,0 +1,38 @@
require "set"
cavern = ARGF.read.split("\n").map { _1.chars.map(&:to_i) }
cavern = (0..4).flat_map {|i| cavern.map {|row|
row.map { (_1 + i - 1) % 9 + 1 }
}}
cavern = cavern.map {|row| (0..4).flat_map {|i|
row.map { (_1 + i - 1) % 9 + 1 }
}}
cavern = cavern
.flat_map.with_index {|row,y| row.map.with_index {|risk,x| [[y,x], risk] }}
.to_h
bottom_right = cavern.keys.max
risks = Hash.new(0)
risks[[0,0]] = 0
edges = Set[[0,0]]
until risks.has_key?(bottom_right)
yx = edges.min_by { risks.fetch(_1) }
edges.delete(yx)
y,x = yx
neighbors = [[-1, 0], [1, 0], [0, 1], [0, -1]]
.map {|dy,dx| [y+dy, x+dx] }
.select { cavern.has_key?(_1) }
.reject { risks.has_key?(_1) }
risk = risks.fetch(yx)
neighbors.each do
risks[_1] = risk + cavern.fetch(_1)
end
edges.merge(neighbors)
end
p risks[bottom_right]

@ -0,0 +1,79 @@
require "strscan"
Packet = Struct.new(:version, :type_id, :content) do
include Enumerable
def self.parse(ss)
version = ss.scan(/.{3}/).to_i(2)
type_id = ss.scan(/.{3}/).to_i(2)
case type_id
when 4 # literal value
value = ss.scan(/(1.{4})*(0.{4})/).chars
.each_slice(5).flat_map { _1[1..4] }.join
.to_i(2)
Literal.new(version, type_id, value)
else # operator
sub_packets = case
when ss.scan(/0(.{15})/)
length = ss.captures[0].to_i(2)
sub_packet = ss.scan(/.{#{length}}/)
sss = StringScanner.new(sub_packet)
sub_packets = []
until sss.eos?
sub_packets << parse(sss)
end
sub_packets
when ss.scan(/1(.{11})/)
n = ss.captures[0].to_i(2)
n.times.map { parse(ss) }
else
fail
end
Operator.new(version, type_id, sub_packets)
end
end
def each
return enum_for(__method__) unless block_given?
yield self
end
end
class Literal < Packet
def value = content
end
class Operator < Packet
def each(&block)
super
content.each do |sub_packet|
sub_packet.each(&block)
end
end
def value
values = content.map(&:value)
case type_id
when 0 then values.sum
when 1 then values.inject(:*)
when 2 then values.min
when 3 then values.max
when 4 then fail
when 5 then values.inject(:>) ? 1 : 0
when 6 then values.inject(:<) ? 1 : 0
when 7 then values.inject(:==) ? 1 : 0
else fail
end
end
end
message = ARGF.read.chomp.chars.map { _1.to_i(16).to_s(2).rjust(4, ?0) }.join
ss = StringScanner.new(message)
packet = Packet.parse(ss)
p packet.sum(&:version)
p packet.value

@ -0,0 +1,29 @@
def fire(v, target)
return enum_for(__method__, v, target) unless block_given?
pos = [0,0]
v_x, v_y = v
loop do
yield pos
return if target.zip(pos).all? { _1.cover?(_2) }
pos = pos.zip([v_x, v_y]).map { _1.sum }
v_x -= 1 if v_x > 0
v_y -= 1
return if pos[0] > target[0].end
return if pos[1] < target[1].begin
end
end
input = ARGF.read.scan(/x=(.+), y=(.+)/)
target = input[0].map { eval(_1) }
xs = (0..target[0].end).select { (1.._1).sum > target[0].begin }
haystack = xs.flat_map {|x| (-256..256).map {|y| [x, y] }}
haystack.select! {|v| fire(v, target).each.any? {|pos| target.zip(pos).all? { _1.cover?(_2) }}}
# p haystack.map {|v| fire(v, target).each.map { _2 }.max }.max
p haystack.count

@ -0,0 +1,75 @@
require "strscan"
def add(a, b)
reduced("[#{a},#{b}]")
end
def reduced(s)
last_s = ""
until s == last_s
last_s = s
to_explode = find_nested(s)
if to_explode
s = explode(s, to_explode)
next
end
s = s.sub(/[1-9]\d+/) {|n|
half = n.to_i / 2.0
pair = [half.floor, half.ceil]
"[#{pair.join(?,)}]"
}
end
s
end
def find_nested(s)
ss = StringScanner.new(s)
depth = 0
until ss.eos?
case
when ss.scan(/\[/)
if depth == 4
a = ss.pos-1
ss.scan(/\d+,\d+\]/)
b = ss.pos-1
return [a, b]
end
depth += 1
when ss.scan(/\]/)
depth -= 1
when ss.scan(/\d+|,/)
# no-op
else
fail
end
end
nil
end
def explode(s, pair_range)
a, b = pair_range
pair = s[a..b].scan(/\d+/).map(&:to_i)
[
s[0...a].reverse.sub(/\d+/) { (_1.reverse.to_i + pair[0]).to_s.reverse }.reverse,
0,
s[b+1..].sub(/(\d+)/) { _1.to_i + pair[1] },
].join
end
class Array
def magnitude = 3*self[0].magnitude + 2*self[1].magnitude
end
class Integer
def magnitude = self
end
# sum = ARGF.read.split("\n").reject(&:empty?).inject {|sum,num| add(sum, num) }
# p eval(sum).magnitude
p ARGF.read.split("\n").reject(&:empty?).permutation(2).map { eval(add(*_1)).magnitude }.max

@ -0,0 +1,52 @@
require "matrix"
require "set"
scanners = ARGF.read.strip.split("\n\n").to_h {|scanner|
id, *rest = scanner.split("\n")
id = id.scan(/\d+/)[0].to_i
coords = rest.map { _1.split(?,).map(&:to_i) }
[id, coords.map { Matrix.column_vector(_1) }]
}
first_scanner = scanners.shift
origin_beacon = first_scanner[1].first
origin_beacon = Matrix.column_vector([-618,-824,-621])
known_scanners = {
first_scanner[0] => [ origin_beacon.map { -_1 }, Matrix.identity(3) ],
}
known_beacons = Set.new(first_scanner[1].map {|beacon| beacon - origin_beacon })
rot_x = Matrix[ [1, 0, 0], [0, 0, -1], [0, 1, 0] ]
rot_y = Matrix[ [0, 0, 1], [0, 1, 0], [-1, 0, 0] ]
rot_z = Matrix[ [0, -1, 0], [1, 0, 0], [0, 0, 1] ]
id = Matrix.identity(3)
ROTATIONS = Set.new(
Array.new(4) { rot_x ** _1 }.flat_map {|x|
Array.new(4) { rot_y ** _1 }.flat_map {|y|
Array.new(4) { rot_z ** _1 }.map {|z| x * y * z }}}
)
def find_overlapping_scanner(known_beacons, scanners)
scanners.filter_map {|id, beacons|
haystack = ROTATIONS.flat_map {|r| beacons.map {|b| [ r*b, r ] }}
# haystack.select { _2 == Matrix.identity(3) }.map(&:first).each { p _1 }
haystack.find {|position, rotation|
translated_beacons = beacons.map { (rotation * _1) - position }
(known_beacons & translated_beacons).size >= 12
}&.then {|p,o| [id, p, o] }
}.first
end
until scanners.empty?
id, position, orientation = find_overlapping_scanner(known_beacons, scanners)
p [id, position, orientation]
known_scanners[id] = [position, orientation]
translated_beacons = scanners[id].map {|b| b.zip(position).map { _2 - _1 }.zip(orientation).map { _1 * _2 }}
known_beacons.merge(translated_beacons)
scanners.delete(id)
end

@ -0,0 +1,50 @@
algorithm, image = ARGF.read.strip.split("\n\n")
algorithm = algorithm.delete("\n") # for the example
algorithm = algorithm.chars.map.with_index { [_2, _1 == ?#] }.to_h
image = image.split("\n").flat_map.with_index {|row, y|
row.chars.map.with_index {|pixel, x| [[y, x], pixel == ?#] }
}.to_h
image.default = false
def each(image)
return enum_for(__method__, image) unless block_given?
ys = image.keys.map(&:first).minmax
xs = image.keys.map(&:last).minmax
(ys[0]-1..ys[1]+1).each do |y|
(xs[0]-1..xs[1]+1).each do |x|
yield [y, x]
end
end
end
def debug(image)
ys = image.keys.map(&:first).minmax
xs = image.keys.map(&:last).minmax
puts (ys[0]-1..ys[1]+1).map {|y|
(xs[0]-1..xs[1]+1).map {|x|
image[[y,x]] ? ?# : ?.
}.join
}.join("\n")
end
50.times {
ys = image.keys.map(&:first).minmax
xs = image.keys.map(&:last).minmax
prev_default = image.default
image = each(image).to_h {|y,x|
area = (-1..1).flat_map {|dy| (-1..1).map {|dx| image[[y+dy, x+dx]] }}
index = area.map { _1 ? 1 : 0 }.join.to_i(2)
pixel = algorithm.fetch(index)
[[y,x], pixel]
}
image.default = prev_default ? algorithm.fetch(511) : algorithm.fetch(0)
}
p image.count { _2 }

@ -0,0 +1,76 @@
# Player = Struct.new(:space, :score)
# one = Player.new(7, 0)
# two = Player.new(3, 0)
# class Die
# def initialize
# @value = 0
# @rolls = 0
# end
# attr_reader :rolls
# def roll
# value = @value
# @value += 1
# @value %= 100
# @rolls += 1
# value
# end
# end
# die = Die.new
# loop do
# one.space += 3.times.sum { die.roll + 1 }
# one.space %= 10
# one.score += one.space + 1
# break if one.score >= 1000
# two.space += 3.times.sum { die.roll + 1 }
# two.space %= 10
# two.score += two.space + 1
# break if two.score >= 1000
# end
# p [one, two].map(&:score).min * die.rolls
ROLLS = (1..3).flat_map {|a| (1..3).flat_map {|b| (1..3).map {|c|
[a, b, c].sum
}}}.tally
Player = Struct.new(:score, :space, keyword_init: true)
wins = Hash.new {|h,k|
one, two = k
multiverse = ROLLS.map {|delta,n|
space = (one.space + delta) % 10
[Player.new(score: one.score + space + 1, space: space), n]
}
one_wins, one_ongoing = multiverse.partition {|player,_| player.score >= 21 }
one_wins = one_wins.sum(&:last)
multiverse = ROLLS.map {|delta,n|
space = (two.space + delta) % 10
[Player.new(score: two.score + space + 1, space: space), n]
}
wins = one_ongoing.flat_map {|one, n_one| multiverse.map {|two, n_two|
n = n_one * n_two
if two.score >= 21
{ one: 0, two: n }
else
h[[one, two]].map { [_1, _2 * n] }.to_h
end
}}
wins = wins.inject({one: 0, two: 0}) {|acc,wins| acc.merge(wins) { _2 + _3 }}
h[k] = {
one: one_wins + wins.fetch(:one),
two: wins.fetch(:two),
}
}
# p wins[[Player.new(score: 0, space: 3), Player.new(score: 0, space: 7)]]
p wins[[Player.new(score: 0, space: 7), Player.new(score: 0, space: 3)]].values.max

@ -0,0 +1,109 @@
require "set"
steps = ARGF.read.scan(/(on|off) x=(.+),y=(.+),z=(.+)/)
.map {|power, *ranges| [power == "on", *ranges.map { eval(_1) }] }
# .select {|_, *ranges| ranges.all? { _1.begin >= -50 && _1.end <= 50 }}
# reactor = Hash.new(false)
# steps.each do |power,x,y,z|
# x.each do |x|
# y.each do |y|
# z.each do |z|
# reactor[[x,y,z]] = power
# end
# end
# end
# end
# p reactor.count { _2 }
# xs = steps.flat_map { [_2.begin, _2.end] }.minmax
# ys = steps.flat_map { [_3.begin, _3.end] }.minmax
# zs = steps.flat_map { [_4.begin, _4.end] }.minmax
# ons = Range.new(*xs).sum {|x| Range.new(*ys).sum {|y| Range.new(*zs).count {|z|
# step = steps.find { _2.cover?(x) && _3.cover?(y) && _4.cover?(z) }
# step ? step[0] : false
# }}}
# p ons
class Range
def overlap(other)
if cover?(other.begin)
min = other.begin
max = [self.end, other.end].min
(min..max)
elsif cover?(other.end)
min = [self.begin, other.begin].max
max = other.end
(min..max)
elsif other.cover?(self.begin)
min = self.begin
max = [self.end, other.end].min
(min..max)
elsif other.cover?(self.end)
min = [self.begin, other.begin].max
max = self.end
(min..max)
else
nil
end
end
def split(other)
overlap = self.overlap(other)
return [] if overlap.nil?
splits = [ overlap ]
splits << (self.begin..overlap.begin-1) if overlap.begin > self.begin
splits << (overlap.end+1..self.end) if overlap.end < self.end
splits
end
end
Cube = Struct.new(:xs, :ys, :zs) do
def -(other)
return self unless o = overlap(other)
xxs = xs.split(other.xs)
yys = ys.split(other.ys)
zzs = zs.split(other.zs)
cuboids = xxs.flat_map {|x| yys.flat_map {|y| zzs.map {|z|
Cube.new(x, y, z)
}}}
cuboids.delete(o)
cuboids
end
def overlap(other)
overlaps = to_a.zip(other.to_a).map { _1.overlap(_2) }
return nil if overlaps.any?(&:nil?)
Cube.new(*overlaps)
end
def overlap?(other) = !overlap(other).nil?
def volume = (xs.end - xs.begin + 1) * (ys.end - ys.begin + 1) * (zs.end - zs.begin + 1)
def to_s = "[#{[xs, ys, zs].map(&:to_s).join(", ")}]"
alias_method :inspect, :to_s
end
steps = steps.map {|power, *ranges| [power, Cube.new(*ranges)] }
reactor = Set.new
steps.each do |power, cube|
reactor
.select { _1.overlap?(cube) }
.each do |overlap|
reactor.delete(overlap)
reactor.merge(overlap - cube)
end
reactor << cube if power
end
p reactor.sum(&:volume)

@ -0,0 +1,35 @@
#############
#...........#
###B#C#B#D###
#A#D#C#A#
#########
#############
#...........#
###D#D#A#A###
#C#C#B#B#
#########
State = Struct.new(:spaces, :energy) do
ENERGY = { A: 1, B: 10, C: 100, D: 1000 }.transform_keys(&:to_s)
ROOMS = [2, 4, 6, 8]
def rooms = ROOMS.to_h { [_1, spaces.fetch(_1)] }
def valid_moves
end
end
spaces = Array.new(11) { [] }
# input = "DC DC AB AB"
input = "BA CD BC DA"
input.split(" ").map(&:chars).each.with_index do |amphipods, i|
spaces[(i+1) * 2] = amphipods
end
start = State.new(spaces, 0)
p start
p start.rooms
p start.valid_moves

@ -0,0 +1,58 @@
INSTRUCTIONS = ARGF.read.split("\n").map { _1.split(/\s+/) }
# INSTRUCTIONS.each do |instruction, *args|
# a, b = *args
# case instruction
# when "inp"
# puts "#{a} = input.shift"
# when "add"
# puts "#{a} += #{b}"
# when "mul"
# puts "#{a} *= #{b}"
# when "div"
# puts "#{a} = (#{a} / #{b}.to_f).floor"
# when "mod"
# puts "#{a} %= #{b}"
# when "eql"
# puts "#{a} = #{a} == #{b} ? 1 : 0"
# else
# fail
# end
# end
# exit
VARS = %w[ w x y z ]
def run(input)
vars = Hash.new(0)
INSTRUCTIONS.each do |instruction, *args|
a, b = *args
b = VARS.include?(b) ? vars[b] : b.to_i
case instruction
when "inp"
vars[a] = input.shift
when "add"
vars[a] += b
when "mul"
vars[a] *= b
when "div"
vars[a] = (vars[a] / b.to_f).floor
when "mod"
vars[a] %= b
when "eql"
vars[a] = vars[a] == b ? 1 : 0
else
fail
end
end
vars
end
99999999999999.downto(11111111111111).lazy.map(&:to_s).reject { _1.include?(?0) }.each do |input|
vars = run(input.chars.map(&:to_i))
if vars[?z].zero?
puts input
exit
end
end

@ -0,0 +1,262 @@
def run(input)
w, x, y, z = 0, 0, 0, 0
# w = input.shift
# x = z % 26
# z = (z / 1.to_f).floor
# x += 13
# x = x == w ? 0 : 1
# y = 25 * x + 1 # either y = 26 or y = 1
# z *= y # 0
# # p [w, x, y, z]
# y = (w + 13) * x
# z += y
# # p [w, x, y, z]
# # puts
# w = input.shift
# x = z % 26
# z = (z / 1.to_f).floor
# x += 11
# x = x == w ? 0 : 1
# y = 25 * x + 1
# z *= y
# # p [w, x, y, z]
# y = (w + 10) * x
# z += y
# # p [w, x, y, z]
# # puts
# w = input.shift
# x = z % 26
# z = (z / 1.to_f).floor
# x += 15
# x = x == w ? 0 : 1
# y = (25 * x) + 1
# z *= y
# # p [w, x, y, z]
# y = (w + 5) * x
# z += y
# # p [w, x, y, z]
# # puts
# w = input.shift
# x = z % 26
# z = (z / 26.to_f).floor
# x += -11
# x = x == w ? 0 : 1
# y = (25 * x) + 1
# z *= y
# # p [w, x, y, z]
# y = (w + 14) * x
# z += y
# # p [w, x, y, z]
# # puts
# return [w, x, y, z]
# w = input.shift
# x = z % 26
# z = (z / 1.to_f).floor
# x += 14
# x = x == w ? 0 : 1
# y = 25 * x + 1
# z *= y
# # p [w, x, y, z]
# y = (w + 5) * x
# z += y
# # p [w, x, y, z]
# # puts
# # puts
# w = input.shift
# x = z % 26
# z = (z / 26.to_f).floor
# x += 0
# x = x == w ? 0 : 1
# y = 25 * x + 1
# z *= y
# # p [w, x, y, z]
# y = (w + 15) * x
# z += y
# # p [w, x, y, z]
# # puts
# return [w, x, y, z]
# w = input.shift
# x = z % 26
# z = (z / 1.to_f).floor
# x += 12
# x = x == w ? 0 : 1
# y = 25 * x + 1
# z *= y
# # p [w, x, y, z]
# y *= 0
# y += w
# y += 4
# y *= x
# z += y
# # p [w, x, y, z]
# w = input.shift
# x *= 0
# x += z
# x %= 26
# z = (z / 1.to_f).floor
# x += 12
# x = x == w ? 1 : 0
# x = x == 0 ? 1 : 0
# y *= 0
# y += 25
# y *= x
# y += 1
# z *= y
# # p [w, x, y, z]
# y *= 0
# y += w
# y += 11
# y *= x
# z += y
# # p [w, x, y, z]
# w = input.shift
# x *= 0
# x += z
# x %= 26
# z = (z / 1.to_f).floor
# x += 14
# x = x == w ? 1 : 0
# x = x == 0 ? 1 : 0
# y *= 0
# y += 25
# y *= x
# y += 1
# z *= y
# # p [w, x, y, z]
# y *= 0
# y += w
# y += 1
# y *= x
# z += y
# # p [w, x, y, z]
# # puts
# # puts
# w = input.shift
# x *= 0
# x += z
# x %= 26
# z = (z / 26.to_f).floor
# x += -6
# x = x == w ? 1 : 0
# x = x == 0 ? 1 : 0
# y *= 0
# y += 25
# y *= x
# y += 1
# z *= y
# # p [w, x, y, z]
# y *= 0
# y += w
# y += 15
# y *= x
# z += y
# # p [w, x, y, z]
# return [w, x, y, z]
# w = input.shift
# x *= 0
# x += z
# x %= 26
# z = (z / 26.to_f).floor
# x += -10
# x = x == w ? 1 : 0
# x = x == 0 ? 1 : 0
# y *= 0
# y += 25
# y *= x
# y += 1
# z *= y
# # p [w, x, y, z]
# y *= 0
# y += w
# y += 12
# y *= x
# z += y
# # p [w, x, y, z]
# return [w, x, y, z]
w = input.shift
x *= 0
x += z
x %= 26
z = (z / 26.to_f).floor
x += -12
x = x == w ? 1 : 0
x = x == 0 ? 1 : 0
y *= 0
y += 25
y *= x
y += 1
z *= y
# p [w, x, y, z]
y *= 0
y += w
y += 8
y *= x
z += y
# p [w, x, y, z]
return [w, x, y, z]
w = input.shift
x = z % 26
z = (z / 26.to_f).floor
x += -3
x = x == w ? 0 : 1
y = 25 * x + 1
z *= y
# p [w, x, y, z]
y = (w + 14) * x
z += y
# p [w, x, y, z]
w = input.shift
x = z % 26 # z - 5 must be w
z = (z / 26.to_f).floor # z must be < 26
x += -5 # w must be x - 5
x = x == w ? 0 : 1 # x must be w
y = 25 * x + 1
z *= y # z must be 0
# p [w, x, y, z]
y = (w + 9) * x # x must be 0
z += y # y must be 0
[w, x, y, z]
end
# 99999999999999.downto(11111111111111).lazy.map(&:to_s).reject { _1.include?(?0) }.each do |input|
vars = run(input.chars.map(&:to_i))
p [input, vars[3]] if vars[3] < 400
if vars[3].zero?
puts input
exit
end
end

1
2022/.gitignore vendored

@ -0,0 +1 @@
day_*.txt

@ -0,0 +1,4 @@
Split {𝕩˜(-˜+`׬)0=¨𝕩}
ParseInt 10×+˜´-'0'
in ParseInt¨ ¨Split •Flines "../day_01.txt"
•Out¨ ,+´3 {𝕎𝕩}¨ <+´¨in

@ -0,0 +1,8 @@
Split {𝕩˜(-˜+`׬)0=¨𝕩}
Transpose ={<𝕨𝕨>𝕩}
OnlyCrates ('A'+26)/
RejectEmpty {((¨𝕩) > 0) / 𝕩}
stacks, moves Split •Flines "../day_05.txt"
stacks RejectEmpty OnlyCrates¨ Transpose stacks
•Show stacks

@ -0,0 +1,11 @@
# •Show 4 + ⊐⟜1 ⍷⊸≡¨ <˘ 4↕ •FChars "../day_06.txt"
# •Show 14 + ⊐⟜1 ⍷⊸≡¨ <˘ 14↕ •FChars "../day_06.txt"
n 4
input •FChars "../day_06.txt"
windows n input
uniq ˘ windows
index uniq 1
•Show n + index
# PktN←{𝕨+⊑1⊐˜(∧´∊)˘𝕨↕𝕩}

@ -0,0 +1 @@
Subproject commit b90e26c29b1742bf164b6121275b5e1ee8a56365

@ -0,0 +1,19 @@
(fn dbg [tbl]
(each [_ chunk (ipairs tbl)]
(print (accumulate [x "" _ i (ipairs chunk)]
(.. x ", " i)))))
(local input (accumulate [input [[]] line (io.lines :../day_01.txt)]
(do
(if (= (length line) 0)
(table.insert input [])
(table.insert (. input (length input)) (tonumber line)))
input)))
(fn sum [l]
(accumulate [sum 0 _ n (ipairs l)]
(+ sum n)))
(local l (icollect [_ l (ipairs input)] (sum l)))
(table.sort l)
(print (. l (length l)))

@ -0,0 +1,8 @@
# frozen_string_literal: true
source "https://rubygems.org"
gem "minitest"
gem "parslet"
gem "ruby-lsp"
gem "z3"

@ -0,0 +1,29 @@
GEM
remote: https://rubygems.org/
specs:
ffi (1.15.5)
language_server-protocol (3.17.0.2)
minitest (5.16.3)
parslet (2.0.0)
prettier_print (1.2.0)
ruby-lsp (0.3.7)
language_server-protocol (~> 3.17.0)
sorbet-runtime
syntax_tree (>= 4.0.2, < 5.0.0)
sorbet-runtime (0.5.10597)
syntax_tree (4.3.0)
prettier_print (>= 1.0.2)
z3 (0.0.20221020)
ffi (~> 1.9)
PLATFORMS
arm64-darwin-21
DEPENDENCIES
minitest
parslet
ruby-lsp
z3
BUNDLED WITH
2.3.18

@ -0,0 +1,2 @@
# p ARGF.read.split("\n\n").map { _1.each_line.map(&:to_i).sum }.max
p ARGF.read.split("\n\n").map { _1.each_line.map(&:to_i).sum }.sort[-3..-1].sum

@ -0,0 +1,14 @@
p ARGF.read.strip.lines(chomp: true).map(&:split).map {|a,b|
a = a.ord - ?A.ord
b = b.ord - ?X.ord
# part 2
b = (a + b - 1) % 3
outcome = case
when (a + 1) % 3 == b then 6
when a == b then 3
else 0
end
outcome + b + 1
}.sum

@ -0,0 +1,8 @@
priorities = (?a..?z).chain(?A..?Z).each.with_index.to_h { [_1, _2+1] }
input = ARGF.read.lines(chomp: true).map(&:chars)
# part 1
p input.sum { priorities.fetch(_1.each_slice(_1.length/2).inject(&:&)[0]) }
# part 2
p input.each_slice(3).sum { priorities.fetch(_1.inject(&:&)[0]) }

@ -0,0 +1,6 @@
p ARGF.read
.scan(/(\d+)-(\d+),(\d+)-(\d+)/)
.map { _1.map(&:to_i) }
.map {|a,b,c,d| [(a..b), (c..d)] }
# .count {|a,b| a.cover?(b) || b.cover?(a) } # part 1
.count {|a,b| a.minmax.any? { b.cover?(_1) } || b.minmax.any? { a.cover?(_1) }}

@ -0,0 +1,18 @@
setup, moves = ARGF.read.split("\n\n")
setup = setup
.lines(chomp: true)
.map(&:chars)
.transpose
.map {|col| col.select { _1 =~ /[A-Z]/ }}
.reject(&:empty?)
moves = moves.scan(/move (\d+) from (\d+) to (\d+)/).map { _1.map(&:to_i) }
moves.each do |n,from,to|
# n.times {
# setup[to-1].unshift(setup[from-1].shift)
# }
setup[to-1].unshift(*setup[from-1].shift(n))
end
p setup.map(&:first).join

@ -0,0 +1,2 @@
# p ARGF.read.chars.each_cons(4).with_index.find {|a,i| a.uniq.size == 4 }.last + 4
p ARGF.read.chars.each_cons(14).with_index.find {|a,i| a.uniq.size == 14 }.last + 14

@ -0,0 +1,61 @@
input = ARGF.read.lines(chomp: true)
Dir = Struct.new(:parent, :name, :children) do
def size = children.sum(&:size)
def each
return enum_for(__method__) unless block_given?
yield self
children.each do |child|
case child
when Dir
child.each { yield _1 }
when File
yield child
else
fail child.inspect
end
end
end
end
File = Struct.new(:parent, :name, :size)
root = Dir.new(nil, ?/, [])
pwd = root
input.each do |line|
case line
when /\$ cd \//
# no-op
when /\$ cd \.\./
pwd = pwd.parent
when /\$ cd (.+)/
pwd = pwd.children.find { _1.name == $1 }
when /\$ ls/
# no-op
when /dir (.+)/
pwd.children << Dir.new(pwd, $1, [])
when /(\d+) (.+)/
pwd.children << File.new(pwd, $2, $1.to_i)
else
fail line
end
end
# part 1
p root.each
.select { Dir === _1 }
.map(&:size)
.select { _1 < 100_000 }
.sum
# part 2
p root.each
.select { Dir === _1 }
.map(&:size)
.sort
.find { _1 >= 30_000_000 - (70_000_000 - root.size) }

@ -0,0 +1,34 @@
grid = ARGF.read.lines(chomp: true).map { _1.chars.map(&:to_i) }
def each(grid)
return enum_for(__method__, grid) unless block_given?
transposed = grid.transpose
grid.each.with_index do |row, y|
row.each.with_index do |tree, x|
col = transposed[x]
sight_lines = [
(0...x).map { row[_1] }.reverse,
(x+1...row.size).map { row[_1] },
(0...y).map { col[_1] }.reverse,
(y+1...row.size).map { col[_1] },
]
yield tree, sight_lines
end
end
end
p each(grid).count {|tree, sight_lines|
sight_lines.any? { _1.empty? || tree > _1.max }
}
p each(grid).map {|tree, sight_lines|
sight_lines
.map {|sl| sl.slice_after { _1 >= tree }.first }
.compact
.map(&:size)
.inject(:*)
}.max

@ -0,0 +1,44 @@
require "set"
motions = ARGF.read.scan(/([RLUD])\s+(\d+)/).map { [_1, _2.to_i] }
class Snake
def initialize
@knots = Array.new(10) { [0, 0] }
end
def tail = @knots.last
def move!(dir)
delta = case dir
when ?L then [ 0, -1]
when ?U then [ 1, 0]
when ?R then [ 0, 1]
when ?D then [-1, 0]
else fail dir.inspect
end
@knots[0] = @knots[0].zip(delta).map { _1 + _2 }
@knots = @knots[1..].inject([@knots[0]]) {|knots, tail|
head = knots.last
delta = head.zip(tail).map { _1 - _2 }
knots << if delta.any? { _1.abs > 1 }
tail.zip(delta.map { _1.clamp(-1, 1) }).map { _1 + _2 }
else
tail
end
}
end
end
snake = Snake.new
seen = Set.new
motions.each do |dir, distance|
distance.times do
snake.move!(dir)
seen << snake.tail
end
end
p seen.size

@ -0,0 +1,42 @@
instructions = ARGF.read.lines(chomp: true)
def exec(instructions)
return enum_for(__method__, instructions) unless block_given?
x = 1
instructions.each do |instruction|
case instruction
when /noop/
yield x
when /addx (-?\d+)/
yield x
yield x
x += $1.to_i
else
fail "invalid instruction: #{instruction}"
end
end
yield x
end
x_hist = exec(instructions).to_a
# part one
p 20.step(by: 40, to: 220).sum { x_hist[_1-1] * _1 }
# part two
puts x_hist.each_slice(40).map {|row|
row.each.with_index.map {|x, cycle|
(-1..1).cover?(cycle - x) ? ?# : ?.
}.join
}.join("\n")
# a functional version of part two, but I think
# the imperative version feels closer to the domain
#
# x_hist.each_slice(40) do |row|
# row.each.with_index do |x, cycle|
# putc (-1..1).cover?(cycle - x) ? ?# : ?.
# end
# puts
# end

@ -0,0 +1,48 @@
Monkey = Struct.new(:id, :items, :operation, :test, :t, :f) do
def throw_to(item)
(item % test).zero? ? t : f
end
end
MONKEY_RE = /Monkey (?<id>\d+):
Starting items: (?<items>(?~\n))
Operation: new = (?<op>(?~\n))
Test: divisible by (?<test>\d+)
If true: throw to monkey (?<t>\d+)
If false: throw to monkey (?<f>\d+)/m
monkeys = ARGF.read.split("\n\n").map {|monkey|
md = MONKEY_RE.match(monkey)
fail if md.nil?
Monkey.new(
md[:id].to_i,
md[:items].split(", ").map(&:to_i),
md[:op],
md[:test].to_i,
md[:t].to_i,
md[:f].to_i,
)
}
max_worry = monkeys.map(&:test).inject(:*)
inspections = Hash.new(0)
# 20.times do
10_000.times do
monkeys.each do |monkey|
until monkey.items.empty?
inspections[monkey.id] += 1
item = monkey.items.shift
old = item
item = eval(monkey.operation)
# item /= 3
item %= max_worry
to = monkey.throw_to(item)
monkeys[to].items << item
end
end
end
p inspections.values.max(2).inject(:*)

@ -0,0 +1,49 @@
class HeightMap
NEIGHBORS = [[0, -1], [-1, 0], [0, 1], [1, 0]]
def initialize(heights)
@heights = heights
end
def shortest(from:, to:, &cond)
frontier = [from]
visited = { from => 0 }
until frontier.empty? || to.any? { visited.has_key?(_1) }
current = frontier.shift
NEIGHBORS.each do |delta|
candidate = current.zip(delta).map { _1 + _2 }
next if visited.has_key?(candidate)
next unless cand_height = @heights[candidate]
next unless cond.(@heights.fetch(current), cand_height)
visited[candidate] = visited.fetch(current) + 1
frontier << candidate
end
frontier.sort_by { visited.fetch(_1) }
end
visited.find {|k,v| to.include?(k) }.last
end
end
heights = ARGF.read.lines(chomp: true).map(&:chars)
.flat_map.with_index {|row,y|
row.map.with_index {|height,x| [[y, x], height] }
}.to_h
s, e = heights.invert.values_at(?S, ?E)
heights[s] = ?a
heights[e] = ?z
hm = HeightMap.new(heights)
# part one
p hm.shortest(from: s, to: [e]) { _1.ord + 1 >= _2.ord }
# part two
as = heights.select { _2 == ?a }.map(&:first)
p hm.shortest(from: e, to: as) { _1.ord - 1 <= _2.ord }

@ -0,0 +1,37 @@
def compare(left, right)
case [left, right]
in [left, nil]
1
in [Integer, Integer]
left <=> right
in [Array, Array]
left.zip(right).each do |left, right|
case compare(left, right)
when -1 then return -1
when 0 # keep going
when 1 then return 1
end
end
(left.size == right.size) ? 0 : -1
else
compare(Array(left), Array(right))
end
end
# part one
pairs = ARGF.read.split("\n\n")
pairs = pairs.map {|pair| pair.lines(chomp: true).map { eval(_1) }}
p pairs.map.with_index
.select {|(l,r),_| compare(l, r) == -1 }
.sum { _1.last + 1 }
# part two
pairs = pairs.flatten(1)
dividers = [[[2]], [[6]]]
pairs.concat(dividers)
pairs = pairs.sort { compare(_1, _2) }
p dividers
.map { pairs.index(_1) + 1 }
.inject(:*)

@ -0,0 +1,52 @@
scan = ARGF.read.lines(chomp: true)
cave = scan.each.with_object({}) {|line, cave|
line.split(" -> ")
.map { _1.split(?,).map(&:to_i) }
.each_cons(2) {|(ax,ay),(bx,by)|
Range.new(*[ax, bx].sort).each do |x|
Range.new(*[ay, by].sort).each do |y|
cave[[x, y]] = ?#
end
end
}
}
def cave.to_s
x_min, x_max = keys.map(&:first).minmax
y_min, y_max = keys.map(&:last).minmax
(0..y_max+1).map {|y|
(x_min-1..x_max+1).map {|x|
self.fetch([x, y], ?.)
}.join
}.join("\n")
end
def pour_sand(cave, stop:)
return enum_for(__method__, cave, stop:) unless block_given?
loop do
# puts cave
pos = [500, 0]
while next_pos = [0, -1, 1].map {|dx| pos.zip([dx, 1]).map { _1 + _2 }}.find { cave[_1].nil? }
pos = next_pos
break if stop.(*pos)
end
break if stop.(*pos)
cave[pos] = ?o
yield pos
end
end
y_max = cave.keys.map(&:last).max
# part one
p pour_sand(cave, stop: ->(_, y) { y >= y_max }).count
# part two
cave.delete_if { _2 == ?o } # reset cave
cave.default_proc = ->(_,(_,y)) { y == y_max + 2 ? ?# : nil }
p pour_sand(cave, stop: ->(x, y) { [x, y] == [500, 0] }).count + 1

@ -0,0 +1,87 @@
require "set"
sensors_and_beacons = ARGF.read
.scan(/Sensor at x=(-?\d+), y=(-?\d+): closest beacon is at x=(-?\d+), y=(-?\d+)/)
.map { _1.map(&:to_i) }
.flatten
.each_slice(2)
# part one
row = 2_000_000
# row = 10
no_beacons = []
sensors_and_beacons.each_slice(2) do |sensor, beacon|
dist = sensor.zip(beacon).sum { (_1 - _2).abs }
dy = (row - sensor[1]).abs
next if dy > dist
dx = dist - dy
x_min, x_max = [sensor[0]-dx, sensor[0]+dx].sort
no_beacons << (x_min..x_max)
end
# remove covered ranges
no_beacons = no_beacons.reject {|x| (no_beacons - [x]).any? { _1.cover?(x) }}
# merge ranges
no_beacons = no_beacons.inject([no_beacons.shift]) {|no_beacons, range|
next no_beacons if no_beacons.any? { _1.cover?(range) }
if overlap = no_beacons.find { _1.cover?(range.begin) }
range = (overlap.end + 1..range.end)
end
if overlap = no_beacons.find { _1.cover?(range.end) }
range = (range.begin..overlap.begin-1)
end
no_beacons << range
}
p no_beacons.sum(&:size) - sensors_and_beacons.to_a.select { _2 == row }.uniq.size
# part two
find_sab = ->(x, y) {
sensors_and_beacons.each_slice(2).find {|sensor, beacon|
dist = sensor.zip(beacon).sum { (_1 - _2).abs }
dist >= sensor.zip([x, y]).sum { (_1 - _2).abs }
}
}
max = 4_000_000
# max = 20
x = 0
y = 0
loop do
p y if (y % 10_000).zero?
sensor, _ = find_sab.(x, y)
dx = sensor[0] - x
if dx >= max / 2
dy = sensor[1] - y
y += dy.positive? ? 2 * dy + 1 : 1
end
loop do
sensor, beacon = find_sab.(x, y)
if sensor.nil?
p 4_000_000 * x + y
exit
end
dist = sensor.zip(beacon).sum { (_1 - _2).abs }
dy = (sensor[1] - y).abs
dx = (dist - dy).abs
x = sensor[0] + dx + 1
if x > max
x = 0
break
end
end
y += 1
break if y > max
end

@ -0,0 +1,103 @@
require "set"
Valve = Data.define(:name, :flow_rate, :tunnels)
valves = ARGF.read.scan(/Valve (.+) has flow rate=(\d+); tunnels? leads? to valves? ((?~\n))/)
.map {|name, flow_rate, tunnels|
Valve.new(name, flow_rate.to_i, tunnels.split(", "))
}
Network = Data.define(:valves) do
def initialize(*)
@connections = Hash.new {|h,start|
current = [[start]]
result = { start => %w[ AA ] }
until current.empty?
path = current.shift
links = valves.fetch(path.last).tunnels
.reject { result.has_key?(_1) }
.map { path + [_1] }
result.merge!(links.to_h { [_1.last, _1] })
current.concat(links)
end
h[start] = result
}
super
end
def connections(start) = @connections[start]
end
Move = Data.define(:reward, :target, :path) do
def cost = path.length
end
State = Data.define(:net, :current, :max, :turn, :pressure, :opened) do
def best_moves(best)
best_state = self
best[opened] = [best.fetch(opened, pressure), pressure].max
moves.each do |move|
next_state = applied(move)
next_state = next_state.best_moves(best);
if next_state.pressure > best_state.pressure
best_state = next_state
end
end
best_state
end
def applied(move)
self.class.new(
net,
move.target,
max,
turn + move.cost,
pressure + move.reward,
Set[*opened, move.target],
)
end
def moves
return enum_for(__method__) unless block_given?
net
.connections(current)
.reject { opened.include?(_1) }
.each do |name, path|
flow = net.valves.fetch(name).flow_rate
reward = flow * (turns_left - path.length)
if reward.positive?
yield Move.new(reward, name, path)
end
end
end
def turns_left = max - turn
end
network = Network.new(valves.to_h { [_1.name, _1] })
# part 1
# state = State.new(network, "AA", 30, 0, 0, [])
# best_state = state.best_moves({})
# pp best_state
# part 2
state = State.new(network, "AA", 26, 0, 0, [])
best = {}
state.best_moves(best)
pp best
.transform_keys(&:to_set)
.to_a
.combination(2)
.select { _1[0].disjoint?(_2[0]) }
.map { _1[1] + _2[1] }
.max

@ -0,0 +1,89 @@
require "set"
rocks = <<~ROCKS.split("\n\n")
####
.#.
###
.#.
..#
..#
###
#
#
#
#
##
##
ROCKS
rocks = rocks
.map {|rock| rock.lines(chomp: true).reverse.map(&:chars) }
.map {|rock|
rock.each.with_index.with_object(Set.new) {|(row, y), rocks|
row.each.with_index do |c, x|
rocks << [x, y] if c == ?#
end
}
}
rocks = rocks.cycle
jet_pattern = ARGF.read.strip.chars
jet_pattern = jet_pattern.cycle
chamber = Hash.new {|_,(x,y)| !(0...7).cover?(x) || y.negative? }
def move_rock(chamber, rock, dx, dy)
next_rock = rock.map {|x,y| [x+dx, y+dy] }
if next_rock.any? {|x,y| chamber[[x, y]] }
rock
else
next_rock
end
end
def debug(chamber, rock)
max_y = [chamber.keys.map(&:last).max || 0, rock.map(&:last).max || 0].max
puts
puts max_y.downto(0).map {|y|
(0...7).map {|x|
(chamber[[x,y]] || rock.include?([x,y])) ? ?# : ?.
}.join
}.join("\n")
end
2022.times do
rock = rocks.next
y = chamber.empty? ? 3 : chamber.keys.map(&:last).max + 4
x = 2
rock = move_rock(chamber, rock, x, y)
loop do
rock = case jet = jet_pattern.next
when ?< then move_rock(chamber, rock, -1, 0)
when ?> then move_rock(chamber, rock, 1, 0)
else fail "invalid jet pattern: #{jet}"
end
next_rock = move_rock(chamber, rock, 0, -1)
break if rock == next_rock
rock = next_rock
end
chamber.merge!(rock.to_h { [_1, true] })
end
# debug(chamber, Set.new)
max_y = chamber.keys.map(&:last).max + 1
p max_y
candidates = (0..max_y).select {|y| (0...7).count {|x| chamber[[x,y]] } == 6 }
# max_delta = candidates.each_cons(2).map { _2 - _1 }.max
candidates.
p candidates
p max_delta

@ -0,0 +1,50 @@
cubes = ARGF.read.lines(chomp: true).map { _1.split(?,).map(&:to_i) }
# part one
# p cubes.sum {|cube|
# 6 - cubes.count {|other|
# cube.zip(other).map { _1 - _2 }.map(&:abs).sum == 1
# }
# }
deltas = [
[-1, 0, 0],
[ 1, 0, 0],
[ 0, -1, 0],
[ 0, 1, 0],
[ 0, 0, -1],
[ 0, 0, 1],
]
bounds = cubes.transpose.map(&:minmax).map {|(min, max)| (min-1..max+1) }
cubes = cubes.to_h { [_1, true] }
corners = [
[bounds[0].begin, bounds[1].begin, bounds[2].begin],
[bounds[0].begin, bounds[1].begin, bounds[2].end],
[bounds[0].begin, bounds[1].end, bounds[2].begin],
[bounds[0].begin, bounds[1].end, bounds[2].end],
[bounds[0].end, bounds[1].begin, bounds[2].begin],
[bounds[0].end, bounds[1].begin, bounds[2].end],
[bounds[0].end, bounds[1].end, bounds[2].begin],
[bounds[0].end, bounds[1].end, bounds[2].end],
]
frontier = [corners[0]]
seen = Hash.new
until frontier.empty?
current = frontier.shift
neighbors = deltas.map {|delta| current.zip(delta).map { _1 + _2 }}
.select {|neighbor| bounds.zip(neighbor).all? {|(bound, i)| bound.cover?(i) }}
seen[current] = neighbors.any? { cubes.has_key?(_1) }
frontier.concat(neighbors.reject {|neighbor| seen.has_key?(neighbor) || cubes.has_key?(neighbor) })
frontier.uniq!
end
p cubes.keys.sum {|cube|
neighbors = deltas.map {|delta| cube.zip(delta).map { _1 + _2 }}
neighbors.count { seen.has_key?(_1) }
}

@ -0,0 +1,92 @@
SEEN = []
class Factory
attr_reader :time, :robots, :resources
def initialize(
blueprint,
time=0,
robots={ ore: 1, clay: 0, obsidian: 0, geode: 0 },
resources={ ore: 0, clay: 0, obsidian: 0, geode: 0 }
)
@blueprint = blueprint
@time = time
@robots = robots
@resources = resources
end
def max_geodes
if @time == 20
pp self if @robots.values_at(:ore, :clay, :obsidian, :geode) == [1, 4, 2, 1]
return @resources.fetch(:geode)
end
resources = @resources.merge(@robots) { _2 + _3 }
branches = @blueprint.filter_map {|robot, cost|
if cost.all? {|res, qty| @resources.fetch(res) >= qty }
Factory.new(
@blueprint,
@time + 1,
@robots.merge({robot => 1}) { _2 + _3 },
resources.merge(cost) { _2 - _3 },
)
else
nil
end
}
if @blueprint.any? {|_, cost| cost.any? {|res, qty| @robots.fetch(res) > 0 && @resources.fetch(res) < qty }}
pp self
branches << Factory.new(@blueprint, @time + 1, @robots, resources)
end
branches = branches.reject {|factory|
SEEN.any? {|other|
%i[ ore clay obsidian geode ].all? {|res|
factory.robots.fetch(res) <= other.robots.fetch(res) &&
factory.resources.fetch(res) <= other.resources.fetch(res) &&
factory.time >= other.time
}
}
}
SEEN.concat(branches)
return @resources.fetch(:geode) if branches.empty?
branches.map(&:max_geodes).max
end
def to_s
"<time: #@time robots: #{@robots.values} resources: #{@resources.values}>"
end
alias_method :inspect, :to_s
end
blueprints = ARGF.read
.split("\n\n").map { _1.lines(chomp: true).join }
.map { _1.scan(/\d+/).map(&:to_i) }
.map {
_1.shift # id
{
ore: {ore: _1.shift },
clay: {ore: _1.shift },
obsidian: {ore: _1.shift, clay: _1.shift },
geode: {ore: _1.shift, obsidian: _1.shift },
}
}
p Factory.new(blueprints[0]).max_geodes
p SEEN.count
__END__
Blueprint 1:
Each ore robot costs 4 ore.
Each clay robot costs 2 ore.
Each obsidian robot costs 3 ore and 14 clay.
Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2:
Each ore robot costs 2 ore.
Each clay robot costs 3 ore.
Each obsidian robot costs 3 ore and 8 clay.
Each geode robot costs 3 ore and 12 obsidian.

@ -0,0 +1,19 @@
list = ARGF.read.lines(chomp: true).map(&:to_i)
list = list.map { _1 * 811589153 }
list = list.map.with_index { [_2, _1] }
10.times do
(0...list.size).each do |i|
j = list.index {|ii,_| ii == i }
_, n = list.delete_at(j)
j += n
j %= list.size
list.insert(j, [i, n])
end
end
list = list.map(&:last)
i = list.index(0)
p [1000, 2000, 3000].sum { list.fetch((i + _1) % list.size) }

@ -0,0 +1,100 @@
monkeys = ARGF.read.lines(chomp: true).to_h {|line| line.split(": ") }
# part one
# monkeys.each do |name, body|
# define_method(name) do
# eval(body)
# end
# end
# p root
# part two
sub_monkeys = monkeys.delete("root").split(" + ")
monkeys.delete("humn")
require "z3"
solver = Z3::Solver.new
solver.assert Z3.Int(sub_monkeys[0]) == Z3.Int(sub_monkeys[1])
monkeys.each do |name, job|
a, op, b = job.split(" ")
if op.nil?
solver.assert Z3.Int(name) == a.to_i
else
a = a =~ /^\d+$/ ? a.to_i : Z3.Int(a)
b = b =~ /^\d+$/ ? b.to_i : Z3.Int(b)
solver.assert Z3.Int(name) == a.send(op, b)
end
end
fail unless solver.satisfiable?
p solver.model[Z3.Int("humn")]
exit
# original part two
monkeys.each do |name, body|
define_method(name) do
eval(body)
end
end
target, unknown = sub_monkeys.partition { eval(_1) rescue nil}.map(&:first)
target = eval(target)
monkeys = monkeys.to_h {|monkey, job|
a, op, b = job.split(" ")
[monkey, { op:, a:, b: }]
}
monkeys["humn"] = { op: :humn }
def apply(monkeys, monkey)
job = monkeys.fetch(monkey)
case op = job.fetch(:op)
when nil
job.fetch(:a).to_i
when :humn
:humn
else
a = apply(monkeys, job.fetch(:a))
b = apply(monkeys, job.fetch(:b))
if a.is_a?(Integer) && b.is_a?(Integer)
eval([a, op, b].join(" "))
else
[job.fetch(:op), a, b]
end
end
end
tree = apply(monkeys, unknown)
def reverse(target, tree)
loop do
case tree
in :humn
return target
in [op, Integer => a, b]
case op
when ?* then target /= a
when ?+ then target -= a
when ?- then target = a - target
else fail tree.inspect
end
tree = b
in [op, a, Integer => b]
case op
when ?- then target += b
when ?/ then target *= b
when ?* then target /= b
when ?+ then target -= b
else fail tree.inspect
end
tree = a
else
fail tree.inspect
end
end
end
p reverse(target, tree)

@ -0,0 +1,78 @@
require "strscan"
include Math
map, path = ARGF.read.chomp.split("\n\n")
map = map.split("\n").each.with_index.with_object({}) {|(row,y),map|
row.chars.each.with_index do |tile,x|
map[[y,x]] = tile if tile != " "
end
}
max_y = map.keys.map(&:first).max
max_x = map.keys.map(&:last).max
start_x = map.keys.select { _1.first.zero? }.map(&:last).min
current = [0, start_x]
facing = 0
ss = StringScanner.new(path)
until ss.eos?
case
when n = ss.scan(/\d+/)
n = n.to_i
n.times do
y, x = current.zip([-sin(facing),cos(facing)]).map { _1 + _2 }.map(&:to_i)
next_tile = map[[y,x]]
unless next_tile
puts
p [y,x, facing]
y, x = case facing
when 0 then [y, 0]
when PI/2 then [max_y, x]
when PI then [y, max_x]
when 3*PI/2 then [0, x]
else fail "unexpected facing: #{facing}"
end
next_tile = map[[y,x]]
while next_tile.nil?
y, x = [y, x].zip([-sin(facing),cos(facing)]).map { _1 + _2 }.map(&:to_i)
next_tile = map[[y,x]]
end
p [y,x,next_tile]
end
case next_tile
when ?.
current = [y,x]
when ?#
break
else
fail "unexpected tile: #{next_tile}"
end
end
when dir = ss.scan(/R|L/)
facing += case dir
when ?R then -PI/2
when ?L then PI/2
else fail "unexpected dir: #{dir}"
end
facing %= 2*PI
else
fail ss.rest
end
end
row, col = current.map { _1 + 1 }
facing = case facing
when 0 then 0
when PI/2 then 3
when PI then 2
when 3*PI/2 then 2
else
fail "unexpected facing: #{facing}"
end
p [1000, 4, 1].zip([row, col, facing]).sum { _1 * _2 }

@ -0,0 +1,50 @@
grove = {}
ARGF.read.lines(chomp: true).each.with_index do |row, y|
row.chars.each.with_index do |c, x|
grove[[y,x]] = c == ?#
end
end
dirs = [
[[-1, -1], [-1, 0], [-1, 1]],
[[ 1, -1], [ 1, 0], [ 1, 1]],
[[-1, -1], [ 0, -1], [ 1, -1]],
[[-1, 1], [ 0, 1], [ 1, 1]],
]
(1..).each do |i|
proposals = grove.select { _2 }
.to_h {|(y,x),_|
to = if dirs.flatten(1).none? {|dy,dx| grove[[y+dy, x+dx]] }
[y, x]
elsif dir = dirs.find {|adj| adj.none? {|dy,dx| grove[[y+dy, x+dx]] }}
dy, dx = dir[1]
[y+dy, x+dx]
else
[y, x]
end
[[y,x], to]
}
proposals.each.with_object(Hash.new {|h,k| h[k] = []}) {|(from, to), conflicts|
conflicts[to] << from
}.select { _2.size > 1 }.values.flatten(1).each do |elf|
proposals[elf] = elf
end
if proposals.all? { _1 == _2 }
puts i
exit
end
proposals.each do |from, to|
grove[from] = false
grove[to] = true
end
dirs.push(dirs.shift)
end
# y = grove.select { _2 }.keys.map(&:first).minmax
# x = grove.select { _2 }.keys.map(&:last).minmax
# p Range.new(*y).sum {|y| Range.new(*x).count {|x| !grove[[y,x]] }}

@ -0,0 +1,93 @@
require "set"
walls = Set.new
blizzards = Hash.new {|h,k| h[k] = Set.new }
clear_ground = Set.new
ARGF.read.lines(chomp: true).each.with_index do |row, y|
row.chars.each.with_index do |pos,x|
case pos
when ?#
walls.add([y,x])
when /[v^<>]/
blizzards[pos].add([y,x])
when ?.
clear_ground.add([y,x])
else
fail pos
end
end
end
x_range = Range.new(*walls.map(&:last).minmax)
y_range = Range.new(*walls.map(&:first).minmax)
debug = ->() do
puts
puts y_range.map {|y|
x_range.map {|x|
if walls.include?([y,x])
?#
elsif blizzards.any? {|_,pos| pos.include?([y,x])}
b = blizzards.select {|_,pos| pos.include?([y,x])}
(b.size == 1) ? b.keys[0] : b.size
else
?.
end
}.join
}.join("\n")
end
start = [0, clear_ground.find {|y,x| y == 0 }.last]
goal = [y_range.end, clear_ground.find {|y,x| y == y_range.end }.last]
dir_deltas = {
?^ => [-1, 0],
?v => [ 1, 0],
?< => [ 0, -1],
?> => [ 0, 1],
}
moves = [*dir_deltas.values, [0, 0]]
frontier = [start]
(1..).each do |time|
if (time % 1).zero?
puts time
# p frontier
# debug.()
end
blizzards = blizzards.to_h {|dir,positions|
delta = dir_deltas.fetch(dir)
edges, positions = positions
.map {|pos| pos.zip(delta).map { _1 + _2 }}
.partition { walls.include?(_1) }
positions.concat(edges.map {|(y,x)|
case dir
when ?^ then [y_range.end - 1, x]
when ?v then [y_range.begin + 1, x]
when ?< then [y, x_range.end - 1]
when ?> then [y, x_range.end + 1]
else fail dir
end
})
[dir, positions]
}
clear_ground = y_range.map {|y| x_range.map {|x| [y, x] }}.flatten(1)
.reject {|pos| walls.include?(pos) || blizzards.any? { _2.include?(pos) }}
options = frontier.map {|current|
moves.filter_map {|delta|
pos = current.zip(delta).map { _1 + _2 }
clear_ground.include?(pos) && pos
}
}.flatten(1)
frontier = options.uniq
if frontier.include?(goal)
puts time + 1
exit
end
end

@ -0,0 +1,29 @@
places = (0..).lazy.map { 5 ** _1 }
digits = { ?- => -1, ?= => -2 }
sum = ARGF.read.lines(chomp: true)
.map {|snafu|
snafu.reverse.chars
.map { digits.fetch(_1, _1.to_i) }
.zip(places)
.map { _1 * _2 }
.sum
}.sum
n_places = places.slice_after { 2*_1 >= sum }.take(1).to_a.flatten.reverse
require "z3"
solver = Z3::Solver.new
n_places.each do |place|
solver.assert Z3.Int(place.to_s) <= 2
solver.assert Z3.Int(place.to_s) >= -2
end
solver.assert n_places.map { _1 * Z3.Int(_1.to_s) }.sum == sum
fail unless solver.satisfiable?
p n_places
.map { solver.model[Z3.Int(_1.to_s)].to_i }
.map { digits.invert.fetch(_1, _1) }
.join

@ -0,0 +1,30 @@
require "minitest/autorun"
def exec(instructions)
return enum_for(__method__, instructions) unless block_given?
x = 1
instructions.each do |instruction|
case instruction
when /noop/
yield x
when /addx (-?\d+)/
yield x
yield x
x += $1.to_i
else
fail "invalid instruction: #{instruction}"
end
end
yield x
end
class TestDay10 < Minitest::Test
def test_example
assert_equal [1, 1, 1, 4, 4, -1], exec(<<~PROG.lines(chomp: true)).to_a
noop
addx 3
addx -5
PROG
end
end

@ -0,0 +1,61 @@
require "bundler/setup"
require "minitest/autorun"
require "parslet"
Monkey = Struct.new(:id, :items, :operation, :test, :t, :f) do
def throw_to(item)
(item % test).zero? ? t : f
end
end
class MonkeyParser < Parslet::Parser
rule(:num) { match("[0-9]").repeat.as(:num) }
rule(:space) { match("\\s").repeat }
rule(:newline) { str("\n") }
rule(:monkey) {
space >> str("Monkey ") >> num.as(:id) >> str(":") >>
space >> str("Starting items: ") >> ( num >> ( str(", ") >> num ).repeat ).as(:items) >>
space >> str("Operation: new = ") >> (newline.absent? >> any).repeat.as(:op) >>
space >> str("Test: divisible by ") >> num.as(:test) >>
space >> str("If true: throw to monkey ") >> num.as(:true) >>
space >> str("If false: throw to monkey ") >> num.as(:false) >>
space
}
rule(:monkeys) { monkey.repeat }
root(:monkeys)
end
class MonkeyTransform < Parslet::Transform
rule(num: simple(:x)) { x.to_i }
rule(
id: simple(:id),
items: sequence(:items),
op: simple(:op),
test: simple(:test),
true: simple(:t),
false: simple(:f),
) {
Monkey.new(id, items, op, test, t, f)
}
end
class TestDay11 < Minitest::Test
def test_day_11
tree = MonkeyParser.new.parse(<<~MONKEY)
Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
MONKEY
monkeys = MonkeyTransform.new.apply(tree)
assert_equal [Monkey.new(0, [79, 98], "old * 19", 23, 2, 3)], monkeys
end
end

File diff suppressed because it is too large Load Diff

@ -0,0 +1,140 @@
.....................#......#...................#...............#........................................#..................................
...........................................................#.............................................................#..................
.....................................................................#.........#......#...........#.............#...........................
.....................................................#.......................................#..............................................
......#.................................#..........................................................................................#........
....................#.........#.............................................................................#...............................
..#.........................................................#.............................................................................#.
........................................................................................#...........#..................#....................
........#....................................#........................#.........................................................#...........
..............................................................................#................................#............................
..................................................#............#............................................................................
.........................#......#........#................................................#..........................................#......
......#..............................................................................#...............#......................................
...................................................................#........................................................................
....................#...........................#............................................................#..............#.....#.........
..................................#....................#.........................................#......#..............................#....
.#..........................................................................................................................................
........#.....#........................#...........#.............#.....................#....................................................
..........................#.................................#.....................#.........................................................
.............................................................................................................................#.............#
...................................#......................................................#....................#............................
.....................#...................#............#..................#.............................................#...........#........
..............................................................................................#.............................................
....#..........#...............#..........................................................................#.................................
.............................................#..............................................................................................
...................................................................#..............#.................................#.......................
..................#........................................................#................................................................
..#.................................#...................#..............................#.........................................#.......#..
...............................................................#...............#.....................#..........#.........#.................
.........#......................#.............................................................#.............................................
..............#...............................#.............................................................................................
........................................#.................................#............................................................#....
..............................................................................................................#......#......#...............
.........................#..........#.............................................#........#................................................
....................................................................#.....................................#.................................
....#...............#........#...............................#........................#........................................#............
........................................................#...................................................................................
............................................#...........................#......................#.....#......................................
.........................................................................................#.............................................#....
...........#....................#..................................#.................................................#...........#..........
.#..........................................................................................................................................
................#........................#..........#.......................................................................................
........................#........................................................................................#..........................
........................................................................#.........#...................#...................#.................
........................................................#......................................................................#............
.....#.....................................................................................#................................................
...............#...................................#.................#..............................................................#.......
.........#..................#..................................#..................................................#.........................
......................................#.......#....................................#......................................................#.
..........................................................................................................#......................#..........
...#..............#.......................#.....................................................#...........................................
................................#...............................................#..........#................................................
..........................#......................#......................#...................................................................
..................................................................#................................#........................................
......................................................#.................................#.........................#...................#.....
..............#..........................#..................................................................................#...............
......#......................#.................................................................#...........#................................
.............................................................................#..............................................................
.......................#..........................#......................................................................#..........#.......
.#.................................#................................................................#....................................#..
........#......#................................................#...............................................#...........................
..........................................................................#.....#.........................#...........#.....#...............
............................#..............#..........#....................................#................................................
............................................................................................................................................
............#..........#....................................................................................................................
............................................................#.......................#..............#........................................
.....................................#...............................#...................................#..................................
.........#.....................................................................#.....................................#...............#.....#
#.............#.............................................................................................................................
......................................................#....................................#....................................#...........
...................................................................#............................................#...........................
............................................................................................................................................
....................#............................#................................................#......................................#..
.............................#...................................................#..........................................................
.........................................................................#...............#.................#................................
.............#.........#.........#.....#......................#............................................................#................
............................................................................................................................................
.............................................#..........#.....................#..................................#..........................
............................................................................................................................................
...................................#.............#................#.....#.....................................................#.............
....#.....................#..................................#..............................................................................
............................................................................................................................................
#.....................................#...................................................................................#.................
...............................................#......................#.....#...................................#...........................
.........#...................#.....................................................#.................#......................................
.......................#...............................#........................................#..............................#............
...#.....................................#..................................................................#...............................
...................................................#......................................#...........................................#.....
.................#..........................................................................................................................
...................................................................................................................#......#.................
.................................#..............#.....#......................#.................#.........#..................................
#....................................................................#........................................#...........................#.
............................................................................................................................................
.........................#..................................................................................................................
...............................#.......................................................................................#....................
..........#...................................#..................#.....................#....................#...............................
............................................................................#.....#.........................................................
....#............#............................................................................#.......#..........#..........................
..................................................................................................................................#.........
...................................#...........................................#............................................................
.............................#..........................#.................................#........#........................................
..............#....................................................#........................................#.............#...........#.....
...............................................#.............#.......................................................#......................
........#..............................................................#....................................................................
.......................................................................................#........#...........................................
......................#........#.........................#..................#........................#......................#...............
.#.........#.....#..............................................#........................................................................#..
.....................................................#......................................................................................
.........................................#...........................#..............................................#.......................
.............................................................#................................................#................#............
......#.......................................#.......................................#...............#.....................................
....................#.......#............................#................#...........................................................#.....
...........#.....................................................................................................#..........................
..........................................................................................#..............#..................................
..................................................#..........................................................................#..............
...............#............................................#.....................................................................#.........
........................#...........................................#............................#..................#.......................
................................................................................#..............................#.......................#....
......................................#...................................#..............#..............#...................................
..#............................................#..............#...........................................................#.................
.........#........................#...................#.....................................................................................
.............................#..............................................................................................................
....................................................................................#.......................................................
.........................#.............#............................................................#......#......#.........#......#........
...................#...........................................................................#...........................................#
.......#...............................................#.....#........#..........#..........................................................
..............#....................#........................................................................................................
........................................................................................................#.................#...........#.....
..#...............................................................#.........#.......#.......................................................
.........#......................#..........................#.....................................#............#.............................
...................#.................................#.................................................................#....................
....................................#.......................................................................................................
...........................#......................................................................................................#.........
............................................#.................#............#...................#.......#...................#................
............#.....................................#.........................................................................................
...........................................................................................................#......#.........................
.....................................#..............................................#......#................................................
.........................................................................#..............................................#...................
#....................#........#...................................................................#.....................................#...
.....#........................................#.........#........................#..........................................................

@ -0,0 +1,4 @@
source "https://rubygems.org"
gem "minitest"
gem "rake"

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save