Initial commit

This commit is contained in:
Dimitri Lozeve 2024-11-12 21:43:32 +01:00
commit f242d2b0df
420 changed files with 62521 additions and 0 deletions

3
2019/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
*\~
*.fasl
compiled/

10
2019/README.org Normal file
View file

@ -0,0 +1,10 @@
* Advent of Code 2019
My answers for [[https://adventofcode.com/2019][Advent of Code 2019]].
Racket tests:
#+begin_src sh
raco make **/*.rkt
raco test **/*.rkt
#+end_src

4
2019/day01/day01.dyalog Normal file
View file

@ -0,0 +1,4 @@
p←⍎¨⊃⎕nget'input.txt'1
f←{0⌈⌊2-⍨⍵÷3}
+/f p ⍝ part 1
+/,↑{(f⍣⍵)p}¨10 ⍝ part 2

16
2019/day01/day01.lisp Normal file
View file

@ -0,0 +1,16 @@
(defparameter *input-file* #P"input.txt")
(defparameter *input* (uiop:read-file-lines *input-file*))
(defun part1 ()
(loop for line in *input*
sum (- (floor (/ (parse-integer line) 3)) 2)))
(defun total-fuel-requirements (total-fuel fuel)
(let ((new-fuel (max 0 (- (floor (/ fuel 3)) 2))))
(if (= new-fuel 0)
(+ total-fuel fuel)
(total-fuel-requirements (+ total-fuel fuel) new-fuel))))
(defun part2 ()
(loop for line in *input*
sum (total-fuel-requirements 0 (- (floor (/ (parse-integer line) 3)) 2))))

100
2019/day01/input.txt Normal file
View file

@ -0,0 +1,100 @@
120847
60347
63340
72773
57020
133960
98163
121548
87233
59150
59712
146816
93205
61936
75319
141998
97125
73450
106250
129939
94854
113782
112044
127923
67114
119770
130034
70876
82204
101939
132604
142836
117066
95861
75597
94630
50085
101107
77937
94286
74091
140875
118543
52767
54544
93062
115681
142065
111737
131214
75160
115432
140504
115376
86589
104631
133012
108690
85993
99533
133725
87698
133480
68379
107852
111209
116623
98717
130227
114356
144516
89663
118355
77816
149914
105080
116793
65259
143900
67838
148389
129753
140524
90005
147305
118428
79940
59110
78120
87066
64722
142066
81410
106958
92984
95584
108534
66362
126340
143660

5
2019/day02/day02.dyalog Normal file
View file

@ -0,0 +1,5 @@
⎕io←0
p←⍎¨','(≠⊆⊢)⊃⊃⎕nget'input.txt'1
f←{i←0 ⊣ s[1 2]←⍵ ⊣ s←p ⋄ ⊃s⊣{i+←4 ⊣ a x y z←s[i+4] ⋄ s[z]←(a-1)⌷s[x](+,×)s[y]}⍣{99=i⌷s}0}
f 12 2 ⍝ part 1
nv←1+,99 99 ⋄ +/100 1×⊃nv[(19690720=f¨nv)1] ⍝ part 2

32
2019/day02/day02.lisp Normal file
View file

@ -0,0 +1,32 @@
(ql:quickload "str")
(defparameter *input-file* #P"input.txt")
(defparameter *input* (uiop:read-file-string *input-file*))
(defun execute (program)
(loop for i from 0 by 4 until (= 99 (aref program i))
do (let ((opcode (aref program i)))
(cond ((= opcode 1)
(setf (aref program (aref program (+ 3 i)))
(+ (aref program (aref program (+ 1 i)))
(aref program (aref program (+ 2 i))))))
((= opcode 2)
(setf (aref program (aref program (+ 3 i)))
(* (aref program (aref program (+ 1 i)))
(aref program (aref program (+ 2 i)))))))))
program)
(defun execute-with-inputs (program-string noun verb)
(let ((program (map 'vector #'parse-integer (str:split "," program-string))))
(setf (aref program 1) noun)
(setf (aref program 2) verb)
(aref (execute program) 0)))
(defun part1 (program-string)
(execute-with-inputs program-string 12 2))
(defun part2 (program-string)
(dotimes (noun 99)
(dotimes (verb 99)
(when (= 19690720 (execute-with-inputs program-string noun verb))
(return-from part2 (+ (* 100 noun) verb))))))

34
2019/day02/day02.rkt Normal file
View file

@ -0,0 +1,34 @@
#lang racket/base
(require "../intcode.rkt"
racket/vector)
(module+ test
(require rackunit))
(define (part1 filename)
(define program (parse-file filename))
(vector-set! program 1 12)
(vector-set! program 2 2)
(define vm (execute (start-machine program '())))
(vector-ref (machine-program vm) 0))
(module+ test
(check-equal? (part1 "input.txt") 6627023))
(define (try-inputs program noun verb)
(define my-program (vector-copy program))
(vector-set! my-program 1 noun)
(vector-set! my-program 2 verb)
(define vm (execute (start-machine my-program '())))
(vector-ref (machine-program vm) 0))
(define (part2 filename)
(define program (parse-file filename))
(for*/first ([noun (in-range 100)]
[verb (in-range 100)]
#:when (eq? 19690720 (try-inputs program noun verb)))
(+ (* 100 noun) verb)))
(module+ test
(check-equal? (part2 "input.txt") 4019))

1
2019/day02/input.txt Normal file
View file

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

7
2019/day03/day03.dyalog Normal file
View file

@ -0,0 +1,7 @@
⎕io←0
p←','(≠⊆⊢)¨⊃⎕nget'input.txt'1
segment←{x y← ⋄ 'R'=⊃⍵:{x y+⍵}¨1↓,(1+⍎1↓⍵),1 ⋄ 'L'=⊃⍵:{x y+⍵}¨1↓,-(1+⍎1↓⍵),1 ⋄ 'D'=⊃⍵:{x y+⍵}¨1↓,-1,1+⍎1↓⍵ ⋄ 'U'=⊃⍵:{x y+⍵}¨1↓,1,1+⍎1↓⍵}
path←{x←⊂0 0 ⋄ 1↓x⊣{x,←(⊃⌽x) segment ⍵}¨⍵}
⌊/+/↑(path ⊃0⌷p) ∩ path ⊃1⌷p ⍝ part 1
c←(path ⊃0⌷p)∩path ⊃1⌷p
2+⌊/((path ⊃0⌷p)c)+(path ⊃1⌷p)c ⍝ part 2

2
2019/day03/input.txt Normal file
View file

@ -0,0 +1,2 @@
R990,U803,R777,U157,R629,D493,R498,D606,R344,U241,L708,D403,R943,U961,L107,D755,R145,D77,L654,D297,L263,D904,R405,U676,R674,U139,L746,U935,R186,U433,L739,D774,R470,D459,R865,D209,L217,U525,R747,D218,R432,U769,L876,D477,R606,D161,R991,D338,R647,D958,R777,D148,R593,D873,L95,U707,R468,U518,R845,U285,R221,U771,R989,D107,R44,U833,L343,D420,R468,D954,L604,D270,L691,U401,R850,U70,R441,U461,R638,D743,R65,U673,L999,U110,R266,U759,R768,U569,L250,D577,R247,U420,L227,U437,L80,D647,L778,U935,R585,U35,L735,D201,R694,U635,L597,U215,R743,D542,L701,U946,L503,U589,R836,D687,L444,U409,L473,U132,L570,U374,R193,D908,L800,U294,L252,U851,R947,D647,L37,D20,L27,U620,L534,D356,L291,U611,L128,D670,L364,U200,L749,D708,R776,U99,R606,D999,L810,D373,R212,D138,R856,D966,L206,D23,L860,D731,L914,U716,L212,U225,R766,U348,L220,D69,L766,D15,L557,U71,R734,D295,R884,D822,R300,D152,L986,D170,R764,U24,R394,D710,L860,U830,L305,U431,R201,D44,R882,U667,R37,D727,R916,U460,L834,D771,R373,U96,L707,D576,R607,D351,R577,D200,L402,U364,L32,D512,L152,D283,L232,U804,R827,U352,R104,D323,L254,U273,L451,D967,R739,D53,L908,D866,R998,U897,L581,U538,R206,U644,L70,D17,L481,U912,L377,D922,L286,U547,R35,U292,L318,U256,R79,D52,R92,U160,R763,U428,R663,D634,R212,D325,R460,U142,L375,U382,R20,D321,L220,D578,R915,D465,L797,D849,L281,D491,L911,D624,R800,U629,L675,U428,L219,U694,R680,U350,R113,D903,L22,D683,L787,D1,R93,U315,L562,U756,R622,D533,L587,D216,L933,U972,R506,U536,R797,U828,L12,D965,L641,U165,R937,D675,R259
L998,D197,L301,D874,L221,U985,L213,D288,R142,D635,R333,D328,R405,D988,L23,D917,R412,D971,R876,U527,R987,D884,R39,D485,L971,U200,R931,U79,L271,U183,R354,D18,R346,D866,L752,D204,L863,U784,R292,U676,R811,U721,L53,U983,L993,U822,R871,U539,L782,D749,R417,U667,R882,U467,R321,U894,R912,U756,L102,U154,L57,D316,R200,U372,L44,U406,L426,D613,R847,U977,R303,U469,R509,U839,L633,D267,L487,D976,R325,U399,L359,U161,L305,U935,R522,D848,R784,D273,L337,D55,L266,U406,L858,D650,L176,D124,R231,U513,L462,U328,L674,D598,R568,D742,L39,D438,L643,D254,R577,U519,R325,U124,R91,U129,L79,D52,R480,D46,R129,D997,R452,D992,L721,U490,L595,D666,R372,D198,R813,U624,L469,U59,R578,U184,R117,D749,L745,U302,R398,D951,L683,D360,R476,D788,R70,U693,R295,D547,L61,U782,R440,D818,L330,D321,L968,U622,R160,U571,L886,D43,L855,U272,R530,D267,L312,D519,L741,D697,R206,U148,L445,U857,R983,D192,L788,U826,R805,U932,R888,D250,L682,D52,R406,D176,R984,D637,L947,D416,L687,U699,L544,D710,L933,D171,L357,D134,L968,D538,R496,D240,L730,U771,R554,U708,R265,D748,L839,U668,L333,U335,R526,U809,L653,D6,R234,D130,R871,U911,R538,U372,L960,D535,L196,U236,L966,D185,L166,U789,L885,U453,R627,D586,R501,U222,L280,U124,R755,D159,L759,U78,R669,D889,L150,D888,L71,D917,L126,D97,L138,U726,R160,D971,R527,D988,R455,D413,R539,U923,R258,U734,L459,D954,R877,U613,R343,D98,R238,U478,R514,U814,L274,U119,L958,U698,R761,U693,R367,D111,L800,D531,L91,U616,R208,D255,R169,U145,R671,U969,L468,U566,R589,D455,R323,D303,R374,D890,R377,D262,L40,U85,L719

14
2019/day04/day04.dyalog Normal file
View file

@ -0,0 +1,14 @@
⎕io←0
a b←245182 790572
p←⊃(,(∘.,))/6/⊂10
x←{(1↓⍵)-¯1↓⍵}¨p
n←10⊥¨((/¨0=x)∧∧/¨0≤x)/p
≢((n>a)∧n<b)/n ⍝ part 1
n2←10⊥¨(({/2=⍵}¨(⊢∘≢⌸)¨p)∧∧/¨0≤x)/p
≢((n2>a)∧n2<b)/n2 ⍝ part 2
⍝ better version (inspired from
⍝ https://github.com/jayfoad/aoc2019apl/blob/master/p4.dyalog)
p←⍉10⊥⍣¯1⊢a+1+b-a
+/({∧/2≤/⍵}∧{/2=/⍵})p ⍝ part 1
+/({∧/2≤/⍵}∧{/¨2=(⊢∘≢⌸)¨↓⍵})p ⍝ part 2

61
2019/day05/day05.lisp Normal file
View file

@ -0,0 +1,61 @@
(defparameter *input-file* #P"input.txt")
(defparameter *input* (uiop:read-file-string *input-file*))
(defvar *program*)
(defun opcode (pc)
(mod (aref *program* pc) 100))
(defun parameter-mode (pc index)
(mod (truncate (aref *program* pc) (expt 10 (+ 1 index))) 10))
(defun parameter (pc index)
(ecase (parameter-mode pc index)
(1 (aref *program* (+ index pc)))
(0 (aref *program* (aref *program* (+ pc index))))))
(defun (setf parameter) (new-value pc index)
(ecase (parameter-mode pc index)
(0 (setf (aref *program* (aref *program* (+ pc index))) new-value))
(1 (error "Cannot write with a parameter in immediate mode"))))
(defun execute (inputs)
(defun execute-instruction (pc inputs outputs)
(ecase (opcode pc)
(99 (return-from execute-instruction outputs))
(1 (setf (parameter pc 3) (+ (parameter pc 1) (parameter pc 2)))
(execute-instruction (+ pc 4) inputs outputs))
(2 (setf (parameter pc 3) (* (parameter pc 1) (parameter pc 2)))
(execute-instruction (+ pc 4) inputs outputs))
(3 (setf (parameter pc 1) (car inputs))
(execute-instruction (+ pc 2) (cdr inputs) outputs))
(4 (execute-instruction (+ pc 2) inputs (cons (parameter pc 1) outputs)))
(5 (if (/= 0 (parameter pc 1))
(execute-instruction (parameter pc 2) inputs outputs)
(execute-instruction (+ pc 3) inputs outputs)))
(6 (if (= 0 (parameter pc 1))
(execute-instruction (parameter pc 2) inputs outputs)
(execute-instruction (+ pc 3) inputs outputs)))
(7 (if (< (parameter pc 1) (parameter pc 2))
(setf (parameter pc 3) 1)
(setf (parameter pc 3) 0))
(execute-instruction (+ pc 4) inputs outputs))
(8 (if (= (parameter pc 1) (parameter pc 2))
(setf (parameter pc 3) 1)
(setf (parameter pc 3) 0))
(execute-instruction (+ pc 4) inputs outputs))))
(execute-instruction 0 inputs nil))
(defun parse-program (program-string)
(map 'vector #'parse-integer (uiop:split-string program-string :separator ",")))
(defun part1 ()
(let ((*program* (parse-program *input*)))
(car (execute '(1)))))
(defun part2 ()
(let ((*program* (parse-program *input*)))
(car (execute '(5)))))
(assert (= (part1) 12896948))
(assert (= (part2) 7704130))

22
2019/day05/day05.rkt Normal file
View file

@ -0,0 +1,22 @@
#lang racket/base
(require "../intcode.rkt")
(module+ test
(require rackunit))
(define (part1 filename)
(define program (parse-file filename))
(define vm (execute (start-machine program '(1))))
(car (machine-outputs vm)))
(module+ test
(check-equal? (part1 "input.txt") 12896948))
(define (part2 filename)
(define program (parse-file filename))
(define vm (execute (start-machine program '(5))))
(car (machine-outputs vm)))
(module+ test
(check-equal? (part2 "input.txt") 7704130))

1
2019/day05/input.txt Normal file
View file

@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1102,46,47,225,2,122,130,224,101,-1998,224,224,4,224,1002,223,8,223,1001,224,6,224,1,224,223,223,1102,61,51,225,102,32,92,224,101,-800,224,224,4,224,1002,223,8,223,1001,224,1,224,1,223,224,223,1101,61,64,225,1001,118,25,224,101,-106,224,224,4,224,1002,223,8,223,101,1,224,224,1,224,223,223,1102,33,25,225,1102,73,67,224,101,-4891,224,224,4,224,1002,223,8,223,1001,224,4,224,1,224,223,223,1101,14,81,225,1102,17,74,225,1102,52,67,225,1101,94,27,225,101,71,39,224,101,-132,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,1002,14,38,224,101,-1786,224,224,4,224,102,8,223,223,1001,224,2,224,1,223,224,223,1,65,126,224,1001,224,-128,224,4,224,1002,223,8,223,101,6,224,224,1,224,223,223,1101,81,40,224,1001,224,-121,224,4,224,102,8,223,223,101,4,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,1008,677,226,224,1002,223,2,223,1005,224,329,1001,223,1,223,107,677,677,224,102,2,223,223,1005,224,344,101,1,223,223,1107,677,677,224,102,2,223,223,1005,224,359,1001,223,1,223,1108,226,226,224,1002,223,2,223,1006,224,374,101,1,223,223,107,226,226,224,1002,223,2,223,1005,224,389,1001,223,1,223,108,226,226,224,1002,223,2,223,1005,224,404,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,419,1001,223,1,223,1107,677,226,224,102,2,223,223,1005,224,434,1001,223,1,223,108,226,677,224,102,2,223,223,1006,224,449,1001,223,1,223,8,677,226,224,102,2,223,223,1006,224,464,1001,223,1,223,1007,677,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1007,677,677,224,1002,223,2,223,1005,224,494,1001,223,1,223,1107,226,677,224,1002,223,2,223,1006,224,509,101,1,223,223,1108,226,677,224,102,2,223,223,1005,224,524,1001,223,1,223,7,226,226,224,102,2,223,223,1005,224,539,1001,223,1,223,8,677,677,224,1002,223,2,223,1005,224,554,101,1,223,223,107,677,226,224,102,2,223,223,1006,224,569,1001,223,1,223,7,226,677,224,1002,223,2,223,1005,224,584,1001,223,1,223,1008,226,226,224,1002,223,2,223,1006,224,599,101,1,223,223,1108,677,226,224,102,2,223,223,1006,224,614,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,629,1001,223,1,223,8,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,226,226,224,102,2,223,223,1005,224,659,101,1,223,223,108,677,677,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226

23
2019/day06/day06.rkt Normal file
View file

@ -0,0 +1,23 @@
#lang racket
(require racket/string
graph)
(define (read-graph filename)
(with-input-from-file filename
(lambda ()
(define g (unweighted-graph/directed '()))
(for ([line (in-lines)])
(define bodies (string-split line ")"))
(add-edge! g (car bodies) (cadr bodies)))
g)))
(define (part1 filename)
(define g (read-graph filename))
(define-values (dists _) (bfs g "COM"))
(for/sum ([i (in-hash-values dists)]) i))
(define (part2 filename)
(define g (read-graph filename))
(define-values (dists _) (bfs g "YOU"))
(- (hash-ref dists "SAN") 2))

1514
2019/day06/input Normal file

File diff suppressed because it is too large Load diff

11
2019/day06/test Normal file
View file

@ -0,0 +1,11 @@
COM)B
B)C
C)D
D)E
E)F
B)G
G)H
D)I
E)J
J)K
K)L

13
2019/day06/test2 Normal file
View file

@ -0,0 +1,13 @@
COM)B
B)C
C)D
D)E
E)F
B)G
G)H
D)I
E)J
J)K
K)L
K)YOU
I)SAN

87
2019/day07/day07.lisp Normal file
View file

@ -0,0 +1,87 @@
(ql:quickload :alexandria)
(defparameter *input-file* #P"input.txt")
(defvar *input*)
(defvar *program*)
(defvar *input-fn*)
(defvar *output-fn*)
(defun opcode (pc)
(mod (aref *program* pc) 100))
(defun parameter-mode (pc index)
(mod (truncate (aref *program* pc) (expt 10 (+ 1 index))) 10))
(defun parameter (pc index)
(ecase (parameter-mode pc index)
(1 (aref *program* (+ index pc)))
(0 (aref *program* (aref *program* (+ pc index))))))
(defun (setf parameter) (new-value pc index)
(ecase (parameter-mode pc index)
(0 (setf (aref *program* (aref *program* (+ pc index))) new-value))
(1 (error "Cannot write with a parameter in immediate mode"))))
(defun execute-instruction (pc)
(ecase (opcode pc)
(99 (return-from execute-instruction))
(1 (setf (parameter pc 3) (+ (parameter pc 1) (parameter pc 2)))
(execute-instruction (+ pc 4)))
(2 (setf (parameter pc 3) (* (parameter pc 1) (parameter pc 2)))
(execute-instruction (+ pc 4)))
(3 (setf (parameter pc 1) (funcall *input-fn*))
(execute-instruction (+ pc 2)))
(4 (funcall *output-fn* (parameter pc 1))
(execute-instruction (+ pc 2)))
(5 (if (/= 0 (parameter pc 1))
(execute-instruction (parameter pc 2))
(execute-instruction (+ pc 3))))
(6 (if (= 0 (parameter pc 1))
(execute-instruction (parameter pc 2))
(execute-instruction (+ pc 3))))
(7 (if (< (parameter pc 1) (parameter pc 2))
(setf (parameter pc 3) 1)
(setf (parameter pc 3) 0))
(execute-instruction (+ pc 4)))
(8 (if (= (parameter pc 1) (parameter pc 2))
(setf (parameter pc 3) 1)
(setf (parameter pc 3) 0))
(execute-instruction (+ pc 4)))))
(defun execute (program &key (input 'input) (output 'output))
(let ((*program* program)
(*input-fn* input)
(*output-fn* output))
(execute-instruction 0)))
(defun parse-program (program-string)
(map 'vector #'parse-integer (uiop:split-string program-string :separator ",")))
(defun amplify (phases)
(let ((amp-input 0))
(loop for phase in phases
do (let ((program (alexandria:copy-array *program*))
(inputs (list phase amp-input))
(output nil))
(execute program :input (lambda () (pop inputs)) :output (lambda (x) (setf output x)))
(setf amp-input output)))
amp-input))
(defun max-thrust ()
(let ((res nil))
(alexandria:map-permutations (lambda (x) (push (amplify x) res)) '(0 1 2 3 4))
(apply #'max res)))
(assert (= 43210 (let ((*program* (parse-program "3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0")))
(max-thrust))))
(assert (= 54321 (let ((*program* (parse-program "3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0")))
(max-thrust))))
(assert (= 65210 (let ((*program* (parse-program "3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0")))
(max-thrust))))
(defun part1 ()
(let ((*program* (parse-program (uiop:read-file-string *input-file*))))
(max-thrust)))

51
2019/day07/day07.rkt Normal file
View file

@ -0,0 +1,51 @@
#lang racket/base
(require "../intcode.rkt"
racket/list)
(module+ test
(require rackunit))
(define (part1 program)
(apply max
(for/list ([phases (in-permutations (range 5))])
(for/fold ([signal 0])
([phase (in-list phases)])
(define vm (execute (start-machine program (list phase signal))))
(car (machine-outputs vm))))))
(module+ test
(check-equal? (part1 (parse "3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0")) 43210)
(check-equal? (part1 (parse "3,23,3,24,1002,24,10,24,1002,23,-1,23,
101,5,23,23,1,24,23,23,4,23,99,0,0")) 54321)
(check-equal? (part1 (parse "3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,
1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0")) 65210)
(check-equal? (part1 (parse-file "input.txt")) 298586))
(define (part2 program)
(define signals
(for/list ([phases (in-permutations (range 5 10))])
(define amplifiers
(for/list ([phase (in-list phases)])
(define vm (execute (start-machine program (list phase))))
vm))
(let loop ([signal 0]
[amplifiers amplifiers])
(if (empty? amplifiers)
signal
(let* ([amp (machine-program (car amplifiers))]
[pc (machine-pc (car amplifiers))]
[new-vm (execute (machine amp (list signal) pc 0 #f '()))]
[new-amplifiers (if (machine-terminated new-vm)
(cdr amplifiers)
(append (cdr amplifiers) (list new-vm)))])
(loop (car (machine-outputs new-vm)) new-amplifiers))))))
(apply max signals))
(module+ test
(check-equal? (part2 (parse "3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,
27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5")) 139629729)
(check-equal? (part2 (parse "3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,
-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,
53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10")) 18216)
(check-equal? (part2 (parse-file "input.txt")) 9246095))

1
2019/day07/input.txt Normal file
View file

@ -0,0 +1 @@
3,8,1001,8,10,8,105,1,0,0,21,42,67,84,109,126,207,288,369,450,99999,3,9,102,4,9,9,1001,9,4,9,102,2,9,9,101,2,9,9,4,9,99,3,9,1001,9,5,9,1002,9,5,9,1001,9,5,9,1002,9,5,9,101,5,9,9,4,9,99,3,9,101,5,9,9,1002,9,3,9,1001,9,2,9,4,9,99,3,9,1001,9,2,9,102,4,9,9,101,2,9,9,102,4,9,9,1001,9,2,9,4,9,99,3,9,102,2,9,9,101,5,9,9,1002,9,2,9,4,9,99,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,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,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,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,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,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,102,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1001,9,1,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,102,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,101,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,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,99,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,99

4
2019/day08/day08.dyalog Normal file
View file

@ -0,0 +1,4 @@
p←100 6 25⍎¨⊃⊃⎕nget'input.txt'1
x←,(⊃⍋+/+/0=p)⌷p
(+/1=x)×+/2=x ⍝ part 1
' ⌺'[{1⌷⍋⍵0 1}¨⊂[1]p] ⍝ part 2

1
2019/day08/input.txt Normal file

File diff suppressed because one or more lines are too long

29
2019/day09/day09.rkt Normal file
View file

@ -0,0 +1,29 @@
#lang racket/base
(require "../intcode.rkt")
(module+ test
(require rackunit))
(define (part12 program input)
(define vm (execute (start-machine program (list input))))
(car (machine-outputs vm)))
(module+ test
(test-case "quine"
(define quine (parse "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99"))
(define vm (execute (start-machine quine '())))
(check-true (machine-terminated vm))
(check-equal? (reverse (machine-outputs vm)) (vector->list quine)))
(test-case "16-digit number"
(define program (parse "1102,34915192,34915192,7,4,7,99,0"))
(define vm (execute (start-machine program '())))
(check-true (machine-terminated vm))
(check-equal? (string-length (number->string (car (machine-outputs vm)))) 16))
(test-case "large number"
(define program (parse "104,1125899906842624,99"))
(define vm (execute (start-machine program '())))
(check-true (machine-terminated vm))
(check-equal? (car (machine-outputs vm)) 1125899906842624))
(check-equal? (part12 (parse-file "input") 1) 3601950151)
(check-equal? (part12 (parse-file "input") 2) 64236))

1
2019/day09/input 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,1101,0,30,1016,1101,37,0,1005,1101,362,0,1023,1101,0,20,1014,1101,39,0,1013,1102,34,1,1007,1101,682,0,1027,1102,664,1,1025,1102,1,655,1028,1101,0,26,1002,1102,1,38,1015,1101,669,0,1024,1101,0,28,1017,1102,1,21,1000,1101,0,27,1012,1102,1,29,1008,1102,1,23,1019,1101,0,24,1011,1101,685,0,1026,1102,646,1,1029,1102,1,369,1022,1101,0,31,1003,1102,1,36,1001,1101,0,0,1020,1102,1,35,1009,1101,32,0,1010,1101,0,1,1021,1102,33,1,1004,1101,22,0,1006,1102,1,25,1018,109,14,1205,6,197,1001,64,1,64,1105,1,199,4,187,1002,64,2,64,109,-4,21107,40,39,9,1005,1019,219,1001,64,1,64,1105,1,221,4,205,1002,64,2,64,109,9,1206,1,239,4,227,1001,64,1,64,1106,0,239,1002,64,2,64,109,-9,2101,0,-8,63,1008,63,26,63,1005,63,261,4,245,1106,0,265,1001,64,1,64,1002,64,2,64,109,-6,2108,37,1,63,1005,63,287,4,271,1001,64,1,64,1105,1,287,1002,64,2,64,109,15,21108,41,44,-2,1005,1017,307,1001,64,1,64,1106,0,309,4,293,1002,64,2,64,109,-16,1207,1,34,63,1005,63,327,4,315,1105,1,331,1001,64,1,64,1002,64,2,64,109,8,1208,-9,29,63,1005,63,347,1106,0,353,4,337,1001,64,1,64,1002,64,2,64,109,4,2105,1,8,1001,64,1,64,1105,1,371,4,359,1002,64,2,64,109,-22,1201,9,0,63,1008,63,27,63,1005,63,391,1106,0,397,4,377,1001,64,1,64,1002,64,2,64,109,18,21107,42,43,5,1005,1016,415,4,403,1106,0,419,1001,64,1,64,1002,64,2,64,109,-8,1201,2,0,63,1008,63,37,63,1005,63,441,4,425,1105,1,445,1001,64,1,64,1002,64,2,64,109,27,1205,-9,463,4,451,1001,64,1,64,1106,0,463,1002,64,2,64,109,-1,1206,-8,475,1105,1,481,4,469,1001,64,1,64,1002,64,2,64,109,-6,21101,43,0,-8,1008,1015,43,63,1005,63,507,4,487,1001,64,1,64,1106,0,507,1002,64,2,64,109,-15,2101,0,-3,63,1008,63,35,63,1005,63,531,1001,64,1,64,1106,0,533,4,513,1002,64,2,64,109,-2,2102,1,-6,63,1008,63,18,63,1005,63,553,1105,1,559,4,539,1001,64,1,64,1002,64,2,64,109,7,21102,44,1,3,1008,1016,44,63,1005,63,581,4,565,1105,1,585,1001,64,1,64,1002,64,2,64,109,-11,1202,7,1,63,1008,63,34,63,1005,63,609,1001,64,1,64,1105,1,611,4,591,1002,64,2,64,109,6,1202,1,1,63,1008,63,35,63,1005,63,637,4,617,1001,64,1,64,1106,0,637,1002,64,2,64,109,16,2106,0,4,4,643,1001,64,1,64,1106,0,655,1002,64,2,64,109,-1,2105,1,1,4,661,1106,0,673,1001,64,1,64,1002,64,2,64,109,5,2106,0,-1,1105,1,691,4,679,1001,64,1,64,1002,64,2,64,109,-24,1208,-2,26,63,1005,63,709,4,697,1105,1,713,1001,64,1,64,1002,64,2,64,109,-10,2102,1,6,63,1008,63,21,63,1005,63,735,4,719,1105,1,739,1001,64,1,64,1002,64,2,64,109,25,21108,45,45,-9,1005,1010,757,4,745,1106,0,761,1001,64,1,64,1002,64,2,64,109,-12,1207,-7,20,63,1005,63,777,1106,0,783,4,767,1001,64,1,64,1002,64,2,64,109,-13,2108,22,6,63,1005,63,799,1106,0,805,4,789,1001,64,1,64,1002,64,2,64,109,17,21102,46,1,0,1008,1011,45,63,1005,63,825,1105,1,831,4,811,1001,64,1,64,1002,64,2,64,109,-6,2107,21,1,63,1005,63,849,4,837,1105,1,853,1001,64,1,64,1002,64,2,64,109,-3,2107,27,0,63,1005,63,873,1001,64,1,64,1105,1,875,4,859,1002,64,2,64,109,12,21101,47,0,0,1008,1014,48,63,1005,63,899,1001,64,1,64,1105,1,901,4,881,4,64,99,21102,27,1,1,21101,0,915,0,1105,1,922,21201,1,42931,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21102,1,957,0,1106,0,922,22201,1,-1,-2,1106,0,968,22101,0,-2,-2,109,-3,2106,0,0

87
2019/day10/day10.rkt Normal file
View file

@ -0,0 +1,87 @@
#lang racket
(module+ test
(require rackunit))
(define (read-input filename)
(string->grid (file->string filename)))
(define (string->grid str)
(for/set ([line (string-split str)]
[i (in-naturals)]
#:when #t
[c (in-string line)]
[j (in-naturals)]
#:when (eq? c #\#))
(make-rectangular j i)))
(define (segment->direction x)
(define a (real-part x))
(define b (imag-part x))
(define r (gcd a b))
(make-rectangular (/ a r) (/ b r)))
(define (detected grid)
(for/hash ([x (in-set grid)])
(values x (for/set ([y (in-set grid)]
#:unless (= x y))
(segment->direction (- y x))))))
(define (find-station grid)
(define visible (detected grid))
(define max-visible (apply max (map set-count (hash-values visible))))
(define pos (for/first ([(k v) (in-hash visible)]
#:when (= max-visible (set-count v)))
k))
(values pos (hash-ref visible pos)))
(define (part1 filename)
(define grid (read-input filename))
(define-values (loc dirs) (find-station grid))
(set-count dirs))
(module+ test
(check-equal? (part1 "test") 8)
(check-equal? (part1 "input") 286))
(define (find-target grid station direction)
(define targets
(for/list ([x (in-set grid)]
#:unless (= x station)
#:when (real? (/ (- x station) direction))
#:when (<= 0 (/ (- x station) direction)))
x))
(car (sort targets
(λ (x y) (< (magnitude (- x station))
(magnitude (- y station)))))))
(define (rotate-left lst)
(if (empty? lst)
'()
(append (cdr lst) (list (car lst)))))
(define (rotate-right lst)
(reverse (rotate-left (reverse lst))))
(define (find-nth-target grid n)
(define-values (station directions) (find-station grid))
(define directions-sorted (rotate-right
(sort (set->list directions)
(λ (x y) (< (angle (* -i x)) (angle (* -i y)))))))
(define-values (final-grid targets)
(for/fold ([grid grid]
[targets '()])
([i (in-range n)]
[dir (in-cycle directions-sorted)])
(define target (find-target grid station dir))
(values (set-remove grid target)
(cons target targets))))
(car targets))
(define (part2 filename)
(define grid (read-input filename))
(define target (find-nth-target grid 200))
(+ (* 100 (real-part target)) (imag-part target)))
(module+ test
(check-equal? (part2 "input") 504))

30
2019/day10/input Normal file
View file

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

5
2019/day10/test Normal file
View file

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

58
2019/day11/day11.rkt Normal file
View file

@ -0,0 +1,58 @@
#lang racket/base
(require "../intcode.rkt"
racket/set)
(module+ test
(require rackunit))
(define (part12 program start-panel [show-grid #f])
(define vm (execute (start-machine program '())))
(define grid (make-hash))
(hash-set! grid 0 start-panel)
(define painted (mutable-set))
(let loop ([vm vm]
[direction 0+1i]
[position 0])
(define new-vm
(execute (machine (machine-program vm)
(list (hash-ref grid position 0))
(machine-pc vm)
(machine-relative-base vm)
#f
'())))
(unless (machine-terminated new-vm)
(hash-set! grid position (cadr (machine-outputs new-vm)))
(set-add! painted position)
(define new-direction (if (= 0 (car (machine-outputs new-vm)))
(* direction 0+1i)
(* direction 0-1i)))
(define new-position (+ position new-direction))
(loop new-vm new-direction new-position)))
(when show-grid
(display-grid grid))
(set-count painted))
(define (display-grid grid)
(define min-x (apply min (map real-part (hash-keys grid))))
(define max-x (apply max (map real-part (hash-keys grid))))
(define min-y (apply min (map imag-part (hash-keys grid))))
(define max-y (apply max (map imag-part (hash-keys grid))))
(for* ([j (in-range max-y (sub1 min-y) -1)]
[i (in-range min-x max-x)])
(if (= 1 (hash-ref grid (make-rectangular i j) 0))
(printf "#")
(printf " "))
(when (= i (sub1 max-x))
(printf "\n"))))
(module+ test
(check-equal? (part12 (parse-file "input") 0) 2511))
;; > (part12 (parse-file "input") 1 #t)
;; # # ## # # ## # # ## ### # #
;; # # # # # # # # # # # # # #
;; #### # ## # ## # # # ####
;; # # # # # # # # # ## ### # #
;; # # # # # # # # # # # # # # #
;; # # ## # # ## # # ### # # #

1
2019/day11/input Normal file
View file

@ -0,0 +1 @@
3,8,1005,8,328,1106,0,11,0,0,0,104,1,104,0,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,1001,8,0,29,1,104,7,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,55,1,2,7,10,1006,0,23,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,1001,8,0,84,1006,0,40,1,1103,14,10,1,1006,16,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,1002,8,1,116,1006,0,53,1,1104,16,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,146,2,1104,9,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,172,1006,0,65,1,1005,8,10,1,1002,16,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,102,1,8,204,2,1104,9,10,1006,0,30,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,233,2,1109,6,10,1006,0,17,1,2,6,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,266,1,106,7,10,2,109,2,10,2,9,8,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,301,1,109,9,10,1006,0,14,101,1,9,9,1007,9,1083,10,1005,10,15,99,109,650,104,0,104,1,21102,1,837548789788,1,21101,0,345,0,1106,0,449,21101,0,846801511180,1,21101,0,356,0,1106,0,449,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,235244981271,0,1,21101,403,0,0,1105,1,449,21102,1,206182744295,1,21101,0,414,0,1105,1,449,3,10,104,0,104,0,3,10,104,0,104,0,21102,837896937832,1,1,21101,0,437,0,1106,0,449,21101,867965862668,0,1,21102,448,1,0,1106,0,449,99,109,2,22102,1,-1,1,21101,40,0,2,21102,1,480,3,21101,0,470,0,1106,0,513,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,475,476,491,4,0,1001,475,1,475,108,4,475,10,1006,10,507,1101,0,0,475,109,-2,2106,0,0,0,109,4,1201,-1,0,512,1207,-3,0,10,1006,10,530,21102,1,0,-3,22102,1,-3,1,21201,-2,0,2,21102,1,1,3,21102,549,1,0,1106,0,554,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,577,2207,-4,-2,10,1006,10,577,21202,-4,1,-4,1106,0,645,21202,-4,1,1,21201,-3,-1,2,21202,-2,2,3,21101,596,0,0,1106,0,554,21201,1,0,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,615,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,637,22102,1,-1,1,21101,637,0,0,105,1,512,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0

64
2019/day12/day12.rkt Normal file
View file

@ -0,0 +1,64 @@
#lang racket
(struct moon
(x y z vx vy vz)
#:transparent)
(define (read-input filename)
(with-input-from-file filename
(lambda ()
(for/list ([line (in-lines)])
(define positions-str
(cdr (regexp-match #rx"<x=(-?[0-9]+), y=(-?[0-9]+), z=(-?[0-9]+)>" line)))
(define positions (map string->number positions-str))
(apply moon (append positions '(0 0 0)))))))
(define (step moons)
(for/list ([cur moons])
(define new-vx (moon-vx cur))
(define new-vy (moon-vy cur))
(define new-vz (moon-vz cur))
(define (gravity-pull pos-cur pos-other)
(cond
[(> pos-other pos-cur) 1]
[(< pos-other pos-cur) -1]
[else 0]))
(for ([other moons] #:unless (eq? other cur))
(set! new-vx (+ new-vx (gravity-pull (moon-x cur) (moon-x other))))
(set! new-vy (+ new-vy (gravity-pull (moon-y cur) (moon-y other))))
(set! new-vz (+ new-vz (gravity-pull (moon-z cur) (moon-z other)))))
(moon (+ (moon-x cur) new-vx)
(+ (moon-y cur) new-vy)
(+ (moon-z cur) new-vz)
new-vx
new-vy
new-vz)))
(define (total-energy moons)
(for/sum ([m moons])
(* (+ (abs (moon-x m))
(abs (moon-y m))
(abs (moon-z m)))
(+ (abs (moon-vx m))
(abs (moon-vy m))
(abs (moon-vz m))))))
(define (part1 filename)
(define moons (read-input filename))
(total-energy (for/fold ([ms moons]) ([i (in-range 1000)]) (step ms))))
(define (cycle-length moons pos speed)
(define-values (states final)
(for/fold ([states (mutable-set)] [ms moons])
([_ (in-naturals)]
#:break (set-member? states (append (map pos ms) (map speed ms))))
(set-add! states (append (map pos ms) (map speed ms)))
(values states (step ms))))
(set-count states))
(define (part2 filename)
(define moons (read-input filename))
(define cycle-x (cycle-length moons moon-x moon-vx))
(define cycle-y (cycle-length moons moon-y moon-vy))
(define cycle-z (cycle-length moons moon-z moon-vz))
(lcm cycle-x cycle-y cycle-z))

4
2019/day12/input Normal file
View file

@ -0,0 +1,4 @@
<x=-17, y=9, z=-5>
<x=-1, y=7, z=13>
<x=-19, y=12, z=5>
<x=-6, y=-6, z=-4>

4
2019/day12/test Normal file
View file

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

4
2019/day12/test2 Normal file
View file

@ -0,0 +1,4 @@
<x=-8, y=-10, z=0>
<x=5, y=5, z=10>
<x=2, y=-7, z=3>
<x=9, y=-8, z=-3>

74
2019/day13/day13.rkt Normal file
View file

@ -0,0 +1,74 @@
#lang racket/base
(require "../intcode.rkt"
racket/list)
(module+ test
(require rackunit))
(define (part1 program)
(define vm (execute (start-machine program '())))
(define screen
(let loop ([screen (hash)]
[instructions (reverse (machine-outputs vm))])
(if (empty? instructions)
screen
(let ([x (car instructions)]
[y (cadr instructions)]
[tile-id (caddr instructions)])
(loop (hash-set screen (list x y) tile-id)
(cdddr instructions))))))
(for/sum ([(k v) (in-hash screen)]
#:when (= v 2))
1))
(module+ test
(check-equal? (part1 (parse-file "input")) 363))
(define (ball-x screen)
(for/first ([(k v) (in-hash screen)]
#:when (= v 4))
(car k)))
(define (paddle-x screen)
(for/first ([(k v) (in-hash screen)]
#:when (= v 3))
(car k)))
(define (block-count screen)
(for/sum ([(k v) (in-hash screen)]
#:when (= v 2))
1))
(define (draw-screen screen instructions)
(if (empty? instructions)
screen
(let ([x (car instructions)]
[y (cadr instructions)]
[tile-id (caddr instructions)])
(draw-screen (hash-set screen (list x y) tile-id)
(cdddr instructions)))))
(define (part2 program)
(vector-set! program 0 2)
(define vm (execute (start-machine program '())))
(define screen
(let loop ([vm vm]
[screen (hash)])
(define new-screen (draw-screen screen (reverse (machine-outputs vm))))
(define ball-pos (ball-x new-screen))
(define paddle-pos (paddle-x new-screen))
(define joystick (cond
[(< ball-pos paddle-pos) -1]
[(= ball-pos paddle-pos) 0]
[(> ball-pos paddle-pos) 1]))
(define new-vm
(execute (machine (machine-program vm) (list joystick)
(machine-pc vm) (machine-relative-base vm) #f '())))
(if (= 0 (block-count new-screen))
new-screen
(loop new-vm new-screen))))
(hash-ref screen (list -1 0)))
(module+ test
(check-equal? (part2 (parse-file "input")) 17159))

1
2019/day13/input Normal file

File diff suppressed because one or more lines are too long

81
2019/day14/day14.rkt Normal file
View file

@ -0,0 +1,81 @@
#lang racket
(module+ test
(require rackunit))
(module+ main
(displayln "Day 14"))
(define (read-rules filename)
(with-input-from-file filename
(lambda ()
(define h (make-hash))
(for ([line (in-lines)])
(define rule
(for/list ([elt (regexp-match* #rx"([0-9]+) ([A-Z]+)" line #:match-select cdr)])
(list (string->number (car elt)) (string->symbol (cadr elt)))))
(define output (last rule))
(hash-set! h
(cadr output)
(cons (car output)
(make-hash (for/list ([elt (drop-right rule 1)])
(cons (cadr elt) (car elt)))))))
h)))
(define (generate! rules needed available)
(for ([(target target-amount) (in-hash needed)]
#:unless (eq? target 'ORE))
(define inputs (cdr (hash-ref rules target)))
(define output-amount (car (hash-ref rules target)))
(define new-target-amount (- target-amount (hash-ref available target 0)))
(define multiple (ceiling (/ new-target-amount output-amount)))
(hash-set! available target (- (* multiple output-amount) new-target-amount))
(hash-set! needed target 0)
(for ([(input input-amount) (in-hash inputs)])
(hash-update! needed input (lambda (v) (+ v (* multiple input-amount))) 0))))
(define (ore-per-fuel rules amount)
(define needed (make-hash `((FUEL . ,amount))))
(define available (make-hash))
(for ([i (in-naturals)]
#:break (= (apply + (hash-values needed)) (hash-ref needed 'ORE 0)))
(generate! rules needed available))
(hash-ref needed 'ORE))
(define (part1 filename)
(define rules (read-rules filename))
(ore-per-fuel rules 1))
(module+ test
(check-eq? 31 (part1 "test1"))
(check-eq? 165 (part1 "test2"))
(check-eq? 13312 (part1 "test3"))
(check-eq? 180697 (part1 "test4"))
(check-eq? 2210736 (part1 "test5")))
(module+ main
(display "Part 1: ")
(displayln (part1 "input")))
(define (part2 filename)
(define rules (read-rules filename))
(define max-fuel 1000000000000)
(define min-fuel 1)
(bisect rules 1000000000000 min-fuel max-fuel))
(define (bisect rules target-ore min-fuel max-fuel)
(define mid-fuel (floor (+ min-fuel (/ (- max-fuel min-fuel) 2))))
(define ore (ore-per-fuel rules mid-fuel))
(cond
[(= 1 (- max-fuel min-fuel)) min-fuel]
[(< ore target-ore) (bisect rules target-ore mid-fuel max-fuel)]
[(< target-ore ore) (bisect rules target-ore min-fuel mid-fuel)]))
(module+ test
(check-eq? 82892753 (part2 "test3"))
(check-eq? 5586022 (part2 "test4"))
(check-eq? 460664 (part2 "test5")))
(module+ main
(display "Part 2: ")
(displayln (part2 "input")))

60
2019/day14/input Normal file
View file

@ -0,0 +1,60 @@
29 PQJGK => 4 SRPZP
6 XKJP, 4 LDSMT => 6 ZVSMJ
9 CGCPW, 2 CFVS => 7 DWZH
1 VQWZC, 1 FRTJG => 1 MGLKL
3 GCTBC, 4 RGKB => 4 RLZR
2 LGLCP => 9 GCTBC
3 DFPW, 12 FRTJG => 2 XVSRT
1 VBXFG => 3 VQWZC
1 GCTBC, 1 BVHM => 8 DGMZB
7 DFPW, 3 JQNL => 7 FRTJG
6 BHQN, 4 VXNP => 5 HBLQT
1 XNBR, 27 FTBNQ, 2 RGKB => 7 JZPMK
6 HKMV, 4 JHDHS, 11 NMSKF => 9 STCX
129 ORE => 5 NVXTP
13 BVHM, 5 XNBR => 3 LKXML
3 SBPM, 4 LDSMT, 13 GPBG => 6 HXFCJ
1 XVSRT, 1 JHDHS => 4 FTBNQ
6 LKXML, 6 HRLWP => 5 PSJK
5 HRLWP, 19 PDHVG => 1 VRQD
3 FTBNQ, 1 QLKTZ => 7 SBPM
2 VXNP => 3 XKJP
4 SRPZP, 7 XVSRT => 8 LMVF
2 GPBG, 8 DWZH, 3 JTCHR, 10 RLZR, 1 CFVS, 20 BFCZ => 2 WZSTV
130 ORE => 9 JQNL
100 ORE => 4 VBXFG
4 XNBR => 8 RDSHN
2 CDBTL, 2 XNBR, 8 QLKTZ => 6 CGCPW
7 CGCPW => 6 BFCZ
7 FTBNQ, 7 VXNP => 1 BVHM
1 HXFCJ, 15 CSXD => 1 DFXPB
1 MCRW, 6 MGLKL, 1 HBLQT => 8 SWRV
19 BZQGL, 10 NMSKF, 20 WZSTV, 15 LVGB, 26 FTBNQ, 45 DWZH, 2 FJWVP, 56 JZPMK => 1 FUEL
12 JTCHR => 4 CDBTL
1 MGLKL => 6 PQJGK
1 NVXTP => 1 LDSMT
3 SWRV, 1 LGLCP => 2 GHVJ
4 DGMZB, 11 HXFCJ, 2 RLZR => 4 SHTB
5 GHVJ, 1 RGKB, 1 GCTBC => 6 HKMV
1 SRPZP => 9 XNBR
1 ZVSMJ => 2 JHDHS
9 SWRV => 5 NMSKF
1 NVXTP => 3 XKBS
7 BHQN => 2 GPBG
21 NMSKF, 12 FTBNQ, 12 SBPM => 3 CMXK
2 GPBG, 12 ZVSMJ, 2 PDHVG => 4 LGLCP
158 ORE => 8 DFPW
3 BVHM, 1 HXFCJ, 5 CGCPW, 5 BFCZ, 6 VRQD, 3 LDSMT => 7 LVGB
1 XVSRT, 1 XKJP => 8 PDHVG
3 VRQD, 16 SHTB, 5 SBPM => 9 BZQGL
1 BVHM, 3 HKMV => 4 CFVS
13 JQNL => 7 VXNP
1 XKJP, 6 XVSRT => 7 MCRW
15 NVXTP, 19 XKBS => 4 BHQN
8 JHDHS, 5 CMXK, 2 GPBG => 8 CSXD
1 JZBR, 13 LKXML, 1 HKMV, 9 DFXPB, 3 XKBS, 2 PSJK, 2 LMVF, 15 HRLWP => 7 FJWVP
1 CGCPW, 3 RDSHN => 8 JZBR
24 PQJGK => 5 JTCHR
1 XVSRT, 5 LDSMT => 6 QLKTZ
17 GPBG => 7 RGKB
4 STCX => 1 HRLWP

6
2019/day14/test1 Normal file
View file

@ -0,0 +1,6 @@
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

7
2019/day14/test2 Normal file
View file

@ -0,0 +1,7 @@
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

9
2019/day14/test3 Normal file
View file

@ -0,0 +1,9 @@
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

12
2019/day14/test4 Normal file
View file

@ -0,0 +1,12 @@
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

17
2019/day14/test5 Normal file
View file

@ -0,0 +1,17 @@
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

64
2019/day15/day15.rkt Normal file
View file

@ -0,0 +1,64 @@
#lang racket/base
(require racket/random
racket/list
racket/match
graph
"../intcode.rkt")
(module+ test
(require rackunit))
(define (possible-directions grid pos)
(define unexplored-directions
(for/list ([step '(-1 -i 1 +i)]
#:unless (hash-has-key? grid (+ pos step)))
step))
(if (empty? unexplored-directions)
(for/list ([step '(-1 -i 1 +i)]
#:unless (eq? 'wall (hash-ref grid (+ pos step) 'floor)))
step)
unexplored-directions))
(define (shortest-distances grid source)
(define g (unweighted-graph/undirected
(for*/list ([(pos tile) (in-hash grid)]
#:unless (eq? 'wall tile)
[step '(-1 -i 1 +i)]
#:unless (eq? 'wall (hash-ref grid (+ pos step) 'wall)))
(list pos (+ pos step)))))
(define-values (distances predecessors) (dijkstra g source))
distances)
(define (part12 program)
(define grid (make-hash '((0 'floor))))
(let loop ([vm (execute (start-machine program '()))]
[pos 0]
[i 0])
(define direction (random-ref (possible-directions grid pos)))
(define direction-code (match direction
[+i 1]
[-i 2]
[-1 3]
[1 4]))
(define new-vm (execute (struct-copy machine vm [inputs (list direction-code)])))
(define next-pos (+ pos direction))
(unless (> i 100000)
(match (car (machine-outputs new-vm))
[0 (hash-set! grid next-pos 'wall)
(loop new-vm pos (add1 i))]
[1 (hash-set! grid next-pos 'floor)
(loop new-vm next-pos (add1 i))]
[2 (hash-set! grid next-pos 'oxygen)
(loop new-vm next-pos (add1 i))])))
(define oxygen (for/first ([(pos tile) (in-hash grid)]
#:when (eq? 'oxygen tile))
pos))
(define distances (shortest-distances grid oxygen))
(values (hash-ref distances 0)
(apply max (hash-values distances))))
(module+ test
(define-values (p1 p2) (part12 (parse-file "input")))
(check-equal? p1 296)
(check-equal? p2 302))

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

73
2019/day16/day16.rkt Normal file
View file

@ -0,0 +1,73 @@
#lang racket
(require racket/sequence)
(module+ test
(require rackunit))
(define (pattern n i)
(define index (remainder (add1 i) (* 4 n)))
(cond
[(< index n) 0]
[(< index (* 2 n)) 1]
[(< index (* 3 n)) 0]
[(< index (* 4 n)) -1]))
(define (last-digit n)
(abs (remainder n 10)))
(define (phase signal)
(for/list ([i (in-range (length signal))])
(last-digit (for/sum ([d (in-list signal)]
[j (in-naturals)]
#:when (>= j i))
(* d (pattern (add1 i) j))))))
(define (number->digits n)
(define (aux n)
(define-values (q r) (quotient/remainder n 10))
(if (> q 0)
(cons r (aux q))
(list r)))
(reverse (aux n)))
(define (digits->number lst)
(for/sum ([d (in-list (reverse lst))]
[i (in-naturals)])
(* d (expt 10 i))))
(define (apply-n-times f n x)
(for/fold ([val x]) ([i (in-range n)])
(f val)))
(define (part1 n)
(digits->number (take (apply-n-times phase 100 n) 8)))
(module+ test
(check-eq? (part1 (number->digits 80871224585914546619083218645595)) 24176176)
(check-eq? (part1 (number->digits 19617804207202209144916044189917)) 73745418)
(check-eq? (part1 (number->digits 69317163492948606335995924319873)) 52432133))
(module+ main
(define input (number->digits
(string->number
(string-trim
(port->string (open-input-file "input") #:close? #t)))))
(displayln (part1 input)))
(define (phase2 signal)
(define-values (s res)
(for/fold ([s (apply + signal)]
[res '()])
([d (in-list signal)])
(values (- s d) (cons (last-digit s) res))))
(reverse res))
(define (part2 input)
(define offset (digits->number (take input 7)))
(define n (drop input offset))
(digits->number (take (apply-n-times phase2 100 n) 8)))
(module+ main
(define input2 (flatten (make-list 10000 input)))
(displayln (part2 input2)))

1
2019/day16/input Normal file
View file

@ -0,0 +1 @@
59749012692497360857047467554796667139266971954850723493205431123165826080869880148759586023048633544809012786925668551639957826693687972765764376332866751104713940802555266397289142675218037547096634248307260671899871548313611756525442595930474639845266351381011380170903695947253040751698337167594183713030695951696818950161554630424143678657203441568388368475123279525515262317457621810448095399401556723919452322199989580496608898965260381604485810760050252737127446449982328185199195622241930968611065497781555948187157418339240689789877555108205275435831320988202725926797165070246910002881692028525921087207954194585166525017611171911807360959

105
2019/day17/day17.rkt Normal file
View file

@ -0,0 +1,105 @@
#lang racket/base
(require "../intcode.rkt"
racket/match
racket/set
racket/list
racket/string)
(module+ test
(require rackunit))
(define (get-grid program)
(define vm (execute (start-machine program '())))
(define map-str (list->ascii (reverse (machine-outputs vm))))
(define-values (grid robot-pos robot-dir pos)
(for/fold ([grid (set)]
[robot-pos #f]
[robot-dir #f]
[pos 0])
([c (in-list (reverse (machine-outputs vm)))])
(match (integer->char c)
[#\newline (values grid robot-pos robot-dir (make-rectangular 0 (add1 (imag-part pos))))]
[#\# (values (set-add grid pos) robot-pos robot-dir (add1 pos))]
[#\^ (values grid pos -i (add1 pos))]
[#\v (values grid pos +i (add1 pos))]
[#\< (values grid pos -1 (add1 pos))]
[#\> (values grid pos 1 (add1 pos))]
[x (values grid robot-pos robot-dir (add1 pos))])))
(values map-str grid robot-pos robot-dir))
(define (part1 program)
(define-values (map-str grid robot-pos robot-dir) (get-grid program))
(define intersections
(for/list ([x (in-set grid)]
#:when (for/and ([step '(-i -1 +i 1)])
(set-member? grid (+ x step))))
x))
(for/sum ([int (in-list intersections)])
(* (real-part int) (imag-part int))))
(module+ test
(check-equal? (part1 (parse-file "input")) 5972))
(define (find-direction grid robot-pos robot-dir)
(for/first ([step '(-i +i -1 1)]
#:unless (= step (- robot-dir))
#:when (set-member? grid (+ robot-pos step)))
step))
(define (get-path grid robot-pos robot-dir)
(define path
(let loop ([pos robot-pos]
[dir robot-dir]
[len 0]
[path '()])
(if (set-member? grid (+ pos dir))
(loop (+ pos dir) dir (add1 len) path)
(let ([new-dir (find-direction grid pos dir)]
[new-path (cons len path)])
(if new-dir
(loop pos new-dir 0 (cons (match (/ new-dir dir) [+i 'R] [-i 'L]) new-path))
(cdr (reverse new-path)))))))
path)
(define (remove-substring lst sublst)
(cond
[(empty? lst) '()]
[(list-prefix? sublst lst) (remove-substring (drop lst (length sublst)) sublst)]
[else (cons (car lst) (remove-substring (cdr lst) sublst))]))
(define (compress path)
(define (prefixes lst)
(for/list ([size (in-range 2 10 2)])
(take lst size)))
(define possibilities
(for*/list ([a (in-list (prefixes path))]
[b (in-list (prefixes (remove-substring path a)))]
[c (in-list (prefixes (remove-substring (remove-substring path a) b)))]
#:when (empty? (remove-substring (remove-substring (remove-substring path a) b) c)))
(list a b c)))
(for/last ([poss (in-list possibilities)])
(match-define (list a b c) poss)
(define result (let loop ([lst path])
(cond
[(empty? lst) '()]
[(list-prefix? c lst) (cons 'C (loop (drop lst (length c))))]
[(list-prefix? b lst) (cons 'B (loop (drop lst (length b))))]
[(list-prefix? a lst) (cons 'A (loop (drop lst (length a))))]
[else '(#f)])))
#:final (last result)
(list result a b c)))
(define (lst->str path)
(string-join (map (λ (v) (format "~a" v)) path) ","))
(define (part2 program)
(define-values (map-str grid robot-pos robot-dir) (get-grid program))
(define path (get-path grid robot-pos robot-dir))
(define inputs (string-join (append (map lst->str (compress path)) '("n\n")) "\n"))
(vector-set! program 0 2)
(define vm (execute (start-machine program inputs)))
(car (machine-outputs vm)))
(module+ test
(check-equal? (part2 (parse-file "input")) 933214))

1
2019/day17/input Normal file
View file

@ -0,0 +1 @@
1,330,331,332,109,3546,1101,0,1182,15,1101,1481,0,24,1001,0,0,570,1006,570,36,102,1,571,0,1001,570,-1,570,1001,24,1,24,1105,1,18,1008,571,0,571,1001,15,1,15,1008,15,1481,570,1006,570,14,21102,58,1,0,1106,0,786,1006,332,62,99,21101,0,333,1,21101,0,73,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,1002,574,1,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21102,1,340,1,1106,0,177,21102,1,477,1,1106,0,177,21101,0,514,1,21102,1,176,0,1105,1,579,99,21102,1,184,0,1106,0,579,4,574,104,10,99,1007,573,22,570,1006,570,165,102,1,572,1182,21102,375,1,1,21101,211,0,0,1106,0,579,21101,1182,11,1,21101,0,222,0,1106,0,979,21102,388,1,1,21102,1,233,0,1106,0,579,21101,1182,22,1,21102,1,244,0,1106,0,979,21101,0,401,1,21102,255,1,0,1106,0,579,21101,1182,33,1,21102,266,1,0,1105,1,979,21102,414,1,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,21102,1,313,0,1105,1,622,1005,575,327,1102,1,1,575,21101,0,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,12,18,0,109,4,2102,1,-3,587,20101,0,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,1106,0,597,109,-4,2106,0,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,20102,1,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,0,702,0,1105,1,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21102,731,1,0,1105,1,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21102,1,756,0,1105,1,786,1105,1,774,21202,-1,-11,1,22101,1182,1,1,21101,0,774,0,1106,0,622,21201,-3,1,-3,1106,0,640,109,-5,2106,0,0,109,7,1005,575,802,21001,576,0,-6,20102,1,577,-5,1106,0,814,21102,1,0,-1,21102,0,1,-5,21102,0,1,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,59,-3,22201,-6,-3,-3,22101,1481,-3,-3,2101,0,-3,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,21102,35,1,-4,1105,1,924,2101,0,-3,878,1008,0,1,570,1006,570,916,1001,374,1,374,1202,-3,1,895,1101,0,2,0,2101,0,-3,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21002,0,1,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,59,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,35,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1101,0,1,575,21102,973,1,0,1105,1,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,1106,0,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,1202,-2,1,0,1105,1,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1105,1,989,21101,0,439,1,1106,0,1150,21102,477,1,1,1106,0,1150,21101,0,514,1,21102,1,1149,0,1105,1,579,99,21101,0,1157,0,1106,0,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,2101,0,-5,1176,1201,-4,0,0,109,-6,2105,1,0,6,13,27,13,6,1,11,1,27,1,11,1,6,1,11,1,27,1,11,1,6,1,11,1,27,1,11,1,6,1,11,1,27,1,11,1,6,1,11,1,27,1,11,1,6,1,11,1,1,9,9,11,9,1,6,1,11,1,1,1,7,1,9,1,7,1,1,1,9,1,6,1,11,13,7,1,7,1,1,1,9,1,6,1,13,1,7,1,1,1,7,1,7,1,1,1,9,1,6,1,13,1,7,1,1,1,5,11,1,1,9,1,6,1,13,1,7,1,1,1,5,1,1,1,9,1,9,1,6,11,3,1,7,1,1,1,5,1,1,1,9,1,1,9,16,1,3,1,7,1,1,1,5,1,1,1,9,1,1,1,24,1,3,1,7,13,7,1,1,1,24,1,3,1,9,1,5,1,1,1,1,1,7,1,1,1,24,1,3,1,9,9,1,1,7,11,16,1,3,1,15,1,3,1,9,1,7,1,12,9,15,1,3,1,9,1,7,1,16,1,19,1,3,1,9,1,7,1,16,1,19,11,3,1,7,1,16,1,23,1,5,1,3,1,7,1,8,9,23,11,7,1,8,1,37,1,11,1,8,1,37,1,11,1,8,1,37,1,11,1,8,1,37,1,11,1,8,1,37,1,11,1,8,1,37,13,8,1,58,1,58,1,58,1,58,1,50,9,50

29
2019/day19/day19.rkt Normal file
View file

@ -0,0 +1,29 @@
#lang racket/base
(require "../intcode.rkt")
(module+ test
(require rackunit))
(define (pulled? program x y)
(define vm (execute (start-machine program (list x y))))
(= 1 (car (machine-outputs vm))))
(define (part1 program)
(length (for*/list ([x (in-range 50)]
[y (in-range 50)]
#:when (pulled? program x y))
(list x y))))
(module+ test
(check-equal? (part1 (parse-file "input")) 229))
(define (part2 program)
(let loop ([x 0] [y 99])
(cond
[(not (pulled? program x y)) (loop (add1 x) y)]
[(pulled? program (+ x 99) (- y 99)) (+ (* 10000 x) (- y 99))]
[else (loop x (add1 y))])))
(module+ test
(check-equal? (part2 (parse-file "input")) 6950903))

1
2019/day19/input Normal file
View file

@ -0,0 +1 @@
109,424,203,1,21101,11,0,0,1105,1,282,21102,1,18,0,1106,0,259,1201,1,0,221,203,1,21101,0,31,0,1106,0,282,21101,0,38,0,1105,1,259,21002,23,1,2,21201,1,0,3,21101,0,1,1,21101,0,57,0,1106,0,303,2102,1,1,222,21002,221,1,3,20102,1,221,2,21102,259,1,1,21101,0,80,0,1105,1,225,21102,1,118,2,21102,91,1,0,1105,1,303,2102,1,1,223,21001,222,0,4,21102,259,1,3,21101,0,225,2,21101,225,0,1,21101,0,118,0,1105,1,225,20101,0,222,3,21102,1,72,2,21102,133,1,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21102,1,148,0,1105,1,259,1201,1,0,223,20101,0,221,4,20101,0,222,3,21101,22,0,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,1,195,0,106,0,108,20207,1,223,2,20101,0,23,1,21102,-1,1,3,21102,214,1,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,1201,-4,0,249,22101,0,-3,1,22101,0,-2,2,22101,0,-1,3,21101,0,250,0,1105,1,225,21202,1,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,22102,1,-2,-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,22101,0,-2,3,21101,0,343,0,1106,0,303,1105,1,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,21101,384,0,0,1106,0,303,1106,0,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,21201,1,0,-4,109,-5,2106,0,0

43
2019/day21/day21.rkt Normal file
View file

@ -0,0 +1,43 @@
#lang racket/base
(require "../intcode.rkt")
(module+ test
(require rackunit))
(define (part1 program)
(define inputs #<<EOF
OR A J
AND B J
AND C J
NOT J J
AND D J
WALK
EOF
)
(define vm (execute (start-machine program inputs)))
(car (machine-outputs vm)))
(module+ test
(check-equal? (part1 (parse-file "input")) 19359533))
(define (part2 program)
(define inputs #<<EOF
OR A J
AND B J
AND C J
NOT J J
AND D J
OR E T
OR H T
AND T J
RUN
EOF
)
(define vm (execute (start-machine program inputs)))
(car (machine-outputs vm)))
(module+ test
(check-equal? (part2 (parse-file "input")) 1140310551))

1
2019/day21/input Normal file

File diff suppressed because one or more lines are too long

117
2019/day22/day22.rkt Normal file
View file

@ -0,0 +1,117 @@
#lang racket
(require racket/string
math/number-theory)
(module+ test
(require rackunit))
(module+ main
(displayln "Day 22"))
(define (read-instructions filename)
(with-input-from-file filename
(lambda ()
(for/list ([line (in-lines)])
(cond
[(string-prefix? line "deal into new stack") 'deal]
[(string-prefix? line "cut") `(cut ,(string->number (last (string-split line " "))))]
[(string-prefix? line "deal with increment") `(increment ,(string->number (last (string-split line " "))))]
[else 'other])))))
(define (deal deck)
(reverse deck))
(define (cut deck n)
(define split-fn (if (> n 0) split-at split-at-right))
(define-values (a b) (split-fn deck (abs n)))
(append b a))
(define (increment deck n)
(for/list ([i (in-range (length deck))])
(list-ref deck
(remainder (* i (modular-inverse n (length deck))) (length deck)))))
(define (execute instruction deck)
(match instruction
['deal (deal deck)]
[(list 'cut n) (cut deck n)]
[(list 'increment n) (increment deck n)]))
(define (shuffle deck instructions)
(for/fold ([d deck]) ([i instructions])
(execute i d)))
(module+ test
(check-equal? (shuffle (range 10) (read-instructions "test1")) '(0 3 6 9 2 5 8 1 4 7))
(check-equal? (shuffle (range 10) (read-instructions "test2")) '(3 0 7 4 1 8 5 2 9 6))
(check-equal? (shuffle (range 10) (read-instructions "test3")) '(6 3 0 7 4 1 8 5 2 9))
(check-equal? (shuffle (range 10) (read-instructions "test4")) '(9 2 5 8 1 4 7 0 3 6)))
(module+ main
(displayln "Part 1:")
(define instructions (read-instructions "input"))
(define deck (range 10007))
(time (index-of (shuffle deck instructions) 2019)))
(define (deal-card deck-size card)
(- (sub1 deck-size) card))
(define (cut-card deck-size n card)
(modulo (- card n) deck-size))
(define (increment-card deck-size n card)
(modulo (* n card) deck-size))
(define (execute-card deck-size instruction card)
(match instruction
['deal (deal-card deck-size card)]
[(list 'cut n) (cut-card deck-size n card)]
[(list 'increment n) (increment-card deck-size n card)]))
(define (shuffle-card deck-size instructions card)
(for/fold ([c card]) ([i instructions])
(execute-card deck-size i c)))
(module+ main
(displayln "Part 1 (better):")
(time (shuffle-card 10007 instructions 2019)))
(define (deal-card-inv deck-size card)
(- (sub1 deck-size) card))
(define (cut-card-inv deck-size n card)
(modulo (+ card n) deck-size))
(define (increment-card-inv deck-size n card)
(remainder (* card (modular-inverse n deck-size)) deck-size))
(define (execute-card-inv deck-size instruction card)
(match instruction
['deal (deal-card-inv deck-size card)]
[(list 'cut n) (cut-card-inv deck-size n card)]
[(list 'increment n) (increment-card-inv deck-size n card)]))
(define (shuffle-card-inv deck-size reversed-instructions card)
(for/fold ([c card]) ([i reversed-instructions])
(execute-card-inv deck-size i c)))
(module+ main
(displayln "Part 2:")
(define deck-size 119315717514047)
(define iterations 101741582076661)
;; Operations are linear, we find the coefficients and apply them directly
(define x 2020)
(define y (shuffle-card-inv deck-size (reverse instructions) x))
(define z (shuffle-card-inv deck-size (reverse instructions) y))
(define a (modulo (* (- z y) (modular-inverse (- y x) deck-size)) deck-size))
(define b (modulo (- y (* a x)) deck-size))
(modulo (+ (* (modular-expt a iterations deck-size)
x)
(* (sub1 (modular-expt a iterations deck-size))
(modular-inverse (sub1 a) deck-size)
b))
deck-size))

100
2019/day22/input Normal file
View file

@ -0,0 +1,100 @@
deal with increment 55
cut -6984
deal into new stack
cut -2833
deal with increment 75
cut 2488
deal with increment 54
cut 9056
deal with increment 52
cut -2717
deal with increment 4
deal into new stack
cut -852
deal with increment 21
cut -3041
deal with increment 38
cut -6871
deal into new stack
deal with increment 32
cut 988
deal with increment 29
deal into new stack
deal with increment 68
cut 5695
deal with increment 36
cut -27
deal with increment 33
deal into new stack
cut -1306
deal with increment 30
cut -4033
deal with increment 28
cut -442
deal into new stack
deal with increment 30
cut -6295
deal with increment 56
cut -4065
deal into new stack
cut 5275
deal with increment 64
cut 9747
deal into new stack
deal with increment 63
cut -3772
deal with increment 61
deal into new stack
cut 1021
deal with increment 73
deal into new stack
deal with increment 7
cut -1232
deal with increment 52
cut -3439
deal with increment 31
cut 1128
deal into new stack
deal with increment 55
deal into new stack
deal with increment 39
cut -3424
deal with increment 11
deal into new stack
cut 4139
deal with increment 15
deal into new stack
cut 5333
deal with increment 16
cut -6787
deal with increment 39
cut -5817
deal into new stack
deal with increment 62
cut -2704
deal with increment 64
deal into new stack
deal with increment 70
cut 3436
deal with increment 65
cut -8686
deal with increment 22
cut -6190
deal with increment 13
cut -100
deal into new stack
cut -619
deal into new stack
cut 3079
deal with increment 53
cut 1725
deal with increment 19
cut 3440
deal with increment 64
cut 8578
deal with increment 5
cut 2341
deal with increment 45
cut 2217
deal with increment 13
deal into new stack

3
2019/day22/test1 Normal file
View file

@ -0,0 +1,3 @@
deal with increment 7
deal into new stack
deal into new stack

3
2019/day22/test2 Normal file
View file

@ -0,0 +1,3 @@
cut 6
deal with increment 7
deal into new stack

3
2019/day22/test3 Normal file
View file

@ -0,0 +1,3 @@
deal with increment 7
deal with increment 9
cut -2

10
2019/day22/test4 Normal file
View file

@ -0,0 +1,10 @@
deal into new stack
cut -2
deal with increment 7
cut 8
cut -4
deal with increment 7
cut 3
deal with increment 9
deal with increment 3
cut -1

30
2019/day23/day23.rkt Normal file
View file

@ -0,0 +1,30 @@
#lang racket/base
(require "../intcode.rkt"
racket/match
racket/list)
(module+ test
(require rackunit))
(define (get-packets vms)
(let loop ([packets (reverse (append* (map machine-outputs vms)))]
[h (hash)])
(match packets
['() h]
[(list* addr x y r) (loop r (hash-update h addr (λ (lst) (append (list x y) lst)) '()))])))
(define (part1 program)
(define vms (for/list ([i (in-range 50)])
(execute (start-machine program (list i)))))
(let loop ([vms vms])
(define packets (get-packets vms))
(if (hash-has-key? packets 255)
(cadr (hash-ref packets 255))
(loop
(for/list ([i (in-range 50)]
[vm (in-list vms)])
(execute (struct-copy machine vm [inputs (hash-ref packets i '(-1))])))))))
(module+ test
(check-equal? (part1 (parse-file "input")) 23266))

1
2019/day23/input Normal file

File diff suppressed because one or more lines are too long

66
2019/day24/day24.rkt Normal file
View file

@ -0,0 +1,66 @@
#lang racket
(module+ test
(require rackunit))
(define (read-input filename)
(for/set ([line (file->lines filename)]
[i (in-naturals)]
#:when #t
[c (in-string line)]
[j (in-naturals)]
#:when (eq? c #\#))
(make-rectangular j i)))
(define (grid-size grid)
(define indices (flatten (map (λ (x) (list (real-part x) (imag-part x))) (set->list grid))))
(add1 (apply max indices)))
(define (display-grid grid)
(define size (grid-size grid))
(for ([j (in-range size)])
(for ([i (in-range size)])
(if (set-member? grid (make-rectangular i j))
(printf "#")
(printf ".")))
(printf "~n")))
(define (count-neighbours grid pos)
(for/sum ([step '(-i -1 +i 1)]
#:when (set-member? grid (+ pos step)))
1))
(define (lives? grid pos)
(define n (count-neighbours grid pos))
(define alive (set-member? grid pos))
(cond
[(and alive (not (= 1 n))) #f]
[(and (not alive) (or (= 1 n) (= 2 n))) #t]
[else alive]))
(define (step grid)
(define size (grid-size grid))
(for*/set ([i (in-range size)]
[j (in-range size)]
#:when (lives? grid (make-rectangular i j)))
(make-rectangular i j)))
(define (biodiversity-rating grid)
(define size (grid-size grid))
(for*/sum ([i (in-range size)]
[j (in-range size)]
#:when (set-member? grid (make-rectangular i j)))
(expt 2 (+ i (* j size)))))
(define (part1 filename)
(define grid (read-input filename))
(define final
(car (for/fold ([grids (list grid)])
([i (in-naturals)]
#:break (member (car grids) (cdr grids)))
(cons (step (car grids)) grids))))
(biodiversity-rating final))
(module+ test
(check-equal? (part1 "test") 2129920)
(check-equal? (part1 "input") 32573535))

5
2019/day24/input Normal file
View file

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

5
2019/day24/test Normal file
View file

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

158
2019/intcode.rkt Normal file
View file

@ -0,0 +1,158 @@
#lang racket/base
(provide parse
parse-file
(struct-out machine)
start-machine
ascii->list
list->ascii
execute)
(require racket/list
racket/string
racket/file
racket/match)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Program I/O ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (parse str)
(list->vector (map string->number (map string-trim (string-split str ",")))))
(define (parse-file filename)
(parse (string-trim (file->string filename))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Instructions ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(struct instruction
(name
parameter-modes
inparams
outparams)
#:transparent)
(define opcodes
(hash
99 'terminate
1 '(add 2 1)
2 '(mul 2 1)
3 '(input 0 1)
4 '(output 1 0)
5 '(jmpt 2 0)
6 '(jmpf 2 0)
7 '(lt 2 1)
8 '(eq 2 1)
9 '(rel 1 0)))
(define (parse-instruction program pc relative-base)
(define opcode (vector-ref program pc))
(define-values (name nin nout)
(match (hash-ref opcodes (remainder opcode 100))
[(list name n m) (values name n m)]
[name (values name 0 0)]))
(define parameter-modes (make-hash))
(for/fold ([n (quotient opcode 100)])
([i (in-naturals)]
#:break (= n 0))
(hash-set! parameter-modes i (remainder n 10))
(quotient n 10))
(define inparams
(for/list ([i (in-range nin)])
(match (hash-ref parameter-modes i 0)
[0 (vector-ref program (vector-ref program (+ pc i 1)))]
[1 (vector-ref program (+ pc i 1))]
[2 (vector-ref program (+ relative-base (vector-ref program (+ pc i 1))))])))
(define outparams
(for/list ([i (in-range nout)])
(match (hash-ref parameter-modes (+ nin i) 0)
[0 (vector-ref program (+ pc nin i 1))]
[1 (error "output parameter cannot be in immediate mode" name pc)]
[2 (+ relative-base (vector-ref program (+ pc nin i 1)))])))
(instruction name parameter-modes inparams outparams))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Virtual machine interfaces ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(struct machine
(program
inputs
pc
relative-base
terminated
outputs)
#:transparent
#:guard (lambda (program inputs pc relative-base terminated outputs name)
(when (not (<= 0 pc (vector-length program)))
(error "invalid program counter" pc))
(values program
(preprocess-inputs inputs)
pc
relative-base
terminated outputs)))
(define (start-machine program inputs)
(machine program inputs 0 0 #f '()))
(define (ascii->list str)
(map char->integer (string->list str)))
(define (list->ascii lst)
(list->string (map integer->char lst)))
(define (preprocess-inputs inputs)
(cond
[(list? inputs) inputs]
[(string? inputs) (ascii->list inputs)]
[else (error "unsupported input type: " inputs)]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Virtual machine execution ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (execute vm)
(define p (make-vector 10000 0))
(vector-copy! p 0 (machine-program vm))
(let loop ([pc (machine-pc vm)]
[relative-base (machine-relative-base vm)]
[inputs (machine-inputs vm)]
[outputs (machine-outputs vm)])
(define instr (parse-instruction p pc relative-base))
(define inparams (instruction-inparams instr))
(define outparams (instruction-outparams instr))
(define next-pc (+ pc (length inparams) (length outparams) 1))
(match (instruction-name instr)
['terminate (machine p inputs pc relative-base #t outputs)]
['add (vector-set! p (car outparams) (apply + inparams))
(loop next-pc relative-base inputs outputs)]
['mul (vector-set! p (car outparams) (apply * inparams))
(loop next-pc relative-base inputs outputs)]
['input (if (empty? inputs)
(machine p inputs pc relative-base #f outputs)
(begin
(vector-set! p (car outparams) (car inputs))
(loop next-pc relative-base (cdr inputs) outputs)))]
['output (loop next-pc relative-base inputs (cons (car inparams) outputs))]
['jmpt (if (not (= 0 (car inparams)))
(loop (cadr inparams) relative-base inputs outputs)
(loop next-pc relative-base inputs outputs))]
['jmpf (if (= 0 (car inparams))
(loop (cadr inparams) relative-base inputs outputs)
(loop next-pc relative-base inputs outputs))]
['lt (vector-set! p (car outparams)
(if (< (car inparams) (cadr inparams)) 1 0))
(loop next-pc relative-base inputs outputs)]
['eq (vector-set! p (car outparams)
(if (= (car inparams) (cadr inparams)) 1 0))
(loop next-pc relative-base inputs outputs)]
['rel (loop next-pc (+ relative-base (car inparams)) inputs outputs)])))