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