diff --git a/day11.chpl b/day11.chpl new file mode 100644 index 0000000..93923c9 --- /dev/null +++ b/day11.chpl @@ -0,0 +1,96 @@ +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); diff --git a/day11.cr b/day11.cr new file mode 100644 index 0000000..3310b2d --- /dev/null +++ b/day11.cr @@ -0,0 +1,58 @@ +require "advent" +require "big" + +class Monkey + property items : Array(Int64) + property op : String + property divBy : Int64 + property ifTrue : Int64 + property ifFalse : Int64 + + def initialize(@items, @op, @divBy, @ifTrue, @ifFalse) + end +end + +INSTS = { + "*" => ->(x: Int64, y: Int64) { x * y }, + "+" => ->(x: Int64, y: Int64) { x + y } +} + +def execute(inst, old, mod) + inst = inst.gsub("old", old.to_s); + l, op, r = inst.split(" ") + l = l.to_i64 % mod + r = r.to_i64 % mod + INSTS[op].call(l,r) +end + +monkeys = [] of Monkey +input(2022, 11).split("\n\n").each do |it| + it = it.lines + items = it[1].split(": ")[1].split(", ").map(&.to_i64).reverse + op = it[2].split("Operation: new = ")[1] + divBy = it[3].split("Test: divisible by ")[1].to_i64 + ifTrue = it[4].split(" If true: throw to monkey ")[1].to_i64 + ifFalse = it[5].split(" If false: throw to monkey ")[1].to_i64 + monkeys << Monkey.new(items, op, divBy, ifTrue, ifFalse) +end + +counts = [0] * monkeys.size +modulus = monkeys.map(&.divBy).product +10000.times do + monkeys.each_with_index do |m, i| + while !m.items.empty? + counts[i] += 1 + item = m.items.pop + item = execute(m.op, item, modulus) + item = item % modulus + if item % m.divBy == 0 + monkeys[m.ifTrue].items.insert(0, item) + else + monkeys[m.ifFalse].items.insert(0, item) + end + end + end +end + +counts.sort! +puts counts[-1].to_big_i * counts[-2].to_big_i