Compare commits

...

38 Commits

Author SHA1 Message Date
3c1a48fe51 Day 22 part 2 2022-10-08 17:05:14 +02:00
0f9d48314e Day 16 part 2 2022-10-08 15:47:26 +02:00
14fc032ffc Day 25 part 1 2022-10-08 12:47:58 +02:00
0089f4337c Day 23 part 2 2022-10-03 09:04:41 +02:00
c8cef9c0ce Extended IntCodeComputer. 2022-10-03 09:03:31 +02:00
420b6152fb day 23 part 1 2022-10-02 19:57:00 +02:00
79ea3c29d0 day20 format 2022-10-02 17:49:00 +02:00
e87d31c941 day20 cleanup 2022-10-02 17:48:35 +02:00
6e06599c33 day20 part 2 2022-10-02 17:46:33 +02:00
3b829649f3 day20 refactored for part 2 - currying 2022-10-02 16:54:45 +02:00
922f2a483c day20 refactored for part 2 2022-10-02 14:17:08 +02:00
4002297ede day20 refactored for part 2 2022-10-02 14:05:24 +02:00
9a34cca688 day20 part 1 2022-10-02 13:19:36 +02:00
358e185501 day20 shortest path to come 2022-10-02 11:28:33 +02:00
eeda13a0d6 day19 format 2022-10-02 11:06:40 +02:00
1686c8a28c day19 cleanup 2022-10-01 23:01:41 +02:00
7724b14053 added idea to git ignore 2022-10-01 22:58:33 +02:00
6ba67d568c day19 cleanup 2022-10-01 22:56:08 +02:00
3c72884fac day19 part 2 2022-10-01 22:43:37 +02:00
3992bf2e58 day19 part 1 2022-10-01 21:02:51 +02:00
357c5d42cc refactoring 2022-09-25 10:46:09 +02:00
f5e98e2851 day 16 added tests 2022-09-25 10:36:32 +02:00
Johannes
126833bbaa Day 22 part 2. 2022-03-23 20:23:18 +01:00
Johannes
333d99539d Update dependencies. 2022-03-21 21:58:56 +01:00
Johannes
49b43a4fed Switch to rust edition 2021. 2022-03-20 20:12:07 +01:00
Johannes
39e2e27533 day 22 task 1 2022-03-20 20:09:20 +01:00
Johannes
d18cfca5ed little cleaning of day 18 2020-01-05 16:19:05 +01:00
Johannes
91e7a8f3fc day24 task 2 2019-12-30 14:24:07 +01:00
Johannes
ece3b0ee29 day 24 task 1 2019-12-26 13:17:20 +01:00
Johannes
a5019f1afb day 17 task 2 for my input only 2019-12-25 22:26:36 +01:00
Johannes
d590b1ad1a day 17 task 1 2019-12-25 21:50:38 +01:00
Johannes
c726b9090f day 18 task 2 2019-12-25 16:12:33 +01:00
Johannes
7b51854bb2 day 18 task 1 2019-12-22 14:11:23 +01:00
Johannes
51f16fa7ad day 16 task 1 and not working idea of task 2... 2019-12-22 11:43:14 +01:00
Johannes
3f6aec0d67 day 15 task 2 2019-12-21 23:14:30 +01:00
Johannes
73b612d25b day 15 task 1 2019-12-21 23:08:59 +01:00
Johannes
73e4d50c51 easier loading of IntCodeComputer program and single step function 2019-12-21 23:08:35 +01:00
Johannes
ddd215c9a2 day 21 task 2 2019-12-21 12:30:00 +01:00
28 changed files with 2447 additions and 49 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/target
**/*.rs.bk
.vscode
.idea

137
Cargo.lock generated
View File

@@ -1,100 +1,149 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.6"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr",
]
[[package]]
name = "aoc_2019"
version = "0.1.0"
dependencies = [
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools",
"mod_exp",
"modinverse",
"num-integer",
"regex",
]
[[package]]
name = "autocfg"
version = "0.1.7"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "either"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
[[package]]
name = "itertools"
version = "0.8.2"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
dependencies = [
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"either",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memchr"
version = "2.2.1"
name = "mod_exp"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb4a3fad6af79fcf8d1417b2f6359d814a173fb413a1bd48ba04208b42b0d8b0"
dependencies = [
"num",
]
[[package]]
name = "modinverse"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f62f577f148cc1a9466e7065a22e59466a7d537cceba5e77e57181d0f706633"
dependencies = [
"num-integer",
]
[[package]]
name = "num"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36"
dependencies = [
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.41"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.10"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"autocfg",
]
[[package]]
name = "regex"
version = "1.3.1"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.12"
version = "0.6.25"
source = "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.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"

View File

@@ -2,11 +2,13 @@
name = "aoc_2019"
version = "0.1.0"
authors = ["Johannes <jschaef@mail.uni-paderborn.de>"]
edition = "2018"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
itertools = "0.8.2"
regex = "1.3.1"
num-integer = "0.1"
itertools = "0.10.3"
regex = "1.5.5"
num-integer = "0.1.44"
modinverse = "0.1.1"
mod_exp = "1.0.1"

1
input/day15.txt Normal file
View File

@@ -0,0 +1 @@
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1001,1034,0,1039,1002,1036,1,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1106,0,124,1001,1034,0,1039,102,1,1036,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,102,1,1035,1040,1002,1038,1,1043,101,0,1037,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,102,1,1035,1040,1001,1038,0,1043,101,0,1037,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,33,1032,1006,1032,165,1008,1040,33,1032,1006,1032,165,1101,0,2,1044,1106,0,224,2,1041,1043,1032,1006,1032,179,1102,1,1,1044,1105,1,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,42,1044,1106,0,224,1102,0,1,1044,1106,0,224,1006,1044,247,1001,1039,0,1034,1001,1040,0,1035,1001,1041,0,1036,1001,1043,0,1038,102,1,1042,1037,4,1044,1106,0,0,6,28,51,33,63,27,52,11,53,13,96,8,87,11,23,65,43,11,13,9,37,66,68,40,19,41,6,90,28,19,38,86,38,22,7,44,36,23,17,1,16,54,36,74,14,79,2,14,83,10,38,19,62,66,27,56,33,52,47,98,41,39,77,83,48,29,49,15,80,59,9,72,79,55,24,66,50,24,27,56,37,41,13,72,35,13,64,70,5,66,78,37,78,24,43,93,22,41,30,58,14,45,6,27,44,48,40,52,31,12,3,72,7,14,59,35,17,63,34,79,93,17,54,98,35,21,91,25,32,77,10,31,88,17,35,79,96,11,83,15,48,9,19,64,24,65,86,32,71,22,88,55,31,18,88,68,34,40,94,1,71,24,40,44,28,43,4,98,21,80,17,53,2,94,6,43,59,23,66,63,12,30,45,39,93,41,85,43,51,18,99,59,86,40,36,26,94,33,41,28,66,79,81,11,61,46,32,72,71,47,39,22,69,60,36,50,12,44,28,41,79,17,6,74,8,56,39,33,67,23,20,51,12,7,26,57,1,92,80,11,52,19,5,54,13,41,56,37,22,57,43,18,97,27,83,30,3,77,85,66,64,17,99,27,25,95,40,81,97,13,35,46,14,25,63,36,72,87,20,96,29,2,69,90,27,27,91,52,14,14,73,55,4,73,19,85,39,84,23,23,90,40,5,88,53,77,8,92,11,82,66,6,27,84,53,38,93,34,37,58,20,43,25,73,78,30,17,92,54,38,26,67,16,30,28,79,77,26,3,15,82,59,34,34,18,44,34,33,83,35,90,31,58,44,16,18,65,8,70,90,32,46,21,41,54,39,43,93,23,99,11,43,50,98,33,34,53,54,53,16,39,88,53,36,69,85,26,44,38,62,98,6,79,26,35,49,67,22,11,74,35,80,4,50,18,54,4,10,4,58,4,46,20,15,77,73,11,41,58,85,39,87,37,73,36,36,67,28,12,17,34,53,38,89,96,34,39,67,64,33,81,37,74,88,20,84,94,53,39,57,73,13,76,1,35,14,73,29,29,23,73,52,16,85,87,33,48,13,2,93,78,7,17,60,49,13,36,89,40,25,44,55,26,81,37,31,84,31,62,2,66,77,23,88,11,81,9,63,46,19,35,54,17,85,24,1,86,28,72,1,1,61,27,38,81,8,67,82,3,11,77,35,62,83,20,28,61,37,37,92,22,72,76,37,52,17,62,68,38,53,2,57,82,67,25,11,59,3,49,97,1,40,91,75,7,85,98,33,90,1,37,57,14,34,67,65,20,85,10,18,86,20,52,84,24,20,70,10,64,16,64,2,15,85,36,28,7,87,47,44,9,29,54,83,28,37,81,68,18,12,80,26,98,97,25,86,69,39,70,22,23,72,15,56,94,27,14,13,8,50,73,90,24,95,14,41,57,22,67,25,80,46,39,84,80,19,22,63,53,45,62,21,84,36,69,41,44,96,38,92,21,23,64,35,11,75,57,88,6,7,90,10,36,19,68,78,23,62,34,49,4,80,38,2,70,48,39,55,20,22,39,8,90,64,38,39,47,41,63,72,5,10,72,88,35,50,5,66,30,80,74,23,97,39,98,19,17,85,38,34,62,37,25,58,15,93,37,13,71,72,72,4,84,40,92,61,88,9,7,62,59,87,17,36,39,43,21,11,16,58,16,58,20,66,18,83,33,66,62,90,32,74,15,58,62,43,16,66,22,90,2,68,30,54,18,59,22,50,12,60,35,66,77,51,36,64,89,82,21,85,0,0,21,21,1,10,1,0,0,0,0,0,0

1
input/day17.txt Normal file
View File

@@ -0,0 +1 @@
1,330,331,332,109,3132,1102,1,1182,16,1101,1467,0,24,101,0,0,570,1006,570,36,101,0,571,0,1001,570,-1,570,1001,24,1,24,1105,1,18,1008,571,0,571,1001,16,1,16,1008,16,1467,570,1006,570,14,21102,58,1,0,1106,0,786,1006,332,62,99,21102,1,333,1,21102,73,1,0,1106,0,579,1101,0,0,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,1001,574,0,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21101,0,340,1,1106,0,177,21101,0,477,1,1105,1,177,21101,514,0,1,21102,176,1,0,1106,0,579,99,21102,1,184,0,1106,0,579,4,574,104,10,99,1007,573,22,570,1006,570,165,1002,572,1,1182,21102,1,375,1,21101,0,211,0,1106,0,579,21101,1182,11,1,21102,1,222,0,1106,0,979,21102,388,1,1,21102,233,1,0,1105,1,579,21101,1182,22,1,21101,244,0,0,1106,0,979,21102,1,401,1,21101,255,0,0,1105,1,579,21101,1182,33,1,21102,266,1,0,1105,1,979,21102,1,414,1,21102,1,277,0,1105,1,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21102,1,1182,1,21101,313,0,0,1105,1,622,1005,575,327,1101,0,1,575,21102,1,327,0,1106,0,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,0,10,0,109,4,1202,-3,1,587,20102,1,0,-1,22101,1,-3,-3,21101,0,0,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1105,1,597,109,-4,2105,1,0,109,5,2102,1,-4,630,20102,1,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,653,20101,0,0,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21101,702,0,0,1105,1,786,21201,-1,-1,-1,1105,1,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21101,0,731,0,1106,0,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21101,0,756,0,1105,1,786,1105,1,774,21202,-1,-11,1,22101,1182,1,1,21102,1,774,0,1106,0,622,21201,-3,1,-3,1106,0,640,109,-5,2106,0,0,109,7,1005,575,802,21002,576,1,-6,20101,0,577,-5,1105,1,814,21101,0,0,-1,21101,0,0,-5,21102,1,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,45,-3,22201,-6,-3,-3,22101,1467,-3,-3,1201,-3,0,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1105,1,924,1205,-2,873,21101,0,35,-4,1105,1,924,2102,1,-3,878,1008,0,1,570,1006,570,916,1001,374,1,374,2102,1,-3,895,1102,2,1,0,1201,-3,0,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21001,0,0,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,45,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,37,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1102,1,1,575,21101,0,973,0,1106,0,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,0,1,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1106,0,1041,21102,1,-4,-2,1105,1,1041,21101,0,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,1202,-2,1,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,2101,0,-2,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1106,0,989,21102,1,439,1,1105,1,1150,21101,0,477,1,1106,0,1150,21102,1,514,1,21102,1,1149,0,1105,1,579,99,21101,1157,0,0,1106,0,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,1201,-5,0,1176,2102,1,-4,0,109,-6,2106,0,0,8,9,36,1,7,1,36,1,1,13,30,1,7,1,5,1,30,1,7,1,5,1,7,11,12,1,7,1,5,1,7,1,9,1,12,1,7,1,5,1,7,1,1,13,8,1,7,1,5,1,7,1,1,1,7,1,3,1,8,1,7,1,5,1,7,1,1,1,7,1,3,1,8,1,7,1,5,1,7,1,1,1,7,1,3,10,5,9,1,13,3,1,3,1,14,1,1,1,7,1,5,1,1,1,3,1,3,1,3,1,8,9,5,9,1,1,3,1,3,1,3,1,8,1,5,1,7,1,1,1,7,1,3,1,3,1,3,1,8,1,5,1,7,1,1,1,7,1,3,1,3,1,3,1,8,1,5,1,7,1,1,1,7,1,3,1,3,1,3,1,8,1,5,1,7,1,1,1,7,9,3,1,8,1,5,1,7,1,1,1,11,1,7,1,8,1,5,1,7,1,1,11,1,9,8,1,5,1,7,1,11,1,18,13,1,1,11,1,24,1,5,1,1,1,11,1,24,9,11,1,30,1,13,1,30,1,13,1,30,1,13,1,30,1,13,9,22,1,21,1,22,11,11,1,32,1,11,1,32,1,11,1,32,1,11,1,32,1,11,1,32,1,11,1,32,1,11,1,32,1,11,1,32,13,2

81
input/day18.txt Normal file
View File

@@ -0,0 +1,81 @@
#################################################################################
#.#...#.....#...............#.....#v....#.........#p....#...#...................#
#.#.#.#.#.#.#M#############.#.###.#####.#####.###.#.###.#.#.#################.#.#
#..n#...#.#...#.#...........#...#.......#.....#.....#.#...#...#.......#...#...#.#
#########.#####.#.###########.#.#######.#.###########.#######.#C#####.#.#.#.###.#
#.........#.#.....#.........#.#.#.......#...........#...........#...#.#.#...#...#
#.#########.#.#########.#####.#W###.###############.###.#########.###.#.#####.###
#.Y...#...#...#.......#z......#...#.#...#...#.....#..d#.#.#..x..#...#.#.#...#.#.#
#####.#.#.#.###.#.###.#####.#####.#.#.#.#.#.#.###.###.#.#.#.###.#.#.#.#.#.#.#.#.#
#.....#.#...#...#.#.#.....#...#...#.#.#.#.#...#.......#...#.#...#.#.....#.#...#.#
#.#######.#######.#.#####.#####.#####.#.#.#############.###.#.###.#########.###.#
#...#...#.#...#...#.#...#.....#...B...#.#.....#...#.....#...#.#.....#....t#.....#
#.#.#.#.#.#.#.#.###.#.#.#####.#.#######.#.###.#.#.###.###.###.#.#####.###.#####N#
#.#...#.#...#.#.#.....#...#...#.#...#...#...#.#.#...#.#...#...#...#...#.#...#.#.#
#.#####.#####.#.#########.#.###.#.#.#.#.###.#.#.###.###.###.#######.###.###.#.#.#
#.#...#.#.......#...#.....#...#...#.#.#.#.#.#...#.#.....#...#.....#.#...#...#.#.#
#.#.###.#########.#.#.###.###.#####.#.#.#.#.#####.#######.###.###.#.#.###.###.#.#
#.#...#.#...#.....#.#...#...#.#...#.#.#.#.#.#.....#.....#...#.#.#...#...#.#...#.#
#.###.#.#.#.#.#####.#.#.#####.#.###.#.###.#.#.###.###.#.###.#.#.#####.#.#J#E###.#
#.....#.#.#...#...#.#.#.....#.#.....#...#.#.#.#.......#.#...#.#...#...#...#.....#
#######.#.#####.###.#######.#.#########.#.#.#.#########.#.###.#.#.#.#########.###
#.......#.#.....#.I.#.....#.............#...#...#.....#.#...#.#.#.#.........#...#
#.#######.###.###.#.#####.#.###########.#.###.#.###.###.###.#####.#########.###.#
#.......#...#.#...#.....#.#.#.......#...#.#...#.#...#.....#.........#.....#.#...#
#.#####.###.#.#.#######.#.###.#####.#.###.#####.#.###.#######.#####.#.###.#.###.#
#.#...#...#.#.#.......#.#.....#.#...#...#.#...#.#...#u#.....#...#...#.#.#.#...#.#
#.###.#.###.#.#######.#.#######.#.#####.#.#.#.#.#.#.#.#.#.#.###.#####.#.#.###.#.#
#...#.#...#.....#.....#.#.....#...#...#.#...#.#.#.#...#.#.#...#.#.....#.#.#...#.#
###.#.###.#####.#.#####.#.#.#.#.###.#.#.#####.#.#.#####.#.#.###.#.#####.#.#.###.#
#...#...#.......#.#.....#.#.#.#.....#.#.#.....#.#.#.....#.#.#...#.....#.#.#.#..k#
#.###.###########.#.#######.#.#######.#.#.#####.###.#####.###.#.#####.#.#.#.#.###
#...#...........#.#.....#...#.......#.#.#...#.........#...#...#.#.....#.#...#.#.#
###.#.###.###.###.#####.#.#.#######.#.#.###.#.#########.#.#.###.#.#####.#####.#.#
#.#.#...#...#.#...#...#.#.#.#.....#.#.#.#.#.#...#.......#.#.#...#...#.....#...#.#
#.#.###.###.#.#.###.#.#.#.###.###.###.###.#.#####.#######.#.#.#####.#.#.#.#.###.#
#.#.#.....#.#.#.....#g#...#...#.#...#...#.#.......#...#...#.#...#.#.#.#.#.#.....#
#.#.#######.#.#######.###.#.###.###.###.#.#########.###.###.###.#.#.#.#.#######.#
#...#.....#.#.#.....#.#...#.......#.#...#.....#.......#.#.#...#...#.#.#.......#.#
#.###.###.#.#.#.###.#.###########.#.#.###.###.#.#####.#.#.###.#####.#.#######.#.#
#.....#.....#...#...#.A...........#.........#.......#.R.....#.......#.......#...#
#######################################.@.#######################################
#.....#.........#...........#......r#...........#.#...#.............#.......#...#
###.###.#.#######.#.#######.#.#####.###.#.#.###.#.#.#.#.#######.###.#.#####.###.#
#...#...#.........#...#...#.#.....#.....#.#...#...#.#...#...#...#.#.#.....#.....#
#.###.###############.#.###.#.###.#####.#.###.#####.#######.#.###.#.#####.#######
#.....#.......#.#.....#...#.#.#...#.....#.#.#.#.....#.......#.#...#.....#.......#
#.#######.###.#.#.#######.#.###.#.#######.#.#.#.#########.###.#.#######G#.#####.#
#.....#...#.#...#.#.......#...#.#.#.....#...#.#.#.....#..a#...#.#.....#.#i....#.#
#####.#.###.###.#.###.#.#####.#.###.###.#####.#.###.#.#.#.#.###.#.###.#.#######.#
#...#.#.#.....#.#...#.#.#.....#.....#...#...#.......#...#.#.#.....#.#.........#.#
#.#.#.#.#.#####.###.#.###.###########.###.#.#.#############.#.#####.#########.#.#
#.#.#.#.#.......#...#.....#.....#...#...#.#.#.#.............#.......#...#.....O.#
#.#.#.#.#########.#######.#.###.#.#.###.#.#.###.###########.#########.#.#######.#
#.#.#e#.........#.#.....#...#...#.#.....#.#.#...#...........#.......#.#.....#...#
###.#.#########.#.#.###.#####P###.#######.#.#.#########.#####.#####.#.#####.#.###
#...#.......#...#...#.#.#...#...#...#...#.#...#.......#.#w....#f..#...#...#.#...#
#.#.#######.#.#######.#.#.#####.#.#.#.#.#.#.###.#####.###.###.#.#.#####.#.#.#####
#.#.#...#...#.........#.#...#...#.#...#.#.#.#.......#.#...#...#.#...#...#.#.#...#
#.#.#.###.#######.###.#.#.#.#.###.#####.#.###.#######.#.#######.###.#.###.#.#.#.#
#.#...#...#.....#...#.#.#.#...#..o..#...#...#...#...#.#...#...F.#...#...#.#...#.#
#.#####.###.###.###.###.#####.#####.#.#.#.#.#.###.#.#.###.#.#####L###.#.#.#####.#
#.......#...#.#.#...#.#.....#.....#.#.#.#.#...#...#.#.#...#...#...#...#.#.....#.#
#K#######.#.#.#.#.###.#####.#####X###.#.#######.###.#.#.#######.#####.#.#######.#
#....j..#.#.#.....#...#.....#...#...#.#.#.......#...#.#.....#...#.S.#.#.........#
#######.###.#####.#.###.#####.#.###.#.###.#######.###.#####.#.###.#.#.###########
#.....#...#.....#.#...#.......#...#.#...#.....#.#.#.......#.#l....#.#.#...#.....#
#T#.#####.#####.#####.#.#########.#.###.#.###.#.#.#####.#.#.#######.#.#.###.###.#
#.#.....#.#.....#.....#.#.......#.#.#...#c#.#.#.....#...#.#...Z.#...#.#.....#...#
#.###.###.#.#.###.#####.#.#####.#.#.#.#.#.#.#.#####.#.#######.###.###.#.#####.#.#
#...#...#...#.#...#...#...#...#.#.#.#.#.#...#.....#...#.....#.#s..#...#.#.#...#.#
###.###.#.#####.###.###.###.#.###.#.#.###.#######.###.#.#.###.#.###.###Q#.#.#####
#.#.#.#.#.#...#...#...#.#...#.....#.#...#.#.....#.#...#.#.#...#.V.#.#...#.#.....#
#.#.#.#.#.#.#.###.#.#.#.#.#########.###.#.#.###.#.#####.#.#.#####.#.#.###.#####.#
#...#.#...#.#...#.#.#.#.#...#...#...#...#.#...#y..#...#.#.#.......#.#.#.......#.#
#.###.#####.###.#.###.#.###.#.###.###.#.#####.#####.#.#.#.#########.#.#.#.#####.#
#.#.....#...#.#...#...#.#...#.#.D.#.U.#.#.....#...#.#.#.#.......#...#..b#.#.....#
#.#####.#.###.#####.###.#.###.#.###.###.#.#####.#.#.#.#.#######.#.#######.#.###.#
#.H...#.#...#...........#.#...#.#.....#.#m......#...#...#.......#.#...#...#.#...#
#####.#.###.#############.#.#.#.#####.#.#.###############.#######.#.#.#####.#.###
#..q......#...............#.#.........#.#...............#...........#.......#..h#
#################################################################################

1
input/day19.txt Normal file
View File

@@ -0,0 +1 @@
109,424,203,1,21101,0,11,0,1105,1,282,21101,18,0,0,1105,1,259,2101,0,1,221,203,1,21101,31,0,0,1105,1,282,21102,38,1,0,1106,0,259,20101,0,23,2,21201,1,0,3,21101,1,0,1,21101,0,57,0,1105,1,303,2101,0,1,222,21001,221,0,3,21001,221,0,2,21101,259,0,1,21101,0,80,0,1106,0,225,21102,117,1,2,21102,91,1,0,1105,1,303,2101,0,1,223,20102,1,222,4,21102,1,259,3,21101,0,225,2,21102,1,225,1,21101,0,118,0,1105,1,225,21001,222,0,3,21102,1,77,2,21102,133,1,0,1105,1,303,21202,1,-1,1,22001,223,1,1,21102,1,148,0,1105,1,259,2102,1,1,223,21002,221,1,4,20101,0,222,3,21102,20,1,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,195,1,0,106,0,109,20207,1,223,2,20102,1,23,1,21101,0,-1,3,21101,0,214,0,1106,0,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,1202,-4,1,249,21201,-3,0,1,21201,-2,0,2,22101,0,-1,3,21102,250,1,0,1106,0,225,22101,0,1,-4,109,-5,2105,1,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21202,-2,1,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,21202,-2,1,3,21102,1,343,0,1105,1,303,1106,0,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21202,-4,1,1,21102,384,1,0,1106,0,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,22101,0,1,-4,109,-5,2105,1,0

109
input/day20.txt Normal file
View File

@@ -0,0 +1,109 @@
V W A S Q A K
D V A H R Y N
#################################.#########.###.#.###.#########.#####.#################################
#...........#.#...#...#.#...#...........#.....#.....#.........#.....#...............#.......#.........#
#.###.#.###.#.###.#.###.###.###.#.#.#####.###.#####.#######.#######.#######.#########.#.#####.#.#####.#
#.#...#.#.#...#...#...#.#.......#.#...#.....#.#.....#.......#.....#.#.#...#.#...#.#.#.#.#.#.#.#...#...#
#########.#.#####.#.###.###.#.#####.###.#.#######.###.#.#####.###.#.#.#.#.#.#.###.#.###.#.#.###.#####.#
#...#...#...#.#.#.....#.....#.....#...#.#.....#.....#.#...#.#...#.#.#...#...#.#...............#.#.#.#.#
#.#.###.###.#.#.#.#####.###.#.#.#######.#######.#####.#####.#.#.#.#.#.#######.#.#######.###.#.#.#.#.###
#.#.......................#.#.#...#.....#...#.....#.......#...#.#...#.............#.#.....#.#.#.....#.#
#.###.#####.#####.#####.#####.#########.#.###.###.###.#.#######.###########.###.###.###.#.#####.###.#.#
#.#...#.....#.#...#.....#.#...#...#.......#...#...#.#.#...#.#...#...#.....#.#.#.......#.#.#.......#...#
#.###########.###########.###.#.#######.#.###.###.#.###.###.#.###.#.#.###.#.#.#####.###.#.#.###.#######
#.#.#...#.#.#...#.#.............#.#...#.#...#.#.#.....#.#.#.......#.#.#.......#.#...#...#.#.#...#.....#
###.#.###.#.#.###.#.###.###.#.#.#.#.###.#######.#.#.###.#.#.#.#.###.#.###.#.###.###.#.###.#####.#####.#
#...............#.#.#...#...#.#.....#...#...#...#.#.#.....#.#.#.#.#.#.#.#.#.......#.#.#.#.#.#...#.....#
#.#######.###.###.#########.#.#.#####.###.#####.###.#.###########.#.#.#.#.#.#.###.#####.###.###.###.###
#.#.#.#.#...#...#.#.#.......#.#.....#.......#...#.#.#.#.....#...#.#.#...#.#.#...#.#...#.....#.#.......#
###.#.#.#####.#.#.#.#####.#########.#####.#####.#.#.#.###.#.###.#.#.#.#####.#.#######.###.###.#.#.#####
#.#.....#.#.#.#.....#.#.....#.......#...#...#.....#.#...#.#.#.....#.#...#...#.#.........#.#...#.#.#.#.#
#.#.#####.#.###.#####.#######.#######.#.###.#.#.#.#.###.#.#.#.###.#.#.###########.#.#####.###.#.###.#.#
#.....#.#.#.......#...#.#...#.......#.#...#.#.#.#.#.#.#...#.#...#...#...#...#.#...#.#.#.#.#.#.#...#.#.#
###.###.#.#####.#####.#.#.#.#.#######.###.#.#.#.###.#.#####.###.#.###.###.###.#.###.#.#.#.#.#.#.###.#.#
#.....#...#.#...#...#.#.#.#.......#.....#...#.#.....#...#...#...#.#.#.#.#.#.......#...#...............#
###.#.###.#.###.#.###.#.#######.#.###.#.#####.#######.#.#.#.#.###.#.#.#.#.###.###############.#.###.###
#...#.#.............#.#.#.......#...#.#.....#.....#...#...#.#...#.#.........#...#.....#.#.#.#.#...#.#.#
###.#######.#.###.###.#.#####.#########.#####.#######.#######.#########.#######.###.###.#.#.###.#####.#
#.....#...#.#...#.#.....# E O X A X L #.#...#...#.#.....#...#.#
#.#.###.#####.###.#####.# N C E Y B O #.###.###.#.#.#####.###.#
#.#.....#.#.#.#...#.....# #.#.#.#.#.#.#...#...#...#
#.#.###.#.#.###.#.#.###.# #.#.#.#.#.#.#.#####.###.#
#.#.#.#...#.#...#...#...# #...............#.#.#.#.#
#####.#.#.#.###.#####.### #.#.#.#.#.#.###.#.#.#.#.#
#.#.....#.....#...#...#.# #.#.#.#.#.#.#...#.....#..UW
#.###.###.#.#.###.#.###.# #.###.#####.#.###.#.#.#.#
DK......#.#.#.#.....#......VG EJ....#.#.....#.#...#.#...#
#####.#.###.###.###.##### #############.#.#.#####.#
#.....#...#.#...#...#....SY #...#...#...#...#.#.#...#
#########.#####.#####.### #.###.#####.#####.#.#####
LO......#.....#.#.#...#...# #.........#.....#.#.....#
#.###.#####.#.###.#####.# #.#.###.###.###.###.###.#
#.#.....................# #.#.#.......#.#...#.#.#..XJ
#.#########.###.######### #.#####.#.###.###.#.#.###
#.#.#.....#...#.#.......# VD....#...#.#.......#.....#
#.#.###.#.#########.###.# #.#.###.#####.#####.###.#
#.#.#...#.........#...#..WV #.#.#...#.#...........#.#
###.###.#####.###.###.### #####.###.###############
XE........#...#.#.........# HX....#...#...#...#.....#.#
###########.############# #.###.#####.#.###.###.#.#
#...#.#...#.........#...# #...#.#.#.#...#.....#.#..XB
#.#.#.#.#.#.###.###.###.# #.#####.#.###.###.#.#.#.#
#.#.....#...#.#.#.......# #.#.#.....#.#...#.#.#.#.#
#.#####.#####.#########.# #.#.#####.#.#.#.###.#.#.#
#.#.....#.......#.#.....# #.............#.....#...#
#.#########.###.#.#.##### ###.#.#.###.#.#######.###
HX..#.#.#...#...#.#........OW XY..#.#.#.#...#.#.....#.#.#
###.#.###.#.############# #.#######.#.###.###.###.#
#.#.....#.#.#.#.#.#...#.# #...#.....#.#...#...#...#
#.#.#####.#.#.#.#.#.#.#.# ###.###########.#.###.#.#
#...#.......#.....#.#....QR #.#.#.#.#.......#.#...#..AG
#.#.###.#.#######.#.##### #.#.#.#.#####.###.#.###.#
WB..#.#...#...#.....#...#.# #...............#...#...#
###.#.#.#######.#.###.#.# #.###.###.#.#######.#####
#.#...#.........#.....#.# #.#...#...#.#.#...#.#...#
#.#####################.# #########.###.###.###.#.#
#.......................# #...#...#.#.#...#.....#..DF
#.###.#.#.#####.#######.# ###.#.#.###.###.#.###.#.#
EN..#...#.#...#...#.#...#.# ZH......#.............#.#.#
#######.#.#.#.###.#.#.#.# ###.###.#######.#.###.###
#...#.#.#.#.#.#.....#...# DF..#.#.....#.....#.#...#.#
###.#.###.###.###.#.##### #.#####.###############.#
#.......#...#.#...#......KN #.#...#.#...#.....#.#...#
###.#.#########.######### #.###.###.#######.#.#.#.#
#...#.#.#.#...#.#.......# #.....................#..GL
#.#.###.#.###.#####.#.### #########################
#.#...#.......#...#.#....AG WW..#.................#...#
#.#.#.#.#########.#.#.### #.#.###.###.#.#####.#.#.#
ZH..#.#.#.#.#...#.....#.#.# #.....#...#.#...#.....#..RP
#####.#.#.#.###.#.#.#.#.# ###.###.#####.#.###.###.#
#...............#.#.#...# #...#.#...#...#.#.....#.#
###.###.###.#.#.#.###.### X S U R W D G ###.#.#.#.###.###.###.###
#...#.#...#.#.#.#.#...#.# J H W P B K L #.#...#.#.#.#.#.#.#.....#
#####.#.###.#.###.#####.#######.#######.#####.###.#####.###########.#.#########.#.#.###.#.#.#.#####.#.#
#.#.....#.#.#...#...#.#.....#.#.....#...#.........#.........#.......#.........#...#...#.#.#.......#.#.#
#.###.#.#.#.#########.#.#####.#.#######.#####.###.#.#.#.#####.#####.#.###.#######.#####.#.###.###.#.#.#
#.#...#.#.......#...............#.#...#.....#.#.#.#.#.#.#...#.#...#.#.#...#...#.#.....#...#.....#.#.#.#
#.###.###.#########.#.#.#####.###.#.###.#.###.#.#####.#####.#.#.#.#######.###.#.###.#####.###.#########
#.......#.#.#.....#.#.#.#.............#.#.#.........#...#.....#.#.....#.........#...#.#...#...........#
#.###.###.#.#.#########.#####.#####.#####.###.#######.###.#.#.#.###.###.###.###.#####.#####.#.#.#####.#
#.#.....#.....#.....#...#.#.#.....#.#.......#.#.#...#...#.#.#...#...#.....#.#...........#.#.#.#.....#.#
#######.###.###.#######.#.#.#.#.#######.###.#.#.#.###.###########.#######.###########.#.#.#####.#####.#
#.......#...........#.#.#.....#.#.#...#.#...#.....#.......#.#...#.#...#.........#...#.#.....#.......#.#
#.#.#####.#.#.#.#.#.#.###.###.###.#.###.#.#.#.#######.#####.###.#.#.#.#.#########.###########.###.#####
#.#.#.#...#.#.#.#.#.#.#.#.#.#.........#.#.#.#.#.#.#.....#...#.......#.#...#.................#.#.......#
###.#.###.###.###.#.#.#.###.#.#.###########.#.#.#.###.###.###.###.#######.#.#####.#.#.###.#######.#.###
#.......#...#...#.#.......#...#.#.......#...#.....#.#.....#.#.#.....#...........#.#.#...#.....#...#.#.#
###.#####.#####.#.#.#.#####.#.#####.###.###.###.###.#.#####.#######.#.###.###.###.#######.###.###.###.#
#.....#...#.....#.#.#.#...#.#.....#.#...#.#.#.....#.....#.....#.....#.#...#...#.......#...#.....#.....#
###.#####.###.###########.#####.#######.#.#.#.#.#####.#######.#.#####.#####.#######.###.#.#####.###.###
#...#.#.....#.#.#.......#.......#...#.#.....#.#.#...#.....#.#.......#...#.#.#.#.#.#...#.#.#.#.#...#...#
#####.#########.###.###.#####.#####.#.###.###.#####.#.#####.#######.#.###.###.#.#.#.#######.#.#########
#.#.......#.#.#.....#.#.............#.....#.#.....#.#...#.....#.....#.#...#.#.#.#.#...#...#...........#
#.###.#####.#.#.#####.#####.#.#.###.#.#####.#.#.#.#.#.###.#.#####.###.#.#.#.#.#.#.#####.#####.#####.###
#...............#.#.#.......#.#...#.#.......#.#.#...#.#...#.#.#.#...#...#.................#.......#...#
#.#.#.#.#.#####.#.#.#.#.#.#.#.#####.#.#.###.#.#####.#.#.###.#.#.###.#.###.#.#.###.#.#.#.#####.#########
#.#.#.#.#.#.....#.....#.#.#.#.#.....#.#.#...#.#.....#...#...#.......#.#...#.#.#...#.#.#...............#
###############################.###.#####.#####.#.#######.###.#########.###############################
X Z V O O S W E
Y Z G C W Y W J

19
input/day20_example1.txt Normal file
View File

@@ -0,0 +1,19 @@
A
A
#######.#########
#######.........#
#######.#######.#
#######.#######.#
#######.#######.#
##### B ###.#
BC...## C ###.#
##.## ###.#
##...DE F ###.#
##### G ###.#
#########.#####.#
DE..#######...###.#
#.#########.###.#
FG..#########.....#
###########.#####
Z
Z

37
input/day20_example2.txt Normal file
View File

@@ -0,0 +1,37 @@
Z L X W C
Z P Q B K
###########.#.#.#.#######.###############
#...#.......#.#.......#.#.......#.#.#...#
###.#.#.#.#.#.#.#.###.#.#.#######.#.#.###
#.#...#.#.#...#.#.#...#...#...#.#.......#
#.###.#######.###.###.#.###.###.#.#######
#...#.......#.#...#...#.............#...#
#.#########.#######.#.#######.#######.###
#...#.# F R I Z #.#.#.#
#.###.# D E C H #.#.#.#
#.#...# #...#.#
#.###.# #.###.#
#.#....OA WB..#.#..ZH
#.###.# #.#.#.#
CJ......# #.....#
####### #######
#.#....CK #......IC
#.###.# #.###.#
#.....# #...#.#
###.### #.#.#.#
XF....#.# RF..#.#.#
#####.# #######
#......CJ NM..#...#
###.#.# #.###.#
RE....#.# #......RF
###.### X X L #.#.#.#
#.....# F Q P #.#.#.#
###.###########.###.#######.#########.###
#.....#...#.....#.......#...#.....#.#...#
#####.#.###.#######.#######.###.###.#.#.#
#.......#.......#.#.#.#.#...#...#...#.#.#
#####.###.#####.#.#.#.#.###.###.#.###.###
#.......#.....#.#...#...............#...#
#############.#.#.###.###################
A O F N
A A D M

100
input/day22.txt Normal file
View File

@@ -0,0 +1,100 @@
deal with increment 3
deal into new stack
cut -2846
deal with increment 33
cut -8467
deal into new stack
deal with increment 46
cut 6752
deal with increment 63
deal into new stack
deal with increment 70
deal into new stack
deal with increment 14
cut -1804
deal with increment 68
cut -4936
deal with increment 15
cut -3217
deal with increment 49
cut -1694
deal with increment 58
cut -6918
deal with increment 13
cut -4254
deal with increment 4
deal into new stack
cut 5490
deal into new stack
deal with increment 35
deal into new stack
deal with increment 7
cut 854
deal with increment 46
cut -8619
deal with increment 32
deal into new stack
cut -6319
deal with increment 31
cut 1379
deal with increment 66
cut -7328
deal with increment 55
cut -6326
deal with increment 10
deal into new stack
cut 4590
deal with increment 18
cut -9588
deal with increment 5
cut 3047
deal with increment 24
cut -1485
deal into new stack
deal with increment 53
cut 5993
deal with increment 54
cut -5935
deal with increment 49
cut -3349
deal into new stack
deal with increment 28
cut -4978
deal into new stack
deal with increment 30
cut -1657
deal with increment 50
cut 3732
deal with increment 30
cut 6838
deal with increment 30
deal into new stack
cut -3087
deal with increment 42
deal into new stack
deal with increment 68
cut 3376
deal with increment 51
cut -3124
deal with increment 57
deal into new stack
cut -158
deal into new stack
cut -3350
deal with increment 33
deal into new stack
cut 3387
deal with increment 54
cut 1517
deal with increment 20
cut -3981
deal with increment 64
cut 6264
deal with increment 3
deal into new stack
deal with increment 5
cut 232
deal with increment 29
deal into new stack
cut -5147
deal with increment 51

1
input/day23.txt Normal file

File diff suppressed because one or more lines are too long

5
input/day24.txt Normal file
View File

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

1
input/day25.txt Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,7 @@
extern crate core;
mod tasks;
fn main() {
tasks::day21::run();
tasks::day22::run();
}

View File

@@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::path::Path;
pub type RAM = HashMap<usize, i128>;
@@ -14,6 +15,15 @@ pub fn run() {
task2(ram.clone());
}
pub fn load_ram<P: AsRef<Path>>(path: P) -> RAM {
let input = std::fs::read_to_string(path).unwrap();
input
.split(",")
.enumerate()
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
.collect()
}
pub struct IntCodeComputer {
input_storage: Vec<i128>,
output_storage: Vec<i128>,
@@ -169,6 +179,13 @@ impl IntCodeComputer {
}
}
pub fn run_single(&mut self, input: i128) -> i128 {
self.set_input(&[input]);
self.clear_output();
self.run_until_input_empty();
*self.get_output().first().unwrap()
}
pub fn run_until_end(&mut self) {
if !self.run_until_input_empty() {
panic!("There wasn't enough input given to run until the program halted");
@@ -200,6 +217,7 @@ impl IntCodeComputer {
op.params[0].store(&mut self.ram, *v, self.relative_base_offset);
self.pc += 2;
} else {
self.input_storage.clear();
return false;
}
}
@@ -265,10 +283,24 @@ impl IntCodeComputer {
}
}
pub fn add_input(&mut self, input: &[i128]) {
for x in input {
self.input_storage.push(*x);
}
}
pub fn get_input(&self) -> &[i128] {
self.input_storage.as_slice()
}
pub fn clear_output(&mut self) {
self.output_storage.clear();
}
pub fn clear_n_output(&mut self, n: usize) {
self.output_storage = Vec::from(self.output_storage.split_at(n).1);
}
pub fn get_output(&self) -> &[i128] {
self.output_storage.as_slice()
}

268
src/tasks/day15.rs Normal file
View File

@@ -0,0 +1,268 @@
use super::day05::*;
use std::collections::HashMap;
use std::collections::VecDeque;
use Direction::*;
#[allow(dead_code)]
pub fn run() {
let ram = load_ram("input/day15.txt");
task1(ram.clone());
task2(ram.clone());
}
fn task1(ram: RAM) {
let (map, goal) = explore_map(ram);
let shortest_path = map.get_shortest_path_to(Pos(0, 0), goal);
/*
map.print(
Map::positions_on_path(Pos(0, 0), &shortest_path)
.iter()
.map(|p| (*p, 'x'))
.collect(),
);
*/
println!(
"Task 1: shortest path to goal ({:?}) has length {}",
goal,
shortest_path.len()
);
}
fn task2(ram: RAM) {
let (map, oxygen) = explore_map(ram);
let max_distance = map
.positions
.iter()
.filter(|(_, c)| **c == '.')
.map(|(pos, _)| map.get_shortest_path_to(oxygen, *pos).len())
.max()
.unwrap();
println!(
"Task 2: time needed to reach most distant room is {} minutes",
max_distance
);
}
fn explore_map(ram: RAM) -> (Map, Pos) {
let mut map = Map {
positions: HashMap::new(),
};
let mut current = Pos(0, 0);
map.positions.insert(current, '.');
let mut target: Option<Pos> = None;
let mut pc = IntCodeComputer::new(vec![], ram);
while let Some(non_explored_neighbor) = map.get_unexplored() {
// move to next field with unexplored neighbors
// *find path
// *follow directions
let round_starts_from = current;
let directions = map.get_shortest_path_to(round_starts_from, non_explored_neighbor);
for d in directions {
let res = pc.run_single(d.to_robot_cmd());
if res == 0 {
map.print(HashMap::new());
panic!("Ran against a wall stepping {:?} from {:?}.", d, current);
}
current = current.neighbor(d);
}
// explore all 4 neighbor positions
// i.e. for every direction move - if result is 0 mark as wall,
// if result is 1 or 2 move back and mark as empty. If result is 2 store
// target position
let ns = vec![N, S, W, E];
for d in ns {
let r = pc.run_single(d.to_robot_cmd());
match r {
0 => {
map.positions.insert(current.neighbor(d), '#');
}
1 => {
map.positions.insert(current.neighbor(d), '.');
pc.run_single(d.opposite().to_robot_cmd());
}
2 => {
map.positions.insert(current.neighbor(d), '.');
pc.run_single(d.opposite().to_robot_cmd());
target = Some(current.neighbor(d));
}
_ => panic!("unknown field type {}", r),
};
}
}
(map, target.unwrap())
}
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
struct Pos(i32, i32);
impl Pos {
fn add(&self, other: Self) -> Self {
Pos(self.0 + other.0, self.1 + other.1)
}
fn direction_to(&self, from: Pos) -> Direction {
let m: HashMap<Pos, Direction> = vec![
(Pos(0, 1), N),
(Pos(0, -1), S),
(Pos(1, 0), W),
(Pos(-1, 0), E),
]
.into_iter()
.collect();
m.get(&Pos(self.0 - from.0, self.1 - from.1))
.map(|p| *p)
.unwrap()
}
fn neighbor(&self, direction: Direction) -> Pos {
match direction {
N => self.add(Pos(0, -1)),
S => self.add(Pos(0, 1)),
W => self.add(Pos(-1, 0)),
E => self.add(Pos(1, 0)),
}
}
}
#[derive(Debug)]
struct Map {
positions: HashMap<Pos, char>,
}
impl Map {
fn get_unexplored(&self) -> Option<Pos> {
let neighbors = vec![Pos(-1, 0), Pos(1, 0), Pos(0, -1), Pos(0, 1)];
let r = self
.positions
.iter()
.filter(|(_, c)| **c == '.')
.map(|(p, _)| p)
.find(|pos| {
neighbors
.iter()
.any(|delta| !self.positions.contains_key(&pos.add(*delta)))
});
r.map(|p| *p)
}
fn get_shortest_path_to(&self, start: Pos, goal: Pos) -> Vec<Direction> {
let neighbors = vec![Pos(-1, 0), Pos(1, 0), Pos(0, -1), Pos(0, 1)];
let mut open: VecDeque<Pos> = VecDeque::new();
open.push_back(start);
let mut predecessors: HashMap<Pos, Option<Pos>> = HashMap::new();
predecessors.insert(start, None);
while let Some(current) = open.pop_front() {
let field = self.positions.get(&current);
if let Some(v) = field {
if *v != '.' {
continue;
}
} else {
continue;
}
neighbors.iter().for_each(|d| {
let n = current.add(*d);
if !predecessors.contains_key(&n) {
predecessors.insert(n, Some(current));
open.push_back(n);
}
});
if current == goal {
break;
}
}
let mut directions = Vec::new();
let mut current = goal;
while let Some(Some(pred)) = predecessors.get(&current) {
directions.push(current.direction_to(*pred).opposite());
current = *pred;
}
directions.reverse();
directions
}
#[allow(dead_code)]
fn positions_on_path(start: Pos, directions: &Vec<Direction>) -> Vec<Pos> {
let mut result = vec![start];
let mut current = start;
for d in directions {
current = current.neighbor(*d);
result.push(current);
}
result
}
fn print(&self, special: HashMap<Pos, char>) {
let xmin = (self
.positions
.iter()
.min_by_key(|(Pos(x, _), _)| x)
.unwrap()
.0)
.0;
let xmax = (self
.positions
.iter()
.max_by_key(|(Pos(x, _), _)| x)
.unwrap()
.0)
.0;
let ymin = (self
.positions
.iter()
.min_by_key(|(Pos(_, y), _)| y)
.unwrap()
.0)
.1;
let ymax = (self
.positions
.iter()
.max_by_key(|(Pos(_, y), _)| y)
.unwrap()
.0)
.1;
for y in ymin..=ymax {
for x in xmin..=xmax {
let c = self.positions.get(&Pos(x, y)).unwrap_or(&' ');
let c = if let Some(s) = special.get(&Pos(x, y)) {
s
} else {
c
};
print!("{}", c);
}
println!("");
}
}
}
#[derive(Hash, PartialEq, Copy, Clone, Debug)]
enum Direction {
N,
S,
W,
E,
}
impl Direction {
fn opposite(&self) -> Self {
match self {
N => S,
S => N,
W => E,
E => W,
}
}
fn to_robot_cmd(&self) -> i128 {
match self {
N => 1,
S => 2,
W => 3,
E => 4,
}
}
}

