From 3350c34a74844e21ea69077e01efff3bae64bdcd Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 23 Mar 2021 17:31:08 -0700 Subject: . --- html/linux/advent2020/4b.mu.html | 376 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 html/linux/advent2020/4b.mu.html (limited to 'html/linux/advent2020/4b.mu.html') diff --git a/html/linux/advent2020/4b.mu.html b/html/linux/advent2020/4b.mu.html new file mode 100644 index 00000000..b48f3811 --- /dev/null +++ b/html/linux/advent2020/4b.mu.html @@ -0,0 +1,376 @@ + + + + +Mu - linux/advent2020/4b.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/linux/advent2020/4b.mu +
+  1 # https://adventofcode.com/2020/day/4
+  2 #
+  3 # To run (on Linux):
+  4 #   $ git clone https://github.com/akkartik/mu
+  5 #   $ cd mu
+  6 #   $ ./translate advent2020/4b.mu
+  7 #   $ ./a.elf < input
+  8 #
+  9 # You'll need to register to download the 'input' file for yourself.
+ 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)  # 256 bytes
+ 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     # read line from stdin
+ 22     clear-stream line
+ 23     read-line-from-real-keyboard line
+ 24     # if line is empty (not even a newline), quit
+ 25     var done?/eax: boolean <- stream-empty? line
+ 26     compare done?, 0/false
+ 27     break-if-!=
+ 28     print-stream-to-real-screen line
+ 29     # if line has just a newline, process passport
+ 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  # skip ':'
+ 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       # treat cid as optional
+ 59       var cid?/eax: boolean <- slice-equal? key-slice, "cid"
+ 60       compare cid?, 0/false
+ 61       loop-if-!=
+ 62       # increment field count
+ 63       curr-passport-field-count <- increment
+ 64       # - validate fields one by one, setting curr-passport-field-count to impossibly high value to signal invalid
+ 65       # byr
+ 66       {
+ 67         var byr?/eax: boolean <- slice-equal? key-slice, "byr"
+ 68         compare byr?, 0/false
+ 69         break-if-=
+ 70         # 1920 <= byr <= 2002
+ 71         var byr/eax: int <- parse-decimal-int-from-slice val-slice
+ 72         compare byr, 0x780  # 1920
+ 73         {
+ 74           break-if->=
+ 75           print-string 0, "invalid\n"
+ 76           curr-passport-field-count <- copy 8
+ 77         }
+ 78         compare byr, 0x7d2  # 2002
+ 79         {
+ 80           break-if-<=
+ 81           print-string 0, "invalid\n"
+ 82           curr-passport-field-count <- copy 8
+ 83         }
+ 84       }
+ 85       # iyr
+ 86       {
+ 87         var iyr?/eax: boolean <- slice-equal? key-slice, "iyr"
+ 88         compare iyr?, 0/false
+ 89         break-if-=
+ 90         # 2010 <= iyr <= 2020
+ 91         var iyr/eax: int <- parse-decimal-int-from-slice val-slice
+ 92         compare iyr, 0x7da  # 2010
+ 93         {
+ 94           break-if->=
+ 95           print-string 0, "invalid\n"
+ 96           curr-passport-field-count <- copy 8
+ 97         }
+ 98         compare iyr, 0x7e4  # 2020
+ 99         {
+100           break-if-<=
+101           print-string 0, "invalid\n"
+102           curr-passport-field-count <- copy 8
+103         }
+104       }
+105       # eyr
+106       {
+107         var eyr?/eax: boolean <- slice-equal? key-slice, "eyr"
+108         compare eyr?, 0/false
+109         break-if-=
+110         # 2020 <= eyr <= 2030
+111         var eyr/eax: int <- parse-decimal-int-from-slice val-slice
+112         compare eyr, 0x7e4  # 2020
+113         {
+114           break-if->=
+115           print-string 0, "invalid\n"
+116           curr-passport-field-count <- copy 8
+117         }
+118         compare eyr, 0x7ee  # 2030
+119         {
+120           break-if-<=
+121           print-string 0, "invalid\n"
+122           curr-passport-field-count <- copy 8
+123         }
+124       }
+125       # hgt
+126       {
+127         var hgt?/eax: boolean <- slice-equal? key-slice, "hgt"
+128         compare hgt?, 0/false
+129         break-if-=
+130         # convert val
+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         # check suffix
+137         var start/edx: int <- length s4
+138         start <- subtract 2  # luckily both 'in' and 'cm' have the same length
+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             # if suffix is "in", 59 <= val <= 96
+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  # 59
+155             {
+156               break-if->=
+157           print-string 0, "invalid\n"
+158               curr-passport-field-count <- copy 8
+159             }
+160             compare val, 0x60  # 96
+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             # if suffix is "cm", 150 <= val <= 193
+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  # 150
+179             {
+180               break-if->=
+181           print-string 0, "invalid\n"
+182               curr-passport-field-count <- copy 8
+183             }
+184             compare val, 0xc1  # 193
+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       # hcl
+198       {
+199         var hcl?/eax: boolean <- slice-equal? key-slice, "hcl"
+200         compare hcl?, 0/false
+201         break-if-=
+202         # convert val
+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         # check length
+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         # check first byte
+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         # check remaining bytes
+227         var i/ebx: int <- copy 1  # skip 0
+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       # ecl
+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       # pid
+272       {
+273         var pid?/eax: boolean <- slice-equal? key-slice, "pid"
+274         compare pid?, 0/false
+275         break-if-=
+276         # convert val
+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         # check length
+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         # check valid decimal int
+291         # parse-decimal-int-from-slice currently returns 0 on invalid parse,
+292         # which isn't ideal but suffices for our purposes
+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   # process final passport
+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 }
+
+ + + -- cgit 1.4.1-2-gfad0