-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday9.clj
93 lines (85 loc) · 6.37 KB
/
day9.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
(ns day9)
(def input [1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,3,0,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,708,1029,1101,1,0,1021,1102,38,1,1015,1101,25,0,1004,1101,21,0,1018,1102,1,34,1016,1101,0,713,1028,1101,735,0,1024,1101,31,0,1003,1102,1,24,1010,1101,20,0,1011,1101,0,27,1005,1102,726,1,1025,1101,426,0,1027,1101,0,777,1022,1102,1,32,1001,1101,37,0,1009,1101,429,0,1026,1102,1,36,1019,1101,0,0,1020,1101,0,30,1012,1101,0,770,1023,1101,0,35,1014,1101,0,33,1007,1102,23,1,1002,1101,0,28,1017,1102,1,22,1013,1102,39,1,1006,1101,0,26,1000,1101,29,0,1008,109,6,2102,1,-1,63,1008,63,27,63,1005,63,203,4,187,1106,0,207,1001,64,1,64,1002,64,2,64,109,-15,2108,26,9,63,1005,63,225,4,213,1106,0,229,1001,64,1,64,1002,64,2,64,109,9,21101,40,0,10,1008,1010,40,63,1005,63,251,4,235,1106,0,255,1001,64,1,64,1002,64,2,64,109,11,21108,41,40,0,1005,1011,271,1106,0,277,4,261,1001,64,1,64,1002,64,2,64,109,-7,1207,3,32,63,1005,63,297,1001,64,1,64,1105,1,299,4,283,1002,64,2,64,109,3,1201,-1,0,63,1008,63,42,63,1005,63,323,1001,64,1,64,1105,1,325,4,305,1002,64,2,64,109,2,2102,1,-7,63,1008,63,24,63,1005,63,345,1106,0,351,4,331,1001,64,1,64,1002,64,2,64,109,-6,21107,42,43,8,1005,1011,369,4,357,1106,0,373,1001,64,1,64,1002,64,2,64,109,-7,2108,30,7,63,1005,63,393,1001,64,1,64,1106,0,395,4,379,1002,64,2,64,109,18,21108,43,43,-3,1005,1011,413,4,401,1106,0,417,1001,64,1,64,1002,64,2,64,109,17,2106,0,-4,1105,1,435,4,423,1001,64,1,64,1002,64,2,64,109,-29,2107,26,2,63,1005,63,451,1105,1,457,4,441,1001,64,1,64,1002,64,2,64,109,20,1206,-2,471,4,463,1105,1,475,1001,64,1,64,1002,64,2,64,109,-9,1205,8,489,4,481,1105,1,493,1001,64,1,64,1002,64,2,64,109,-12,1202,-1,1,63,1008,63,26,63,1005,63,515,4,499,1105,1,519,1001,64,1,64,1002,64,2,64,109,25,1205,-6,531,1106,0,537,4,525,1001,64,1,64,1002,64,2,64,109,-31,1208,8,31,63,1005,63,555,4,543,1106,0,559,1001,64,1,64,1002,64,2,64,109,13,1207,1,38,63,1005,63,577,4,565,1106,0,581,1001,64,1,64,1002,64,2,64,109,4,21101,44,0,1,1008,1013,47,63,1005,63,605,1001,64,1,64,1106,0,607,4,587,1002,64,2,64,109,-6,2107,38,0,63,1005,63,629,4,613,1001,64,1,64,1106,0,629,1002,64,2,64,109,13,21102,45,1,-7,1008,1012,45,63,1005,63,655,4,635,1001,64,1,64,1105,1,655,1002,64,2,64,109,9,1206,-7,667,1106,0,673,4,661,1001,64,1,64,1002,64,2,64,109,-27,2101,0,7,63,1008,63,29,63,1005,63,699,4,679,1001,64,1,64,1106,0,699,1002,64,2,64,109,17,2106,0,10,4,705,1106,0,717,1001,64,1,64,1002,64,2,64,109,14,2105,1,-8,4,723,1001,64,1,64,1106,0,735,1002,64,2,64,109,-21,1202,-8,1,63,1008,63,34,63,1005,63,755,1105,1,761,4,741,1001,64,1,64,1002,64,2,64,109,18,2105,1,-6,1001,64,1,64,1106,0,779,4,767,1002,64,2,64,109,-15,1201,-6,0,63,1008,63,29,63,1005,63,801,4,785,1105,1,805,1001,64,1,64,1002,64,2,64,109,-14,1208,0,24,63,1005,63,825,1001,64,1,64,1106,0,827,4,811,1002,64,2,64,109,15,21102,46,1,-2,1008,1013,49,63,1005,63,847,1106,0,853,4,833,1001,64,1,64,1002,64,2,64,109,-17,2101,0,2,63,1008,63,23,63,1005,63,873,1106,0,879,4,859,1001,64,1,64,1002,64,2,64,109,16,21107,47,46,2,1005,1016,899,1001,64,1,64,1105,1,901,4,885,4,64,99,21101,0,27,1,21101,0,915,0,1106,0,922,21201,1,55486,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,942,1,0,1105,1,922,22102,1,1,-1,21201,-2,-3,1,21101,0,957,0,1105,1,922,22201,1,-1,-2,1105,1,968,22101,0,-2,-2,109,-3,2106,0,0])
(def ^:dynamic *input* [])
(def ^:dynamic *output* [])
(def ^:dynamic *relative-base* nil)
(defn parse-opcode [opcode]
(let [[p3 p2 p1] (take-last 3 (drop-last 2 (str "0000" opcode)))]
[(rem opcode 100)
(case p1
\0 (fn pos [code pos] (code (code (+ 1 pos))))
\1 (fn imm [code pos] (code (+ 1 pos)))
\2 (fn rel [code pos] (code (+ @*relative-base* (code (+ 1 pos))))))
(case p2
\0 (fn pos [code pos] (code (code (+ 2 pos))))
\1 (fn imm [code pos] (code (+ 2 pos)))
\2 (fn rel [code pos] (code (+ @*relative-base* (code (+ 2 pos))))))]))
(defn parse-target-pos [opcode]
(let [[p3 p2 p1] (take-last 3 (drop-last 2 (str "0000" opcode)))]
[(case p1
\0 (fn pos [code pos] (code (+ 1 pos)))
\1 (fn imm [code pos] (+ 1 pos))
\2 (fn rel [code pos] (+ @*relative-base* (code (+ 1 pos)))))
(case p2
\0 (fn pos [code pos] (code (+ 2 pos)))
\1 (fn imm [code pos] (+ 2 pos))
\2 (fn rel [code pos] (+ @*relative-base* (code (+ 2 pos)))))
(case p3
\0 (fn pos [code pos] (code (+ 3 pos)))
\1 (fn imm [code pos] (assert false "Not used!"))
\2 (fn rel [code pos] (+ @*relative-base* (code (+ 3 pos)))))]))
(defn exec-intcode [code pos]
(assert (sequential? code) (str "Not seq: " code))
(assert (integer? pos))
(assert (not (neg? pos)))
(let [[opcode get-1 get-2] (parse-opcode (code pos))
[set-1 _ set-3] (parse-target-pos (code pos))]
; (println "opcode: " opcode)
(case opcode
99 nil
1 [(+ pos 4)
(assoc code (set-3 code pos) (+ (get-1 code pos) (get-2 code pos)))]
2 [(+ pos 4)
(assoc code (set-3 code pos) (* (get-1 code pos) (get-2 code pos)))]
3 [(+ pos 2)
(let [n (first @*input*)]
(swap! *input* next)
(assoc code (set-1 code pos) n))]
4 [(+ pos 2)
(do
(swap! *output* conj (get-1 code pos))
code)]
;; second part:
5 (if (zero? (get-1 code pos))
[(+ pos 3) code]
[(get-2 code pos) code])
6 (if-not (zero? (get-1 code pos))
[(+ pos 3) code]
[(get-2 code pos) code])
7 (if (< (get-1 code pos) (get-2 code pos))
[(+ pos 4) (assoc code (set-3 code pos) 1)]
[(+ pos 4) (assoc code (set-3 code pos) 0)])
8 (if (= (get-1 code pos) (get-2 code pos))
[(+ pos 4) (assoc code (set-3 code pos) 1)]
[(+ pos 4) (assoc code (set-3 code pos) 0)])
;; relative base adjustment
9
[(+ pos 2)
(do (swap! *relative-base* + (get-1 code pos))
code)])))
(defn eval-intcode [code input]
(binding [*input* (atom (seq input))
*output* (atom [])
*relative-base* (atom 0)]
(loop [pos 0
code code]
(if-let [[next-pos code] (exec-intcode code pos)]
(recur next-pos code)
{:output @*output*}))))
(println
(eval-intcode
(mapv bigint
(concat
input ;quine ;ztest2 ; quine ;input
(repeat 10000 0)))
[1]))