Compare commits

..

11 commits
day9 ... master

Author SHA1 Message Date
foosinn
655b99da1b day15 2020-06-03 23:21:32 +02:00
foosinn
244e308200 day13 2020-05-28 22:49:16 +02:00
foosinn
0bd196febf proper intcode program resize 2020-05-27 14:11:56 +02:00
foosinn
a9b5197ca7 fix tests 2020-05-27 13:11:20 +02:00
foosinn
e16cafaa52 day14 2020-05-26 17:25:50 +02:00
foosinn
e27c10d3b0 day11 2020-05-25 07:58:25 +02:00
b851d2bbe6 day12 2020-05-24 13:12:19 +02:00
Stefan Schwarz
9b09b974eb remove non-astroids from map 2020-05-13 09:05:27 +02:00
f12c16a06a day10 2020-05-13 00:40:38 +02:00
ccc5c8038a lets add the inputs 2020-04-23 23:26:08 +02:00
4e908b8bf9 day9 part2 2020-04-23 23:02:48 +02:00
25 changed files with 2407 additions and 62 deletions

1
.gitignore vendored
View file

@ -1,2 +1 @@
/input*
/target/

32
Cargo.lock generated
View file

@ -3,3 +3,35 @@
[[package]]
name = "aoc2019"
version = "0.1.0"
dependencies = [
"ncurses",
]
[[package]]
name = "cc"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
[[package]]
name = "libc"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
[[package]]
name = "ncurses"
version = "5.99.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15699bee2f37e9f8828c7b35b2bc70d13846db453f2d507713b758fabe536b82"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"

View file

