this repo has no description
at master 6.7 kB view raw
1<!-- livebook:{"persist_outputs":true} --> 2 3# Day 11 4 5```elixir 6Mix.install([ 7 {:kino_aoc, git: "https://github.com/ljgago/kino_aoc"} 8]) 9``` 10 11<!-- livebook:{"output":true} --> 12 13``` 14:ok 15``` 16 17## Section 18 19<!-- livebook:{"attrs":{"day":"11","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} --> 20 21```elixir 22{:ok, puzzle_input} = 23 KinoAOC.download_puzzle("2022", "11", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) 24``` 25 26<!-- livebook:{"output":true} --> 27 28``` 29{:ok, 30 "Monkey 0:\n Starting items: 93, 98\n Operation: new = old * 17\n Test: divisible by 19\n If true: throw to monkey 5\n If false: throw to monkey 3\n\nMonkey 1:\n Starting items: 95, 72, 98, 82, 86\n Operation: new = old + 5\n Test: divisible by 13\n If true: throw to monkey 7\n If false: throw to monkey 6\n\nMonkey 2:\n Starting items: 85, 62, 82, 86, 70, 65, 83, 76\n Operation: new = old + 8\n Test: divisible by 5\n If true: throw to monkey 3\n If false: throw to monkey 0\n\nMonkey 3:\n Starting items: 86, 70, 71, 56\n Operation: new = old + 1\n Test: divisible by 7\n If true: throw to monkey 4\n If false: throw to monkey 5\n\nMonkey 4:\n Starting items: 77, 71, 86, 52, 81, 67\n Operation: new = old + 4\n Test: divisible by 17\n If true: throw to monkey 1\n If false: throw to monkey 6\n\nMonkey 5:\n Starting items: 89, 87, 60, 78, 54, 77, 98\n Operation: new = old * 7\n Test: divisible by 2\n If true: throw to monkey 1\n If false: throw to monkey 4\n\nMonkey 6:\n Starting items: 69, 65, 63\n Operation: new = old + 6\n Test: divisible by 3\n If true: throw to monkey 7\n If false: throw to monkey 2\n\nMonkey 7:\n Starting items: 89\n Operation: new = old * old\n Test: divisible by 11\n If true: throw to monkey 0\n If false: throw to monkey 2\n"} 31``` 32 33```elixir 34defmodule Monkey do 35 defstruct items: [], 36 operation: &Function.identity/1, 37 test: nil, 38 true: nil, 39 false: nil, 40 passes: 0 41 42 def parse(input) do 43 [ 44 _, 45 "Starting items: " <> items, 46 "Operation: new = old " <> operation, 47 "Test: divisible by " <> test, 48 "If true: throw to monkey " <> if_true, 49 "If false: throw to monkey " <> if_false 50 ] = 51 input 52 |> String.split("\n", trim: true) 53 |> Enum.map(&String.trim/1) 54 55 %__MODULE__{ 56 items: parse_items(items), 57 operation: parse_operation(operation), 58 test: String.to_integer(test), 59 true: String.to_integer(if_true), 60 false: String.to_integer(if_false) 61 } 62 end 63 64 def run(%__MODULE__{} = monkey, calming, lcm \\ 1) do 65 {true_val, false_val} = 66 monkey.items 67 |> Enum.map(fn item -> 68 item 69 |> then(monkey.operation) 70 |> div(calming) 71 |> rem(lcm) 72 end) 73 |> Enum.split_with(fn item -> 74 rem(item, monkey.test) == 0 75 end) 76 77 {struct(monkey, passes: monkey.passes + length(monkey.items), items: []), 78 {monkey.true, true_val}, {monkey.false, false_val}} 79 end 80 81 def add_items(%__MODULE__{} = monkey, new_items) do 82 struct(monkey, items: monkey.items ++ new_items) 83 end 84 85 defp parse_items(items) do 86 items 87 |> String.split(", ") 88 |> Enum.map(&String.to_integer/1) 89 end 90 91 defp parse_operation("* old"), 92 do: fn old -> old * old end 93 94 defp parse_operation("* " <> num) do 95 num = String.to_integer(num) 96 97 fn old -> old * num end 98 end 99 100 defp parse_operation("+ " <> num) do 101 num = String.to_integer(num) 102 103 fn old -> old + num end 104 end 105end 106``` 107 108<!-- livebook:{"output":true} --> 109 110``` 111{:module, Monkey, <<70, 79, 82, 49, 0, 0, 24, ...>>, {:parse_operation, 1}} 112``` 113 114```elixir 115monkeys = 116 puzzle_input 117 |> String.split("\n\n") 118 |> Enum.map(&Monkey.parse/1) 119``` 120 121<!-- livebook:{"output":true} --> 122 123``` 124[ 125 %Monkey{ 126 items: ']b', 127 operation: #Function<3.112681941/1 in Monkey.parse_operation/1>, 128 test: 19, 129 true: 5, 130 false: 3, 131 passes: 0 132 }, 133 %Monkey{ 134 items: '_HbRV', 135 operation: #Function<1.112681941/1 in Monkey.parse_operation/1>, 136 test: 13, 137 true: 7, 138 false: 6, 139 passes: 0 140 }, 141 %Monkey{ 142 items: 'U>RVFASL', 143 operation: #Function<1.112681941/1 in Monkey.parse_operation/1>, 144 test: 5, 145 true: 3, 146 false: 0, 147 passes: 0 148 }, 149 %Monkey{ 150 items: 'VFG8', 151 operation: #Function<1.112681941/1 in Monkey.parse_operation/1>, 152 test: 7, 153 true: 4, 154 false: 5, 155 passes: 0 156 }, 157 %Monkey{ 158 items: 'MGV4QC', 159 operation: #Function<1.112681941/1 in Monkey.parse_operation/1>, 160 test: 17, 161 true: 1, 162 false: 6, 163 passes: 0 164 }, 165 %Monkey{ 166 items: 'YW<N6Mb', 167 operation: #Function<3.112681941/1 in Monkey.parse_operation/1>, 168 test: 2, 169 true: 1, 170 false: 4, 171 passes: 0 172 }, 173 %Monkey{ 174 items: 'EA?', 175 operation: #Function<1.112681941/1 in Monkey.parse_operation/1>, 176 test: 3, 177 true: 7, 178 false: 2, 179 passes: 0 180 }, 181 %Monkey{ 182 items: 'Y', 183 operation: #Function<2.112681941/1 in Monkey.parse_operation/1>, 184 test: 11, 185 true: 0, 186 false: 2, 187 passes: 0 188 } 189] 190``` 191 192```elixir 193defmodule MonkeyBusiness do 194 import Kernel, except: [round: 1] 195 196 defstruct monkeys: [], lcm: nil 197 198 def new(monkeys) do 199 lcm = Enum.reduce(monkeys, 1, &lcm(&1.test, &2)) 200 201 %__MODULE__{ 202 monkeys: monkeys, 203 lcm: lcm 204 } 205 end 206 207 def run(%__MODULE__{} = mb, rounds, calming) do 208 1..rounds 209 |> Enum.reduce(mb, fn _, mb -> 210 # IO.inspect(r, label: :round) 211 round(mb, calming) 212 end) 213 |> Map.get(:monkeys) 214 |> Enum.map(& &1.passes) 215 |> Enum.sort(:desc) 216 |> Enum.take(2) 217 |> Enum.product() 218 end 219 220 defp round(%__MODULE__{} = mb, calming) do 221 0..(length(mb.monkeys) - 1) 222 |> Enum.reduce(mb, fn idx, mb -> 223 {monkey, {a, a_val}, {b, b_val}} = 224 mb.monkeys 225 |> Enum.at(idx) 226 |> Monkey.run(calming, mb.lcm) 227 228 mb 229 |> put_in([Access.key(:monkeys), Access.at(idx)], monkey) 230 |> update_in([Access.key(:monkeys), Access.at(a)], &Monkey.add_items(&1, a_val)) 231 |> update_in([Access.key(:monkeys), Access.at(b)], &Monkey.add_items(&1, b_val)) 232 end) 233 end 234 235 defp lcm(a, b), do: div(a * b, Integer.gcd(a, b)) 236end 237``` 238 239<!-- livebook:{"output":true} --> 240 241``` 242{:module, MonkeyBusiness, <<70, 79, 82, 49, 0, 0, 20, ...>>, {:lcm, 2}} 243``` 244 245## Task 1 246 247```elixir 248monkeys 249|> MonkeyBusiness.new() 250|> MonkeyBusiness.run(20, 3) 251``` 252 253<!-- livebook:{"output":true} --> 254 255``` 25678678 257``` 258 259## Task 2 260 261```elixir 262monkeys 263|> MonkeyBusiness.new() 264|> MonkeyBusiness.run(10000, 1) 265``` 266 267<!-- livebook:{"output":true} --> 268 269``` 27015333249714 271```