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