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

      1 # https://adventofcode.com/2020/day/2
      2 #
      3 # To run (on Linux):
      4 #   $ git clone https://github.com/akkartik/mu
      5 #   $ cd mu
      6 #   $ ./translate advent2020/2b.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   var valid-password-count/edi: int <- copy 0
     13   var line-storage: (stream byte 0x100)  # 256 bytes
     14   var line/edx: (addr stream byte) <- address line-storage
     15   var slice-storage: slice
     16   var slice/ecx: (addr slice) <- address slice-storage
     17   {
     18     # read line from stdin
     19     clear-stream line
     20     read-line-from-real-keyboard line
     21     # if line is empty (not even a newline), quit
     22     var done?/eax: boolean <- stream-empty? line
     23     compare done?, 0/false
     24     break-if-!=
     25     print-stream-to-real-screen line
     26     # slice = next-token(line, '-')
     27     next-token line, 0x2d, slice
     28     # pos1 = parse-int(slice)
     29     var _pos1/eax: int <- parse-decimal-int-from-slice slice
     30     var pos1/ebx: int <- copy _pos1
     31     var dash/eax: byte <- read-byte line  # skip '-'
     32     # slice = next-token(line, ' ')
     33     next-token line, 0x20, slice
     34     var _pos2/eax: int <- parse-decimal-int-from-slice slice
     35     var pos2/esi: int <- copy _pos2
     36     print-int32-decimal 0, pos1
     37     print-string 0, " "
     38     print-int32-decimal 0, pos2
     39     print-string 0, "\n"
     40     compare pos1, pos2
     41     {
     42       break-if-<=
     43       print-string 0, "out of order!\n"
     44       return 1
     45     }
     46     # letter = next non-space
     47     skip-chars-matching-whitespace line
     48     var letter/eax: byte <- read-byte line
     49     # skip some stuff
     50     {
     51       var colon/eax: byte <- read-byte line  # skip ':'
     52     }
     53     skip-chars-matching-whitespace line
     54     # now check the rest of the line
     55     var valid?/eax: boolean <- valid? pos1, pos2, letter, line
     56     compare valid?, 0/false
     57     {
     58       break-if-=
     59       print-string 0, "valid!\n"
     60       valid-password-count <- increment
     61     }
     62     loop
     63   }
     64   print-int32-decimal 0, valid-password-count
     65   print-string 0, "\n"
     66   return 0
     67 }
     68
     69 # ideally password would be a random-access array
     70 # we'll just track an index
     71 # one benefit: we can easily start at 1
     72 fn valid? pos1: int, pos2: int, letter: byte, password: (addr stream byte) -> _/eax: boolean {
     73   var i/esi: int <- copy 1
     74   var letter-count/edi: int <- copy 0
     75   # while password stream isn't empty
     76   #   c = read byte from password
     77   #   if (c == letter)
     78   #     if (i == pos1)
     79   #       ++letter-count
     80   #     if (i == pos2)
     81   #       ++letter-count
     82   #     ++i
     83   {
     84 #?     print-string 0, "  "
     85 #?     print-int32-decimal 0, i
     86 #?     print-string 0, "\n"
     87     var done?/eax: boolean <- stream-empty? password
     88     compare done?, 0/false
     89     break-if-!=
     90     var c/eax: byte <- read-byte password
     91 #?     {
     92 #?       var c2/eax: int <- copy c
     93 #?       print-int32-decimal 0, c2
     94 #?       print-string 0, "\n"
     95 #?     }
     96     compare c, letter
     97     {
     98       break-if-!=
     99       compare i, pos1
    100       {
    101         break-if-!=
    102         letter-count <- increment
    103 #?         print-string 0, "  hit\n"
    104       }
    105       compare i, pos2
    106       {
    107         break-if-!=
    108         letter-count <- increment
    109 #?         print-string 0, "  hit\n"
    110       }
    111     }
    112     i <- increment
    113     loop
    114   }
    115   # return (letter-count == 1)
    116   compare letter-count, 1
    117   {
    118     break-if-!=
    119     return 1/true
    120   }
    121   return 0/false
    122 }