https://github.com/akkartik/mu/blob/main/linux/advent2020/3a.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   print-int32-decimal 0, num-rows
     69   print-string 0, "x"
     70   print-int32-decimal 0, width
     71   print-string 0, "\n"
     72   var row/ecx: int <- copy 0
     73   var col/edx: int <- copy 0
     74   var num-trees-hit/edi: int <- copy 0
     75   {
     76     compare row, num-rows
     77     break-if->=
     78     var curr/eax: int <- index2d trees, row, col, width
     79     compare curr, 0
     80     {
     81       break-if-=
     82       num-trees-hit <- increment
     83     }
     84     # right 3, down 1
     85     col <- add 3
     86     row <- add 1
     87     loop
     88   }
     89   print-int32-decimal 0, num-trees-hit
     90   print-string 0, "\n"
     91   return 0
     92 }
     93
     94 fn index2d _arr: (addr array int), _row: int, _col: int, width: int -> _/eax: int {
     95   # handle repeating columns of trees
     96   var dummy/eax: int <- copy 0
     97   var col/edx: int <- copy 0
     98   dummy, col <- integer-divide _col, width
     99   # compute index
    100   var index/eax: int <- copy _row
    101   index <- multiply width
    102   index <- add col
    103   # look up array
    104   var arr/esi: (addr array int) <- copy _arr
    105   var src/eax: (addr int) <- index arr, index
    106   return *src
    107 }