this repo has no description
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

ft: add day 11.2022

+279
+279
2022/day11.livemd
··· 1 + <!-- livebook:{"persist_outputs":true} --> 2 + 3 + # Day 11 4 + 5 + ```elixir 6 + Mix.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"},"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 34 + defmodule 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 105 + end 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 115 + monkeys = 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 193 + defmodule 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 r, 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.reduce(&*/2) 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)) 236 + end 237 + ``` 238 + 239 + <!-- livebook:{"output":true} --> 240 + 241 + ``` 242 + warning: variable "r" is unused (if the variable is not meant to be used, prefix it with an underscore) 243 + 2022/day11.livemd#cell:wtmu5fny2ud5f5f6xet6khgysonm2y3n:17: MonkeyBusiness.run/3 244 + 245 + ``` 246 + 247 + <!-- livebook:{"output":true} --> 248 + 249 + ``` 250 + {:module, MonkeyBusiness, <<70, 79, 82, 49, 0, 0, 21, ...>>, {:lcm, 2}} 251 + ``` 252 + 253 + ## Task 1 254 + 255 + ```elixir 256 + monkeys 257 + |> MonkeyBusiness.new() 258 + |> MonkeyBusiness.run(20, 3) 259 + ``` 260 + 261 + <!-- livebook:{"output":true} --> 262 + 263 + ``` 264 + 78678 265 + ``` 266 + 267 + ## Task 2 268 + 269 + ```elixir 270 + monkeys 271 + |> MonkeyBusiness.new() 272 + |> MonkeyBusiness.run(10000, 1) 273 + ``` 274 + 275 + <!-- livebook:{"output":true} --> 276 + 277 + ``` 278 + 15333249714 279 + ```