Compare commits

...

56 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
Johannes
2040bc00aa day 21 task 1 2019-12-21 11:49:40 +01:00
Johannes
f2117fd2a8 day 16 task 1 2019-12-16 18:32:10 +01:00
Johannes
e8b911fac0 day12 task 2 2019-12-15 11:46:40 +01:00
Johannes
71d068ab2c day 14 task 2 2019-12-14 22:01:01 +01:00
Johannes
83dce003d8 day 14 task 1 2019-12-14 21:29:36 +01:00
Johannes
9a2531b982 day 13 task 2 UI fix 2019-12-14 18:11:05 +01:00
Johannes
b67ed69f7d day 13 task 2 2019-12-14 18:02:24 +01:00
Johannes
ad3b71b159 day 13 task 1 2019-12-14 16:53:42 +01:00
Johannes
eb7467f615 day12 task 1 2019-12-12 16:27:27 +01:00
Johannes
8849191a6b day11 task 2 2019-12-12 11:40:05 +01:00
Johannes
009d1b8f86 day11 task 1 2019-12-12 11:32:38 +01:00
Johannes
f28caa727d day10 task 2 2019-12-11 20:16:14 +01:00
Johannes
0f17084f18 day10 task 1 2019-12-11 18:07:39 +01:00
Johannes
d3ef4235a0 day10 task 1 beginning 2019-12-10 22:12:10 +01:00
Johannes
3917746851 day09 task 2 2019-12-09 23:04:03 +01:00
Johannes
17e0eea8dc day09 task 1 2019-12-09 23:02:09 +01:00
Johannes
2dc626e227 day09 prepared IntCodeComputer to use HashSet memory and new intructions 2019-12-09 23:01:55 +01:00
Johannes
676fb13a59 cleaned up double code in IntCodeComputer 2019-12-08 21:06:08 +01:00
43 changed files with 3488 additions and 131 deletions

1
.gitignore vendored
View File

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

136
Cargo.lock generated
View File

@@ -1,25 +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.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "aoc_2019"
version = "0.1.0"
dependencies = [
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools",
"mod_exp",
"modinverse",
"num-integer",
"regex",
]
[[package]]
name = "autocfg"
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",
]
[metadata]
"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"
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
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.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"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.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "regex"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"

View File

@@ -2,9 +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"
itertools = "0.10.3"
regex = "1.5.5"
num-integer = "0.1.44"
modinverse = "0.1.1"
mod_exp = "1.0.1"

1
input/day09.txt Normal file
View File

@@ -0,0 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,0,0,1020,1101,34,0,1004,1101,0,26,1008,1102,1,37,1011,1101,39,0,1018,1102,587,1,1022,1101,1,0,1021,1102,22,1,1012,1101,0,33,1014,1101,24,0,1016,1101,0,752,1029,1101,36,0,1002,1101,35,0,1006,1101,32,0,1009,1102,38,1,1003,1102,584,1,1023,1101,0,20,1001,1102,892,1,1025,1102,29,1,1000,1101,411,0,1026,1102,1,901,1024,1101,0,761,1028,1101,23,0,1017,1102,30,1,1013,1101,0,27,1015,1102,28,1,1005,1101,408,0,1027,1101,25,0,1007,1102,31,1,1019,1101,0,21,1010,109,5,1207,-2,39,63,1005,63,199,4,187,1105,1,203,1001,64,1,64,1002,64,2,64,109,12,21102,40,1,-1,1008,1016,40,63,1005,63,229,4,209,1001,64,1,64,1106,0,229,1002,64,2,64,109,-5,1207,-5,24,63,1005,63,249,1001,64,1,64,1106,0,251,4,235,1002,64,2,64,109,-14,2102,1,6,63,1008,63,32,63,1005,63,271,1106,0,277,4,257,1001,64,1,64,1002,64,2,64,109,2,1202,1,1,63,1008,63,20,63,1005,63,303,4,283,1001,64,1,64,1106,0,303,1002,64,2,64,109,7,2108,34,2,63,1005,63,319,1106,0,325,4,309,1001,64,1,64,1002,64,2,64,109,6,2101,0,-6,63,1008,63,24,63,1005,63,349,1001,64,1,64,1105,1,351,4,331,1002,64,2,64,109,4,21107,41,42,0,1005,1017,369,4,357,1105,1,373,1001,64,1,64,1002,64,2,64,109,5,21101,42,0,-5,1008,1017,41,63,1005,63,397,1001,64,1,64,1106,0,399,4,379,1002,64,2,64,109,9,2106,0,-4,1106,0,417,4,405,1001,64,1,64,1002,64,2,64,109,-20,21108,43,43,0,1005,1011,435,4,423,1105,1,439,1001,64,1,64,1002,64,2,64,109,-15,2102,1,8,63,1008,63,34,63,1005,63,465,4,445,1001,64,1,64,1105,1,465,1002,64,2,64,109,3,1201,6,0,63,1008,63,28,63,1005,63,491,4,471,1001,64,1,64,1106,0,491,1002,64,2,64,109,18,21108,44,46,0,1005,1017,511,1001,64,1,64,1106,0,513,4,497,1002,64,2,64,109,12,1205,-8,527,4,519,1105,1,531,1001,64,1,64,1002,64,2,64,109,-17,1208,-3,32,63,1005,63,553,4,537,1001,64,1,64,1105,1,553,1002,64,2,64,109,-13,1208,10,31,63,1005,63,573,1001,64,1,64,1105,1,575,4,559,1002,64,2,64,109,17,2105,1,7,1105,1,593,4,581,1001,64,1,64,1002,64,2,64,109,-8,2107,19,-7,63,1005,63,615,4,599,1001,64,1,64,1105,1,615,1002,64,2,64,109,4,1206,8,629,4,621,1106,0,633,1001,64,1,64,1002,64,2,64,109,-2,2101,0,-6,63,1008,63,34,63,1005,63,655,4,639,1105,1,659,1001,64,1,64,1002,64,2,64,109,10,1205,0,671,1105,1,677,4,665,1001,64,1,64,1002,64,2,64,109,-21,2107,26,8,63,1005,63,693,1106,0,699,4,683,1001,64,1,64,1002,64,2,64,109,19,1201,-9,0,63,1008,63,30,63,1005,63,719,1105,1,725,4,705,1001,64,1,64,1002,64,2,64,109,9,1206,-6,741,1001,64,1,64,1106,0,743,4,731,1002,64,2,64,109,-5,2106,0,6,4,749,1001,64,1,64,1105,1,761,1002,64,2,64,109,-14,1202,-1,1,63,1008,63,27,63,1005,63,781,1105,1,787,4,767,1001,64,1,64,1002,64,2,64,109,1,21107,45,44,5,1005,1014,807,1001,64,1,64,1105,1,809,4,793,1002,64,2,64,109,8,21101,46,0,0,1008,1017,46,63,1005,63,835,4,815,1001,64,1,64,1106,0,835,1002,64,2,64,109,-26,2108,20,10,63,1005,63,857,4,841,1001,64,1,64,1106,0,857,1002,64,2,64,109,24,21102,47,1,-5,1008,1010,46,63,1005,63,881,1001,64,1,64,1106,0,883,4,863,1002,64,2,64,109,6,2105,1,3,4,889,1001,64,1,64,1105,1,901,4,64,99,21102,27,1,1,21101,915,0,0,1105,1,922,21201,1,29830,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,0,942,0,1105,1,922,21202,1,1,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1105,1,968,21201,-2,0,-2,109,-3,2106,0,0

