advent2022

Advent of Code 2022 Solutions
git clone https://todayiwilllaunchmyinfantsonintoorbit.com/advent2022.git
Log | Files | Refs

eleven.a68 (8289B)


      1 MODE MONKEY = STRUCT(REF FLEX[]INT items,
      2                      PROC(INT,INT)INT worry function,
      3                      INT worry value,
      4                      INT throw divisor,
      5                      INT true monkey,
      6                      INT false monkey);
      7 
      8 CO Allow us to add more monkeys to our monkeys CO
      9 OP +:= = (REF FLEX[]MONKEY list, REF REF MONKEY new) VOID:
     10 BEGIN
     11    INT upb := UPB list;
     12    REF FLEX[]MONKEY new list := HEAP FLEX[0 : upb + 1]MONKEY;
     13    (new list[0:upb] := list[0:upb], new list[upb + 1] := new);
     14    list := new list
     15 END;
     16 
     17 CO append int to flex list CO
     18 OP +:= = (REF FLEX []INT list, INT new) VOID:
     19 BEGIN
     20    INT lwb := LWB list;
     21    INT upb := UPB list;
     22    REF FLEX[]INT new list := HEAP FLEX[lwb : upb + 1]INT;
     23    (new list[lwb:upb] := list[lwb:upb], new list[upb + 1] := new);
     24    list := new list
     25 END;
     26 
     27 PROC (INT,INT)INT add worry = (INT addend, INT old)INT: (old + addend);
     28 
     29 PROC (INT,INT)INT multiply worry = (INT multiplicand, INT old)INT: (old * multiplicand);
     30 
     31 PROC (INT,INT)INT square worry = (INT ignore, INT old)INT: (old**2);
     32 
     33 PROC REF FLEX[]MONKEY read monkeys = REF FLEX[]MONKEY:
     34 BEGIN
     35    PROC (STRING)INT parse integer = (STRING str)INT:
     36    BEGIN
     37       INT int := 0;
     38       FOR idx FROM LWB str TO UPB str
     39       DO
     40          int := (int * 10) + (ABS str[idx] - 48)
     41       OD;
     42       int
     43    END;
     44    
     45    FILE puzzle input;
     46    REF FLEX[]MONKEY monkeys = HEAP FLEX[0:-1]MONKEY;
     47 
     48    IF open(puzzle input, "input", stand in channel)/=0
     49    THEN
     50       print(("Can't open input for read", newline))
     51    FI;
     52 
     53    INT monkey index;
     54    REF MONKEY new monkey;
     55    on logical file end(puzzle input, (REF FILE file) BOOL: GOTO done);
     56    DO
     57       STRING line;
     58 
     59       get(puzzle input, (line, newline));
     60 
     61       IF line = "" THEN BEGIN
     62          monkeys +:= new monkey;
     63       END
     64       ELIF line[1:6] = "Monkey"
     65       THEN BEGIN
     66          new monkey := HEAP MONKEY;
     67          monkey index := parse integer(line[8:UPB line - 1])
     68       END
     69       ELIF line[3:17] = "Starting items:"
     70       THEN BEGIN
     71          PROC (STRING)INT find comma := (STRING input)INT:
     72          BEGIN
     73             INT index := 1;
     74             WHILE (index < UPB input) AND (input[index] /= ",") DO
     75                index +:= 1
     76             OD;
     77             index                                                 
     78          END;
     79          STRING starting items := line[19:UPB line];
     80          REF FLEX[]INT items := HEAP FLEX[1:0]INT;
     81          INT comma index := 1;
     82          WHILE comma index <= UPB starting items
     83          DO
     84             comma index := find comma(starting items);
     85             IF comma index < UPB starting items
     86             THEN BEGIN
     87                INT item value := parse integer(starting items[1:comma index - 1]);
     88                items +:= item value;
     89                starting items := starting items[comma index + 2:UPB starting items]
     90             END
     91             ELSE BEGIN
     92                INT item value := parse integer(starting items[1:UPB starting items]);
     93                items +:= item value;
     94                starting items := "";
     95             END
     96             FI
     97          OD;
     98          IF UPB starting items > 1 THEN BEGIN
     99             INT item value := parse integer(starting items);
    100             items +:= item value
    101          END
    102          FI;
    103          items OF new monkey := items
    104       END
    105       ELIF line[3:12] = "Operation:"
    106       THEN BEGIN
    107          STRING expression = line[14:UPB line];
    108          CHAR op = expression[11];
    109          worry function OF new monkey :=
    110             IF expression[11:UPB expression] = "* old" THEN
    111                worry value OF new monkey := 0;
    112                square worry
    113             ELSE
    114                worry value OF new monkey := parse integer(expression[13:UPB expression]);
    115                (op = "+" | add worry | multiply worry)
    116             FI
    117       END
    118       ELIF line[3:7] = "Test:"
    119       THEN BEGIN
    120          STRING test = line[9:UPB line];
    121          throw divisor OF new monkey := parse integer(test[14:UPB test]);
    122          get(puzzle input, (line, newline));
    123          STRING true clause := line[14:UPB line];
    124          true monkey OF new monkey := parse integer(true clause[17:UPB true clause]);
    125          get(puzzle input, (line, newline));
    126          STRING false clause := line[15:UPB line];
    127          false monkey OF new monkey := parse integer(false clause[17:UPB false clause])
    128       END
    129       FI
    130    OD;
    131    done: monkeys +:= new monkey; CO Save last monkey CO
    132    close(puzzle input);
    133    monkeys
    134 END;
    135 
    136 PROC ([]INT)INT list length = ([]INT list)INT:
    137 BEGIN
    138    ((UPB list - LWB list) + 1)
    139 END;
    140                          
    141 PROC (REF []INT, REF []INT)REF []INT merge lists = (REF []INT left, REF []INT right)REF []INT:
    142 BEGIN
    143    INT total length := list length(left) + list length(right);
    144    REF FLEX[]INT merged := HEAP [1:total length]INT;
    145    INT left index := LWB left;
    146    INT right index := LWB right;
    147    INT merged index := 1;
    148    WHILE (left index <= UPB left) AND (right index <= UPB right) DO
    149       IF left[left index] >= right[right index] THEN
    150       BEGIN
    151          merged[merged index] := left[left index];
    152          left index := left index + 1;
    153       END
    154       ELSE BEGIN
    155          merged[merged index] := right[right index];
    156          right index := right index + 1;
    157       END
    158       FI;
    159       merged index := merged index + 1
    160    OD;
    161    IF left index <= UPB left THEN
    162       merged[merged index:UPB merged] := left[left index:UPB left]
    163    ELIF right index <= UPB right THEN
    164       merged[merged index:UPB merged] := right[right index:UPB left]
    165    FI;
    166    merged
    167 END;
    168                          
    169 PROC (REF []INT)REF []INT sort integer list = (REF []INT list)REF []INT:
    170 BEGIN
    171    INT length = list length(list);
    172    IF length <= 1 THEN
    173       list
    174    ELSE
    175       INT mid := ((length % 2) + LWB list);
    176       merge lists(sort integer list(list[LWB list:mid - 1]), sort integer list(list[mid:UPB list]))
    177    FI
    178 END;
    179 
    180 BEGIN
    181    []MONKEY monkeys = read monkeys();
    182    REF []INT inspections = LOC [0:UPB monkeys]INT;
    183    FOR iterations FROM 1 TO 20
    184    DO
    185       FOR monkey index FROM 0 TO UPB monkeys
    186       DO
    187          MONKEY monkey := monkeys[monkey index];           
    188          REF FLEX[]INT items = items OF monkey;
    189          IF iterations = 1 THEN
    190             inspections[monkey index] := 0
    191          FI;
    192          IF UPB items >= LWB items THEN
    193          BEGIN
    194             FOR item index FROM LWB items TO UPB items
    195             DO
    196                inspections[monkey index] := inspections[monkey index] + 1;
    197                INT worry value := (worry function OF monkey)(worry value OF monkey, items[item index]) % 3;
    198                INT throw target := ((worry value MOD throw divisor OF monkey) = 0 | true monkey OF monkey | false monkey OF monkey);
    199                items OF monkeys[throw target] +:= worry value;
    200             OD;
    201             items OF (monkeys[monkey index]) := HEAP FLEX[1:0]INT
    202          END
    203          FI
    204       OD
    205    OD;
    206 
    207    [1:UPB monkeys + 1]INT sorted := sort integer list(inspections);
    208    print(("Monkey business (star 1): ", sorted[1] * sorted[2], new line));
    209 
    210    []MONKEY monkeys again = read monkeys(); CO Reread because we're lazy CO
    211    INT throw divisor := 1;
    212    FOR i FROM 0 TO UPB monkeys again
    213    DO
    214       throw divisor := throw divisor * throw divisor OF monkeys again[i]
    215    OD;
    216    FOR iterations FROM 1 TO 10000
    217    DO
    218       FOR monkey index FROM 0 TO UPB monkeys again
    219       DO
    220          MONKEY monkey := monkeys again[monkey index];           
    221          REF FLEX[]INT items = items OF monkey;
    222          IF iterations = 1 THEN
    223             inspections[monkey index] := 0
    224          FI;
    225          IF UPB items >= LWB items THEN
    226          BEGIN
    227             FOR item index FROM LWB items TO UPB items
    228             DO
    229                inspections[monkey index] := inspections[monkey index] + 1;
    230                INT worry value := (worry function OF monkey)(worry value OF monkey, items[item index]);
    231                INT throw target := ((worry value MOD throw divisor OF monkey) = 0 | true monkey OF monkey | false monkey OF monkey);
    232                items OF monkeys again[throw target] +:= worry value MOD throw divisor;
    233             OD;
    234             items OF (monkeys again[monkey index]) := HEAP FLEX[1:0]INT
    235          END
    236          FI
    237       OD;
    238    OD;
    239 
    240    sorted := sort integer list(inspections);
    241    print(("Monkey business (star 2): ", sorted[1] * sorted[2], new line));
    242 END