@ -4,7 +4,8 @@ version = "0.1.0"
authors = ["Stefan Schwarz <stefan@f2o.io>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ncurses = "5.99.0"
[[bin]]
name = "day1"
@ -32,4 +33,28 @@ path = "src/day7/main.rs"
[[bin]]
name = "day9"
path = "src/day9/main.rs"
path = "src/day9/main.rs"
[[bin]]
name = "day10"
path = "src/day10/main.rs"
[[bin]]
name = "day11"
path = "src/day11/main.rs"
[[bin]]
name = "day12"
path = "src/day12/main.rs"
[[bin]]
name = "day13"
path = "src/day13/main.rs"
[[bin]]
name = "day14"
path = "src/day14/main.rs"
[[bin]]
name = "day15"
path = "src/day15/main.rs"

1
README.md Normal file
View file

@ -0,0 +1 @@
# Advent of Code 2019

100
input1 Normal file
View file

@ -0,0 +1,100 @@
119606
94066
80497
136413
83710
136098
113785
100655
148973
78186
75572
68954
140581
76963
123969
111620
106957
80469
140605
119650
112495
124851
119725
93118
123105
92952
131053
74500
135647
107536
56501
64458
115542
111894
51608
85570
133474
118513
109296
128000
87127
146391
149508
107219
70461
85261
137378
138297
106834
112664
53841
124055
96992
91394
135390
119457
84966
110652
138798
65060
108499
126384
116976
135353
52801
53139
54144
69494
52068
61600
62762
102578
100023
119232
97153
94554
114131
54643
65729
124430
106513
133856
96803
132140
113994
65320
123970
115693
129066
132805
143283
132702
109683
126041
63310
82628
68097
58927
123635
117809

24
input10 Normal file
View file

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

1
input11 Normal file
View file

@ -0,0 +1 @@
3,8,1005,8,320,1106,0,11,0,0,0,104,1,104,0,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,29,2,1005,1,10,1006,0,11,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,57,1,8,15,10,1006,0,79,1,6,3,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,101,0,8,90,2,103,18,10,1006,0,3,2,105,14,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,123,2,9,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,1001,8,0,150,1,2,2,10,2,1009,6,10,1,1006,12,10,1006,0,81,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,187,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,209,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,231,1,1008,11,10,1,1001,4,10,2,1104,18,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,264,1,8,14,10,1006,0,36,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,293,1006,0,80,1006,0,68,101,1,9,9,1007,9,960,10,1005,10,15,99,109,642,104,0,104,1,21102,1,846914232732,1,21102,1,337,0,1105,1,441,21102,1,387512115980,1,21101,348,0,0,1106,0,441,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,21102,209533824219,1,1,21102,1,395,0,1106,0,441,21101,0,21477985303,1,21102,406,1,0,1106,0,441,3,10,104,0,104,0,3,10,104,0,104,0,21101,868494234468,0,1,21101,429,0,0,1106,0,441,21102,838429471080,1,1,21102,1,440,0,1106,0,441,99,109,2,21201,-1,0,1,21101,0,40,2,21102,472,1,3,21101,0,462,0,1106,0,505,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,467,468,483,4,0,1001,467,1,467,108,4,467,10,1006,10,499,1102,1,0,467,109,-2,2106,0,0,0,109,4,2101,0,-1,504,1207,-3,0,10,1006,10,522,21101,0,0,-3,21202,-3,1,1,22101,0,-2,2,21102,1,1,3,21102,541,1,0,1106,0,546,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,569,2207,-4,-2,10,1006,10,569,22102,1,-4,-4,1105,1,637,22102,1,-4,1,21201,-3,-1,2,21202,-2,2,3,21102,588,1,0,1105,1,546,22101,0,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,607,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,629,21201,-1,0,1,21102,629,1,0,105,1,504,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0

1
input13 Normal file

File diff suppressed because one or more lines are too long

56
input14 Normal file
View file

@ -0,0 +1,56 @@
18 FHWM => 1 XGQNZ
4 FVPWN, 9 CQGW => 7 QGHT
22 KZMS, 1 DMCJL => 8 TWGCK
1 LMGQN, 1 DSWDM, 1 GKGZ => 1 TGPH
22 WCSW => 1 LVTG
13 JSWR => 4 GKGZ
162 ORE => 3 FVPWN
59 CQGW, 15 MSNG, 6 XGKRF, 10 LJRQ, 1 HRKGV, 15 RKVC => 1 FUEL
5 DMCJL => 1 QBLH
2 XDRJ, 2 RKVC => 8 CTCNL
1 QXHX => 5 GFPSK
22 QGHT, 6 GFPSK, 5 DHTPL => 3 CSDR
4 QGHT, 2 HFXD => 4 XDRJ
10 WQCGV, 1 JSWR, 21 RHTLN => 7 VTPC
11 CQGW, 1 FVPWN => 3 HFXD
5 VTPC => 2 NCXW
8 LDZVS => 6 DQLH
117 ORE => 2 KWZNB
3 TGPH, 1 JPFQ, 2 WHWLK, 5 RKVC, 16 DQLH => 9 LJRQ
14 KWZNB, 2 CQGW => 8 MLPK
6 LDZVS => 2 JSWR
1 RKVC, 8 HCGT, 9 DHTPL => 6 FHWM
3 DHTPL, 1 HWSR, 36 LDZVS => 6 DSWDM
5 WHWLK, 1 LJHWT, 8 HSTHS => 7 VMPX
22 ZJCDZ, 3 WQCGV => 5 DHTPL
10 LJHWT, 32 GFPSK, 2 RHTLN => 4 HFRMP
2 FKVD, 3 TWGCK, 1 HWSR => 1 RNLZW
2 CSDR, 3 DQLH, 2 HSTHS => 9 JPFQ
1 JSWR, 1 PCWS, 1 HFRMP => 3 XGKRF
2 QGHT, 9 LVTG, 3 QBLH => 7 RHTLN
10 LJHWT, 4 CTCNL => 8 QXHX
16 MLPK, 1 HFXD => 9 ZJCDZ
6 QGHT => 9 WCSW
4 HWSR, 4 MLPK, 1 KZMS => 3 BGZHQ
12 MLPK => 8 RKVC
1 HWSR, 1 VNWFS => 7 BGFJ
7 FHWM, 11 CTDF, 1 LDZVS => 2 VNWFS
4 CTDF => 4 HSTHS
2 ZJCDZ => 6 LJHWT
1 VMPX, 1 NCXW, 1 HSTHS, 41 XGKRF, 30 HLNG, 1 GKGZ => 7 HRKGV
1 XGQNZ, 10 PCWS, 3 BGFJ => 8 FKVD
1 GFPSK, 1 DMCJL, 1 LVTG => 5 XDTZB
3 WCSW => 5 KZMS
6 TWGCK, 1 QXHX, 4 BGFJ => 2 LMGQN
1 WCSW => 7 LDZVS
1 XDTZB, 9 VNWFS => 3 WHWLK
3 HFXD, 4 WCSW, 1 MLPK => 5 WQCGV
2 BGFJ, 1 HSTHS, 22 MDCB, 10 HWSR, 6 RNLZW, 8 GKGZ => 5 MSNG
4 QGHT, 1 FKVD => 7 MDCB
9 MLPK, 3 LJHWT => 7 DMCJL
121 ORE => 2 CQGW
9 DHTPL, 2 BGZHQ => 8 CTDF
2 JSWR, 30 RHTLN => 7 HLNG
2 QBLH => 7 PCWS
14 LVTG => 8 HWSR
7 DMCJL => 1 HCGT

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

1
input2 Normal file
View file

@ -0,0 +1 @@
1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,10,19,1,6,19,23,1,10,23,27,2,27,13,31,1,31,6,35,2,6,35,39,1,39,5,43,1,6,43,47,2,6,47,51,1,51,5,55,2,55,9,59,1,6,59,63,1,9,63,67,1,67,10,71,2,9,71,75,1,6,75,79,1,5,79,83,2,83,10,87,1,87,5,91,1,91,9,95,1,6,95,99,2,99,10,103,1,103,5,107,2,107,6,111,1,111,5,115,1,9,115,119,2,119,10,123,1,6,123,127,2,13,127,131,1,131,6,135,1,135,10,139,1,13,139,143,1,143,13,147,1,5,147,151,1,151,2,155,1,155,5,0,99,2,0,14,0

2
input3 Normal file
View file

@ -0,0 +1,2 @@
R1009,D117,L888,D799,L611,U766,L832,U859,L892,D79,R645,U191,L681,D787,R447,D429,L988,U536,L486,D832,R221,D619,R268,D545,L706,U234,L528,D453,R493,D24,L688,U658,L74,D281,R910,D849,L5,U16,R935,D399,L417,U609,R22,D782,L432,D83,L357,D982,L902,U294,L338,U102,R342,D621,R106,U979,L238,U158,R930,D948,L700,D808,R445,U897,R980,U227,L466,D416,R244,U396,R576,U157,R548,U795,R709,U550,R137,U212,L977,U786,L423,D792,R391,D974,R390,U771,R270,D409,L917,D9,R412,D699,L170,D276,L912,U710,R814,U656,R4,D800,R596,U970,L194,U315,L845,D490,L303,U514,L675,D737,L880,D86,L253,D525,R861,D5,R424,D113,L764,D900,R485,D421,R125,U684,R53,U96,L871,U260,R456,U378,L448,D450,L903,D482,R750,U961,R264,D501,R605,D367,R550,U642,R228,U164,L343,U868,R595,D318,R452,U845,L571,D281,R49,D889,L481,U963,R182,U358,R454,U267,L790,D252,R455,D188,L73,U256,L835,D816,R503,U895,L259,U418,R642,U818,L187,U355,R772,U466,R21,U91,R707,D349,L200,U305,R931,D982,L334,D416,L247,D935,L326,U449,L398,D914,R602,U10,R762,D944,L639,D141,L457,U579,L198,U527,R750,U167,R816,D753,R850,D281,L712,D583,L172,D254,L544,D456,R966,U839,R673,D479,R730,D912,R992,D969,R766,U205,R477,D719,R172,D735,R998,D687,R698,D407,R172,U945,R199,U348,L256,D876,R580,U770,L483,D437,R353,D214,R619,U541,R234,D962,R842,U639,R520,D354,L279,D15,R42,U138,L321,D376,L628,D893,L670,D574,L339,U298,L321,D120,L370,U408,L333,D353,L263,D79,R535,D487,R113,D638,R623,D59,L508,D866,R315,U166,L534,U927,L401,D626,L19,D994,L778,D317,L936,U207,L768,U948,R452,U165,R864,D283,L874
L995,D93,L293,U447,L793,D605,R497,D155,L542,D570,R113,D779,L510,U367,L71,D980,R237,U290,L983,U49,R745,U182,L922,D174,L189,D629,R315,D203,R533,U72,L981,D848,L616,U654,R445,D864,R526,D668,L678,U378,L740,D840,L202,D429,R136,D998,L116,D554,L893,U759,R617,U942,R999,U582,L220,U447,R895,D13,R217,U743,L865,U950,R91,D381,R662,D518,L798,D637,L213,D93,L231,D185,R704,U581,L268,U773,R405,U862,R796,U73,L891,U553,L952,U450,R778,D868,R329,D669,L182,U378,L933,D83,R574,U807,R785,D278,R139,D362,R8,U546,R651,U241,L462,D309,L261,D307,L85,U701,L913,U271,R814,U723,L777,D256,R417,U814,L461,U652,R198,D747,R914,U520,R806,U956,L771,D229,R984,U685,R663,D812,R650,U214,R839,U574,L10,U66,R644,D371,L917,D819,L73,D236,R277,U611,R390,U723,L129,D496,L552,D451,R584,U105,L805,U165,R179,D372,L405,D702,R14,U332,L893,D419,R342,D146,R907,D672,L316,U257,L903,U919,L942,U771,R879,U624,L280,U150,L320,U220,R590,D242,R744,U291,R562,U418,L898,U66,L564,U495,R837,D555,L739,D780,R409,D122,L426,D857,R937,D600,R428,D592,R727,U917,R256,D680,L422,U630,L14,U240,R617,D664,L961,D554,L302,U925,L376,D187,L700,D31,L762,U397,L554,D217,R679,D683,R680,D572,R54,D164,L940,D523,R140,U52,L506,D638,R331,D415,R389,D884,R410,D62,R691,U665,R889,U864,L663,D690,R487,U811,L190,U780,L758,U267,R155,D344,L133,D137,R93,D229,L729,U878,L889,D603,R288,U890,R251,U531,L249,D995,R863,D257,R655,D311,R874,U356,L833,U151,L741,U246,R694,D899,L48,U915,L900,U757,L861,U402,R971,U537,R460,D844,R54,U956,L151,U74,R892,U248,R677,D881,R99,D931,R427

1
input5 Normal file
View file

@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1001,92,74,224,1001,224,-85,224,4,224,1002,223,8,223,101,1,224,224,1,223,224,223,1101,14,63,225,102,19,83,224,101,-760,224,224,4,224,102,8,223,223,101,2,224,224,1,224,223,223,1101,21,23,224,1001,224,-44,224,4,224,102,8,223,223,101,6,224,224,1,223,224,223,1102,40,16,225,1102,6,15,225,1101,84,11,225,1102,22,25,225,2,35,96,224,1001,224,-350,224,4,224,102,8,223,223,101,6,224,224,1,223,224,223,1101,56,43,225,101,11,192,224,1001,224,-37,224,4,224,102,8,223,223,1001,224,4,224,1,223,224,223,1002,122,61,224,1001,224,-2623,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,1,195,87,224,1001,224,-12,224,4,224,1002,223,8,223,101,5,224,224,1,223,224,223,1101,75,26,225,1101,6,20,225,1102,26,60,224,101,-1560,224,224,4,224,102,8,223,223,101,3,224,224,1,223,224,223,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,108,677,226,224,102,2,223,223,1006,224,329,1001,223,1,223,1108,226,677,224,1002,223,2,223,1006,224,344,101,1,223,223,7,226,677,224,102,2,223,223,1006,224,359,1001,223,1,223,1007,226,677,224,1002,223,2,223,1006,224,374,1001,223,1,223,1108,677,226,224,102,2,223,223,1005,224,389,1001,223,1,223,107,226,226,224,102,2,223,223,1006,224,404,101,1,223,223,1107,226,226,224,1002,223,2,223,1005,224,419,1001,223,1,223,1007,677,677,224,102,2,223,223,1006,224,434,101,1,223,223,1107,226,677,224,1002,223,2,223,1006,224,449,101,1,223,223,107,677,677,224,102,2,223,223,1005,224,464,1001,223,1,223,1008,226,226,224,1002,223,2,223,1005,224,479,101,1,223,223,1007,226,226,224,102,2,223,223,1005,224,494,1001,223,1,223,8,677,226,224,1002,223,2,223,1005,224,509,1001,223,1,223,108,677,677,224,1002,223,2,223,1005,224,524,1001,223,1,223,1008,677,677,224,102,2,223,223,1006,224,539,1001,223,1,223,7,677,226,224,1002,223,2,223,1005,224,554,101,1,223,223,1108,226,226,224,1002,223,2,223,1005,224,569,101,1,223,223,107,677,226,224,102,2,223,223,1005,224,584,101,1,223,223,8,226,226,224,1002,223,2,223,1005,224,599,101,1,223,223,108,226,226,224,1002,223,2,223,1006,224,614,1001,223,1,223,7,226,226,224,102,2,223,223,1006,224,629,1001,223,1,223,1107,677,226,224,102,2,223,223,1005,224,644,101,1,223,223,8,226,677,224,102,2,223,223,1006,224,659,1001,223,1,223,1008,226,677,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226

1
input7 Normal file
View file

@ -0,0 +1 @@
3,8,1001,8,10,8,105,1,0,0,21,46,59,72,93,110,191,272,353,434,99999,3,9,101,4,9,9,1002,9,3,9,1001,9,5,9,102,2,9,9,1001,9,5,9,4,9,99,3,9,1002,9,5,9,1001,9,5,9,4,9,99,3,9,101,4,9,9,1002,9,4,9,4,9,99,3,9,102,3,9,9,101,3,9,9,1002,9,2,9,1001,9,5,9,4,9,99,3,9,1001,9,2,9,102,4,9,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,99,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,99

1
input9 Normal file
View file

@ -0,0 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,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,1102,1,432,1027,1101,439,0,1026,1101,0,36,1010,1101,0,34,1018,1102,278,1,1029,1101,0,24,1002,1102,1,20,1016,1102,1,31,1011,1102,319,1,1024,1102,21,1,1012,1102,1,763,1022,1102,1,25,1007,1101,0,287,1028,1102,32,1,1008,1101,0,22,1013,1102,38,1,1001,1101,0,314,1025,1102,35,1,1009,1102,1,23,1015,1102,39,1,1019,1102,27,1,1000,1102,1,37,1003,1102,1,28,1017,1101,0,0,1020,1101,0,29,1004,1102,1,30,1006,1102,1,756,1023,1102,1,33,1005,1101,0,1,1021,1102,26,1,1014,109,13,2108,28,-7,63,1005,63,201,1001,64,1,64,1105,1,203,4,187,1002,64,2,64,109,8,21107,40,41,-3,1005,1018,225,4,209,1001,64,1,64,1105,1,225,1002,64,2,64,109,-3,1206,2,239,4,231,1105,1,243,1001,64,1,64,1002,64,2,64,109,-21,1201,6,0,63,1008,63,35,63,1005,63,267,1001,64,1,64,1105,1,269,4,249,1002,64,2,64,109,35,2106,0,-4,4,275,1001,64,1,64,1105,1,287,1002,64,2,64,109,-11,1205,-1,303,1001,64,1,64,1105,1,305,4,293,1002,64,2,64,109,8,2105,1,-5,4,311,1106,0,323,1001,64,1,64,1002,64,2,64,109,-7,21108,41,38,-6,1005,1016,339,1106,0,345,4,329,1001,64,1,64,1002,64,2,64,109,2,21102,42,1,-8,1008,1016,45,63,1005,63,369,1001,64,1,64,1105,1,371,4,351,1002,64,2,64,109,-14,21101,43,0,1,1008,1011,43,63,1005,63,397,4,377,1001,64,1,64,1106,0,397,1002,64,2,64,109,-8,21101,44,0,8,1008,1010,47,63,1005,63,417,1105,1,423,4,403,1001,64,1,64,1002,64,2,64,109,25,2106,0,0,1001,64,1,64,1105,1,441,4,429,1002,64,2,64,109,-20,2107,37,-6,63,1005,63,463,4,447,1001,64,1,64,1106,0,463,1002,64,2,64,109,8,2108,25,-8,63,1005,63,485,4,469,1001,64,1,64,1106,0,485,1002,64,2,64,109,-1,21107,45,44,-1,1005,1013,505,1001,64,1,64,1106,0,507,4,491,1002,64,2,64,109,-11,1207,-1,25,63,1005,63,529,4,513,1001,64,1,64,1106,0,529,1002,64,2,64,109,23,1206,-5,545,1001,64,1,64,1106,0,547,4,535,1002,64,2,64,109,-31,2102,1,5,63,1008,63,27,63,1005,63,569,4,553,1106,0,573,1001,64,1,64,1002,64,2,64,109,27,21102,46,1,-9,1008,1013,46,63,1005,63,595,4,579,1105,1,599,1001,64,1,64,1002,64,2,64,109,-26,2101,0,6,63,1008,63,24,63,1005,63,625,4,605,1001,64,1,64,1106,0,625,1002,64,2,64,109,5,1208,0,37,63,1005,63,645,1001,64,1,64,1105,1,647,4,631,1002,64,2,64,109,7,2102,1,-3,63,1008,63,31,63,1005,63,671,1001,64,1,64,1105,1,673,4,653,1002,64,2,64,109,2,1202,-5,1,63,1008,63,33,63,1005,63,699,4,679,1001,64,1,64,1105,1,699,1002,64,2,64,109,-4,2101,0,-3,63,1008,63,35,63,1005,63,719,1105,1,725,4,705,1001,64,1,64,1002,64,2,64,109,-5,1207,4,32,63,1005,63,741,1106,0,747,4,731,1001,64,1,64,1002,64,2,64,109,29,2105,1,-7,1001,64,1,64,1106,0,765,4,753,1002,64,2,64,109,-26,2107,36,5,63,1005,63,781,1105,1,787,4,771,1001,64,1,64,1002,64,2,64,109,10,1201,-6,0,63,1008,63,32,63,1005,63,809,4,793,1106,0,813,1001,64,1,64,1002,64,2,64,109,3,21108,47,47,-5,1005,1012,835,4,819,1001,64,1,64,1106,0,835,1002,64,2,64,109,-24,1202,9,1,63,1008,63,25,63,1005,63,859,1001,64,1,64,1106,0,861,4,841,1002,64,2,64,109,19,1205,9,875,4,867,1106,0,879,1001,64,1,64,1002,64,2,64,109,-3,1208,-1,32,63,1005,63,897,4,885,1106,0,901,1001,64,1,64,4,64,99,21102,27,1,1,21101,915,0,0,1105,1,922,21201,1,60043,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21101,957,0,0,1106,0,922,22201,1,-1,-2,1105,1,968,22102,1,-2,-2,109,-3,2105,1,0

384
src/day10/main.rs Normal file
View file

@ -0,0 +1,384 @@
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::ops::Sub;
#[derive(Clone, Debug, PartialEq)]
enum Position {
Empty,
Astroid,
}
impl From<&u8> for Position {
fn from(c: &u8) -> Self {
match c {
b'.' => Position::Empty,
b'#' => Position::Astroid,
_ => panic!("invalid input"),
}
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
struct XY {
x: isize,
y: isize,
}
impl From<(usize, usize)> for XY {
fn from((x, y): (usize, usize)) -> Self {
XY {
x: x as isize,
y: y as isize,
}
}
}
impl Sub for &XY {
type Output = XY;
fn sub(self, other: &XY) -> Self::Output {
let xy = XY {
x: self.x - other.x,
y: self.y - other.y,
};
xy
}
}
impl XY {
fn direction(&self) -> Self {
let d = gcd(self.y, self.x).abs();
if d != 0 {
XY {
x: self.x / d,
y: self.y / d,
}
} else {
self.clone()
}
}
fn distance(&self) -> f64 {
let sum = (self.x.pow(2) + self.y.pow(2)) as f64;
(sum as f64).sqrt()
}
fn angle(&self) -> f64 {
let a = (-self.y as f64).atan2(-self.x as f64) * (180 as f64 / std::f64::consts::PI)
- 90 as f64;
if a < 0 as f64 {
a + 360 as f64
} else {
a
}
}
}
struct MonitoringStation {
map: Vec<XY>,
}
impl MonitoringStation {
fn laser(&self, root: &XY, skip: usize, n: usize) -> Vec<XY> {
let mut map: HashMap<XY, Vec<&XY>> = HashMap::new();
// collect vec for each direction
map = self
.map
.iter()
.filter_map(|xy| {
if xy == root {
return None;
}
let rel = xy - &root;
Some((xy, rel.direction()))
})
.fold(map, |mut acc, (xy, dir)| {
acc.entry(dir).or_insert(vec![]).push(xy);
acc
});
// order angle vecs by distance
map.iter_mut().for_each(|(_, val)| {
val.sort_by(|a, b| {
((root - b).distance().partial_cmp(&(root - a).distance())).unwrap()
});
});
// lets iterate over sorted angles
let mut angles = map.keys().cloned().collect::<Vec<XY>>();
angles.sort_by(|a, b| a.angle().partial_cmp(&b.angle()).unwrap());
// cycle around and return first element of each vec
angles
.iter()
.cycle()
.map(|xy| match map.get_mut(xy) {
Some(xy) => {
if let Some(xy) = xy.pop() {
Some(xy)
} else {
None
}
}
None => None,
})
.flatten()
.skip(skip)
.take(n)
.cloned()
.collect::<Vec<XY>>()
}
fn find(&self) -> (usize, XY) {
let best = (0, &XY::from((0, 0)));
let best = self
.map
.iter()
.map(|root| {
let insight = self
.map
.iter()
// get direction to any of the astroids
.filter_map(|xy| {
let rel = xy - root;
Some(rel.direction())
})
// and keep only one in each direction
.fold(HashSet::new(), |mut acc, xy| {
acc.insert(xy);
acc
})
.len()
- 1;
(insight, root)
})
.fold(
best,
|acc, astroid| {
if astroid.0 > acc.0 {
astroid
} else {
acc
}
},
);
(best.0, best.1.clone())
}
}
impl<T> From<T> for MonitoringStation
where
T: BufRead,
{
fn from(reader: T) -> Self {
let map = reader
.split(b'\n')
.enumerate()
.flat_map(|(y, line)| {
line.unwrap()
.into_iter()
.enumerate()
.filter_map(move |(x, c)| {
let xy = XY::from((x, y));
match Position::from(&c) {
Position::Astroid => Some(xy),
Position::Empty => None,
}
})
})
.collect::<Vec<XY>>();
MonitoringStation { map }
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let f = File::open("input10")?;
let reader = BufReader::new(f);
let station = MonitoringStation::from(reader);
let best = station.find();
println!("best: {:?}", best);
let lasered = station.laser(&best.1, 199, 1);
let lasered = lasered.iter().next().unwrap();
println!("lasered: {:?}", lasered);
Ok(())
}
fn gcd(x: isize, y: isize) -> isize {
let mut x = x;
let mut y = y;
while y != 0 {
let t = y;
y = x % y;
x = t;
}
x
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example1() {
let reader = BufReader::new(".#..#\n.....\n#####\n....#\n...##".as_bytes());
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 3, y: 4 });
assert_eq!(count, 8);
}
#[test]
fn example2() {
let reader = BufReader::new(
"
......#.#.
#..#.#....
..#######.
.#.#.###..
.#..#.....
..#....#.#
#..#....#.
.##.#..###
##...#..#.
.#....####"
.trim()
.as_bytes(),
);
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 5, y: 8 });
assert_eq!(count, 33);
}
#[test]
fn example3() {
let reader = BufReader::new(
"
#.#...#.#.
.###....#.
.#....#...
##.#.#.#.#
....#.#.#.
.##..###.#
..#...##..
..##....##
......#...
.####.###."
.trim()
.as_bytes(),
);
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 1, y: 2 });
assert_eq!(count, 35);
}
#[test]
fn example4() {
let reader = BufReader::new(
"
.#..#..###
####.###.#
....###.#.
..###.##.#
##.##.#.#.
....###..#
..#.#..#.#
#..#.#.###
.##...##.#
.....#.#.."
.trim()
.as_bytes(),
);
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 6, y: 3 });
assert_eq!(count, 41);
}
#[test]
fn example5() {
let reader = BufReader::new(
"
.#..##.###...#######
##.############..##.
.#.######.########.#
.###.#######.####.#.
#####.##.#.##.###.##
..#####..#.#########
####################
#.####....###.#.#.##
##.#################
#####.##.###..####..
..######..##.#######
####.##.####...##..#
.#####..#.######.###
##...#.##########...
#.##########.#######
.####.#.###.###.#.##
....##.##.###..#####
.#.#.###########.###
#.#.#.#####.####.###
###.##.####.##.#..##"
.trim()
.as_bytes(),
);
let (count, xy) = MonitoringStation::from(reader).find();
assert_eq!(xy, XY { x: 11, y: 13 });
assert_eq!(count, 210);
}
#[test]
fn example6() {
let reader = BufReader::new(
"
.#....#####...#..
##...##.#####..##
##...#...#.#####.
..#.....#...###..
..#.#.....#....##
"
.trim()
.as_bytes(),
);
let ms = MonitoringStation::from(reader);
ms.find();
assert_eq!(
ms.laser(&XY::from((8, 3)), 0, 36),
vec![
XY { x: 8, y: 1 },
XY { x: 9, y: 0 },
XY { x: 9, y: 1 },
XY { x: 10, y: 0 },
XY { x: 9, y: 2 },
XY { x: 11, y: 1 },
XY { x: 12, y: 1 },
XY { x: 11, y: 2 },
XY { x: 15, y: 1 },
XY { x: 12, y: 2 },
XY { x: 13, y: 2 },
XY { x: 14, y: 2 },
XY { x: 15, y: 2 },
XY { x: 12, y: 3 },
XY { x: 16, y: 4 },
XY { x: 15, y: 4 },
XY { x: 10, y: 4 },
XY { x: 4, y: 4 },
XY { x: 2, y: 4 },
XY { x: 2, y: 3 },
XY { x: 0, y: 2 },
XY { x: 1, y: 2 },
XY { x: 0, y: 1 },
XY { x: 1, y: 1 },
XY { x: 5, y: 2 },
XY { x: 1, y: 0 },
XY { x: 5, y: 1 },
XY { x: 6, y: 1 },
XY { x: 6, y: 0 },
XY { x: 7, y: 0 },
XY { x: 8, y: 0 },
XY { x: 10, y: 1 },
XY { x: 14, y: 0 },
XY { x: 16, y: 1 },
XY { x: 13, y: 3 },
XY { x: 14, y: 3 }
]
)
}
}