24
input/day10.txt Normal file
View File

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

1
input/day11.txt Normal file
View File

@@ -0,0 +1 @@
3,8,1005,8,361,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,1001,8,0,28,2,1104,18,10,1006,0,65,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,57,1,1101,5,10,2,108,15,10,2,102,12,10,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,91,2,1005,4,10,2,1107,10,10,1006,0,16,2,109,19,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,129,1,104,3,10,1,1008,9,10,1006,0,65,1,104,5,10,3,8,1002,8,-1,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,165,1,1106,11,10,1,1106,18,10,1,8,11,10,1,4,11,10,3,8,1002,8,-1,10,101,1,10,10,4,10,108,1,8,10,4,10,1001,8,0,203,2,1003,11,10,1,1105,13,10,1,101,13,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,101,0,8,237,2,7,4,10,1006,0,73,1,1003,7,10,1006,0,44,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,101,0,8,273,2,108,14,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,299,1,1107,6,10,1006,0,85,1,1107,20,10,1,1008,18,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,1001,8,0,337,2,107,18,10,101,1,9,9,1007,9,951,10,1005,10,15,99,109,683,104,0,104,1,21102,1,825594852248,1,21101,378,0,0,1105,1,482,21101,0,387240006552,1,21101,0,389,0,1106,0,482,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,29032025091,1,21101,436,0,0,1106,0,482,21101,29033143299,0,1,21102,1,447,0,1105,1,482,3,10,104,0,104,0,3,10,104,0,104,0,21101,988669698916,0,1,21101,0,470,0,1106,0,482,21101,0,709052072804,1,21102,1,481,0,1106,0,482,99,109,2,21202,-1,1,1,21101,0,40,2,21101,0,513,3,21101,503,0,0,1106,0,546,109,-2,2105,1,0,0,1,0,0,1,109,2,3,10,204,-1,1001,508,509,524,4,0,1001,508,1,508,108,4,508,10,1006,10,540,1101,0,0,508,109,-2,2105,1,0,0,109,4,1202,-1,1,545,1207,-3,0,10,1006,10,563,21102,0,1,-3,21202,-3,1,1,22101,0,-2,2,21102,1,1,3,21101,582,0,0,1105,1,587,109,-4,2106,0,0,109,5,1207,-3,1,10,1006,10,610,2207,-4,-2,10,1006,10,610,21202,-4,1,-4,1106,0,678,22102,1,-4,1,21201,-3,-1,2,21202,-2,2,3,21102,629,1,0,1106,0,587,22102,1,1,-4,21101,0,1,-1,2207,-4,-2,10,1006,10,648,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,670,21202,-1,1,1,21101,670,0,0,105,1,545,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0

4
input/day12.txt Normal file
View File

@@ -0,0 +1,4 @@
<x=19, y=-10, z=7>
<x=1, y=2, z=-3>
<x=14, y=-4, z=1>
<x=8, y=7, z=-6>

1
input/day13.txt Normal file

File diff suppressed because one or more lines are too long

54
input/day14.txt Normal file
View File

@@ -0,0 +1,54 @@
156 ORE => 6 TLFQZ
1 SZFV => 5 TNXGD
1 BQLJ, 3 VNKPF => 8 BQXZ
43 FPRFS, 5 CQJT, 20 LDKTQ, 48 ZPBLH, 21 MFVG, 43 WLWZQ, 1 ZWZQ, 11 PQZJP, 56 CTJGD, 35 SGDVW => 1 FUEL
11 BQXZ, 1 PRCSN => 7 DVFD
7 VWXB, 2 PRCSN, 24 VJSR, 9 MDWCG, 4 MFVG => 4 ZWZQ
32 BQXZ, 5 XDSHP, 16 KTXJR, 7 VJSR, 3 MDWCG, 11 KZFZG, 3 NVBN => 5 ZPBLH
2 BQLJ, 2 RSKH, 3 VWXB => 2 GWXCF
6 PRCSN, 1 NCRZ => 8 VJSR
5 TMQLD => 9 VDQL
9 MZQZS, 1 FLRB => 5 BQLJ
4 KLHS => 5 PQZJP
1 WJTS, 1 NCRZ, 27 XDSHP => 8 MFVG
1 FNXMV, 30 FPKM => 8 RDMDL
1 TNXGD, 21 XBCLW, 5 CWNV => 3 RSKH
4 KQFPJ => 2 NCRZ
10 CWNV, 8 HSXW => 9 FNXMV
2 TNXGD, 4 CWNV, 13 VJSR => 8 KTXJR
3 NCRZ, 1 GWXCF, 8 NVBN, 6 MDWCG, 3 VWXB, 4 KTXJR, 4 DVFD, 3 QXCV => 9 FPRFS
5 MZQZS, 9 TBVRN => 7 SZFV
37 GWXCF, 15 RDMDL, 2 MDWCG => 7 CQJT
1 VDQL, 2 HSXW => 4 NVBN
18 QHMTL, 7 FLRB, 1 SZFV => 3 FPKM
6 VDQL => 1 FNCN
3 QPHT => 7 LDKTQ
1 TLFQZ => 8 FWFR
7 VDQL, 8 KZFZG => 3 HSXW
9 TBVRN => 7 MZQZS
1 FLRB, 44 VNKPF, 1 LVZF => 8 QXCV
1 WLWZQ, 3 TBVRN, 4 TLFQZ => 9 KQFPJ
1 BQLJ, 1 PRCSN, 8 DHTNG => 5 VWXB
1 XDSHP, 6 NVBN => 1 BDGC
8 PRCSN, 1 DHTNG => 2 WJTS
19 DHTNG, 22 WLWZQ => 9 LVZF
185 ORE => 7 WLWZQ
1 TMQLD, 1 MZQZS => 8 KZFZG
111 ORE => 4 TBVRN
31 VDQL, 14 MZQZS => 7 XBCLW
6 VDQL, 3 KVPK => 9 SGDVW
1 FNCN => 6 QMKT
1 FNCN, 3 TMQLD => 7 VNKPF
2 QPHT => 6 VQXCJ
2 LDKTQ, 3 VQXCJ => 5 FLRB
1 FNCN, 3 FPKM, 1 SZFV => 2 DHTNG
1 KZFZG => 9 QHMTL
141 ORE => 5 QPHT
16 TNXGD => 9 CWNV
1 KQFPJ, 29 FWFR => 2 KVPK
1 TNXGD, 7 KLHS => 2 XDSHP
7 WJTS => 6 MDWCG
3 BDGC, 3 XDSHP, 1 NCRZ => 4 CTJGD
3 QMKT => 6 PRCSN
24 FWFR => 2 TMQLD
8 VNKPF => 3 KLHS

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

