From b378808cda4fc542977e827c43f5cfd9f3a42f74 Mon Sep 17 00:00:00 2001 From: Sven Weidauer Date: Sun, 11 Dec 2022 11:20:08 +0100 Subject: [PATCH] 2022 Day 11 part 1 --- 2022/day11.swift | 136 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 2022/day11.swift diff --git a/2022/day11.swift b/2022/day11.swift new file mode 100644 index 0000000..1d661de --- /dev/null +++ b/2022/day11.swift @@ -0,0 +1,136 @@ +import Foundation + +typealias Item = Int + +class Monkey { + var items: [Item] + var operation: Operation + var operand: Operand + var test: Int + var trueTarget: Int + var falseTarget: Int + var inspectCount = 0 + + init(items: [Item], operation: Operation, operand: Operand, test: Int, trueTarget: Int, falseTarget: Int) { + self.items = items + self.operation = operation + self.operand = operand + self.test = test + self.trueTarget = trueTarget + self.falseTarget = falseTarget + } + + func run() { + for item in items { + inspectCount += 1 + let newLevel = operation.apply(item, operand.value(item: item)) / 3 + let target = newLevel.isMultiple(of: test) ? trueTarget : falseTarget + monkeys[target].add(newLevel) + } + items.removeAll() + } + + func add(_ item: Item) { + items.append(item) + } +} + +extension Monkey { + convenience init?(scanner: Scanner) { + guard scanner.scanString("Monkey") != nil, scanner.scanInt() != nil, scanner.scanString(":") != nil else { + return nil + } + + guard scanner.scanString("Starting items:") != nil else { return nil } + let items = scanner.scanList().map(Item.init(_:)) + + guard scanner.scanString("Operation: new = old") != nil, let operation = scanner.scanOperation(), let operand = scanner.scanOperand() else { return nil } + + guard scanner.scanString("Test: divisible by") != nil, let test = scanner.scanInt() else { return nil } + guard scanner.scanString("If true: throw to monkey") != nil, let trueTarget = scanner.scanInt() else { return nil } + guard scanner.scanString("If false: throw to monkey") != nil, let falseTarget = scanner.scanInt() else { return nil } + + self.init(items: items, operation: operation, operand: operand, test: test, trueTarget: trueTarget, falseTarget: falseTarget) + } +} + + +enum Operation: String, CaseIterable { + case add = "+" + case multiply = "*" + + func apply(_ lhs: Item, _ rhs: Item) -> Item { + switch self { + case .add: return lhs + rhs + case .multiply: return lhs * rhs + } + } +} + +enum Operand { + case number(Int) + case old + + func value(item: Item) -> Item { + switch self { + case .number(let number): return Item(number) + case .old: return item + } + } +} + +extension Scanner { + func scanList() -> [Int] { + var result: [Int] = [] + while true { + guard let int = scanInt() else { + break + } + result.append(int) + guard scanString(",") != nil else { + break + } + } + return result + } + + func scanOperation() -> Operation? { + for op in Operation.allCases { + if scanString(op.rawValue) != nil { + return op + } + } + return nil + } + + func scanOperand() -> Operand? { + if let int = scanInt() { + return .number(int) + } + + if scanString("old") != nil { + return .old + } + + return nil + } +} + +let input = try String(contentsOf: URL(fileURLWithPath: "day11.input")) +let scanner = Scanner(string: input) +var monkeys: [Monkey] = [] + +while !scanner.isAtEnd, let monkey = Monkey(scanner: scanner) { + monkeys.append(monkey) +} + + +for _ in 0..<20 { + for monkey in monkeys { + monkey.run() + } +} + + +let monkeyBusiness = monkeys.map(\.inspectCount).sorted(by: >).prefix(2).reduce(1, *) +print("Part 1:", monkeyBusiness)