diff options
| author | An0nSaiko <porfeas12@gmail.com> | 2022-12-12 05:24:54 +0200 |
|---|---|---|
| committer | An0nSaiko <porfeas12@gmail.com> | 2022-12-12 05:24:54 +0200 |
| commit | 5604051de7cdc23bbb03121c97ae77f7b3a066aa (patch) | |
| tree | 8723e69be21aee6e29d45e6605c83192bf3f8b37 | |
| parent | Day 11 (diff) | |
| download | aoc22-5604051de7cdc23bbb03121c97ae77f7b3a066aa.tar.gz aoc22-5604051de7cdc23bbb03121c97ae77f7b3a066aa.zip | |
Day 11
| -rw-r--r-- | day11/example.txt | 27 | ||||
| -rw-r--r-- | day11/solution.nim | 108 |
2 files changed, 135 insertions, 0 deletions
diff --git a/day11/example.txt b/day11/example.txt new file mode 100644 index 0000000..30e09e5 --- /dev/null +++ b/day11/example.txt | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | Monkey 0: | ||
| 2 | Starting items: 79, 98 | ||
| 3 | Operation: new = old * 19 | ||
| 4 | Test: divisible by 23 | ||
| 5 | If true: throw to monkey 2 | ||
| 6 | If false: throw to monkey 3 | ||
| 7 | |||
| 8 | Monkey 1: | ||
| 9 | Starting items: 54, 65, 75, 74 | ||
| 10 | Operation: new = old + 6 | ||
| 11 | Test: divisible by 19 | ||
| 12 | If true: throw to monkey 2 | ||
| 13 | If false: throw to monkey 0 | ||
| 14 | |||
| 15 | Monkey 2: | ||
| 16 | Starting items: 79, 60, 97 | ||
| 17 | Operation: new = old * old | ||
| 18 | Test: divisible by 13 | ||
| 19 | If true: throw to monkey 1 | ||
| 20 | If false: throw to monkey 3 | ||
| 21 | |||
| 22 | Monkey 3: | ||
| 23 | Starting items: 74 | ||
| 24 | Operation: new = old + 3 | ||
| 25 | Test: divisible by 17 | ||
| 26 | If true: throw to monkey 0 | ||
| 27 | If false: throw to monkey 1 | ||
diff --git a/day11/solution.nim b/day11/solution.nim index e69de29..3ff61e5 100644 --- a/day11/solution.nim +++ b/day11/solution.nim | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | import strutils | ||
| 2 | import sequtils | ||
| 3 | import algorithm | ||
| 4 | import sugar | ||
| 5 | import re | ||
| 6 | |||
| 7 | type | ||
| 8 | Operation = tuple | ||
| 9 | operator: char | ||
| 10 | operand: int64 | ||
| 11 | |||
| 12 | Monkey = tuple | ||
| 13 | items: seq[int64] | ||
| 14 | operation: Operation | ||
| 15 | test: int64 | ||
| 16 | success: int | ||
| 17 | failure: int | ||
| 18 | score: int64 | ||
| 19 | |||
| 20 | func parseFile(content: string): seq[Monkey] = | ||
| 21 | let monkeysStr = content.split("\n\n") | ||
| 22 | |||
| 23 | for monkeyStr in monkeysStr: | ||
| 24 | let tokens = monkeyStr.splitLines() | ||
| 25 | # list of numbers eg: [5, 13, 45] | ||
| 26 | let items = map(tokens[1].replace(re"[^0-9\,]").split(","), (snum) => int64(snum.parseInt())) | ||
| 27 | # operator followed by operand eg: "+6" | ||
| 28 | let operationStr = tokens[2].replace(re"[^0-9\+\-\*]") | ||
| 29 | var operation: Operation | ||
| 30 | try: | ||
| 31 | operation = (operationStr[0], int64(operationStr[1 .. ^1].parseInt())) | ||
| 32 | except: | ||
| 33 | operation = (operationStr[0], int64(0)) | ||
| 34 | # test number eg: 13 | ||
| 35 | let test = tokens[3].replace(re"[^0-9]").parseInt() | ||
| 36 | # divisor number eg: 3 | ||
| 37 | let success = tokens[4].replace(re"[^0-9]").parseInt() | ||
| 38 | let failure = tokens[5].replace(re"[^0-9]").parseInt() | ||
| 39 | |||
| 40 | result.add((items, operation, int64(test), success, failure, int64(0))) | ||
| 41 | |||
| 42 | var LCM: int64 | ||
| 43 | var part2 = false | ||
| 44 | proc calc(item: int64, op: Operation): int64 = | ||
| 45 | var operation = op | ||
| 46 | if operation.operand == 0: | ||
| 47 | operation.operand = item | ||
| 48 | |||
| 49 | case operation.operator: | ||
| 50 | of '+': | ||
| 51 | result = item + operation.operand | ||
| 52 | of '-': | ||
| 53 | result = item - operation.operand | ||
| 54 | of '*': | ||
| 55 | result = item * operation.operand | ||
| 56 | else: | ||
| 57 | assert(false) | ||
| 58 | |||
| 59 | if part2: | ||
| 60 | result = result mod LCM | ||
| 61 | |||
| 62 | proc doRound(monkeys: var seq[Monkey]): void = | ||
| 63 | for monkey in monkeys.mitems(): | ||
| 64 | for item in monkey.items: | ||
| 65 | var nextItem: int64 | ||
| 66 | if not part2: | ||
| 67 | nextItem = calc(item, monkey.operation) div 3 | ||
| 68 | else: | ||
| 69 | nextItem = calc(item, monkey.operation) | ||
| 70 | monkey.score += 1 | ||
| 71 | if nextItem mod monkey.test == 0: | ||
| 72 | monkeys[monkey.success].items.add(nextItem) | ||
| 73 | else: | ||
| 74 | monkeys[monkey.failure].items.add(nextItem) | ||
| 75 | monkey.items = @[] | ||
| 76 | |||
| 77 | proc emulate(monkeys: seq[Monkey], rounds: int, part2 = false): int64 = | ||
| 78 | var monkeys = monkeys | ||
| 79 | for round in 1 .. rounds: | ||
| 80 | doRound(monkeys) | ||
| 81 | |||
| 82 | monkeys.sort((lhs, rhs) => lhs.score < rhs.score) | ||
| 83 | let best = map(monkeys, (monkey) => monkey.score)[0..<2] | ||
| 84 | best[0] * best[1] | ||
| 85 | |||
| 86 | func gcd(a, b: int64): int64 = | ||
| 87 | var | ||
| 88 | a = a | ||
| 89 | b = b | ||
| 90 | if a < b: | ||
| 91 | swap(a, b) | ||
| 92 | |||
| 93 | while a != 0 and b != 0: | ||
| 94 | let r = a mod b | ||
| 95 | a = b | ||
| 96 | b = r | ||
| 97 | return a | ||
| 98 | |||
| 99 | let content = readFile("./input.txt").strip() | ||
| 100 | let monkeys = parseFile(content) | ||
| 101 | |||
| 102 | LCM = monkeys[0].test | ||
| 103 | for monkey in monkeys: | ||
| 104 | LCM = monkey.test div gcd(LCM, monkey.test) * LCM | ||
| 105 | |||
| 106 | echo emulate(monkeys, 20) | ||
| 107 | part2 = true | ||
| 108 | echo emulate(monkeys, 10_000, true) | ||