186
src/day11/main.rs Normal file
View file

@ -0,0 +1,186 @@
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io;
use aoc2019::intcode;
#[derive(Hash, Default, PartialEq, Eq, Clone)]
struct Panel {
x: isize,
y: isize,
}
enum Color {
Black,
White,
}
impl From<isize> for Color {
fn from(color: isize) -> Self {
match color {
0 => Color::Black,
1 => Color::White,
_ => panic!("invalid color"),
}
}
}
impl Into<isize> for &Color {
fn into(self) -> isize {
match self {
Color::Black => 0,
Color::White => 1,
}
}
}
impl Color {
fn char(&self) -> char {
match self {
Color::Black => ' ',
Color::White => '\u{2588}',
}
}
}
enum Direction {
Up,
Down,
Left,
Right,
}
enum Turn {
Left,
Right,
}
impl From<isize> for Turn {
fn from(turn: isize) -> Self {
match turn {
0 => Turn::Left,
1 => Turn::Right,
_ => panic!("invalid turn direction"),
}
}
}
struct Robot {
panel: Panel,
direction: Direction,
}
impl Robot {
fn turn(&mut self, direction: Turn) {
self.direction = match self.direction {
Direction::Up => match direction {
Turn::Left => Direction::Left,
Turn::Right => Direction::Right,
},
Direction::Right => match direction {
Turn::Left => Direction::Up,
Turn::Right => Direction::Down,
},
Direction::Down => match direction {
Turn::Left => Direction::Right,
Turn::Right => Direction::Left,
},
Direction::Left => match direction {
Turn::Left => Direction::Down,
Turn::Right => Direction::Up,
},
}
}
fn step(&mut self) {
self.panel = match self.direction {
Direction::Up => Panel {
x: self.panel.x,
y: self.panel.y + 1,
},
Direction::Left => Panel {
x: self.panel.x + 1,
y: self.panel.y,
},
Direction::Down => Panel {
x: self.panel.x,
y: self.panel.y - 1,
},
Direction::Right => Panel {
x: self.panel.x - 1,
y: self.panel.y,
},
}
}
}
fn main() -> io::Result<()> {
let filename = env::args().nth(1).expect("provide file as first param");
let mut computer = intcode::Computer::from(File::open(filename)?);
let mut canvas: HashMap<Panel, Color> = HashMap::new();
canvas.insert(Panel { x: 0, y: 0 }, Color::White);
let mut robot = Robot {
panel: Panel::default(),
direction: Direction::Up,
};
let mut input: isize = canvas
.get(&robot.panel)
.or_else(|| Some(&Color::Black))
.unwrap()
.into();
while let Some(output) = computer.run_io(input) {
canvas.insert(robot.panel.clone(), Color::from(output));
let output = computer.run_must_output();
robot.turn(Turn::from(output));
robot.step();
input = canvas
.get(&robot.panel)
.or_else(|| Some(&Color::Black))
.unwrap()
.into();
}
let mut xmin: isize = 0;
let mut xmax: isize = 0;
let mut ymin: isize = 0;
let mut ymax: isize = 0;
let painted = canvas
.iter()
.map(|(k, _)| {
if k.x < xmin {
xmin = k.x;
}
if k.x > xmax {
xmax = k.x;
}
if k.y < ymin {
ymin = k.y;
}
if k.y > ymax {
ymax = k.y;
}
})
.count();
println!("painted: {}", painted);
println!("canvas: x:{}-{} y:{}-{}", xmin, xmax, ymin, ymax);
for y in (ymin..=ymax).rev() {
for x in (xmin..=xmax).rev() {
print!(
"{}",
canvas
.get(&Panel { x, y })
.unwrap_or_else(|| &Color::Black)
.char()
)
}
println!()
}
Ok(())
}

