https://github.com/akkartik/mu/blob/main/linux/apps/advent2020/4b.mu
1
2
3
4
5
6
7
8
9
10
11 fn main -> _/ebx: int {
12 var curr-passport-field-count/esi: int <- copy 0
13 var valid-passport-count/edi: int <- copy 0
14 var line-storage: (stream byte 0x100)
15 var line/ecx: (addr stream byte) <- address line-storage
16 var key-slice-storage: slice
17 var key-slice/edx: (addr slice) <- address key-slice-storage
18 var val-slice-storage: slice
19 var val-slice/ebx: (addr slice) <- address val-slice-storage
20 $main:line-loop: {
21
22 clear-stream line
23 read-line-from-real-keyboard line
24
25 var done?/eax: boolean <- stream-empty? line
26 compare done?, 0/false
27 break-if-!=
28 print-stream-to-real-screen line
29
30 skip-chars-matching-whitespace line
31 var new-passport?/eax: boolean <- stream-empty? line
32 {
33 compare new-passport?, 0/false
34 break-if-=
35 compare curr-passport-field-count, 7
36 {
37 break-if-!=
38 valid-passport-count <- increment
39 print-string 0, "=> "
40 print-int32-decimal 0, valid-passport-count
41 print-string 0, "\n"
42 }
43 curr-passport-field-count <- copy 0
44 loop $main:line-loop
45 }
46 $main:word-loop: {
47 skip-chars-matching-whitespace line
48 var done?/eax: boolean <- stream-empty? line
49 compare done?, 0/false
50 break-if-!=
51 next-token line, 0x3a, key-slice
52 var dummy/eax: byte <- read-byte line
53 next-raw-word line, val-slice
54 print-slice-to-real-screen key-slice
55 print-string 0, " : "
56 print-slice-to-real-screen val-slice
57 print-string 0, "\n"
58
59 var cid?/eax: boolean <- slice-equal? key-slice, "cid"
60 compare cid?, 0/false
61 loop-if-!=
62
63 curr-passport-field-count <- increment
64
65
66 {
67 var byr?/eax: boolean <- slice-equal? key-slice, "byr"
68 compare byr?, 0/false
69 break-if-=
70
71 var byr/eax: int <- parse-decimal-int-from-slice val-slice
72 compare byr, 0x780
73 {
74 break-if->=
75 print-string 0, "invalid\n"
76 curr-passport-field-count <- copy 8
77 }
78 compare byr, 0x7d2
79 {
80 break-if-<=
81 print-string 0, "invalid\n"
82 curr-passport-field-count <- copy 8
83 }
84 }
85
86 {
87 var iyr?/eax: boolean <- slice-equal? key-slice, "iyr"
88 compare iyr?, 0/false
89 break-if-=
90
91 var iyr/eax: int <- parse-decimal-int-from-slice val-slice
92 compare iyr, 0x7da
93 {
94 break-if->=
95 print-string 0, "invalid\n"
96 curr-passport-field-count <- copy 8
97 }
98 compare iyr, 0x7e4
99 {
100 break-if-<=
101 print-string 0, "invalid\n"
102 curr-passport-field-count <- copy 8
103 }
104 }
105
106 {
107 var eyr?/eax: boolean <- slice-equal? key-slice, "eyr"
108 compare eyr?, 0/false
109 break-if-=
110
111 var eyr/eax: int <- parse-decimal-int-from-slice val-slice
112 compare eyr, 0x7e4
113 {
114 break-if->=
115 print-string 0, "invalid\n"
116 curr-passport-field-count <- copy 8
117 }
118 compare eyr, 0x7ee
119 {
120 break-if-<=
121 print-string 0, "invalid\n"
122 curr-passport-field-count <- copy 8
123 }
124 }
125
126 {
127 var hgt?/eax: boolean <- slice-equal? key-slice, "hgt"
128 compare hgt?, 0/false
129 break-if-=
130
131 var s: (handle array byte)
132 var s2/eax: (addr handle array byte) <- address s
133 _slice-to-string val-slice, s2
134 var s3/eax: (addr array byte) <- lookup *s2
135 var s4/ebx: (addr array byte) <- copy s3
136
137 var start/edx: int <- length s4
138 start <- subtract 2
139 {
140 var suffix-h: (handle array byte)
141 var suffix-ah/ecx: (addr handle array byte) <- address suffix-h
142 substring s4, start, 2, suffix-ah
143 var suffix/eax: (addr array byte) <- lookup *suffix-ah
144 {
145 var match?/eax: boolean <- string-equal? suffix, "in"
146 compare match?, 0/false
147 break-if-=
148
149 var num-h: (handle array byte)
150 var num-ah/ecx: (addr handle array byte) <- address num-h
151 substring s4, 0, start, num-ah
152 var num/eax: (addr array byte) <- lookup *num-ah
153 var val/eax: int <- parse-decimal-int num
154 compare val, 0x3b
155 {
156 break-if->=
157 print-string 0, "invalid\n"
158 curr-passport-field-count <- copy 8
159 }
160 compare val, 0x60
161 {
162 break-if-<=
163 print-string 0, "invalid\n"
164 curr-passport-field-count <- copy 8
165 }
166 loop $main:word-loop
167 }
168 {
169 var match?/eax: boolean <- string-equal? suffix, "cm"
170 compare match?, 0/false
171 break-if-=
172
173 var num-h: (handle array byte)
174 var num-ah/ecx: (addr handle array byte) <- address num-h
175 substring s4, 0, start, num-ah
176 var num/eax: (addr array byte) <- lookup *num-ah
177 var val/eax: int <- parse-decimal-int num
178 compare val, 0x96
179 {
180 break-if->=
181 print-string 0, "invalid\n"
182 curr-passport-field-count <- copy 8
183 }
184 compare val, 0xc1
185 {
186 break-if-<=
187 print-string 0, "invalid\n"
188 curr-passport-field-count <- copy 8
189 }
190 loop $main:word-loop
191 }
192 print-string 0, "invalid\n"
193 curr-passport-field-count <- copy 8
194 loop $main:word-loop
195 }
196 }
197
198 {
199 var hcl?/eax: boolean <- slice-equal? key-slice, "hcl"
200 compare hcl?, 0/false
201 break-if-=
202
203 var s: (handle array byte)
204 var s2/eax: (addr handle array byte) <- address s
205 _slice-to-string val-slice, s2
206 var s3/eax: (addr array byte) <- lookup *s2
207
208 var len/ebx: int <- length s3
209 compare len, 7
210 {
211 break-if-=
212 print-string 0, "invalid\n"
213 curr-passport-field-count <- copy 8
214 loop $main:word-loop
215 }
216
217 {
218 var c/eax: (addr byte) <- index s3, 0
219 var c2/eax: byte <- copy-byte *c
220 compare c2, 0x23/hash
221 break-if-=
222 print-string 0, "invalid2\n"
223 curr-passport-field-count <- copy 8
224 loop $main:word-loop
225 }
226
227 var i/ebx: int <- copy 1
228 {
229 compare i, 7
230 break-if->=
231 var c/eax: (addr byte) <- index s3, i
232 {
233 var c2/eax: byte <- copy-byte *c
234 var valid?/eax: boolean <- hex-digit? c2
235 compare valid?, 0
236 loop-if-= $main:word-loop
237 }
238 i <- increment
239 loop
240 }
241 }
242
243 {
244 var ecl?/eax: boolean <- slice-equal? key-slice, "ecl"
245 compare ecl?, 0/false
246 break-if-=
247 var amb?/eax: boolean <- slice-equal? val-slice, "amb"
248 compare amb?, 0/false
249 loop-if-!= $main:word-loop
250 var blu?/eax: boolean <- slice-equal? val-slice, "blu"
251 compare blu?, 0/false
252 loop-if-!= $main:word-loop
253 var brn?/eax: boolean <- slice-equal? val-slice, "brn"
254 compare brn?, 0/false
255 loop-if-!= $main:word-loop
256 var gry?/eax: boolean <- slice-equal? val-slice, "gry"
257 compare gry?, 0/false
258 loop-if-!= $main:word-loop
259 var grn?/eax: boolean <- slice-equal? val-slice, "grn"
260 compare grn?, 0/false
261 loop-if-!= $main:word-loop
262 var hzl?/eax: boolean <- slice-equal? val-slice, "hzl"
263 compare hzl?, 0/false
264 loop-if-!= $main:word-loop
265 var oth?/eax: boolean <- slice-equal? val-slice, "oth"
266 compare oth?, 0/false
267 loop-if-!= $main:word-loop
268 print-string 0, "invalid\n"
269 curr-passport-field-count <- copy 8
270 }
271
272 {
273 var pid?/eax: boolean <- slice-equal? key-slice, "pid"
274 compare pid?, 0/false
275 break-if-=
276
277 var s: (handle array byte)
278 var s2/eax: (addr handle array byte) <- address s
279 _slice-to-string val-slice, s2
280 var s3/eax: (addr array byte) <- lookup *s2
281
282 var len/eax: int <- length s3
283 compare len, 9
284 {
285 break-if-=
286 print-string 0, "invalid\n"
287 curr-passport-field-count <- copy 8
288 loop $main:word-loop
289 }
290
291
292
293 var val/eax: int <- parse-decimal-int-from-slice val-slice
294 compare val, 0
295 {
296 break-if->
297 print-string 0, "invalid\n"
298 curr-passport-field-count <- copy 8
299 }
300 }
301 loop
302 }
303 loop
304 }
305
306 compare curr-passport-field-count, 7
307 {
308 break-if-!=
309 valid-passport-count <- increment
310 }
311 print-int32-decimal 0, valid-passport-count
312 print-string 0, "\n"
313 return 0
314 }