1
input/day21.txt Normal file

File diff suppressed because one or more lines are too long

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 +0,0 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1102,68,5,225,1101,71,12,225,1,117,166,224,1001,224,-100,224,4,224,102,8,223,223,101,2,224,224,1,223,224,223,1001,66,36,224,101,-87,224,224,4,224,102,8,223,223,101,2,224,224,1,223,224,223,1101,26,51,225,1102,11,61,224,1001,224,-671,224,4,224,1002,223,8,223,1001,224,5,224,1,223,224,223,1101,59,77,224,101,-136,224,224,4,224,1002,223,8,223,1001,224,1,224,1,223,224,223,1101,11,36,225,1102,31,16,225,102,24,217,224,1001,224,-1656,224,4,224,102,8,223,223,1001,224,1,224,1,224,223,223,101,60,169,224,1001,224,-147,224,4,224,102,8,223,223,101,2,224,224,1,223,224,223,1102,38,69,225,1101,87,42,225,2,17,14,224,101,-355,224,224,4,224,102,8,223,223,1001,224,2,224,1,224,223,223,1002,113,89,224,101,-979,224,224,4,224,1002,223,8,223,1001,224,7,224,1,224,223,223,1102,69,59,225,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,7,677,677,224,1002,223,2,223,1006,224,329,1001,223,1,223,1007,226,226,224,1002,223,2,223,1006,224,344,1001,223,1,223,1108,226,677,224,102,2,223,223,1005,224,359,1001,223,1,223,1107,226,677,224,1002,223,2,223,1006,224,374,101,1,223,223,1107,677,226,224,1002,223,2,223,1006,224,389,101,1,223,223,7,226,677,224,1002,223,2,223,1005,224,404,101,1,223,223,1008,677,226,224,102,2,223,223,1005,224,419,101,1,223,223,1008,226,226,224,102,2,223,223,1006,224,434,101,1,223,223,107,226,226,224,1002,223,2,223,1005,224,449,1001,223,1,223,108,226,677,224,102,2,223,223,1005,224,464,101,1,223,223,1108,677,226,224,102,2,223,223,1005,224,479,101,1,223,223,1007,226,677,224,102,2,223,223,1006,224,494,101,1,223,223,107,677,677,224,102,2,223,223,1005,224,509,101,1,223,223,108,677,677,224,102,2,223,223,1006,224,524,1001,223,1,223,8,226,677,224,102,2,223,223,1005,224,539,101,1,223,223,107,677,226,224,102,2,223,223,1005,224,554,1001,223,1,223,8,226,226,224,102,2,223,223,1006,224,569,1001,223,1,223,7,677,226,224,1002,223,2,223,1005,224,584,1001,223,1,223,1108,226,226,224,102,2,223,223,1005,224,599,1001,223,1,223,1107,677,677,224,1002,223,2,223,1006,224,614,1001,223,1,223,1007,677,677,224,1002,223,2,223,1006,224,629,1001,223,1,223,108,226,226,224,102,2,223,223,1005,224,644,1001,223,1,223,8,677,226,224,1002,223,2,223,1005,224,659,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226

View File

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

View File

