97 lines
2.4 KiB
Chapel
97 lines
2.4 KiB
Chapel
|
use IO, List;
|
||
|
|
||
|
var modulus = 1;
|
||
|
|
||
|
record DivByThree {
|
||
|
var underlying: int;
|
||
|
operator +(lhs: DivByThree, rhs: DivByThree) {
|
||
|
return new DivByThree((lhs.underlying + rhs.underlying) / 3);
|
||
|
}
|
||
|
operator *(lhs: DivByThree, rhs: DivByThree) {
|
||
|
return new DivByThree((lhs.underlying * rhs.underlying) / 3);
|
||
|
}
|
||
|
proc divBy(x: int) return underlying % x == 0;
|
||
|
}
|
||
|
|
||
|
record Modulo {
|
||
|
var underlying: int;
|
||
|
|
||
|
operator +(lhs: Modulo, rhs: Modulo) {
|
||
|
return new Modulo((lhs.underlying + rhs.underlying) % modulus);
|
||
|
}
|
||
|
operator *(lhs: Modulo, rhs: Modulo) {
|
||
|
return new Modulo((lhs.underlying * rhs.underlying) % modulus);
|
||
|
}
|
||
|
proc divBy(x: int) return underlying % x == 0;
|
||
|
}
|
||
|
|
||
|
config type numtype = DivByThree;
|
||
|
config const steps = 20;
|
||
|
|
||
|
class Op {
|
||
|
proc apply(x: ?t) return x;
|
||
|
}
|
||
|
|
||
|
class SquareOp : Op {
|
||
|
override proc apply(x) return x * x;
|
||
|
}
|
||
|
|
||
|
class AddOp : Op {
|
||
|
var toAdd;
|
||
|
override proc apply(x) return x + toAdd;
|
||
|
}
|
||
|
|
||
|
class MulOp : Op {
|
||
|
var toMul;
|
||
|
override proc apply(x) return x * toMul;
|
||
|
}
|
||
|
|
||
|
proc parse(op: string): owned Op {
|
||
|
if op == "old * old" then return new SquareOp();
|
||
|
if op.startsWith("old + ") then return new AddOp(new numtype(op[6..] : int));
|
||
|
return new MulOp(new numtype(op[6..] : int));
|
||
|
}
|
||
|
|
||
|
record Monkey {
|
||
|
var op : owned Op;
|
||
|
var divBy, ifTrue, ifFalse : int;
|
||
|
var items: list(numtype);
|
||
|
var count: int = 0;
|
||
|
|
||
|
iter tossItems() {
|
||
|
while !items.isEmpty() {
|
||
|
var item = items.pop(0);
|
||
|
var changed = op.apply(item);
|
||
|
var nextIdx = if changed.divBy(divBy) then ifTrue else ifFalse;
|
||
|
count += 1;
|
||
|
yield (changed, nextIdx);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var monkeys = new list(Monkey);
|
||
|
var line: string;
|
||
|
while readLine(line) {
|
||
|
proc toNum(x: string) return new numtype(x : int);
|
||
|
readLine(line, stripNewline=true);
|
||
|
var items = new list(toNum(line[" Starting items: ".size..].split(", ")));
|
||
|
readLine(line, stripNewline=true);
|
||
|
var op = parse(line[" Operation: new = ".size..]);
|
||
|
var divBy, ifTrue, ifFalse: int;
|
||
|
readf(" Test: divisible by %i\n", divBy);
|
||
|
readf(" If true: throw to monkey %i\n", ifTrue);
|
||
|
readf(" If false: throw to monkey %i\n", ifFalse);
|
||
|
monkeys.append(new Monkey(op, divBy, ifTrue, ifFalse, items));
|
||
|
modulus *= divBy;
|
||
|
if (!readln()) then break;
|
||
|
}
|
||
|
|
||
|
for 1..steps {
|
||
|
for monkey in monkeys {
|
||
|
for (item, nextIdx) in monkey.tossItems() {
|
||
|
monkeys[nextIdx].items.append(item);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
writeln(monkeys.these().count);
|