332
src/day12/main.rs Normal file
View file

@ -0,0 +1,332 @@
use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
#[derive(PartialEq, Debug, Default, Clone, Hash)]
struct Object {
x: isize,
y: isize,
z: isize,
}
impl From<(isize, isize, isize)> for Object {
fn from(o: (isize, isize, isize)) -> Self {
Object {
x: o.0,
y: o.1,
z: o.2,
}
}
}
impl Object {
fn attract(&self, other: &Object, v: &mut Object) {
v.x += Object::cmp(self.x, other.x);
v.y += Object::cmp(self.y, other.y);
v.z += Object::cmp(self.z, other.z);
}
fn apply(&mut self, v: &Object) {
self.x += v.x;
self.y += v.y;
self.z += v.z;
}
fn cmp(a: isize, b: isize) -> isize {
match b.cmp(&a) {
Ordering::Less => -1,
Ordering::Equal => 0,
Ordering::Greater => 1,
}
}
fn energy(&self) -> usize {
return (self.x.abs() + self.y.abs() + self.z.abs()) as usize;
}
}
struct Space {
iteration: u128,
moons: Vec<Object>,
velocy: Vec<Object>,
}
impl From<Vec<Object>> for Space {
fn from(moons: Vec<Object>) -> Self {
let iteration = 0;
let velocy = Vec::from_iter((0..moons.len()).map(|_| Object::default()));
Space {
iteration,
moons,
velocy,
}
}
}
impl Hash for Space {
fn hash<H: Hasher>(&self, state: &mut H) {
self.moons.iter().for_each(|m| m.hash(state));
self.velocy.iter().for_each(|v| v.hash(state));
}
}
impl Space {
fn step(&mut self) {
self.iteration += 1;
let moons: &mut Vec<Object> = self.moons.as_mut();
let velocy: &mut Vec<Object> = self.velocy.as_mut();
moons.iter().enumerate().for_each(|(idx, a)| {
moons.iter().for_each(|b| {
if a == b {
return;
}
a.attract(b, velocy.get_mut(idx).unwrap())
})
});
moons
.iter_mut()
.enumerate()
.for_each(|(idx, m)| m.apply(velocy.get(idx).unwrap()));
}
fn status(&self) -> impl Iterator<Item = (&'_ Object, &'_ Object)> {
self.moons
.iter()
.zip(self.velocy.iter())
.map(|(a, b)| (a, b))
}
fn iteration(&self) -> u128 {
return self.iteration;
}
fn hashed(&self) -> u64 {
let mut hash = DefaultHasher::new();
self.hash(&mut hash);
hash.finish()
}
fn reapeats(mut self) -> u128 {
let mut known: HashMap<u64, u128> = HashMap::new();
loop {
println!("a lot");
known.insert(self.hashed(), self.iteration());
// 4686774924
for _ in 0..10000000 {
self.step();
if let Some(iteration) = known.get(&self.hashed()) {
let ago = self.iteration() - iteration;
return ago;
}
}
}
}
}
#[derive(Eq, PartialEq, Clone)]
struct Axis {
p: isize,
}
impl From<isize> for Axis {
fn from(p: isize) -> Self {
Axis { p }
}
}
impl Axis {
fn attract(&self, other: &Axis, v: &mut Axis) {
v.p += Axis::cmp(self.p, other.p);
}
fn apply(&mut self, v: &Axis) {
self.p += v.p;
}
fn cmp(a: isize, b: isize) -> isize {
match b.cmp(&a) {
Ordering::Less => -1,
Ordering::Equal => 0,
Ordering::Greater => 1,
}
}
fn energy(&self) -> usize {
return self.p.abs() as usize;
}
}
struct AxisSpace {
iteration: usize,
moons: Vec<Axis>,
velocy: Vec<Axis>,
}
impl From<Vec<isize>> for AxisSpace {
fn from(moons: Vec<isize>) -> Self {
let iteration = 0;
let moons = Vec::from_iter(moons.iter().map(|i| Axis::from(*i)));
let velocy = Vec::from_iter((0..moons.len()).map(|_| Axis::from(0)));
AxisSpace {
iteration,
moons,
velocy,
}
}
}
impl AxisSpace {
fn step(&mut self) {
self.iteration += 1;
let moons: &mut Vec<Axis> = self.moons.as_mut();
let velocy: &mut Vec<Axis> = self.velocy.as_mut();
moons.iter().enumerate().for_each(|(idx, a)| {
moons.iter().for_each(|b| {
if a == b {
return;
}
a.attract(&b, &mut velocy[idx])
})
});
moons
.iter_mut()
.enumerate()
.for_each(|(idx, m)| m.apply(velocy.get(idx).unwrap()));
}
fn iteration(&self) -> usize {
return self.iteration;
}
fn reapeats(mut self) -> usize {
let want = self.moons.clone();
self.step();
while self.moons != want {
self.step();
}
return self.iteration() + 1;
}
}
fn gcd(x: usize, y: usize) -> usize {
let mut x = x;
let mut y = y;
while y != 0 {
let t = y;
y = x % y;
x = t;
}
x
}
fn lcm(a: usize, b: usize) -> usize {
a * b / gcd(a, b)
}
fn lcm3(a: usize, b: usize, c: usize) -> usize {
lcm(a, lcm(b, c))
}
fn main() {
// part1
let moons = vec![
Object::from((17, 5, 1)),
Object::from((-2, -8, 8)),
Object::from((7, -6, 14)),
Object::from((1, -10, 4)),
];
let mut space = Space::from(moons);
let mut step_energy = 0;
(1..=100).for_each(|_i| {
(1..=10).for_each(|_| {
space.step();
});
step_energy = space
.status()
.map(|(o, v)| o.energy() * v.energy())
.fold(0, |mut acc, c| {
acc += c;
acc
});
});
println!("energy: {}", step_energy);
// part2
let xspace = AxisSpace::from(vec![-1, 2, 4, 3]);
let yspace = AxisSpace::from(vec![0, -10, -8, 5]);
let zspace = AxisSpace::from(vec![2, -7, 8, -1]);
let total = lcm3(xspace.reapeats(), yspace.reapeats(), zspace.reapeats());
println!("matching space found {} iterations ago", total);
let xspace = AxisSpace::from(vec![-8, 5, 2, 9]);
let yspace = AxisSpace::from(vec![-10, 5, -7, -8]);
let zspace = AxisSpace::from(vec![0, 10, 3, -3]);
let total = lcm3(xspace.reapeats(), yspace.reapeats(), zspace.reapeats());
println!("matching space found {} iterations ago", total);
let xspace = AxisSpace::from(vec![17, -2, 7, 1]);
let yspace = AxisSpace::from(vec![5, -8, -6, -10]);
let zspace = AxisSpace::from(vec![1, 8, 14, 4]);
let total = lcm3(xspace.reapeats(), yspace.reapeats(), zspace.reapeats());
println!("matching space found {} iterations ago", total);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn day12example1() {
let space = Space::from(vec![
Object::from((-1, 0, 2)),
Object::from((2, -10, -7)),
Object::from((4, -8, 8)),
Object::from((3, 5, -1)),
]);
assert!(space.status().eq(vec![
(&Object::from((-1, 0, 2)), &Object::default()),
(&Object::from((2, -10, -7)), &Object::from((0, 0, 0))),
(&Object::from((4, -8, 8)), &Object::from((0, 0, 0))),
(&Object::from((3, 5, -1)), &Object::from((0, 0, 0))),
]));
}
#[test]
fn day12part1() {
let mut space = Space::from(vec![
Object::from((17, 5, 1)),
Object::from((-2, -8, 8)),
Object::from((7, -6, 14)),
Object::from((1, -10, 4)),
]);
(1..=1000).for_each(|_| {
space.step();
});
let energy = space
.status()
.map(|(o, v)| {
println!("{:?} {:?}", o, v);
o.energy() * v.energy()
})
.fold(0, |mut acc, c| {
acc += c;
acc
});
assert_eq!(energy, 9876)
}
#[test]
fn day12example2() {
let space = Space::from(vec![
Object::from((-1, 0, 2)),
Object::from((2, -10, -7)),
Object::from((4, -8, 8)),
Object::from((3, 5, -1)),
]);
assert_eq!(space.reapeats(), 2772)
}
}

