https://github.com/akkartik/mu/blob/main/linux/apps/advent2020/1b.mu
  1 # https://adventofcode.com/2020/day/1
  2 #
  3 # To run (on Linux):
  4 #   $ git clone https://github.com/akkartik/mu
  5 #   $ cd mu
  6 #   $ ./translate apps/advent2020/1b.mu
  7 #   $ ./a.elf < input
  8 #   found
  9 #   143 407 1470
 10 #   85555470
 11 #
 12 # You'll need to register to download the 'input' file for yourself.
 13 
 14 fn main -> _/ebx: int {
 15   # data structure
 16   var numbers-storage: (array int 0x100)  # 256 ints
 17   var numbers/esi: (addr array int) <- address numbers-storage
 18   var numbers-index/ecx: int <- copy 0
 19   # phase 1: parse each line from stdin and add it to numbers
 20   {
 21     var line-storage: (stream byte 0x100)  # 256 bytes
 22     var line/edx: (addr stream byte) <- address line-storage
 23     {
 24 #?       print-string 0, "== iter\n"
 25       # read line from stdin
 26       clear-stream line
 27       read-line-from-real-keyboard line
 28       # if line is empty (not even a newline), quit
 29       var done?/eax: boolean <- stream-empty? line
 30       compare done?, 0/false
 31       break-if-!=
 32 #?       print-stream-to-real-screen line
 33       # convert line to int and append it to numbers
 34       var n/eax: int <- parse-decimal-int-from-stream line
 35 #?       print-int32-decimal 0, n
 36 #?       print-string 0, "\n"
 37       var dest/ebx: (addr int) <- index numbers, numbers-index
 38       copy-to *dest, n
 39       numbers-index <- increment
 40 #?       print-string 0, "== "
 41 #?       print-int32-decimal 0, numbers-index
 42 #?       print-string 0, "\n"
 43       loop
 44     }
 45   }
 46   # phase 2: for every pair of distinct numbers, check if the rest of the
 47   # array has 2020-it
 48   var i/edi: int <- copy 0
 49   {
 50     compare i, numbers-index
 51     break-if->=
 52     # for j from i+1 to end
 53     var j/edx: int <- copy i
 54     j <- increment
 55     {
 56       compare j, numbers-index
 57       break-if->=
 58       {
 59         compare i, j
 60         break-if-=
 61         var target/ebx: int <- copy 0x7e4  # 2020
 62         var src/edi: (addr int) <- index numbers, i
 63         target <- subtract *src
 64         var src2/ecx: (addr int) <- index numbers, j
 65         target <- subtract *src2
 66         {
 67           var found?/eax: boolean <- find-after numbers, j, target
 68           compare found?, 0/false
 69           break-if-=
 70           print-string 0, "found\n"
 71           print-int32-decimal 0, *src
 72           print-string 0, " "
 73           print-int32-decimal 0, *src2
 74           print-string 0, " "
 75           print-int32-decimal 0, target
 76           print-string 0, "\n"
 77           target <- multiply *src
 78           target <- multiply *src2
 79           print-int32-decimal 0, target
 80           print-string 0, "\n"
 81           return 0/success
 82         }
 83       }
 84       j <- increment
 85       loop
 86     }
 87     i <- increment
 88     loop
 89   }
 90   return 1/not-found
 91 }
 92 
 93 fn find-after _numbers: (addr array int), start: int, _target: int -> _/eax: boolean {
 94   var numbers/esi: (addr array int) <- copy _numbers
 95   var target/edi: int <- copy _target
 96   var len/ecx: int <- length numbers
 97   var i/eax: int <- copy start
 98   i <- increment
 99   {
100     compare i, len
101     break-if->=
102     var src/edx: (addr int) <- index numbers, i
103     # if *src == target, return true
104     compare *src, target
105     {
106       break-if-!=
107       return 1/true
108     }
109     i <- increment
110     loop
111   }
112   return 0/false
113 }