@@ -1,19 +1,35 @@
use std::collections::HashMap;
use std::path::Path;
pub type RAM = HashMap<usize, i128>;
#[allow(dead_code)]
pub fn run() {
let input = std::fs::read_to_string("input/day05.txt").unwrap();
let ram: Vec<i32> = input
let ram: RAM = input
.split(",")
.map(|s| s.parse::<i32>().unwrap())
.enumerate()
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
.collect();
task1(ram.clone());
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<i32>,
output_storage: Vec<i32>,
input_storage: Vec<i128>,
output_storage: Vec<i128>,
pc: usize,
ram: Vec<i32>,
ram: RAM,
relative_base_offset: i128,
}
#[derive(PartialEq, Debug)]
@@ -26,35 +42,44 @@ enum OpCode {
JumpIfFalse,
LessThan,
Equals,
AdjustRelBase,
Terminate,
}
#[derive(Debug)]
enum OpParam {
Immediate(i32),
Immediate(i128),
Memory(usize),
Relative(i128),
}
impl OpParam {
fn from(val: i32, type_number: i32) -> Self {
fn from(val: i128, type_number: i128) -> Self {
match type_number {
0 => OpParam::Memory(val as usize),
1 => OpParam::Immediate(val),
2 => OpParam::Relative(val),
_ => unreachable!("unexpected parameter"),
}
}
fn retrieve(&self, memory: &Vec<i32>) -> i32 {
fn retrieve(&self, memory: &RAM, relative_base_offset: i128) -> i128 {
match self {
OpParam::Immediate(v) => *v,
OpParam::Memory(i) => memory[*i],
OpParam::Memory(i) => memory.get_default(*i),
OpParam::Relative(i) => memory.get_default((relative_base_offset + *i) as usize),
}
}
fn store(&self, memory: &mut Vec<i32>, value: i32) {
fn store(&self, memory: &mut RAM, value: i128, relative_base_offset: i128) {
match self {
OpParam::Immediate(_) => panic!("cannot save to immediate position"),
OpParam::Memory(i) => memory[*i] = value,
OpParam::Memory(i) => {
memory.insert(*i, value);
}
OpParam::Relative(i) => {
memory.insert((relative_base_offset + *i) as usize, value);
}
}
}
}
@@ -66,9 +91,9 @@ struct Op {
}
impl Op {
fn from(pc: usize, memory: &Vec<i32>) -> Self {
fn from(pc: usize, memory: &RAM) -> Self {
//opcode: 123xx -> 1, 2, 3: parameter type for parameters 1-3, xx = actual op code
let mut opcode = memory[pc];
let mut opcode = memory.get_default(pc);
let p_type1 = opcode / 10_000;
opcode %= 10_000;
let p_type2 = opcode / 1000;
@@ -79,57 +104,61 @@ impl Op {
1 => Op {
opcode: OpCode::Add,
params: vec![
OpParam::from(memory[pc + 1], p_type3),
OpParam::from(memory[pc + 2], p_type2),
OpParam::from(memory[pc + 3], p_type1),
OpParam::from(memory.get_default(pc + 1), p_type3),
OpParam::from(memory.get_default(pc + 2), p_type2),
OpParam::from(memory.get_default(pc + 3), p_type1),
],
},
2 => Op {
opcode: OpCode::Multiply,
params: vec![
OpParam::from(memory[pc + 1], p_type3),
OpParam::from(memory[pc + 2], p_type2),
OpParam::from(memory[pc + 3], p_type1),
OpParam::from(memory.get_default(pc + 1), p_type3),
OpParam::from(memory.get_default(pc + 2), p_type2),
OpParam::from(memory.get_default(pc + 3), p_type1),
],
},
3 => Op {
opcode: OpCode::Input,
params: vec![OpParam::from(memory[pc + 1], p_type3)],
params: vec![OpParam::from(memory.get_default(pc + 1), p_type3)],
},
4 => Op {
opcode: OpCode::Output,
params: vec![OpParam::from(memory[pc + 1], p_type3)],
params: vec![OpParam::from(memory.get_default(pc + 1), p_type3)],
},
5 => Op {
opcode: OpCode::JumpIfTrue,
params: vec![
OpParam::from(memory[pc + 1], p_type3),
OpParam::from(memory[pc + 2], p_type2),
OpParam::from(memory.get_default(pc + 1), p_type3),
OpParam::from(memory.get_default(pc + 2), p_type2),
],
},
6 => Op {
opcode: OpCode::JumpIfFalse,
params: vec![
OpParam::from(memory[pc + 1], p_type3),
OpParam::from(memory[pc + 2], p_type2),
OpParam::from(memory.get_default(pc + 1), p_type3),
OpParam::from(memory.get_default(pc + 2), p_type2),
],
},
7 => Op {
opcode: OpCode::LessThan,
params: vec![
OpParam::from(memory[pc + 1], p_type3),
OpParam::from(memory[pc + 2], p_type2),
OpParam::from(memory[pc + 3], p_type1),
OpParam::from(memory.get_default(pc + 1), p_type3),
OpParam::from(memory.get_default(pc + 2), p_type2),
OpParam::from(memory.get_default(pc + 3), p_type1),
],
},
8 => Op {
opcode: OpCode::Equals,
params: vec![
OpParam::from(memory[pc + 1], p_type3),
OpParam::from(memory[pc + 2], p_type2),
OpParam::from(memory[pc + 3], p_type1),
OpParam::from(memory.get_default(pc + 1), p_type3),
OpParam::from(memory.get_default(pc + 2), p_type2),
OpParam::from(memory.get_default(pc + 3), p_type1),
],
},
9 => Op {
opcode: OpCode::AdjustRelBase,
params: vec![OpParam::from(memory.get_default(pc + 1), p_type3)],
},
99 => Op {
opcode: OpCode::Terminate,
params: vec![],
@@ -140,75 +169,26 @@ impl Op {
}
impl IntCodeComputer {
pub fn new(input: Vec<i32>, memory: Vec<i32>) -> Self {
pub fn new(input: Vec<i128>, memory: RAM) -> Self {
IntCodeComputer {
input_storage: input,
output_storage: Vec::new(),
pc: 0,
ram: memory,
relative_base_offset: 0,
}
}
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) {
let mut op = Op::from(self.pc, &self.ram);
let mut inputs = self.input_storage.iter();
while op.opcode != OpCode::Terminate {
match op.opcode {
OpCode::Add => {
let r = op.params[0].retrieve(&self.ram) + op.params[1].retrieve(&self.ram);
op.params[2].store(&mut self.ram, r);
self.pc += 4;
}
OpCode::Multiply => {
let r = op.params[0].retrieve(&self.ram) * op.params[1].retrieve(&self.ram);
op.params[2].store(&mut self.ram, r);
self.pc += 4;
}
OpCode::Input => {
let v = inputs.next().expect("Not enough inputs given");
op.params[0].store(&mut self.ram, *v);
self.pc += 2;
}
OpCode::Output => {
self.output_storage.push(op.params[0].retrieve(&self.ram));
self.pc += 2;
}
OpCode::JumpIfTrue => {
if op.params[0].retrieve(&self.ram) > 0 {
self.pc = op.params[1].retrieve(&self.ram) as usize;
} else {
self.pc += 3;
}
}
OpCode::JumpIfFalse => {
if op.params[0].retrieve(&self.ram) == 0 {
self.pc = op.params[1].retrieve(&self.ram) as usize;
} else {
self.pc += 3;
}
}
OpCode::LessThan => {
let r = if op.params[0].retrieve(&self.ram) < op.params[1].retrieve(&self.ram) {
1
} else {
0
};
op.params[2].store(&mut self.ram, r);
self.pc += 4;
}
OpCode::Equals => {
let r = if op.params[0].retrieve(&self.ram) == op.params[1].retrieve(&self.ram)
{
1
} else {
0
};
op.params[2].store(&mut self.ram, r);
self.pc += 4;
}
OpCode::Terminate => {}
}
op = Op::from(self.pc, &self.ram);
if !self.run_until_input_empty() {
panic!("There wasn't enough input given to run until the program halted");
}
}
@@ -221,60 +201,74 @@ impl IntCodeComputer {
while op.opcode != OpCode::Terminate {
match op.opcode {
OpCode::Add => {
let r = op.params[0].retrieve(&self.ram) + op.params[1].retrieve(&self.ram);
op.params[2].store(&mut self.ram, r);
let r = op.params[0].retrieve(&self.ram, self.relative_base_offset)
+ op.params[1].retrieve(&self.ram, self.relative_base_offset);
op.params[2].store(&mut self.ram, r, self.relative_base_offset);
self.pc += 4;
}
OpCode::Multiply => {
let r = op.params[0].retrieve(&self.ram) * op.params[1].retrieve(&self.ram);
op.params[2].store(&mut self.ram, r);
let r = op.params[0].retrieve(&self.ram, self.relative_base_offset)
* op.params[1].retrieve(&self.ram, self.relative_base_offset);
op.params[2].store(&mut self.ram, r, self.relative_base_offset);
self.pc += 4;
}
OpCode::Input => {
if let Some(v) = inputs.next() {
op.params[0].store(&mut self.ram, *v);
op.params[0].store(&mut self.ram, *v, self.relative_base_offset);
self.pc += 2;
} else {
self.input_storage.clear();
return false;
}
}
OpCode::Output => {
self.output_storage.push(op.params[0].retrieve(&self.ram));
self.output_storage
.push(op.params[0].retrieve(&self.ram, self.relative_base_offset));
self.pc += 2;
}
OpCode::JumpIfTrue => {
if op.params[0].retrieve(&self.ram) > 0 {
self.pc = op.params[1].retrieve(&self.ram) as usize;
if op.params[0].retrieve(&self.ram, self.relative_base_offset) > 0 {
self.pc =
op.params[1].retrieve(&self.ram, self.relative_base_offset) as usize;
} else {
self.pc += 3;
}
}
OpCode::JumpIfFalse => {
if op.params[0].retrieve(&self.ram) == 0 {
self.pc = op.params[1].retrieve(&self.ram) as usize;
if op.params[0].retrieve(&self.ram, self.relative_base_offset) == 0 {
self.pc =
op.params[1].retrieve(&self.ram, self.relative_base_offset) as usize;
} else {
self.pc += 3;
}
}
OpCode::LessThan => {
let r = if op.params[0].retrieve(&self.ram) < op.params[1].retrieve(&self.ram) {
1
} else {
0
};
op.params[2].store(&mut self.ram, r);
self.pc += 4;
}
OpCode::Equals => {
let r = if op.params[0].retrieve(&self.ram) == op.params[1].retrieve(&self.ram)
let r = if op.params[0].retrieve(&self.ram, self.relative_base_offset)
< op.params[1].retrieve(&self.ram, self.relative_base_offset)
{
1
} else {
0
};
op.params[2].store(&mut self.ram, r);
op.params[2].store(&mut self.ram, r, self.relative_base_offset);
self.pc += 4;
}
OpCode::Equals => {
let r = if op.params[0].retrieve(&self.ram, self.relative_base_offset)
== op.params[1].retrieve(&self.ram, self.relative_base_offset)
{
1
} else {
0
};
op.params[2].store(&mut self.ram, r, self.relative_base_offset);
self.pc += 4;
}
OpCode::AdjustRelBase => {
self.relative_base_offset +=
op.params[0].retrieve(&self.ram, self.relative_base_offset);
self.pc += 2;
}
OpCode::Terminate => {}
}
op = Op::from(self.pc, &self.ram);
@@ -282,32 +276,56 @@ impl IntCodeComputer {
return true;
}
pub fn set_input(&mut self, input: &[i32]) {
pub fn set_input(&mut self, input: &[i128]) {
self.input_storage.clear();
for x in input {
self.input_storage.push(*x);
}
}
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 get_output(&self) -> &[i32] {
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()
}
}
fn task1(ram: Vec<i32>) {
fn task1(ram: RAM) {
let mut computer = IntCodeComputer::new(vec![1], ram);
computer.run_until_end();
println!("{:?}", computer.get_output());
println!("Task 1: {}", computer.get_output().last().unwrap());
}
fn task2(ram: Vec<i32>) {
fn task2(ram: RAM) {
let mut computer = IntCodeComputer::new(vec![5], ram);
computer.run_until_end();
println!("{:?}", computer.get_output());
println!("Task 2: {}", computer.get_output().last().unwrap());
}
trait Easy {
fn get_default(&self, index: usize) -> i128;
}
impl Easy for RAM {
fn get_default(&self, index: usize) -> i128 {
**self.get(&index).get_or_insert(&0)
}
}

View File

@@ -6,20 +6,23 @@ pub fn run() {
let prog_code: Vec<_> = std::fs::read_to_string("input/day07.txt")
.unwrap()
.split(",")
.map(|s| s.parse::<i32>().unwrap())
.map(|s| s.parse::<i128>().unwrap())
.collect();
task1(prog_code.clone());
task2(prog_code.clone());
}
fn task1(input: Vec<i32>) {
fn task1(input: Vec<i128>) {
let phases = vec![0, 1, 2, 3, 4];
let result = phases
.iter()
.permutations(phases.len())
.map(|perm| {
perm.iter().fold(0, |signal, phase| {
let mut computer = IntCodeComputer::new(vec![**phase, signal], input.clone());
let mut computer = IntCodeComputer::new(
vec![**phase, signal],
input.clone().into_iter().enumerate().collect(),
);
computer.run_until_end();
*computer.get_output().last().unwrap()
})
@@ -28,7 +31,7 @@ fn task1(input: Vec<i32>) {
println!("Task 1: best signal is {}", result.unwrap());
}
fn task2(input: Vec<i32>) {
fn task2(input: Vec<i128>) {
let phases = vec![5, 6, 7, 8, 9];
let result = phases
.iter()
@@ -37,7 +40,10 @@ fn task2(input: Vec<i32>) {
let mut machines: Vec<IntCodeComputer> = perm
.iter()
.map(|phase| {
let mut comp = IntCodeComputer::new(vec![**phase], input.clone());
let mut comp = IntCodeComputer::new(
vec![**phase],
input.clone().into_iter().enumerate().collect(),
);
comp.run_until_input_empty();
comp
})

27
src/tasks/day09.rs Normal file
View File

@@ -0,0 +1,27 @@
use super::day05::{IntCodeComputer, RAM};
#[allow(dead_code)]
pub fn run() {
let input = std::fs::read_to_string("input/day09.txt").unwrap();
let ram: RAM = input
.split(",")
.enumerate()
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
.collect();
task1(ram.clone());
task2(ram.clone());
}
fn task1(ram: RAM) {
let mut computer = IntCodeComputer::new(vec![1], ram);
computer.run_until_end();
println!("{:?}", computer.get_output());
println!("Task 1: {}", computer.get_output().last().unwrap());
}
fn task2(ram: RAM) {
let mut computer = IntCodeComputer::new(vec![2], ram);
computer.run_until_end();
println!("{:?}", computer.get_output());
println!("Task 2: {}", computer.get_output().last().unwrap());
}

129
src/tasks/day10.rs Normal file
View File

@@ -0,0 +1,129 @@
use itertools::Itertools;
use std::collections::HashSet;
#[allow(dead_code)]
pub fn run() {
let asteroids: HashSet<(i32, i32)> = std::fs::read_to_string("input/day10.txt")
.unwrap()
.lines()
.enumerate()
.map(|(y, line)| {
line.chars()
.enumerate()
.filter(|(_, it)| *it == '#')
.map(move |(x, _)| (x as i32, y as i32))
})
.flatten()
.collect();
task1(&asteroids);
task2(&asteroids);
}
fn task1(asteroids: &HashSet<(i32, i32)>) {
let (max, _) = get_best_station(&asteroids);
println!(
"Task 1: maximum visible asteroids from another asteroid are {}",
max
);
}
fn task2(asteroids: &HashSet<(i32, i32)>) {
let (_, station) = get_best_station(&asteroids);
println!("Task 2: The station is at {:?}", station);
let mut others = asteroids.clone();
others.remove(&station);
// map to polar coordinate
let mut others: Vec<((i32, i32), (f32, f32))> = others
.into_iter()
.map(|other| (other, to_polar(station, other)))
.collect();
use std::cmp::Ordering;
others.sort_by(|(_, a), (_, b)| {
// sort by angle
if a.0 < b.0 {
Ordering::Less
} else {
Ordering::Greater
}
});
let mut v: Vec<(f32, Vec<_>)> = others
.iter()
.group_by(|(_, (alpha, _))| alpha)
.into_iter()
.map(|(angle, group)| (*angle, group.collect()))
.collect();
let mut i = 0;
let mut shot = Vec::new();
while shot.len() < 200 {
while v[i].1.is_empty() {
i = (i + 1) % v.len();
}
shot.push(v[i].1.remove(0));
i = (i + 1) % v.len();
}
let ((x, y), _) = shot.last().unwrap();
println!("Task 2: {}", x * 100 + y);
}
fn d(a: (i32, i32), b: (i32, i32)) -> f32 {
((a.0 - b.0) as f32).powi(2) + ((a.1 - b.1) as f32).powi(2).sqrt()
}
/**
* generate polar coordinate relative to POV.
* rotate angles such that "up" is 0.
*/
fn to_polar(pov: (i32, i32), other: (i32, i32)) -> (f32, f32) {
let mut alpha =
((other.1 - pov.1) as f32).atan2((other.0 - pov.0) as f32) + std::f32::consts::FRAC_PI_2;
if alpha < 0.0 {
alpha += 2.0 * std::f32::consts::PI;
}
(alpha, d(pov, other))
}
fn blocks_view(pov: (i32, i32), target: (i32, i32), occluder: (i32, i32)) -> bool {
if occluder == target {
return false;
}
// using polar coordinates
let (ao, d_o) = to_polar(pov, occluder);
let (at, d_t) = to_polar(pov, target);
(ao - at).abs() <= std::f32::EPSILON && d_t > d_o
}
fn get_best_station(asteroids: &HashSet<(i32, i32)>) -> (usize, (i32, i32)) {
asteroids
.iter()
.map(|asteroid| {
// map to number of other asteroids it sees
let mut others = asteroids.clone();
others.remove(&asteroid);
// count those asteroids that are not blocked by another
let count = others
.iter()
.filter(|target| {
let blocker = others
.iter()
.find(|occluder| blocks_view(*asteroid, **target, **occluder));
!blocker.is_some()
})
.count();
(count, *asteroid)
})
.max_by_key(|(count, _)| *count)
.unwrap()
}
mod test {
#[test]
fn block_test() {
assert_eq!(true, super::blocks_view((3, 4), (1, 0), (2, 2)));
assert_eq!(false, super::blocks_view((3, 4), (2, 2), (1, 0)));
assert_eq!(false, super::blocks_view((3, 4), (1, 0), (1, 2)));
assert_eq!(true, super::blocks_view((4, 4), (4, 0), (4, 3)));
assert_eq!(false, super::blocks_view((3, 2), (1, 0), (4, 3)));
}
}

106
src/tasks/day11.rs Normal file
View File

@@ -0,0 +1,106 @@
use super::day05::{IntCodeComputer, RAM};
use std::collections::{HashMap, HashSet};
#[allow(dead_code)]
pub fn run() {
let input = std::fs::read_to_string("input/day11.txt").unwrap();
let ram: RAM = input
.split(",")
.enumerate()
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
.collect();
task1(ram.clone());
task2(ram.clone());
}
fn task1(ram: RAM) {
let directions: HashMap<_, _> =
vec![('^', (0, -1)), ('v', (0, 1)), ('<', (-1, 0)), ('>', (1, 0))]
.into_iter()
.collect();
let turns: HashMap<_, _> = vec![
(('^', 0), '<'),
(('^', 1), '>'),
(('v', 0), '>'),
(('v', 1), '<'),
(('<', 0), 'v'),
(('<', 1), '^'),
(('>', 0), '^'),
(('>', 1), 'v'),
]
.into_iter()
.collect();
let mut colors: HashMap<(i32, i32), i128> = HashMap::new();
let mut painted_positions: HashSet<(i32, i32)> = HashSet::new();
let get = |colors: &HashMap<_, _>, (x, y)| **colors.get(&(x, y)).get_or_insert(&0);
let turn = |(c, d)| turns.get(&(c, d)).unwrap();
let mov = |(x0, y0), (x1, y1)| (x0 + x1, y0 + y1);
let mut done = false;
let mut computer = IntCodeComputer::new(vec![], ram);
let mut pos = (0, 0);
let mut dir = '^';
while !done {
computer.set_input(&[get(&colors, pos)]);
computer.clear_output();
done = computer.run_until_input_empty();
let color = computer.get_output()[0];
let turn_indicator = computer.get_output()[1];
colors.insert(pos, color);
painted_positions.insert(pos);
dir = *turn((dir, turn_indicator));
pos = mov(pos, *directions.get(&dir).unwrap());
}
println!("Task 1: {} positions were painted", painted_positions.len());
}
fn task2(ram: RAM) {
let directions: HashMap<_, _> =
vec![('^', (0, -1)), ('v', (0, 1)), ('<', (-1, 0)), ('>', (1, 0))]
.into_iter()
.collect();
let turns: HashMap<_, _> = vec![
(('^', 0), '<'),
(('^', 1), '>'),
(('v', 0), '>'),
(('v', 1), '<'),
(('<', 0), 'v'),
(('<', 1), '^'),
(('>', 0), '^'),
(('>', 1), 'v'),
]
.into_iter()
.collect();
let mut colors: HashMap<(i32, i32), i128> = HashMap::new();
colors.insert((0, 0), 1);
let mut painted_positions: HashSet<(i32, i32)> = HashSet::new();
let get = |colors: &HashMap<_, _>, (x, y)| **colors.get(&(x, y)).get_or_insert(&0);
let turn = |(c, d)| turns.get(&(c, d)).unwrap();
let mov = |(x0, y0), (x1, y1)| (x0 + x1, y0 + y1);
let mut done = false;
let mut computer = IntCodeComputer::new(vec![], ram);
let mut pos = (0, 0);
let mut dir = '^';
while !done {
computer.set_input(&[get(&colors, pos)]);
computer.clear_output();
done = computer.run_until_input_empty();
let color = computer.get_output()[0];
let turn_indicator = computer.get_output()[1];
colors.insert(pos, color);
painted_positions.insert(pos);
dir = *turn((dir, turn_indicator));
pos = mov(pos, *directions.get(&dir).unwrap());
}
let xmin = painted_positions.iter().min_by_key(|it| it.0).unwrap().0;
let xmax = painted_positions.iter().max_by_key(|it| it.0).unwrap().0;
let ymin = painted_positions.iter().min_by_key(|it| it.1).unwrap().1;
let ymax = painted_positions.iter().max_by_key(|it| it.1).unwrap().1;
(ymin..=ymax).into_iter().for_each(|y| {
(xmin..=xmax).into_iter().for_each(|x| {
print!("{}", if get(&colors, (x, y)) == 1 { '#' } else { ' ' });
});
println!("")
})
}

140
src/tasks/day12.rs Normal file
View File

@@ -0,0 +1,140 @@
use num_integer::Integer;
use regex::Regex;
#[allow(dead_code)]
pub fn run() {
let regex = Regex::new("<x=(-?\\d+),\\sy=(-?\\d+),\\sz=(-?\\d+)").unwrap();
let input: Vec<Point> = std::fs::read_to_string("input/day12.txt")
.unwrap()
.lines()
.map(|line| {
let m = regex.captures(&line).unwrap();
let x: i32 = m[1].parse().unwrap();
let y: i32 = m[2].parse().unwrap();
let z: i32 = m[3].parse().unwrap();
Point { x, y, z }
})
.collect();
let moons: Vec<_> = input
.into_iter()
.map(|pos| Moon {
pos: pos,
vel: Point::new(0, 0, 0),
})
.collect();
task1(moons.clone());
task2(moons.clone());
}
fn task1(moons: Vec<Moon>) {
let finals = (0..1000).fold(moons, |moons, _run| step(moons));
let energy: i32 = finals
.iter()
.map(|moon| moon.pos.energy() * moon.vel.energy())
.sum();
println!("Task 1: sum of energy is {}", energy);
}
fn task2(moons: Vec<Moon>) {
let xstart: Vec<_> = moons.iter().map(|it| [it.pos.x, it.vel.x]).collect();
let ystart: Vec<_> = moons.iter().map(|it| [it.pos.y, it.vel.y]).collect();
let zstart: Vec<_> = moons.iter().map(|it| [it.pos.z, it.vel.z]).collect();
let result = (1 as usize..)
.scan((None, None, None, moons), |(dx, dy, dz, moons), run| {
let mut new_moons = step(moons.clone());
moons.clear();
moons.append(&mut new_moons);
let xv: Vec<_> = moons.iter().map(|it| [it.pos.x, it.vel.x]).collect();
let yv: Vec<_> = moons.iter().map(|it| [it.pos.y, it.vel.y]).collect();
let zv: Vec<_> = moons.iter().map(|it| [it.pos.z, it.vel.z]).collect();
if *dx == None && xv == xstart {
*dx = Some(run);
}
if *dy == None && yv == ystart {
*dy = Some(run);
}
if *dz == None && zv == zstart {
*dz = Some(run);
}
if dx.is_some() && dy.is_some() && dz.is_some() {
Some(Some((dx.unwrap(), dy.unwrap(), dz.unwrap())))
} else {
Some(None)
}
})
.find(|bla| bla.is_some());
if let Some(Some((x, y, z))) = result {
println!(
"Task 2: {:?} until a visited state is reached again",
x.lcm(&y.lcm(&z))
);
}
}
fn step(moons: Vec<Moon>) -> Vec<Moon> {
let gravities: Vec<Point> = moons
.iter()
.map(|base| {
moons.iter().fold(Point::new(0, 0, 0), |grav, other_moon| {
grav.add(base.pos.gravity(other_moon.pos))
})
})
.collect();
let moons = moons
.into_iter()
.zip(gravities.into_iter())
.map(|(mut moon, grav)| {
moon.vel = moon.vel.add(grav);
moon.pos = moon.pos.add(moon.vel);
moon
})
.collect();
moons
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
struct Moon {
pos: Point,
vel: Point,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
struct Point {
x: i32,
y: i32,
z: i32,
}
impl Point {
fn new(x: i32, y: i32, z: i32) -> Self {
Point { x, y, z }
}
fn add(&self, other: Self) -> Self {
Point {
x: self.x + other.x,
y: self.y + other.y,
z: self.z + other.z,
}
}
fn gravity(&self, other: Self) -> Self {
fn d(a: i32, b: i32) -> i32 {
use std::cmp::Ordering;
match a.cmp(&b) {
Ordering::Less => 1,
Ordering::Equal => 0,
Ordering::Greater => -1,
}
}
Point {
x: d(self.x, other.x),
y: d(self.y, other.y),
z: d(self.z, other.z),
}
}
fn energy(&self) -> i32 {
self.x.abs() + self.y.abs() + self.z.abs()
}
}

239
src/tasks/day13.rs Normal file
View File

@@ -0,0 +1,239 @@
use super::day05::{IntCodeComputer, RAM};
use itertools::Itertools;
use std::collections::HashMap;
use std::fmt;
#[allow(dead_code)]
pub fn run() {
let program: RAM = std::fs::read_to_string("input/day13.txt")
.unwrap()
.split(",")
.map(|it| it.parse::<i128>().unwrap())
.enumerate()
.collect();
task1(program.clone());
task2_ai(program.clone());
}
#[derive(PartialEq)]
enum FieldType {
Empty,
Wall,
Block,
HorizontalPaddle,
Ball,
}
impl fmt::Display for FieldType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
Self::Empty => " ",
Self::Wall => "X",
Self::Block => "B",
Self::HorizontalPaddle => "_",
Self::Ball => "O",
}
)
}
}
impl FieldType {
fn from(input: i128) -> Self {
match input {
0 => Self::Empty,
1 => Self::Wall,
2 => Self::Block,
3 => Self::HorizontalPaddle,
4 => Self::Ball,
_ => unreachable!("unexpected field type {}", input),
}
}
}
struct Game {
pc: IntCodeComputer,
field: HashMap<(i128, i128), FieldType>,
score: i128,
show_output: bool,
}
impl Game {
fn new(coins: Option<i128>, mut ram: RAM, show_output: bool) -> Self {
if let Some(c) = coins {
ram.insert(0, c);
}
let pc = IntCodeComputer::new(vec![], ram);
Game {
pc,
field: HashMap::new(),
score: 0,
show_output,
}
}
/**
* true means the game is over, false means input is awaited
*/
fn run(&mut self) -> bool {
self.pc.clear_output();
let done = self.pc.run_until_input_empty();
let output = self.pc.get_output().into_iter().map(|it| *it).collect_vec();
let mut score = None;
output
.iter()
.tuples()
.scan(&mut self.field, |map, (x, y, t)| {
if *x == -1 && *y == 0 {
score = Some(*t);
} else {
map.insert((*x, *y), FieldType::from(*t));
}
Some(())
})
.any(|_| false);
// stupid workaround because I cannot access score from within the clojure,
// due to then double-borrowing of mutable reference to self
if let Some(score) = score {
self.score = score;
}
if self.show_output {
self.print();
}
done
}
fn set_input(&mut self, input: Input) {
self.pc.set_input(&[input.int()]);
}
fn print(&self) {
let xmin = *self.field.iter().map(|((x, _), _)| x).min().unwrap();
let xmax = *self.field.iter().map(|((x, _), _)| x).max().unwrap();
let ymin = *self.field.iter().map(|((_, y), _)| y).min().unwrap();
let ymax = *self.field.iter().map(|((_, y), _)| y).max().unwrap();
for y in ymin..=ymax {
for x in xmin..=xmax {
if let Some(f) = self.field.get(&(x, y)) {
print!("{}", f);
} else {
panic!("There is an unspecified tile in the field");
}
}
println!();
}
println!("Score: {}", self.score);
}
}
#[derive(PartialEq)]
enum Input {
Neutral,
Left,
Right,
}
impl Input {
fn int(&self) -> i128 {
match self {
Self::Neutral => 0,
Self::Left => -1,
Self::Right => 1,
}
}
fn from(input: char) -> Self {
match input {
's' => Self::Neutral,
'a' => Self::Left,
'd' => Self::Right,
_ => Self::Neutral,
}
}
}
fn task1(program: RAM) {
let mut game = Game::new(None, program, true);
if game.run() {
let block_count = game
.field
.iter()
.filter(|(_, ftype)| **ftype == FieldType::Block)
.count();
println!("Task 1: There are {} blocks in the field", block_count);
} else {
unreachable!("In this task the game should end without any input.");
}
}
#[allow(dead_code)]
fn task2(program: RAM) {
use std::io::{self, BufRead};
let mut game = Game::new(Some(2), program, true);
let stdin = io::stdin();
let mut input_iter = stdin.lock().lines();
while !game.run() {
// read input
let next = input_iter.next().unwrap().unwrap().chars().next();
if let Some(s) = next {
game.set_input(Input::from(s));
} else {
game.set_input(Input::Neutral);
}
}
println!(
"You won against the game! Your final score was {}",
game.score
);
}
fn task2_ai(program: RAM) {
let mut game = Game::new(Some(2), program, false);
let mut moves = 0;
while !game.run() {
// always keep the paddle under the ball
let x_ball = game
.field
.iter()
.find_map(|((x, _), t)| {
if *t == FieldType::Ball {
Some(*x)
} else {
None
}
})
.unwrap();
let x_paddle = game
.field
.iter()
.find_map(|((x, _), t)| {
if *t == FieldType::HorizontalPaddle {
Some(*x)
} else {
None
}
})
.unwrap();
let direction = if x_ball < x_paddle {
Input::Left
} else if x_ball > x_paddle {
Input::Right
} else {
Input::Neutral
};
game.set_input(direction);
moves += 1;
}
println!("Played for {} moves", moves);
println!(
"Game is over! There are {} blocks left. Your final score is {}",
game.field
.iter()
.filter(|(_, t)| **t == FieldType::Block)
.count(),
game.score
);
}

115
src/tasks/day14.rs Normal file
View File

@@ -0,0 +1,115 @@
use itertools::Itertools;
use std::collections::HashMap;
#[allow(dead_code)]
pub fn run() {
fn parser(s: &str) -> Chemical {
let (n, t) = s.split(" ").collect_tuple().unwrap();
Chemical(n.parse().unwrap(), t)
}
let text = std::fs::read_to_string("input/day14.txt").unwrap();
// maps from a chemical to the chemicals required to create it
let rules: HashMap<_, _> = text
.lines()
.map(|line| {
let (left, right) = line
.split("=>")
.map(|it| it.trim())
.collect_tuple()
.unwrap();
(
parser(right).1,
(
parser(right).0,
left.split(",").map(|it| parser(it.trim())).collect_vec(),
),
)
})
.collect();
task1(&rules);
task2(&rules);
}
fn task1(rules: &HashMap<&str, (usize, Vec<Chemical>)>) {
println!("Task 1: {} ORE is needed", calc_ore_for_fuel(1, rules));
}
fn task2(rules: &HashMap<&str, (usize, Vec<Chemical>)>) {
const ORE_STORAGE: usize = 1_000_000_000_000;
// binary search max fuel
let (max_fuel, _) = std::iter::successors(Some((1, ORE_STORAGE)), |(min, max)| {
if max - min > 1 {
let middle = (max + min) / 2;
let ore = calc_ore_for_fuel(middle, rules);
if ore > ORE_STORAGE {
Some((*min, middle))
} else {
Some((middle, *max))
}
} else {
None
}
})
.last()
.unwrap();
println!("Task 2: the maximum amount of fuel is {}", max_fuel);
}
fn calc_ore_for_fuel(fuel: usize, rules: &HashMap<&str, (usize, Vec<Chemical>)>) -> usize {
/*
The idea is: the rules create a DAG of requirements.
We store for every chemical a list of the chemicals that rely on it.
We create a mapping from the chemicals to the amount of the chemicals needed
by its already processed ancestors in the rule DAG.
Then we process all chemicals C, starting with "FUEL", of which all ancestors are already
processed. That means, that our mapping of the amounts stores the correct sum of what is
needed of the chemical (we round that up, so it matches the amount given on the right
hand rule side). We then calculate, using the rules, how much of other chemicals C' we need
to produce the desired amount. We add up the amount of the required children C' in
`requirements`. We then remove C from the chem_used_by list of C'.
Once a chemical has an empty used_by list it is ready for processing.
*/
// maps for every chemical to the ones using it
let mut chem_used_by: HashMap<&str, Vec<&str>> =
rules
.iter()
.fold(HashMap::new(), |mut map, (result, (_, ingredients))| {
ingredients.iter().for_each(|Chemical(_, ingredient)| {
map.entry(&ingredient).or_insert(vec![]).push(result)
});
map
});
chem_used_by.insert("FUEL", vec![]);
// the amount of a not processed chemical C, which is needed by the chemicals that rely on C
let mut requirements = HashMap::<&str, usize>::new();
requirements.insert("FUEL", fuel);
while let Some((name, amount)) = requirements
.iter()
.find(|(name, _)| chem_used_by[*name].is_empty() && **name != "ORE")
{
// needed to remove immutable borrow of `requirements` from above
let name = *name;
let amount = *amount;
let (reaction_size, req_vec) = &rules
.get(&name)
.expect(&format!("unknown chemical in rules: {}", name));
let demand = if amount % reaction_size == 0 {
amount / reaction_size
} else {
amount / reaction_size + 1
};
for Chemical(req_amount, req_name) in req_vec {
chem_used_by
.get_mut(req_name)
.unwrap()
.retain(|x| *x != name);
*requirements.entry(req_name).or_insert(0) += demand * req_amount;
}
requirements.remove(name);
}
requirements["ORE"]
}
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
struct Chemical<'a>(usize, &'a str);

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);
}
}

66
src/tasks/day21.rs Normal file
View File

@@ -0,0 +1,66 @@
use super::day05::*;
#[allow(dead_code)]
pub fn run() {
let input = std::fs::read_to_string("input/day21.txt").unwrap();
let ram: RAM = input
.split(",")
.enumerate()
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
.collect();
task1(ram.clone());
task2(ram.clone());
}
fn task1(ram: RAM) {
let p = r"NOT A J
NOT B T
OR T J
NOT C T
OR T J
AND D J
WALK
"
.to_string();
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();
let output = computer.get_output();
let s: String = output
.iter()
.map(|i| {
if *i > 255 {
format!("{}", i)
} else {
format!("{}", (*i as u8) as char)
}
})
.collect();
println!("{}", s);
}

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

@@ -5,3 +5,21 @@ pub mod day05;
pub mod day06;
pub mod day07;
pub mod day08;
pub mod day09;
pub mod day10;
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;