135
src/day13/main.rs Normal file
View file

@ -0,0 +1,135 @@
use aoc2019::intcode;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::error::Error;
use std::fs::File;
use ncurses;
fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("input13")?;
let mut computer = intcode::Computer::from(f);
let mut grid: Grid = HashMap::new();
while let Some(output) = computer.run_until_n_output(3) {
let mut output = output.into_iter();
let xy = XY {
x: output.next().unwrap(),
y: output.next().unwrap(),
};
let tile = Tile::from(output.next().unwrap());
grid.insert(xy, tile);
}
// part 1
let blocks = grid.iter().filter(|(_, v)| **v == Tile::Block).count();
println!("blocks: {}", blocks);
// part2
ncurses::initscr();
ncurses::noecho();
let mut computer = computer.clone_with_modified_program(vec![(0, 2)]);
let mut paddlex = 0;
let mut score = 0;
while !computer.halted {
if let Some(output) = &computer.run_until_input() {
output.chunks(3).for_each(|c| {
if let &[x, y, value] = c {
if x == -1 && y == 0 {
score = value;
} else {
let tile = Tile::from(value);
if Tile::from(value) == Tile::HorizontalPaddle {
paddlex = x;
}
ncurses::mvprintw((y + 1) as i32, x as i32, tile.char());
}
}
});
}
let np = next_pos(&mut computer.clone());
ncurses::mvprintw(
0,
0,
&format!(
"willx: {:0>2} paddlex: {:0>2} score: {:0>7}",
np, paddlex, score
),
);
let joystick = match np.cmp(&paddlex) {
Ordering::Less => -1,
Ordering::Equal => 0,
Ordering::Greater => 1,
};
computer.push_input_and_step(joystick);
ncurses::refresh();
}
ncurses::endwin();
println!("score: {}", score);
Ok(())
}
fn next_pos(computer: &mut intcode::Computer) -> isize {
while !computer.halted {
if let Some(output) = computer.run_until_input() {
for c in output.chunks(3) {
if let &[x, y, value] = c {
if x == -1 && y == 0 {
// skip score
} else if Tile::from(value) == Tile::Ball && y == 23 {
return x;
}
}
}
}
computer.push_input_and_step(0);
}
0
}
#[derive(Eq, PartialEq)]
enum Tile {
Empty,
Wall,
Block,
HorizontalPaddle,
Ball,
}
impl From<isize> for Tile {
fn from(i: isize) -> Self {
match i {
0 => Tile::Empty,
1 => Tile::Wall,
2 => Tile::Block,
3 => Tile::HorizontalPaddle,
4 => Tile::Ball,
_ => unreachable!("there are only 5 tiles..."),
}
}
}
impl Tile {
fn char(&self) -> &str {
match self {
Tile::Empty => " ",
Tile::Wall => "X",
Tile::Block => "O",
Tile::HorizontalPaddle => "-",
Tile::Ball => "*",
}
}
}
#[derive(Eq, PartialEq, Hash)]
struct XY {
x: isize,
y: isize,
}
impl From<(isize, isize)> for XY {
fn from(xy: (isize, isize)) -> Self {
XY { x: xy.0, y: xy.1 }
}
}
type Grid = HashMap<XY, Tile>;

385
src/day14/main.rs Normal file
View file

