https://github.com/akkartik/mu/blob/main/linux/advent2020/3b.mu

      1 # https://adventofcode.com/2020/day/3
      2 #
      3 # To run (on Linux):
      4 #   $ git clone https://github.com/akkartik/mu
      5 #   $ cd mu
      6 #   $ ./translate advent2020/3a.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   # represent trees in a 2D array of ints
     13   # wasteful since each tree is just one bit
     14   var trees-storage: (array int 0x2800)  # 10k ints
     15   var trees/esi: (addr array int) <- address trees-storage
     16   var trees-length/ecx: int <- copy 0
     17   var num-rows: int
     18   var width: int
     19   # phase 1: parse each row of trees from stdin
     20   {
     21     var line-storage: (stream byte 0x40)  # 64 bytes
     22     var line/edx: (addr stream byte) <- address line-storage
     23     {
     24       # read line from stdin
     25       clear-stream line
     26       read-line-from-real-keyboard line
     27       # if line is empty (not even a newline), quit
     28       var done?/eax: boolean <- stream-empty? line
     29       compare done?, 0/false
     30       break-if-!=
     31       # wastefully recompute width on every line
     32       # zero error-checking; we assume input lines are all equally long
     33       copy-to width, 0
     34       # turn each byte into a tree and append it
     35       $main:line-loop: {
     36         var done?/eax: boolean <- stream-empty? line
     37         compare done?, 0/false
     38         break-if-!=
     39 #?         print-int32-decimal 0, num-rows
     40 #?         print-string 0, " "
     41 #?         print-int32-decimal 0, width
     42 #?         print-string 0, "\n"
     43         var dest/ebx: (addr int) <- index trees, trees-length
     44         var c/eax: byte <- read-byte line
     45         # newline comes only at end of line
     46         compare c, 0xa/newline
     47         break-if-=
     48         # '#' = tree
     49         compare c, 0x23/hash
     50         {
     51           break-if-!=
     52           copy-to *dest, 1
     53         }
     54         # anything else = no tree
     55         {
     56           break-if-=
     57           copy-to *dest, 0
     58         }
     59         increment width
     60         trees-length <- increment
     61         loop
     62       }
     63       increment num-rows
     64       loop
     65     }
     66   }
     67   # phase 2: compute
     68   var product/edi: int <- copy 1
     69   var result/eax: int <- num-trees-hit trees, width, num-rows, 1, 1
     70   print-int32-decimal 0, result
     71   print-string 0, " x "
     72   product <- multiply result
     73   var result/eax: int <- num-trees-hit trees, width, num-rows, 3, 1
     74   print-int32-decimal 0, result
     75   print-string 0, " x "
     76   product <- multiply result
     77   var result/eax: int <- num-trees-hit trees, width, num-rows, 5, 1
     78   print-int32-decimal 0, result
     79   print-string 0, " x "
     80   product <- multiply result
     81   var result/eax: int <- num-trees-hit trees, width, num-rows, 7, 1
     82   print-int32-decimal 0, result
     83   print-string 0, " x "
     84   product <- multiply result
     85   var result/eax: int <- num-trees-hit trees, width, num-rows, 1, 2
     86   print-int32-decimal 0, result
     87   print-string 0, " = "
     88   product <- multiply result
     89   print-int32-hex 0, product
     90   print-string 0, "\n"
     91   return 0
     92 }
     93
     94 fn num-trees-hit trees: (addr array int), width: int, num-rows: int, right: int, down: int -> _/eax: int {
     95 #?   print-string 0, "== "
     96 #?   print-int32-decimal 0, right
     97 #?   print-string 0, " "
     98 #?   print-int32-decimal 0, down
     99 #?   print-string 0, "\n"
    100   var row/ecx: int <- copy 0
    101   var col/edx: int <- copy 0
    102   var num-trees-hit/edi: int <- copy 0
    103   {
    104     compare row, num-rows
    105     break-if->=
    106 #?     print-int32-decimal 0, col
    107 #?     print-string 0, "\n"
    108     var curr/eax: int <- index2d trees, row, col, width
    109     compare curr, 0
    110     {
    111       break-if-=
    112       num-trees-hit <- increment
    113     }
    114     col <- add right
    115     row <- add down
    116     loop
    117   }
    118   return num-trees-hit
    119 }
    120
    121 fn index2d _arr: (addr array int), _row: int, _col: int, width: int -> _/eax: int {
    122   # handle repeating columns of trees
    123   var dummy/eax: int <- copy 0
    124   var col/edx: int <- copy 0
    125   dummy, col <- integer-divide _col, width
    126 #?   print-string 0, "  "
    127 #?   print-int32-decimal 0, col
    128 #?   print-string 0, "\n"
    129   # compute index
    130   var index/eax: int <- copy _row
    131   index <- multiply width
    132   index <- add col
    133   # look up array
    134   var arr/esi: (addr array int) <- copy _arr
    135   var src/eax: (addr int) <- index arr, index
    136   return *src
    137 }