https://github.com/akkartik/mu/blob/main/linux/apps/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 apps/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 }