@ -0,0 +1,385 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use std::convert::*;
use std::fs::File;
use std::io::{BufRead, BufReader};
type Resource = String;
type Pipeline = HashMap<Resource, ResourceBuilder>;
#[derive(Debug)]
struct ResourceBuilder {
requirements: Vec<Resource>,
out_count: usize,
}
impl From<(Vec<Resource>, usize)> for ResourceBuilder {
fn from(build: (Vec<Resource>, usize)) -> Self {
ResourceBuilder {
requirements: build.0,
out_count: build.1,
}
}
}
#[derive(Default, Debug)]
struct NanoFactory {
pipeline: Pipeline,
ordered: Vec<Resource>,
}
#[derive(Debug)]
enum NanoFactoryBuildState {
InputCount,
InputResource,
OutputArrow,
OutputCount,
OutputResource,
}
impl NanoFactory {
/// sort resources
fn resolve_order(&mut self) {
self.ordered = vec![Resource::from("ORE")];
let mut sortable: HashMap<Resource, Vec<Resource>> = self
.pipeline
.iter()
.map(|(k, v)| (k.clone(), v.requirements.clone()))
.collect();
while sortable.len() > 0 {
sortable = sortable
.into_iter()
.filter_map(|(k, v)| {
if v.iter().all(|i| self.ordered.contains(i)) {
self.ordered.push(k);
None
} else {
Some((k, v))
}
})
.collect();
}
self.ordered.reverse();
self.ordered.retain(|res| res != "ORE");
}
/// calculate how much ores are required for required_fuel
fn resource_usage(&self, required_fuel: u128) -> usize {
// create storage to track leftover resources
let mut storage: HashMap<Resource, u128> = HashMap::new();
storage.insert(Resource::from("FUEL"), required_fuel);
// calculate resource costs
self.ordered.iter().for_each(|res| {
let rb = self.pipeline.get(res).unwrap();
let count = (storage.get(res).unwrap().clone() + (rb.out_count as u128) - 1)
/ (rb.out_count as u128);
rb.requirements.iter().for_each(|req| {
storage
.entry(req.clone())
.and_modify(|v| *v += count)
.or_insert(count);
storage.insert(res.clone(), 0);
})
});
// return cost for ore
println!("{:?}", storage);
*storage.get("ORE").unwrap() as usize
}
/// generate a single fuel
fn generate_fuel(&self) -> usize {
let mut storage: HashMap<Resource, usize> = HashMap::new();
self.lookup_resource(&mut storage, "FUEL")
}
/// recursively calculate the cost of a resource in ores
fn lookup_resource(&self, storage: &mut HashMap<Resource, usize>, resource: &str) -> usize {
if resource == "ORE" {
return 1;
}
// use from storage
if let Some(count) = storage.get_mut(resource) {
if *count > 0 {
*count -= 1;
return 0;
}
}
// initialize storage with zero
if storage.get(resource).is_none() {
storage.insert(resource.into(), 0);
}
// build resource and and to storage
let required = self
.pipeline
.get(resource)
.expect("unable to find resource");
let cost = required.requirements.iter().fold(0, |mut acc, c| {
acc += self.lookup_resource(storage, c);
acc
});
// update storage
let stored = storage.get_mut(resource).unwrap();
*stored += required.out_count - 1;
cost
}
}
impl<T> From<T> for NanoFactory
where
T: BufRead,
{
fn from(bufreader: T) -> Self {
let mut f = NanoFactory::default();
let mut state = NanoFactoryBuildState::InputCount;
bufreader.split(b'\n').enumerate().for_each(|(nr, line)| {
let line = line.unwrap();
let mut line = line.into_iter().peekable();
let mut count_var = 0;
let mut cur_requirements = Vec::new();
loop {
match state {
// numeric input
NanoFactoryBuildState::InputCount | NanoFactoryBuildState::OutputCount => {
while let Some(c) = next_if_in_range(&mut line, 48..=57) {
count_var = count_var * 10 + (c as usize) - 48;
}
assert_eq!(line.next().unwrap(), b' ');
state = match state {
NanoFactoryBuildState::InputCount => {
NanoFactoryBuildState::InputResource
}
NanoFactoryBuildState::OutputCount => {
NanoFactoryBuildState::OutputResource
}
_ => unreachable!(),
}
}
// input resouce name
NanoFactoryBuildState::InputResource => {
let mut r = Resource::new();
while let Some(c) = next_if_in_range(&mut line, 65..=90) {
r.push(c.into());
}
for _ in 0..count_var {
cur_requirements.push(r.clone());
}
r.truncate(0);
count_var = 0;
let next = line.next();
match next {
Some(b',') => {
assert_eq!(line.next().unwrap(), b' ');
state = NanoFactoryBuildState::InputCount;
}
Some(b' ') => state = NanoFactoryBuildState::OutputArrow,
_ => panic!(
"invalid format in line {}, expected ' ' or ',', got '{:?}'",
nr, next
),
}
}
// output resource name
NanoFactoryBuildState::OutputResource => {
let mut r = Resource::new();
while let Some(c) = next_if_in_range(&mut line, 65..=90) {
r.push(c.into());
}
f.pipeline
.insert(r, ResourceBuilder::from((cur_requirements, count_var)));
state = NanoFactoryBuildState::InputCount;
return;
}
// arrow between input and output ' => '
NanoFactoryBuildState::OutputArrow => {
assert_eq!(line.next().unwrap(), b'=');
assert_eq!(line.next().unwrap(), b'>');
assert_eq!(line.next().unwrap(), b' ');
state = NanoFactoryBuildState::OutputCount
}
};
}
});
f
}
}
fn next_if_in_range<I, T>(
peekable: &mut std::iter::Peekable<I>,
range: std::ops::RangeInclusive<T>,
) -> Option<T>
where
I: std::iter::Iterator<Item = T>,
T: Copy + std::cmp::PartialOrd,
{
if let Some(peeked) = peekable.peek() {
if range.contains(peeked) {
peekable.next()
} else {
None
}
} else {
None
}
}
fn main() {
let f = File::open("input14").unwrap();
let bufreader = BufReader::new(f);
let mut factory = NanoFactory::from(bufreader);
// part1
println!("ores: {}", factory.generate_fuel());
// part2 as binary search
factory.resolve_order();
let mut min = 1;
let mut max = 1_000_000_000_000;
let mut fuel;
loop {
fuel = (min + max) / 2;
let ore = factory.resource_usage(fuel);
match 1_000_000_000_000.cmp(&ore) {
Ordering::Less => max = fuel - 1,
Ordering::Greater => {
min = fuel + 1;
if min > max {
break;
}
}
Ordering::Equal => {
break;
}
};
}
println!("ammount: {}", fuel);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example1() {
let bufreader = BufReader::new(
"10 ORE => 10 A
1 ORE => 1 B
7 A, 1 B => 1 C
7 A, 1 C => 1 D
7 A, 1 D => 1 E
7 A, 1 E => 1 FUEL
"
.trim()
.as_bytes(),
);
let mut factory = NanoFactory::from(bufreader);
factory.resolve_order();
assert_eq!(factory.generate_fuel(), 31);
assert_eq!(factory.resource_usage(1), 31);
}
#[test]
fn example2() {
let bufreader = BufReader::new(
"
9 ORE => 2 A
8 ORE => 3 B
7 ORE => 5 C
3 A, 4 B => 1 AB
5 B, 7 C => 1 BC
4 C, 1 A => 1 CA
2 AB, 3 BC, 4 CA => 1 FUEL
"
.trim()
.as_bytes(),
);
let mut factory = NanoFactory::from(bufreader);
factory.resolve_order();
assert_eq!(factory.generate_fuel(), 165);
assert_eq!(factory.resource_usage(1), 165);
}
#[test]
fn example3() {
let bufreader = BufReader::new(
"
157 ORE => 5 NZVS
165 ORE => 6 DCFZ
44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL
12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ
179 ORE => 7 PSHF
177 ORE => 5 HKGWZ
7 DCFZ, 7 PSHF => 2 XJWVT
165 ORE => 2 GPVTF
3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT
"
.trim()
.as_bytes(),
);
let factory = NanoFactory::from(bufreader);
assert_eq!(factory.generate_fuel(), 13312);
}
#[test]
fn example4() {
let bufreader = BufReader::new(
"
2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG
17 NVRVD, 3 JNWZP => 8 VPVL
53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL
22 VJHF, 37 MNCFX => 5 FWMGM
139 ORE => 4 NVRVD
144 ORE => 7 JNWZP
5 MNCFX, 7 RFSQX, 2 FWMGM, 2 VPVL, 19 CXFTF => 3 HVMC
5 VJHF, 7 MNCFX, 9 VPVL, 37 CXFTF => 6 GNMV
145 ORE => 6 MNCFX
1 NVRVD => 8 CXFTF
1 VJHF, 6 MNCFX => 4 RFSQX
176 ORE => 6 VJHF
"
.trim()
.as_bytes(),
);
let mut factory = NanoFactory::from(bufreader);
factory.resolve_order();
assert_eq!(factory.generate_fuel(), 180697);
assert_eq!(factory.resource_usage(1), 180697);
}
#[test]
fn example5() {
let bufreader = BufReader::new(
"
171 ORE => 8 CNZTR
7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL
114 ORE => 4 BHXH
14 VRPVC => 6 BMBT
6 BHXH, 18 KTJDG, 12 WPTQ, 7 PLWSL, 31 FHTLT, 37 ZDVW => 1 FUEL
6 WPTQ, 2 BMBT, 8 ZLQW, 18 KTJDG, 1 XMNCP, 6 MZWV, 1 RJRHP => 6 FHTLT
15 XDBXC, 2 LTCX, 1 VRPVC => 6 ZLQW
13 WPTQ, 10 LTCX, 3 RJRHP, 14 XMNCP, 2 MZWV, 1 ZLQW => 1 ZDVW
5 BMBT => 4 WPTQ
189 ORE => 9 KTJDG
1 MZWV, 17 XDBXC, 3 XCVML => 2 XMNCP
12 VRPVC, 27 CNZTR => 2 XDBXC
15 KTJDG, 12 BHXH => 5 XCVML
3 BHXH, 2 VRPVC => 7 MZWV
121 ORE => 7 VRPVC
7 XCVML => 6 RJRHP
5 BHXH, 4 VRPVC => 5 LTCX
"
.trim()
.as_bytes(),
);
let mut factory = NanoFactory::from(bufreader);
factory.resolve_order();
assert_eq!(factory.generate_fuel(), 2210736);
assert_eq!(factory.resource_usage(1), 2210736);
}
}

205
src/day15/main.rs Normal file
View file

