@@ -88,17 +88,20 @@ Prize: X=18641, Y=10279")
88
88
; filtrerer vekk løsninger som gir ratio (feks `1/3`):
89
89
90
90
^{:nextjournal.clerk/visibility {:result :hide }}
91
- (defn part-1 [acc {:keys [prize a b]}]
91
+ (defn tokens-needed [[a b]]
92
+ (+ (* 3 a) b))
93
+
94
+ ^{:nextjournal.clerk/visibility {:result :hide }}
95
+ (defn part-1 [{:keys [prize a b]}]
92
96
(let [{a 'a b 'b} (solve-game prize a b)]
93
97
(if (or (< 100 a) (< 100 b)
94
98
(ratio? a) (ratio? b))
95
- acc
96
- (+ acc ( * a 3 ) b ))))
99
+ 0
100
+ (tokens-needed [a b] ))))
97
101
98
102
^{:nextjournal.clerk/visibility {:result :hide }}
99
103
(defn solve [solver input]
100
- (reduce solver 0
101
- (get-games input)))
104
+ (transduce (map solver) + (get-games input)))
102
105
103
106
; Nå kan vi løse del 1 for test-dataene:
104
107
@@ -117,14 +120,14 @@ Prize: X=18641, Y=10279")
117
120
; reflektert i den nye reduceren for del 2:
118
121
119
122
^{:nextjournal.clerk/visibility {:result :hide }}
120
- (defn part-2 [acc {:keys [prize a b]}]
123
+ (defn part-2 [{:keys [prize a b]}]
121
124
(let [bigger-prize (-> prize
122
125
(update :x + 10000000000000 )
123
126
(update :y + 10000000000000 ))
124
127
{a 'a b 'b} (solve-game bigger-prize a b)]
125
128
(if (or (ratio? a) (ratio? b))
126
- acc
127
- (+ acc ( * a 3 ) b ))))
129
+ 0
130
+ (tokens-needed [a b] ))))
128
131
129
132
; Ellers kan vi løse oppgaven på samme måte som i del 1 for test-input:
130
133
@@ -133,3 +136,76 @@ Prize: X=18641, Y=10279")
133
136
; Og faktiske input:
134
137
135
138
(solve part-2 (input/get-input 2024 13 ))
139
+
140
+ ; ## Matriser
141
+
142
+ ; Et alternativ til expresso er å bruke "Cramer's rule", hvor en ligning
143
+ ; med to ukjente og kun ett gyldig svar kan løses med matriseregning.
144
+
145
+ (defn transpose [matrix]
146
+ (apply mapv vector matrix))
147
+
148
+ ^{:nextjournal.clerk/visibility {:result :hide }}
149
+ (defn game-matrices [input]
150
+ (eduction
151
+ (map (fn [game-text]
152
+ (transpose (partitionv 2 (map parse-long (re-seq #"\d +" game-text))))))
153
+ (.. input trim (split " \n\n " ))))
154
+
155
+ (defn det-2d
156
+ " Determinant i en 2d-matrise"
157
+ [[[ax bx]
158
+ [ay by]]]
159
+ (- (* ax by)
160
+ (* bx ay)))
161
+
162
+ (defn cramers-rule
163
+ " I Cramer's regel er en ukjent lik determinanten av 2d-matrisen
164
+ hvor en kolonne er byttet ut med løsningsvektoren, dividert med
165
+ den opprinnelige 2d-matrisen."
166
+ [[[ax bx rx]
167
+ [ay by ry]]]
168
+ (let [A [[ax bx]
169
+ [ay by]]
170
+ A1 [[rx bx]
171
+ [ry by]]
172
+ A2 [[ax rx]
173
+ [ay ry]]]
174
+ [(/ (det-2d A1)
175
+ (det-2d A))
176
+ (/ (det-2d A2)
177
+ (det-2d A))]))
178
+
179
+ ^{:nextjournal.clerk/visibility {:result :hide }}
180
+ (defn solve-mx [games & {:keys [scale max-presses]
181
+ :or {scale nil max-presses nil }}]
182
+ (eduction
183
+ (map (fn [[[ax bx rx]
184
+ [ay by ry] :as matrix]]
185
+ (if scale
186
+ [[ax bx (+ rx scale)]
187
+ [ay by (+ ry scale)]]
188
+ matrix)))
189
+ (map cramers-rule)
190
+ (remove (fn [[a b :as _result]]
191
+ (when max-presses
192
+ (and (>= a max-presses)
193
+ (>= b max-presses)))))
194
+ (remove (fn [result] (some ratio? result)))
195
+ games))
196
+
197
+ (->> (solve-mx (game-matrices test-data)
198
+ :max-presses 100 )
199
+ (transduce (map tokens-needed) +))
200
+
201
+ (->> (solve-mx (game-matrices (input/get-input 2024 13 ))
202
+ :max-presses 100 )
203
+ (transduce (map tokens-needed) +))
204
+
205
+ (->> (solve-mx (game-matrices test-data)
206
+ :scale 10000000000000 )
207
+ (transduce (map tokens-needed) +))
208
+
209
+ (->> (solve-mx (game-matrices (input/get-input 2024 13 ))
210
+ :scale 10000000000000 )
211
+ (transduce (map tokens-needed) +))
0 commit comments