175
src/tasks/day16.rs Normal file
View File

@@ -0,0 +1,175 @@
use std::collections::HashMap;
use std::iter;
use itertools::Itertools;
const BASE_PATTERN: [i32; 4] = [0, 1, 0, -1];
const INPUT: &str = "59750530221324194853012320069589312027523989854830232144164799228029162830477472078089790749906142587998642764059439173975199276254972017316624772614925079238407309384923979338502430726930592959991878698412537971672558832588540600963437409230550897544434635267172603132396722812334366528344715912756154006039512272491073906389218927420387151599044435060075148142946789007756800733869891008058075303490106699737554949348715600795187032293436328810969288892220127730287766004467730818489269295982526297430971411865028098708555709525646237713045259603175397623654950719275982134690893685598734136409536436003548128411943963263336042840301380655801969822";
#[allow(dead_code)]
pub fn run() {
let input = to_digits(INPUT);
task1(input.clone());
task2(to_digits("02935109699940807407585447034323"));
task2(input.clone());
}
fn task1(input: Vec<V>) -> String {
let mut s = S { input, cache: HashMap::new() };
s.prep();
let result = format!("{:.*}", 8, (0..8).map(|position| {
let r = s.get(position, 100);
r
}).join(""));
println!("Task 1: {result}");
result
}
fn to_digits(input: &str) -> Vec<i32> {
input
.chars()
.map(|it| it.to_digit(10).unwrap() as i32)
.collect_vec()
}
fn task2(input: Vec<i32>) -> String {
let big_input = iter::repeat(input.clone().into_iter())
.take(10_000)
.flatten()
.collect_vec();
let mut s = S { input: big_input, cache: HashMap::new() };
let result_position = format!("{}", input.split_at(7).0.iter().join("")).parse::<usize>().unwrap();
s.prep_after(result_position);
let result = format!("{:.*}", 8, (0..8).map(|position| {
let r = s.get(position + result_position, 100);
r
}).join(""));
println!("Task 2: {result}");
result
}
type V = i32;
struct S {
input: Vec<V>,
cache: HashMap<(usize, usize), V>,
}
impl S {
fn pattern(&self, position: usize, size: usize) -> Vec<i32> {
let pattern = BASE_PATTERN.iter().map(|x| iter::repeat(*x).take(position)).flatten();
let iter = iter::repeat(pattern).flatten().skip(1).take(size);
iter.collect()
}
fn get(&mut self, index: usize, phase: usize) -> V {
if phase == 0 {
return self.input[index];
}
if self.cache.contains_key(&(phase, index)) {
return self.cache[&(phase, index)];
}
if index == self.input.len() - 1 {
let v = self.get(index, phase - 1);
self.cache.insert((phase, index), v);
return v;
}
if index > (self.input.len() / 2 + 1) {
let v = self.get(index + 1, phase) + self.get(index, phase - 1);
let v = v.abs() % 10;
self.cache.insert((phase, index), v);
return v;
}
let pattern = self.pattern(index + 1, self.input.len());
let val: i32 = pattern
.iter()
.enumerate()
.map(|(i, p)| if *p == 0 { 0 } else { *p * self.get(i, phase - 1) })
.sum();
let result = val.abs() % 10;
self.cache.insert((phase, index), result);
result
}
fn prep(&mut self) {
for phase in 1..=100 {
for i in 1..self.input.len() / 2 {
self.get(self.input.len() - i, phase);
}
}
println!("preparation done")
}
fn prep_after(&mut self, start: usize) {
for phase in 1..=100 {
for i in (start..self.input.len()).rev() {
self.get(i, phase);
}
}
println!("preparation done")
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_part_1_examples() {
assert_eq!(
task1(to_digits("80871224585914546619083218645595")),
"24176176"
);
assert_eq!(
task1(to_digits("19617804207202209144916044189917")),
"73745418"
);
assert_eq!(
task1(to_digits("69317163492948606335995924319873")),
"52432133"
);
}
#[test]
fn test_part_1_solution() {
assert_eq!(task1(to_digits(INPUT)), "84487724");
}
#[test]
fn test_part_2_solution() {
assert_eq!(task2(to_digits(INPUT)), "84692524");
}
#[test]
fn test_trivial() {
let mut s = S { input: to_digits("12345678"), cache: HashMap::new() };
s.prep();
let result = format!("{:.*}", 8, (0..8).map(|position| {
let r = s.get(position, 1);
r
}).join(""));
assert_eq!(result, "48226158");
}
#[test]
fn test_part_2_examples() {
assert_eq!(
task2(to_digits("02935109699940807407585447034323")),
"78725270"
);
assert_eq!(
task2(to_digits("03036732577212944063491565474664")),
"84462026"
);
assert_eq!(
task2(to_digits("03081770884921959731165446850517")),
"53553731"
);
}
}

78
src/tasks/day17.rs Normal file
View File

@@ -0,0 +1,78 @@
use super::day05::*;
#[allow(dead_code)]
pub fn run() {
let input: RAM = std::fs::read_to_string("input/day17.txt")
.unwrap()
.split(",")
.enumerate()
.map(|(i, it)| (i, it.parse::<i128>().unwrap()))
.collect();
task1(input.clone());
task2(input.clone());
}
fn task1(ram: RAM) {
let mut pc = IntCodeComputer::new(vec![], ram);
pc.run_until_end();
let map: Vec<Vec<char>> = pc
.get_output()
.iter()
.map(|it| (*it as u8) as char)
.collect::<String>()
.lines()
.map(|line| line.chars().collect())
.collect();
let height = map.len();
let width = map[0].len();
let alignment_sum = (1..height - 1).fold(0, |sum, y| {
sum + (1..width - 1).fold(0, |sum, x| {
let pos = Pos(x, y);
if map[y][x] == '#'
&& pos
.neighbors()
.iter()
.all(|Pos(xp, yp)| map[*yp][*xp] == '#')
{
sum + pos.0 * pos.1
} else {
sum
}
})
});
println!("Task 1: sum of alignment parameters is {}", alignment_sum);
}
fn task2(mut ram: RAM) {
// R,8,L,10,R,8,R,12,R,8,L,8,12,R,8,L,10,R,8,L,12,L,10,L,8,R,8,L,10,R,8,R,12,R,8,L,8,L,12,L,12,L,10,L,8,L,12,L,10,L,8,R,8,L,10,R,8,R,12,R,8,L,8,L,12
/*
R,8,L,10,R,8
R,12,R,8,L,8,L,12
L,12,L,10,L,8
*/
let main = "A,B,A,C,A,B,C,C,A,B";
let a = "R,8,L,10,R,8";
let b = "R,12,R,8,L,8,L,12";
let c = "L,12,L,10,L,8";
let program = format!("{}\n{}\n{}\n{}\nn\n", main, a, b, c);
ram.insert(0, 2);
let mut pc = IntCodeComputer::new(program.chars().map(|it| (it as u8) as i128).collect(), ram);
pc.run_until_end();
let out = pc.get_output();
println!("{:?}", out.last().unwrap());
}
struct Pos(usize, usize);
impl Pos {
fn neighbors(&self) -> Vec<Pos> {
vec![
Pos(self.0 - 1, self.1),
Pos(self.0 + 1, self.1),
Pos(self.0, self.1 - 1),
Pos(self.0, self.1 - 1),
]
}
}

299
src/tasks/day18.rs Normal file
View File

@@ -0,0 +1,299 @@
use itertools::Itertools;
use std::cmp::{Ord, Ordering, PartialOrd};
use std::collections::BinaryHeap;
use std::collections::HashSet;
use std::collections::VecDeque;
use std::rc::Rc;
#[allow(dead_code)]
pub fn run() {
let input: Map = Map(std::fs::read_to_string("input/day18.txt")
.unwrap()
.lines()
.map(|line| line.chars().collect_vec())
.collect_vec());
let t1 = task(input.clone());
println!("Task 1: best bound to get all keys is {}", t1);
//let t2 = task(input.clone().split_robot());
//println!("Task 2: best bound to get all keys is {}", t2);
}
fn task(map: Map) -> usize {
let mut all_keys = map
.0
.iter()
.flatten()
.filter(|c| c.is_alphabetic() && c.is_lowercase())
.collect_vec();
all_keys.sort();
let all_keys: String = all_keys.into_iter().collect();
let map = Rc::from(map);
let mut visited: HashSet<StateSummary> = HashSet::new();
let mut open: BinaryHeap<State> = BinaryHeap::new();
open.push(State::new(map.clone()));
while let Some(state) = open.pop() {
let summary = StateSummary::from(&state);
if visited.contains(&summary) {
// there could come no better solution
continue;
}
if summary.1 == all_keys {
return state.steps_taken;
}
state
.get_available_options()
.into_iter()
.for_each(|s| open.push(s));
visited.insert(summary);
}
panic!("if we reach this point no path can be found");
}
#[derive(Eq, PartialEq, Hash, Debug)]
struct StateSummary(Vec<Pos>, String);
impl StateSummary {
fn from(state: &State) -> Self {
let mut s = state.opened.iter().collect_vec();
s.sort();
Self(
state.currents.clone(),
s.into_iter()
.map(|c| {
let mut x = *c;
x.make_ascii_lowercase();
x
})
.collect(),
)
}
}
#[derive(Eq, PartialEq)]
struct StateSummaryDist(Pos, HashSet<char>, usize);
#[derive(PartialEq, Eq, Clone)]
struct Map(Vec<Vec<char>>);
#[allow(dead_code)]
impl Map {
fn coordinate_of(&self, symbol: char) -> Vec<Pos> {
self.0
.iter()
.enumerate()
.fold(Vec::new(), |vec, (y, line)| {
line.iter()
.enumerate()
.filter(|(_x, c)| **c == symbol)
.fold(vec, |mut vec, (x, _c)| {
vec.push(Pos(x, y));
vec
})
})
}
/**
* return: (char: found key, usize1: index of moved robot,
* usize2: distance that robot moved, Pos: new position of robot[index]),
* usize3: number of empty points on path to last_door_opened
*/
fn reachable_keys(
&self,
start_points: Vec<Pos>,
open_doors: &HashSet<char>,
last_door_opened: Option<char>,
) -> Vec<(char, usize, usize, Pos, usize)> {
let all_keys = 'a'..='z';
let bfs = |start: Pos, open_doors: &HashSet<char>| {
// key, distance, new_pos, number of steps of distance until last_open door is met
let mut result: Vec<(char, usize, Pos, usize)> = vec![];
let mut open: VecDeque<(Pos, usize, usize)> = VecDeque::new(); //position, distance form start, distance until last door opened is met
open.push_back((start, 0, 0));
let mut visited: HashSet<Pos> = HashSet::new();
while let Some((current, walked, ldod)) = open.pop_front() {
if visited.contains(&current) {
continue;
}
let field = self.0[current.1][current.0];
let field_is_key = all_keys.contains(&field);
// if can move over current type: push neighbors to open
if field == '.' || field == '@' || open_doors.contains(&field) || field_is_key {
let mut ldod = 0;
if let Some(ldo) = last_door_opened {
if ldo == field {
ldod = walked;
}
};
current
.neighbors()
.iter()
.for_each(|n| open.push_back((*n, walked + 1, ldod)));
}
// if it is a key: push it to result
if field_is_key {
result.push((field, walked, current, ldod));
}
// anyways: push to visited
visited.insert(current);
}
result
};
start_points
.iter()
.enumerate()
.flat_map(|(robot_i, robot_pos)| {
bfs(*robot_pos, open_doors)
.into_iter()
.map(|(key, dist, final_pos, ldod)| (key, robot_i, dist, final_pos, ldod))
.collect_vec()
})
.collect_vec()
}
fn split_robot(mut self) -> Self {
let Pos(x, y) = self.coordinate_of('@')[0];
self.0[x][y] = '#';
self.0[x - 1][y - 1] = '@';
self.0[x - 1][y] = '#';
self.0[x - 1][y + 1] = '@';
self.0[x + 1][y] = '#';
self.0[x + 1][y + 1] = '@';
self.0[x][y - 1] = '#';
self.0[x + 1][y - 1] = '@';
self.0[x][y + 1] = '#';
self
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct Pos(usize, usize);
impl Pos {
fn neighbors(&self) -> [Pos; 4] {
[
Pos(self.0 - 1, self.1),
Pos(self.0 + 1, self.1),
Pos(self.0, self.1 - 1),
Pos(self.0, self.1 + 1),
]
}
}
#[derive(Eq, PartialEq)]
struct State {
currents: Vec<Pos>,
underrun: Vec<usize>, // the number of steps a robot is behind the leading robots steps
opened: HashSet<char>, // capital letter
map: Rc<Map>,
steps_taken: usize,
last_door_opened: Option<char>,
}
impl State {
fn new(map: Rc<Map>) -> Self {
let currents = map.coordinate_of('@');
let no_robots = currents.len();
Self {
currents: currents,
underrun: std::iter::repeat(0).take(no_robots).collect_vec(),
opened: HashSet::new(),
map: map,
steps_taken: 0,
last_door_opened: None,
}
}
fn get_available_options(&self) -> Vec<State> {
// find all keys that are not yet collected + their distance + position
let next_keys = self
.map
.reachable_keys(self.currents.clone(), &self.opened, self.last_door_opened)
.into_iter()
.filter(|(key, _, _, _, _)| {
let mut c = *key;
c.make_ascii_uppercase();
!self.opened.contains(&c)
})
.collect_vec();
// create new state with one open door added + steps increased + current position updated
next_keys
.into_iter()
.map(|(key, robot_i, distance, current, ldod)| {
self.advance(key, robot_i, distance, current, ldod)
})
.collect_vec()
}
fn advance(
&self,
key_added: char,
robot_index: usize,
additional_steps: usize,
new_pos: Pos,
ldod: usize,
) -> Self {
let mut open_doors = self.opened.clone();
let mut door = key_added;
door.make_ascii_uppercase();
open_doors.insert(door);
let mut positions = self.currents.clone();
positions[robot_index] = new_pos;
let underrun = self
.underrun
.iter()
.enumerate()
.map(|(i, u)| {
if i != robot_index {
*u + additional_steps
} else {
0
}
})
.collect();
let usable_underrun = if self.underrun[robot_index] >= ldod {
ldod
} else {
self.underrun[robot_index]
};
let steps_diff = additional_steps - usable_underrun;
Self {
currents: positions,
underrun: underrun,
opened: open_doors,
map: self.map.clone(),
steps_taken: self.steps_taken + steps_diff as usize,
last_door_opened: Some(key_added),
}
}
}
// The priority queue depends on `Ord`.
// Explicitly implement the trait so the queue becomes a min-heap
// instead of a max-heap.
impl Ord for State {
fn cmp(&self, other: &State) -> Ordering {
// Notice that the we flip the ordering on costs.
// In case of a tie we compare positions - this step is necessary
// to make implementations of `PartialEq` and `Ord` consistent.
other.steps_taken.cmp(&self.steps_taken)
}
}
// `PartialOrd` needs to be implemented as well.
impl PartialOrd for State {
fn partial_cmp(&self, other: &State) -> Option<Ordering> {
Some(self.cmp(other))
}
}

82
src/tasks/day19.rs Normal file
View File

@@ -0,0 +1,82 @@
use super::day05::{IntCodeComputer, RAM};
use itertools::Itertools;
use std::collections::HashMap;
#[allow(dead_code)]
pub fn run() {
let program = super::day05::load_ram("input/day19.txt");
part1(&program, 50);
part2(&program);
}
fn part1(program: &RAM, max_perimeter: i128) {
let result = (0..max_perimeter)
.flat_map(|x| {
(0..max_perimeter)
.map(|y| read_coordinate(program, x, y))
.collect_vec()
})
.filter(|v| *v)
.count();
println!("Part 1: {result}");
}
const SHIP_SIZE: i128 = 100;
fn part2(program: &RAM) {
let mut map: HashMap<(i128, i128), bool> = HashMap::new();
(0..SHIP_SIZE).for_each(|x| {
(0..SHIP_SIZE).for_each(|y| {
map.insert((x, y), read_coordinate(program, x, y));
})
});
for perimeter in 0.. {
extend_horizon(program, &mut map, perimeter);
if let Some((x, y)) = check_all_squares_starting_at(&map, perimeter) {
let result = x * 10_000 + y;
println!("Part 2: starts at {x},{y} -> {}", result);
break;
}
}
}
fn check_all_squares_starting_at(
map: &HashMap<(i128, i128), bool>,
perimeter: i128,
) -> Option<(i128, i128)> {
for i in 0..=perimeter {
if let Some(point) = check_fits(map, i, perimeter) {
return Some(point);
}
if let Some(point) = check_fits(map, perimeter, i) {
return Some(point);
}
}
None
}
fn check_fits(map: &HashMap<(i128, i128), bool>, x: i128, y: i128) -> Option<(i128, i128)> {
let ul = map[&(x, y)];
let ur = map[&(x + SHIP_SIZE - 1, y)];
let ll = map[&(x, y + SHIP_SIZE - 1)];
let lr = map[&(x + SHIP_SIZE, y + SHIP_SIZE - 1)];
if ul && ur && ll && lr {
return Some((x, y));
}
None
}
fn extend_horizon(program: &RAM, map: &mut HashMap<(i128, i128), bool>, starts: i128) {
(0..=SHIP_SIZE + starts).for_each(|i| {
let j = SHIP_SIZE + starts;
map.insert((j, i), read_coordinate(program, j, i));
map.insert((i, j), read_coordinate(program, i, j));
});
}
fn read_coordinate(program: &RAM, x: i128, y: i128) -> bool {
let mut computer = IntCodeComputer::new(vec![x, y], program.clone());
computer.run_until_end();
*computer.get_output().first().unwrap() == 1
}

364
src/tasks/day20.rs Normal file
View File

@@ -0,0 +1,364 @@
use std::collections::{HashMap, HashSet, VecDeque};
#[allow(dead_code)]
pub fn run() {
let input = std::fs::read_to_string("input/day20.txt").unwrap();
let maze = Maze::from(&input, PortalField::curried_factory);
let part1 = maze.shortest_path();
println!("Part 1: {}", part1);
let maze = Maze::from(&input, DimensionField::curried_factory);
let part1 = maze.shortest_path();
println!("Part 2: {}", part1);
}
type C = i32;
type FieldFactory = Box<dyn Fn(&MapPoint) -> Box<dyn Field>>;
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)]
struct MapPoint {
x: C,
y: C,
}
impl MapPoint {
fn of(x: C, y: C) -> Self {
MapPoint { x, y }
}
fn neighbors(self) -> Vec<MapPoint> {
vec![
MapPoint::of(self.x + 1, self.y),
MapPoint::of(self.x, self.y + 1),
MapPoint::of(self.x - 1, self.y),
MapPoint::of(self.x, self.y - 1),
]
}
}
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)]
struct RealPoint {
x: C,
y: C,
level: usize,
}
impl RealPoint {
fn map_point(&self) -> MapPoint {
MapPoint {
x: self.x,
y: self.y,
}
}
}
impl RealPoint {
fn from(map_point: MapPoint, level: usize) -> Self {
RealPoint {
x: map_point.x,
y: map_point.y,
level,
}
}
}
trait Field {
fn neighbors(&self, at_level: usize) -> Vec<RealPoint>;
fn set_label_partner(&mut self, point: MapPoint);
fn set_neighbors(&mut self, neighbors: Vec<MapPoint>);
fn curried_factory(width: C, height: C) -> FieldFactory
where
Self: Sized;
}
struct PortalField {
neighbors: Vec<MapPoint>,
}
impl PortalField {
fn new() -> Self {
PortalField { neighbors: vec![] }
}
}
impl Field for PortalField {
fn neighbors(&self, _: usize) -> Vec<RealPoint> {
self.neighbors
.iter()
.map(|p| RealPoint::from(*p, 0))
.collect()
}
fn set_label_partner(&mut self, point: MapPoint) {
self.neighbors.push(point);
}
fn set_neighbors(&mut self, neighbors: Vec<MapPoint>) {
self.neighbors = neighbors;
}
fn curried_factory(_: C, _: C) -> FieldFactory {
Box::new(|_| Box::new(PortalField::new()))
}
}
struct DimensionField {
point: MapPoint,
neighbors: Vec<MapPoint>,
jump: Option<MapPoint>,
map_width: C,
map_height: C,
}
impl DimensionField {
fn is_inward(&self) -> bool {
let p = self.point;
p.x > 2 && p.x < self.map_width - 3 && p.y > 2 && p.y < self.map_height - 3
}
}
impl Field for DimensionField {
fn neighbors(&self, at_level: usize) -> Vec<RealPoint> {
let mut result: Vec<RealPoint> = self
.neighbors
.iter()
.map(|n| RealPoint::from(*n, at_level))
.collect();
if let Some(destination) = self.jump {
if self.is_inward() {
result.push(RealPoint::from(destination, at_level + 1));
} else if at_level > 0 {
result.push(RealPoint::from(destination, at_level - 1));
}
}
result
}
fn set_label_partner(&mut self, point: MapPoint) {
self.jump = Some(point);
}
fn set_neighbors(&mut self, neighbors: Vec<MapPoint>) {
self.neighbors = neighbors;
}
fn curried_factory(width: C, height: C) -> FieldFactory {
Box::new(move |point: &MapPoint| {
Box::new(Self {
point: *point,
neighbors: vec![],
jump: None,
map_width: width,
map_height: height,
})
})
}
}
type FieldMap = HashMap<MapPoint, Box<dyn Field>>;
struct Maze {
map: FieldMap,
start: RealPoint,
finish: RealPoint,
}
impl Maze {
fn from(input: &String, factory: fn(C, C) -> FieldFactory) -> Self {
let (moc, width, height) = Self::map_of_chars(input);
let mut map = Self::create_map_of_free_spots(&moc, factory(width, height));
Self::add_physical_neighbors(&mut map);
let labels = Self::labels(&moc, width, height);
Self::process_labels(&mut map, &labels);
let start = labels["AA"][0];
let finish = labels["ZZ"][0];
Maze {
map,
start: RealPoint::from(start, 0),
finish: RealPoint::from(finish, 0),
}
}
fn shortest_path(&self) -> usize {
bfs(&self.map, self.start, self.finish)
}
fn process_labels(map: &mut FieldMap, labels: &HashMap<String, Vec<MapPoint>>) {
for (label, points) in labels {
if label == "AA" || label == "ZZ" {
continue;
}
map.get_mut(&points[0])
.unwrap()
.set_label_partner(points[1]);
map.get_mut(&points[1])
.unwrap()
.set_label_partner(points[0]);
}
}
fn labels(
moc: &HashMap<MapPoint, char>,
width: C,
height: C,
) -> HashMap<String, Vec<MapPoint>> {
let horizontal: Vec<(String, MapPoint)> = (0..width - 2)
.into_iter()
.flat_map(|x| {
(0..height).into_iter().flat_map(move |y| {
let mut triple = [
moc[&MapPoint::of(x, y)],
moc[&MapPoint::of(x + 1, y)],
moc[&MapPoint::of(x + 2, y)],
];
let left = Self::label(triple).map(|label| (label, MapPoint::of(x, y)));
triple.reverse();
let right = Self::label(triple).map(|label| (label, MapPoint::of(x + 2, y)));
vec![left, right]
})
})
.flatten()
.collect();
let vertical: Vec<(String, MapPoint)> = (0..width)
.into_iter()
.flat_map(|x| {
(0..height - 2).into_iter().flat_map(move |y| {
let mut triple = [
moc[&MapPoint::of(x, y)],
moc[&MapPoint::of(x, y + 1)],
moc[&MapPoint::of(x, y + 2)],
];
let left = Self::label(triple).map(|label| (label, MapPoint::of(x, y)));
triple.reverse();
let right = Self::label(triple).map(|label| (label, MapPoint::of(x, y + 2)));
vec![left, right]
})
})
.flatten()
.collect();
let mut result = HashMap::new();
for (s, p) in horizontal.into_iter().chain(vertical.into_iter()) {
if !result.contains_key(&s) {
result.insert(s.clone(), vec![]);
}
result.get_mut(&s).unwrap().push(p);
}
result
}
fn label(chars: [char; 3]) -> Option<String> {
if chars[0] == '.' && chars[1].is_alphabetic() && chars[2].is_alphabetic() {
let label = if chars[1] < chars[2] {
format!("{}{}", chars[1], chars[2])
} else {
format!("{}{}", chars[2], chars[1])
};
Some(label)
} else {
None
}
}
fn add_physical_neighbors(map: &mut FieldMap) {
let points: HashSet<MapPoint> = map.keys().map(|p| *p).collect();
map.iter_mut().for_each(|(p, f)| {
let neighbors = p
.neighbors()
.into_iter()
.filter(|neighbor| points.contains(neighbor))
.collect();
f.set_neighbors(neighbors);
})
}
fn create_map_of_free_spots(
moc: &HashMap<MapPoint, char>,
field_factory: FieldFactory,
) -> FieldMap {
moc.keys()
.filter(|p| moc[p] == '.')
.map(|p| (*p, field_factory(p)))
.collect()
}
fn map_of_chars(input: &String) -> (HashMap<MapPoint, char>, C, C) {
let mut map: HashMap<MapPoint, char> = input
.lines()
.enumerate()
.flat_map(|(y, line)| {
line.chars()
.enumerate()
.map(move |(x, c)| (MapPoint::of(x as C, y as C), c))
})
.collect();
let width = map.keys().map(|p| p.x).max().unwrap() + 1;
let height = map.keys().map(|p| p.y).max().unwrap() + 1;
for x in 0..width {
for y in 0..height {
if !map.contains_key(&MapPoint::of(x, y)) {
map.insert(MapPoint::of(x, y), ' ');
}
}
}
(map, width, height)
}
}
fn bfs(map: &FieldMap, start: RealPoint, finish: RealPoint) -> usize {
let mut open: VecDeque<(RealPoint, usize)> = VecDeque::new();
let mut seen: HashSet<RealPoint> = HashSet::new();
open.push_back((start, 0));
seen.insert(start);
while let Some((p, d)) = open.pop_front() {
if p == finish {
return d;
}
for neighbor in map[&p.map_point()].neighbors(p.level) {
if !seen.contains(&neighbor) {
open.push_back((neighbor, d + 1));
seen.insert(neighbor);
}
}
}
panic!("no path found")
}
#[cfg(test)]
mod test {
use crate::tasks::day20::{DimensionField, Field, Maze, PortalField};
#[test]
fn example_part1() {
let input = std::fs::read_to_string("input/day20_example1.txt").unwrap();
let maze = Maze::from(&input, PortalField::curried_factory);
assert_eq!(maze.shortest_path(), 23);
}
#[test]
fn example_part2() {
let input = std::fs::read_to_string("input/day20_example2.txt").unwrap();
let maze = Maze::from(&input, DimensionField::curried_factory);
assert_eq!(maze.shortest_path(), 396);
}
#[test]
fn result() {
let input = std::fs::read_to_string("input/day20.txt").unwrap();
let maze = Maze::from(&input, PortalField::curried_factory);
assert_eq!(maze.shortest_path(), 454);
let maze = Maze::from(&input, DimensionField::curried_factory);
assert_eq!(maze.shortest_path(), 5744);
}
}