@ -0,0 +1,205 @@
use std::collections::HashMap;
use std::error::Error;
use std::fs::File;
use aoc2019::intcode;
fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("input15")?;
let computer = intcode::Computer::from(f);
let mut map = Map::new();
let steps = map.walk(&XY { x: 0, y: 0 }, &computer, 0).unwrap();
for y in map.ymin..=map.ymax {
for x in map.xmin..=map.xmax {
if x == 0 && y == 0 {
print!("0");
continue;
}
let status = map.m.get(&XY { x, y }).unwrap_or(&Status::Empty);
let c = match status {
Status::HitWall => "#",
Status::MoveComplete => ".",
Status::Finished => "X",
Status::Empty => " ",
Status::Oxigenated => "o",
};
print!("{}", c);
}
println!("");
}
println!("i walked {} steps", steps);
let steps = map.fill();
println!("filled with oxygen after {} minutes", steps);
Ok(())
}
#[derive(Default, Debug)]
struct Map {
m: HashMap<XY, Status>,
xmin: isize,
xmax: isize,
ymin: isize,
ymax: isize,
}
impl Map {
fn new() -> Self {
Map::default()
}
fn walk(&mut self, start: &XY, computer: &intcode::Computer, steps: usize) -> Option<usize> {
let steps = steps + 1;
let mut result = None;
for dir in 1..=4 {
let direction = Direction::from(dir);
let xy = start.add((&direction).into());
if self.m.contains_key(&xy) {
continue;
}
self.update_limits(&xy);
let mut computer = computer.clone();
if let Some(status) = computer.run_io(dir) {
let status = Status::from(status);
self.m.insert(xy.clone(), status.clone());
match status {
Status::HitWall => (),
Status::MoveComplete => match self.walk(&xy, &computer, steps) {
Some(i) => result = Some(i + 1),
None => (),
},
Status::Finished => result = Some(1),
_ => unreachable!("unknown status"),
}
} else {
unreachable!("computer unexpectedly halted");
}
}
result
}
fn fill(&mut self) -> usize {
let mut src: Vec<XY> = self
.m
.iter()
.filter_map(|(xy, status)| match status {
Status::Finished => Some(xy),
_ => None,
})
.cloned()
.collect();
let mut steps = 0;
while src.len() > 0 {
steps += 1;
src.iter()
.for_each(|xy| *self.m.get_mut(xy).unwrap() = Status::Oxigenated);
src = src
.into_iter()
.map(|xy| {
(1..=4)
.map(Direction::from)
.map(move |d| xy.add((&d).into()))
})
.flatten()
.filter(|xy| match self.m.get(xy) {
Some(Status::MoveComplete) => true,
_ => false,
})
.collect();
}
assert_eq!(
self.m
.values()
.filter(|status| match status {
Status::MoveComplete => true,
_ => false,
})
.count(),
0
);
steps - 1
}
fn update_limits(&mut self, xy: &XY) {
if self.xmin > xy.x {
self.xmin = xy.x
}
if self.xmax < xy.x {
self.xmax = xy.x
}
if self.ymin > xy.y {
self.ymin = xy.y
}
if self.ymax < xy.y {
self.ymax = xy.y
}
}
}
#[derive(Debug)]
enum Direction {
North = 1,
South = 2,
West = 3,
East = 4,
}
impl From<isize> for Direction {
fn from(i: isize) -> Self {
match i {
1 => Direction::North,
2 => Direction::South,
3 => Direction::West,
4 => Direction::East,
_ => unreachable!("no status for computer output"),
}
}
}
impl Into<(isize, isize)> for &Direction {
fn into(self) -> (isize, isize) {
match self {
Direction::North => (0, 1),
Direction::South => (0, -1),
Direction::West => (-1, 0),
Direction::East => (1, 0),
}
}
}
#[derive(Clone, Debug)]
enum Status {
HitWall = 0,
MoveComplete = 1,
Finished = 2,
Empty = 3,
Oxigenated = 4,
}
impl From<isize> for Status {
fn from(i: isize) -> Self {
match i {
0 => Status::HitWall,
1 => Status::MoveComplete,
2 => Status::Finished,
_ => unreachable!("no status for computer output"),
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
struct XY {
x: isize,
y: isize,
}
impl XY {
fn add(&self, delta: (isize, isize)) -> XY {
XY {
x: self.x + delta.0,
y: self.y + delta.1,
}
}
}

View file

@ -10,29 +10,6 @@ enum Var {
C,
}
// impl From<usize> for Var {
// fn from(i: usize) -> Self {
// match i {
// 0 => Var::Opcode,
// 1 => Var::A,
// 2 => Var::B,
// 3 => Var::C,
// _ => panic!("invalid variable")
// }
// }
// }
//
// impl Into<usize> for Var {
// fn into(self) -> usize {
// match self {
// Var::Opcode => 0,
// Var::A => 1,
// Var::B => 2,
// Var::C => 3,
// }
// }
// }
#[derive(Copy, Clone, Debug)]
enum Mode {
Position,
@ -263,12 +240,13 @@ impl Computer {
}
fn get(&self, v: &Var) -> i64 {
let x = *self.program.get(self.pos + *v as usize).unwrap_or(&0);
match self.modes.mode_for(v) {
Mode::Position => self.get_pos(x as usize),
Mode::Immediate => x,
Mode::Relative => self.get_pos((self.rel + x) as usize),
}
let want = self.pos + *v as usize;
let want = match self.modes.mode_for(v) {
Mode::Position => self.get_pos(want as usize) as usize,
Mode::Immediate => want,
Mode::Relative => (self.rel + self.get_pos(want)) as usize,
};
self.get_pos(want)
}
fn get_a(&self) -> i64 {
@ -283,12 +261,12 @@ impl Computer {
let length = self.program.len();
let want = self.pos + *v as usize;
let want = match self.modes.mode_for(v) {
Mode::Position => self.get_pos(want),
Mode::Immediate => want as i64,
Mode::Relative => self.get_pos((self.rel + want as i64) as usize),
} as usize;
Mode::Position => self.get_pos(want) as usize,
Mode::Immediate => want,
Mode::Relative => (self.rel + self.get_pos(want)) as usize,
};
if length < want {
let missing = (want - length) + 2;
let missing = (want - length) + 5;
self.program.extend_from_slice(&vec![0; missing])
}
self.program[want] = value;
@ -371,9 +349,15 @@ impl Computer {
fn main() -> io::Result<()> {
let filename = env::args().nth(1).expect("provide file as first param");
let computer = Computer::from(File::open(filename)?);
// part1
let result = computer.clone_with_input(vec![1]).run_must_output();
println!("{:?}", result);
// part2
let result = computer.clone_with_input(vec![2]).run_must_output();
println!("{:?}", result);
Ok(())
}
@ -401,43 +385,56 @@ mod tests {
#[test]
fn example3() {
assert_eq!(
Computer::from(vec![104,1125899906842624,99]).run_must_output(),
1125899906842624
)
assert_eq!(
Computer::from(vec![104, 1125899906842624, 99]).run_must_output(),
1125899906842624
)
}
#[test]
fn day5exampe1() {
let computer = Computer::from(vec![3,9,8,9,10,9,4,9,99,-1,8]);
assert_eq!(computer.clone_with_input(vec![1]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
let computer = Computer::from(vec![3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8]);
assert_eq!(computer.clone_with_input(vec![1]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
}
#[test]
fn day5exampe2() {
let computer = Computer::from(vec![3,3,1108,-1,8,3,4,3,99]);
assert_eq!(computer.clone_with_input(vec![1]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
let computer = Computer::from(vec![3, 3, 1108, -1, 8, 3, 4, 3, 99]);
assert_eq!(computer.clone_with_input(vec![1]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
}
#[test]
fn day5exampe3() {
let computer = Computer::from(vec![3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
let computer = Computer::from(vec![3,3,1105,-1,9,1101,0,0,12,4,12,99,1]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
let computer = Computer::from(vec![
3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9,
]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
let computer = Computer::from(vec![3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
}
#[test]
fn day5exampe4() {
let computer = Computer::from(vec![3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,
999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 999);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1000);
assert_eq!(computer.clone_with_input(vec![9]).run_must_output(), 1001);
let computer = Computer::from(vec![
3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36, 98, 0,
0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000, 1, 20, 4,
20, 1105, 1, 46, 98, 99,
]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 999);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1000);
assert_eq!(computer.clone_with_input(vec![9]).run_must_output(), 1001);
}
#[test]
fn day9part1() {
let computer = Computer::from(File::open("input9").unwrap());
assert_eq!(
computer.clone_with_input(vec![1]).run_must_output(),
3063082071
);
}
}

477
src/intcode.rs Normal file
View file

@ -0,0 +1,477 @@
use std::collections::VecDeque;
use std::fs::File;
use std::io::{BufRead, BufReader};
#[derive(Copy, Clone)]
enum Var {
A = 1,
B,
C,
}
#[derive(Copy, Clone, Debug)]
enum Mode {
Position,
Immediate,
Relative,
}
impl Default for Mode {
fn default() -> Self {
Mode::Position
}
}
impl From<isize> for Mode {
fn from(b: isize) -> Self {
match b {
0 => Mode::Position,
1 => Mode::Immediate,
2 => Mode::Relative,
_ => panic!("invalid mode {}", b),
}
}
}
#[derive(Copy, Clone, Default, Debug)]
struct Modes {
a: Mode,
b: Mode,
c: Mode,
}
impl Modes {
fn mode_for(&self, v: &Var) -> Mode {
match v {
Var::A => self.a,
Var::B => self.b,
Var::C => self.c,
}
}
}
impl From<(Mode, Mode, Mode)> for Modes {
fn from(modes: (Mode, Mode, Mode)) -> Self {
Modes {
a: modes.0,
b: modes.1,
c: modes.2,
}
}
}
impl From<&ModedOpcode> for Modes {
fn from(mo: &ModedOpcode) -> Self {
mo.modes
}
}
#[derive(Copy, Clone)]
enum Opcode {
Add,
Multiply,
Input,
Output,
JumpIfTrue,
JumpIfFalse,
LessThan,
Equals,
RelativeAdj,
Halt,
}
impl From<&ModedOpcode> for Opcode {
fn from(mo: &ModedOpcode) -> Self {
mo.op
}
}
impl From<isize> for Opcode {
fn from(i: isize) -> Self {
match i {
1 => Opcode::Add,
2 => Opcode::Multiply,
3 => Opcode::Input,
4 => Opcode::Output,
5 => Opcode::JumpIfTrue,
6 => Opcode::JumpIfFalse,
7 => Opcode::LessThan,
8 => Opcode::Equals,
9 => Opcode::RelativeAdj,
99 => Opcode::Halt,
_ => panic!("invalid opcode {}", i),
}
}
}
struct ModedOpcode {
modes: Modes,
op: Opcode,
}
impl From<isize> for ModedOpcode {
fn from(i: isize) -> Self {
let code = i % 100;
let modes = i / 100;
let a = (modes % 10) / 1;
let b = (modes % 100) / 10;
let c = (modes % 1000) / 100;
let modes = (Mode::from(a), Mode::from(b), Mode::from(c));
ModedOpcode {
modes: Modes::from(modes),
op: Opcode::from(code),
}
}
}
pub struct Computer {
pos: usize,
rel: isize,
program: Vec<isize>,
modes: Modes,
inputs: VecDeque<isize>,
outputs: VecDeque<isize>,
pub halted: bool,
}
impl Clone for Computer {
fn clone(&self) -> Self {
Computer::from(self.program.clone())
}
}
impl From<File> for Computer {
fn from(f: File) -> Self {
let f = BufReader::new(f);
let program: Vec<isize> = f
.split(b',')
.map(|o| {
let o = o.unwrap();
let mut o = o.iter().peekable();
let sign = if o.peek() == Some(&&b'-') { -1 } else { 1 };
o.filter(|i| **i >= b'0' && **i <= b'9')
.fold(0, |s, i| ((i - b'0') as isize + 10 * s))
* sign
})
.collect();
Computer::from(program)
}
}
impl From<Vec<isize>> for Computer {
fn from(program: Vec<isize>) -> Self {
Computer {
pos: 0,
rel: 0,
program,
modes: Default::default(),
inputs: VecDeque::new(),
outputs: VecDeque::new(),
halted: false,
}
}
}
impl Computer {
pub fn get_outputs(&self) -> &VecDeque<isize> {
&self.outputs
}
pub fn pop_output(&mut self) -> Option<isize> {
self.outputs.pop_front()
}
pub fn push_input_and_step(&mut self, input: isize) {
self.inputs.push_back(input);
self.step()
}
pub fn clone_with_modified_program(&self, u: Vec<(usize, isize)>) -> Computer {
let mut computer = self.clone();
for (pos, val) in u {
computer.program[pos] = val;
}
computer
}
pub fn clone_with_input(&self, input: Vec<isize>) -> Computer {
let mut computer = self.clone();
computer.inputs = VecDeque::from(input);
computer
}
pub fn run(&mut self) {
while !self.halted {
self.step();
}
}
pub fn run_until_input(&mut self) -> Option<Vec<isize>> {
self.step_until_input();
if self.outputs.len() > 0 {
return Some(self.outputs.split_off(0).into_iter().collect());
}
return None;
}
pub fn run_until_n_output(&mut self, n: usize) -> Option<Vec<isize>> {
loop {
self.step();
if self.outputs.len() >= n {
return Some(self.outputs.split_off(0).into_iter().collect());
}
if self.halted {
return None;
}
}
}
pub fn run_until_output(&mut self) -> Option<isize> {
loop {
self.step();
if self.outputs.len() > 0 {
return self.outputs.pop_front();
}
if self.halted {
return None;
}
}
}
pub fn run_must_output(&mut self) -> isize {
self.run_until_output()
.expect("computer halted without output")
}
pub fn run_io(&mut self, input: isize) -> Option<isize> {
self.inputs.push_back(input);
self.run_until_output()
}
fn step_until_input(&mut self) {
while !self.halted {
let instruction = self.program[self.pos];
let instruction = ModedOpcode::from(instruction);
self.modes = Modes::from(&instruction);
let advance = match Opcode::from(&instruction) {
Opcode::Add => self.add(),
Opcode::Multiply => self.multiply(),
Opcode::Input => return,
Opcode::Output => self.output(),
Opcode::JumpIfTrue => self.jump_if_true(),
Opcode::JumpIfFalse => self.jump_if_false(),
Opcode::LessThan => self.less_than(),
Opcode::Equals => self.equals(),
Opcode::RelativeAdj => self.relative_adj(),
Opcode::Halt => self.halt(),
};
self.pos += advance;
}
}
pub fn step(&mut self) {
let instruction = self.program[self.pos];
let instruction = ModedOpcode::from(instruction);
self.modes = Modes::from(&instruction);
let advance = match Opcode::from(&instruction) {
Opcode::Add => self.add(),
Opcode::Multiply => self.multiply(),
Opcode::Input => self.input(),
Opcode::Output => self.output(),
Opcode::JumpIfTrue => self.jump_if_true(),
Opcode::JumpIfFalse => self.jump_if_false(),
Opcode::LessThan => self.less_than(),
Opcode::Equals => self.equals(),
Opcode::RelativeAdj => self.relative_adj(),
Opcode::Halt => self.halt(),
};
self.pos += advance;
}
fn get_pos(&self, pos: usize) -> isize {
*self.program.get(pos).unwrap_or(&0)
}
fn get(&self, v: &Var) -> isize {
let want = self.pos + *v as usize;
let want = match self.modes.mode_for(v) {
Mode::Position => self.get_pos(want as usize) as usize,
Mode::Immediate => want,
Mode::Relative => (self.rel + self.get_pos(want)) as usize,
};
self.get_pos(want)
}
fn get_a(&self) -> isize {
self.get(&Var::A)
}
fn get_b(&self) -> isize {
self.get(&Var::B)
}
fn set(&mut self, v: &Var, value: isize) {
let length = self.program.len();
let want = self.pos + *v as usize;
let want = match self.modes.mode_for(v) {
Mode::Position => self.get_pos(want) as usize,
Mode::Immediate => want,
Mode::Relative => (self.rel + self.get_pos(want)) as usize,
};
if length <= want {
self.program.resize(want + 1, 0);
}
self.program[want] = value;
}
fn set_a(&mut self, value: isize) {
self.set(&Var::A, value)
}
fn set_c(&mut self, value: isize) {
self.set(&Var::C, value)
}
fn add(&mut self) -> usize {
self.set_c(self.get_a() + self.get_b());
4
}
fn multiply(&mut self) -> usize {
self.set_c(self.get_a() * self.get_b());
4
}
fn input(&mut self) -> usize {
let value = self.inputs.pop_front().expect("no input provided");
self.set_a(value);
2
}
fn output(&mut self) -> usize {
self.outputs.push_back(self.get_a());
2
}
fn jump_if_true(&mut self) -> usize {
if self.get_a() > 0 {
self.pos = self.get_b() as usize;
return 0;
}
3
}
fn jump_if_false(&mut self) -> usize {
if self.get_a() == 0 {
self.pos = self.get_b() as usize;
return 0;
}
3
}
fn less_than(&mut self) -> usize {
if self.get_a() < self.get_b() {
self.set_c(1)
} else {
self.set_c(0)
}
4
}
fn equals(&mut self) -> usize {
if self.get_a() == self.get_b() {
self.set_c(1)
} else {
self.set_c(0)
}
4
}
fn relative_adj(&mut self) -> usize {
self.rel = self.rel + self.get_a();
2
}
fn halt(&mut self) -> usize {
self.halted = true;
0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example1() {
let program = vec![
109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99,
];
let mut computer = Computer::from(program.clone());
computer.run();
assert_eq!(computer.get_outputs().iter().eq(program.iter()), true)
}
#[test]
fn example2() {
assert_eq!(
Computer::from(vec![1102, 34915192, 34915192, 7, 4, 7, 99, 0]).run_must_output(),
1219070632396864
)
}
#[test]
fn example3() {
assert_eq!(
Computer::from(vec![104, 1125899906842624, 99]).run_must_output(),
1125899906842624
)
}
#[test]
fn day5exampe1() {
let computer = Computer::from(vec![3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8]);
assert_eq!(computer.clone_with_input(vec![1]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
}
#[test]
fn day5exampe2() {
let computer = Computer::from(vec![3, 3, 1108, -1, 8, 3, 4, 3, 99]);
assert_eq!(computer.clone_with_input(vec![1]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
}
#[test]
fn day5exampe3() {
let computer = Computer::from(vec![
3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9,
]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
let computer = Computer::from(vec![3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 0);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1);
}
#[test]
fn day5exampe4() {
let computer = Computer::from(vec![
3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36, 98, 0,
0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000, 1, 20, 4,
20, 1105, 1, 46, 98, 99,
]);
assert_eq!(computer.clone_with_input(vec![0]).run_must_output(), 999);
assert_eq!(computer.clone_with_input(vec![8]).run_must_output(), 1000);
assert_eq!(computer.clone_with_input(vec![9]).run_must_output(), 1001);
}
#[test]
fn day9part1() {
let computer = Computer::from(File::open("input9").unwrap());
assert_eq!(
computer.clone_with_input(vec![1]).run_must_output(),
3063082071
);
}
}

1
src/lib.rs Normal file
View file

@ -0,0 +1 @@
pub mod intcode;

View file

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}