View File

@@ -1,5 +1,6 @@
use super::day05::*;
#[allow(dead_code)]
pub fn run() {
let input = std::fs::read_to_string("input/day21.txt").unwrap();
let ram: RAM = input
@@ -8,6 +9,7 @@ pub fn run() {
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
.collect();
task1(ram.clone());
task2(ram.clone());
}
fn task1(ram: RAM) {
@@ -23,6 +25,29 @@ WALK
play(ram.clone(), p);
}
fn task2(ram: RAM) {
// jump if NOT(A and B and C) and D and (H or (E and I) or (E and F))
let p = r"OR H J
OR E T
AND I T
OR T J
NOT E T
NOT T T
AND F T
OR T J
AND D J
NOT A T
NOT T T
AND B T
AND C T
NOT T T
AND T J
RUN
"
.to_string();
play(ram.clone(), p);
}
fn play(ram: RAM, program: String) {
let mut computer = IntCodeComputer::new(program.chars().map(|c| c as i128).collect(), ram);
computer.run_until_end();

159
src/tasks/day22.rs Normal file
View File

@@ -0,0 +1,159 @@
use std::collections::VecDeque;
use mod_exp::mod_exp;
use modinverse::modinverse;
use crate::tasks::day22::Cmd::{Cut, Deal, Stack};
pub fn run() {
let input = std::fs::read_to_string("input/day22.txt").unwrap();
println!("Task 1: {}", task1(&input));
println!("Task 2: {}", task2(&input));
}
type Deck = VecDeque<u16>;
type Size = i128;
fn task1(input: &str) -> usize {
let deck_size = 10_007;
let mut deck: Deck = (0..deck_size).collect();
for line in input.lines() {
if line.starts_with("deal into new stack") {
deck = into_new_stack(deck);
} else if line.starts_with("cut") {
let s = line.split("cut ").collect::<Vec<_>>();
let n = s[1].parse::<i32>().unwrap();
deck = cut_cards(deck, n);
} else if line.starts_with("deal with increment") {
let s = line.split("deal with increment ").collect::<Vec<_>>();
let n = s[1].parse::<usize>().unwrap();
deck = deal_with_increment(deck, n);
}
}
let pos_2019 = deck
.iter()
.enumerate()
.find_map(|(i, card)| if *card == 2019 { Some(i) } else { None });
println!("Result: {:?}", pos_2019);
pos_2019.unwrap()
}
fn into_new_stack(deck: Deck) -> Deck {
deck.into_iter().rev().collect()
}
fn cut_cards(mut deck: Deck, n: i32) -> Deck {
if n > 0 {
deck.rotate_left(n as usize);
} else {
deck.rotate_right(-n as usize);
};
deck
}
fn deal_with_increment(deck: Deck, n: usize) -> Deck {
let mut new = vec![0; deck.len()];
let mut index = 0;
for card in deck.into_iter() {
new[index] = card;
index = (index + n) % new.len();
}
new.into_iter().collect()
}
#[derive(Clone, Copy)]
enum Cmd { Stack, Cut(i128), Deal(i128) }
// I don't understand this solution but I copied it because I wanted the last star :> (c) AxlLind@github
fn task2(input: &String) -> Size {
const M: i128 = 119_315_717_514_047;
const N: i128 = 101_741_582_076_661;
let commands: Vec<_> = input.lines().map(|line| {
if line.starts_with("deal into new stack") {
Stack
} else if line.starts_with("cut") {
let s = line.split("cut ").collect::<Vec<_>>();
let n = s[1].parse::<i128>().unwrap();
Cut(n)
} else if line.starts_with("deal with increment") {
let s = line.split("deal with increment ").collect::<Vec<_>>();
let n = s[1].parse::<i128>().unwrap();
Deal(n)
} else {
panic!("'{line}' is illegal")
}
}).collect();
// Convert the whole process to a linear equation: ax + b
let (a, b) = commands.iter().rev().fold((1, 0), |(a, b), &cmd| {
let (a_new, b_new) = match cmd {
Stack => (-a, -b - 1),
Cut(n) => (a, b + n),
Deal(n) => {
let n = mod_exp(n, M - 2, M);
(a * n, b * n)
}
};
(a_new % M, b_new % M)
});
// Applying the function n times simplifies to:
// x * a^n + b * (a^n - 1) / (a-1)
let term1 = 2020 * mod_exp(a, N, M) % M;
let tmp = (mod_exp(a, N, M) - 1) * mod_exp(a - 1, M - 2, M) % M;
let term2 = b * tmp % M;
(term1 + term2) % M
}
fn revert_iteration_find_start(shuffles: &Vec<String>, deck_size: Size, field_after: Size) -> Size {
let mut current: Size = field_after;
for line in shuffles {
if line.starts_with("deal into new stack") {
current = deck_size - 1 - current;
} else if line.starts_with("cut") {
let s = line.split("cut ").collect::<Vec<_>>();
let n = s[1].parse::<Size>().unwrap();
current += n;
current += deck_size;
current %= deck_size;
} else if line.starts_with("deal with increment") {
let s = line.split("deal with increment ").collect::<Vec<_>>();
let n = s[1].parse::<Size>().unwrap();
current = revert_finite_field_multiplikation(deck_size, n, current);
}
}
current
}
fn revert_finite_field_multiplikation(
field_length: Size,
multiplicator: Size,
result: Size,
) -> Size {
let multiplicator_inverse =
modinverse(multiplicator, field_length).expect("no modular inverse found");
(result * multiplicator_inverse) % field_length
}
#[cfg(test)]
mod test {
use crate::tasks::day22::task1;
use crate::tasks::day22::task2;
#[test]
fn part1() {
let input = std::fs::read_to_string("input/day22.txt").unwrap();
assert_eq!(7545, task1(&input));
}
#[test]
fn part2() {
let input = std::fs::read_to_string("input/day22.txt").unwrap();
assert_eq!(2019, task2(&input));
}
}

100
src/tasks/day23.rs Normal file
View File

@@ -0,0 +1,100 @@
use std::collections::VecDeque;
use crate::tasks::day05::{IntCodeComputer, load_ram, RAM};
#[allow(dead_code)]
pub fn run() {
let ram = load_ram("input/day23.txt");
part1(ram.clone());
part2(ram.clone());
}
fn part1(ram: RAM) {
let mut computers: Vec<IntCodeComputer> = (0..50).map(|address| IntCodeComputer::new(vec![address], ram.clone())).collect();
let mut buffer: VecDeque<Packet> = VecDeque::new();
loop {
for computer in &mut computers {
computer.add_input(&[-1]);
computer.run_until_input_empty();
if computer.get_output().len() >= 3 {
buffer.push_back(Packet::from(&computer.get_output()[0..3]));
computer.clear_n_output(3);
}
}
while let Some(packet) = buffer.pop_front() {
if packet.destination == 255 {
println!("Part 1: Finished with first y={} to 255", packet.y);
return;
}
computers[packet.destination].add_input(packet.to_input().as_slice());
}
}
}
fn part2(ram: RAM) {
let mut computers: Vec<IntCodeComputer> = (0..50).map(|address| IntCodeComputer::new(vec![address], ram.clone())).collect();
let mut buffer: VecDeque<Packet> = VecDeque::new();
let mut rounds_without_packets = 0;
let mut nat_content: Option<Packet> = None;
let mut pushed_to_first: Vec<Packet> = Vec::new();
loop {
for computer in &mut computers {
if computer.get_input().is_empty() {
computer.add_input(&[-1, -1, -1]);
}
computer.run_until_input_empty();
while computer.get_output().len() >= 3 {
buffer.push_back(Packet::from(&computer.get_output()[0..3]));
computer.clear_n_output(3);
}
}
if buffer.is_empty() {
rounds_without_packets += 1;
}
if let Some(ref energy_packet) = nat_content {
if rounds_without_packets > 5 {
if let Some(last) = pushed_to_first.last() {
if last == energy_packet {
println!("Part 2: Got the same packet twice. Y was {}", last.y);
return;
}
}
pushed_to_first.push(energy_packet.clone());
buffer.push_back(energy_packet.clone());
rounds_without_packets = 0;
}
}
while let Some(packet) = buffer.pop_front() {
if packet.destination == 255 {
nat_content = Some(Packet { destination: 0, x: packet.x, y: packet.y });
continue;
}
computers[packet.destination].add_input(packet.to_input().as_slice());
}
}
}
#[derive(Clone, PartialEq, Debug)]
struct Packet {
destination: usize,
x: i128,
y: i128,
}
impl Packet {
fn from(slice: &[i128]) -> Packet {
if slice.len() != 3 {
panic!("not enough for a packet")
}
Packet { destination: slice[0] as usize, x: slice[1], y: slice[2] }
}
fn to_input(&self) -> Vec<i128> {
vec![self.x, self.y]
}
}

352
src/tasks/day24.rs Normal file
View File

@@ -0,0 +1,352 @@
use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use std::fmt;
use Tile::*;
#[allow(dead_code)]
pub fn run() {
let input = "..#.#
#####
.#?..
...#.
##...
";
let _einput = "....#
#..#.
#..##
..#..
#....";
task1(Life::from(input));
task2(input);
}
fn task1(mut life: Life) {
let mut hashes = HashMap::<Life, usize>::new();
hashes.insert(life.clone(), 0);
for round in 1.. {
life.round();
if hashes.contains_key(&life) {
break;
} else {
hashes.insert(life.clone(), round);
}
}
println!(
"Task 1: bio diversity of first reoccuring state is {}",
life.bio_diversity()
);
}
fn task2(input: &str) {
let mut state: HashMap<Field, Tile> = input
.lines()
.enumerate()
.flat_map(|(y, line)| {
line.chars()
.enumerate()
.filter_map(|(x, c)| {
if c == '#' || c == '.' {
Some((
Field(0, x as i32, y as i32),
if c == '#' { Bug } else { Empty },
))
} else {
None
}
})
.collect_vec()
})
.collect();
for _round in 1..=200 {
let new: HashMap<Field, Tile> = state
.keys()
.map(|field| {
let v = field
.neighbors()
.iter()
.chain(std::iter::once(field))
.map(|f| *f)
.collect_vec();
v
})
.flatten()
.map(|f| (f, new_state_of(f, &state)))
.collect();
state = new;
}
let bug_count = state.iter().filter(|(_k, tile)| **tile == Bug).count();
println!("Task 2: we have {} bugs overall", bug_count);
}
#[allow(dead_code)]
fn print_levels(state: &HashMap<Field, Tile>, mark_neighbors: Field) {
let mut levels = state
.iter()
.map(|(Field(level, _, _), _)| *level)
.collect::<HashSet<i32>>()
.into_iter()
.collect_vec();
levels.sort();
let neighbors = mark_neighbors.neighbors();
for level in levels {
println!("Depth {}:", level);
for y in 0..5 {
for x in 0..5 {
let c = if x == 2 && y == 2 {
'?'
} else if Field(level, x, y) == mark_neighbors {
'O'
} else if neighbors.contains(&Field(level, x, y)) {
'x'
} else if let Some(tile) = state.get(&Field(level, x, y)) {
match tile {
Bug => '#',
Empty => '.',
}
} else {
'*'
};
print!("{}", c);
}
println!("");
}
}
}
fn new_state_of(field: Field, state: &HashMap<Field, Tile>) -> Tile {
let at = |f| *state.get(&f).unwrap_or(&Empty);
let old = at(field);
if at(field) == Bug {
if field
.neighbors()
.into_iter()
.filter(|p| at(*p) == Bug)
.count()
!= 1
{
Empty
} else {
old
}
} else {
let count = field
.neighbors()
.into_iter()
.filter(|p| at(*p) == Bug)
.count();
if count == 1 || count == 2 {
Bug
} else {
old
}
}
}
#[derive(Eq, PartialEq, Hash, Clone, Copy, Debug)]
struct Field(i32, i32, i32);
impl Field {
fn neighbors(&self) -> Vec<Self> {
let mut res = vec![
Self(self.0, self.1 - 1, self.2),
Self(self.0, self.1 + 1, self.2),
Self(self.0, self.1, self.2 - 1),
Self(self.0, self.1, self.2 + 1),
];
res.retain(|p| !(p.1 == 2 && p.2 == 2) && ((0..5).contains(&p.1) && (0..5).contains(&p.2)));
// link to higher level
if self.1 == 0 {
res.push(Self(self.0 - 1, 1, 2));
}
if self.1 == 4 {
res.push(Self(self.0 - 1, 3, 2));
}
if self.2 == 0 {
res.push(Self(self.0 - 1, 2, 1));
}
if self.2 == 4 {
res.push(Self(self.0 - 1, 2, 3));
}
// link to lower level
match self {
Field(lvl, 2, 1) => (0..5).for_each(|x| res.push(Self(lvl + 1, x, 0))),
Field(lvl, 2, 3) => (0..5).for_each(|x| res.push(Self(lvl + 1, x, 4))),
Field(lvl, 1, 2) => (0..5).for_each(|y| res.push(Self(lvl + 1, 0, y))),
Field(lvl, 3, 2) => (0..5).for_each(|y| res.push(Self(lvl + 1, 4, y))),
_ => (),
}
res
}
}
#[derive(PartialEq, Eq, Hash, Clone)]
struct Life {
area: [[Tile; 5]; 5],
}
impl Life {
fn from(string: &str) -> Self {
let vecs = string
.lines()
.map(|line| {
line.chars()
.map(|c| if c == '#' { Bug } else { Empty })
.collect_vec()
})
.collect_vec();
assert_eq!(5, vecs.len());
assert_eq!(5, vecs[0].len());
let mut life = Life {
area: [[Empty; 5]; 5],
};
for x in 0..5 {
for y in 0..5 {
life.area[x][y] = vecs[y][x];
}
}
life
}
fn at(&self, pos: Pos) -> Tile {
if (0..5).contains(&pos.0) && (0..5).contains(&pos.1) {
self.area[pos.0 as usize][pos.1 as usize]
} else {
Empty
}
}
fn round(&mut self) {
let mut new = self.area.clone();
for y in 0..5 {
for x in 0..5 {
if self.at(Pos(x, y)) == Bug {
if Pos(x, y)
.neighbors()
.iter()
.filter(|p| self.at(**p) == Bug)
.count()
!= 1
{
new[x as usize][y as usize] = Empty;
}
} else {
let count = Pos(x, y)
.neighbors()
.iter()
.filter(|p| self.at(**p) == Bug)
.count();
if count == 1 || count == 2 {
new[x as usize][y as usize] = Bug;
}
}
}
}
self.area = new;
}
fn bio_diversity(&self) -> usize {
(0..5)
.map(|x| {
(0..5)
.map(|y| {
if self.at(Pos(x, y)).is_bug() {
let v = 1usize.wrapping_shl((5 * y + x) as u32);
v
} else {
0 as usize
}
})
.sum::<usize>()
})
.sum()
}
}
impl fmt::Display for Life {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for y in 0..5 {
for x in 0..5 {
let r = write!(f, "{}", self.area[x][y]);
if let fmt::Result::Err(_) = r {
return r;
}
}
let r = writeln!(f, "");
if let fmt::Result::Err(_) = r {
return r;
}
}
fmt::Result::Ok(())
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
enum Tile {
Bug,
Empty,
}
impl Tile {
fn is_bug(&self) -> bool {
*self == Bug
}
}
impl fmt::Display for Tile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match self {
Bug => '#',
Empty => '.',
}
)
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct Pos(i32, i32);
impl Pos {
fn neighbors(&self) -> [Pos; 4] {
[
Pos(self.0 - 1, self.1),
Pos(self.0 + 1, self.1),
Pos(self.0, self.1 - 1),
Pos(self.0, self.1 + 1),
]
}
}
#[allow(unused)]
mod test {
use super::Field;
#[test]
fn neighborhood_bijective() {
for x in 0..5 {
for y in 0..5 {
if x == 2 && y == 2 {
continue;
}
let field = Field(0, x, y);
let neighbors = field.neighbors();
neighbors.into_iter().for_each(|n| {
assert_eq!(
n.neighbors().contains(&field),
true,
"{:?} is not a neighbor of its neighbor {:?}",
field,
n
);
});
}
}
}
}

44
src/tasks/day25.rs Normal file
View File

@@ -0,0 +1,44 @@
use std::io;
use crate::tasks::day05::{IntCodeComputer, load_ram};
#[allow(dead_code)]
pub fn run() {
let ram = load_ram("input/day25.txt");
let mut computer = IntCodeComputer::new(vec![], ram);
loop {
let done = computer.run_until_input_empty();
println!("{}", to_ascii(computer.get_output()));
computer.clear_output();
if done {
println!("Game Over");
return;
}
let input = read_line();
computer.set_input(&input);
}
// needed items:
// fixed point
// polygon
// candy cane
// shell
// result: 136839232
}
fn to_ascii(output: &[i128]) -> String {
output.iter().map(|i| (*i as u8) as char).collect()
}
fn read_line() -> Vec<i128> {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).unwrap();
if !buffer.is_ascii() {
panic!("'{}' is not ascii input", buffer);
}
buffer.chars().map(|c| c as i128).collect()
}

View File

@@ -11,5 +11,15 @@ pub mod day11;
pub mod day12;
pub mod day13;
pub mod day14;
pub mod day15;
pub mod day16;
pub mod day17;
pub mod day18;
pub mod day19;
pub mod day20;
pub mod day21;
#[allow(dead_code)]
pub mod day22;
pub mod day23;
pub mod day24;
pub mod day25;