this repo has no description

Finish fight with day 05

hauleth.dev 95116d1f fceb5e95

verified
Changed files
+70 -319
2023
+1 -1
2023/day04.livemd
··· 196 196 10378710 197 197 ``` 198 198 199 - <!-- livebook:{"offset":11578,"stamp":{"token":"XCP.lXGe3Iu191OYuBQqrLXtyX10eAJRxaC7kWxJhXV-XwPuZXy80YHtfPI-uAobs5Ncg0KyodauGARY5zWPhVt6a96P5flHG1j0LHMDzRblFBObyqrIKaYaIlaYVVUXUtasrA","version":2}} --> 199 + <!-- livebook:{"offset":11578,"stamp":{"token":"XCP.MkFlr54HtUrLxNpCiRslp5uHY2WvhZ1VtV-O2Kmdgys3ejH3O0uJAEJe8o8FxytUQyFTMJeefRatVMyr9J3CU3x5R4g7Ie-s_vb0vC-AepFre8COUMkA6Ws70S_FqoCSbA","version":2}} -->
+69 -318
2023/day05.livemd
··· 3 3 # Day 05 4 4 5 5 ```elixir 6 - Mix.install([:kino_aoc, {:range_set, path: "../range_set"}]) 6 + Mix.install([:kino_aoc, {:range_set, github: "hauleth/range_set"}]) 7 7 ``` 8 8 9 9 ## Parse ··· 23 23 ``` 24 24 25 25 ```elixir 26 - puzzle_input = 27 - """ 28 - seeds: 79 14 55 13 26 + # puzzle_input = 27 + """ 28 + seeds: 79 14 55 13 29 29 30 - seed-to-soil map: 31 - 50 98 2 32 - 52 50 48 30 + seed-to-soil map: 31 + 50 98 2 32 + 52 50 48 33 33 34 - soil-to-fertilizer map: 35 - 0 15 37 36 - 37 52 2 37 - 39 0 15 34 + soil-to-fertilizer map: 35 + 0 15 37 36 + 37 52 2 37 + 39 0 15 38 38 39 - fertilizer-to-water map: 40 - 49 53 8 41 - 0 11 42 42 - 42 0 7 43 - 57 7 4 39 + fertilizer-to-water map: 40 + 49 53 8 41 + 0 11 42 42 + 42 0 7 43 + 57 7 4 44 44 45 - water-to-light map: 46 - 88 18 7 47 - 18 25 70 45 + water-to-light map: 46 + 88 18 7 47 + 18 25 70 48 48 49 - light-to-temperature map: 50 - 45 77 23 51 - 81 45 19 52 - 68 64 13 49 + light-to-temperature map: 50 + 45 77 23 51 + 81 45 19 52 + 68 64 13 53 53 54 - temperature-to-humidity map: 55 - 0 69 1 56 - 1 0 69 54 + temperature-to-humidity map: 55 + 0 69 1 56 + 1 0 69 57 57 58 - humidity-to-location map: 59 - 60 56 37 60 - 56 93 4 61 - """ 62 - |> String.trim() 58 + humidity-to-location map: 59 + 60 56 37 60 + 56 93 4 61 + """ 62 + |> String.trim() 63 63 ``` 64 64 65 65 <!-- livebook:{"output":true} --> ··· 72 72 defmodule Mapping do 73 73 @behaviour Access 74 74 75 + import Kernel, except: [apply: 2] 76 + 75 77 defstruct [:values] 76 78 77 79 def from_list(lst) do 78 - # true = Enum.all?(lst, fn {a, b} -> Range.size(a) == Range.size(b) end) 79 80 %__MODULE__{values: Enum.sort(lst)} 80 81 end 81 82 82 - def squash(%__MODULE__{values: from}, %__MODULE__{values: to}) do 83 - from_list(do_squash(from, to)) 84 - end 85 - 86 - defp do_squash([], rest), do: rest 87 - defp do_squash(rest, []), do: rest 88 - 89 - # a---b 90 - # c---d 91 - defp do_squash([{_src, a.._b} | _] = xs, [{_c..d, _out} = v | ys]) when d < a do 92 - [v | do_squash(xs, ys)] 93 - end 94 - 95 - # a---b 96 - # c---d 97 - defp do_squash([{_src, _a..b} = v | xs], [{c.._d, _out} | _] = ys) when b < c do 98 - [v | do_squash(xs, ys)] 99 - end 100 - 101 - # a---b 102 - # c---d 103 - defp do_squash([{src, range} | xs], [{range, out} | ys]) do 104 - [{src, out} | do_squash(xs, ys)] 105 - end 83 + defp apply({a.._, to}, v), do: v - a + to 106 84 107 - # a------b 108 - # c--d 109 - defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a <= c and b >= d do 110 - range_match(src, [ 111 - a..(c - 1), 112 - out, 113 - (d + 1)..b 114 - ]) 115 - |> Enum.concat(do_squash(xs, ys)) 85 + @impl Access 86 + def fetch(%__MODULE__{values: list}, key) when is_integer(key) do 87 + {:ok, sorted_find(list, key)} 116 88 end 117 89 118 - # a--b 119 - # c------d 120 - defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a >= c and b <= d do 121 - range_match( 122 - [ 123 - c..(a - 1), 124 - src, 125 - (b + 1)..d 126 - ], 127 - out 128 - ) 129 - |> Enum.concat(do_squash(xs, ys)) 90 + def fetch(%__MODULE__{values: map}, %RangeSet{ranges: ranges}) do 91 + ranges 92 + |> Enum.flat_map(&map_range(&1, map)) 93 + |> RangeSet.new() 94 + |> then(&{:ok, &1}) 130 95 end 131 96 132 - # a---b 133 - # c---d 134 - defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when c in a..b and b in c..d do 135 - {s1, s2} = Range.split(src, Range.size(a..c) - 1) 136 - {o1, o2} = Range.split(out, Range.size(c..b)) 97 + defp sorted_find([], n), do: n 98 + defp sorted_find([{a..b, _} = result | _], n) when n in a..b, do: apply(result, n) 99 + defp sorted_find([{a.._, _} | _], n) when n < a, do: n 100 + defp sorted_find([_ | rest], n), do: sorted_find(rest, n) 137 101 138 - [ 139 - {s1, a..(c - 1)}, 140 - {s2, o1}, 141 - {(b + 1)..d, o2} 142 - ] 143 - |> Enum.concat(do_squash(xs, ys)) 144 - end 102 + defp map_range(range, []), do: [range] 103 + defp map_range(_..hi = range, [{lo.._, _} | _]) when lo > hi, do: [range] 104 + defp map_range(lo.._ = range, [{_..hi, _} | rest]) when lo > hi, do: map_range(range, rest) 145 105 146 - # a---b 147 - # c---d 148 - defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a > c and b > d do 149 - IO.puts("foo") 150 - {of, ol} = Range.split(out, Range.size(c..a) - 1) 151 - {sf, sl} = Range.split(src, Range.size(a..d)) 106 + defp map_range(arg_range, [{fun_range, _} = fun_def | maps]) do 107 + fun_lo..fun_hi = fun_range 108 + arg_lo..arg_hi = arg_range 109 + lo = max(fun_lo, arg_lo) 110 + hi = min(fun_hi, arg_hi) 152 111 153 112 [ 154 - {c..(a - 1), of}, 155 - {sf, ol}, 156 - {sl, (d + 1)..b} 113 + apply(fun_def, lo)..apply(fun_def, hi) 114 + | if(hi < arg_hi, do: map_range((hi + 1)..arg_hi, maps), else: []) 157 115 ] 158 - |> Enum.concat(do_squash(xs, ys)) 159 - end 160 - 161 - defp range_match(list, a.._) when is_list(list) do 162 - Enum.reduce(list, {[], a}, fn 163 - _.._//1 = range, {acc, s} -> 164 - to = s + Range.size(range) - 1 165 - {[{range, s..to} | acc], to + 1} 166 - 167 - _, acc -> 168 - acc 169 - end) 170 - |> elem(0) 171 - end 172 - 173 - defp range_match(_.._ = range, list) when is_list(list) do 174 - for {a, b} <- range_match(list, range), do: {b, a} 175 - end 176 - 177 - @impl Access 178 - def fetch(%__MODULE__{values: list}, key) when is_integer(key) do 179 - val = 180 - with {a.._, b.._} <- Enum.find(list, key, fn {range, _} -> key in range end) do 181 - key - a + b 182 - end 183 - 184 - {:ok, val} 185 116 end 186 117 end 187 118 ··· 198 129 |> Enum.map(&String.split/1) 199 130 |> Enum.map(fn line -> 200 131 [to, from, len] = Enum.map(line, &String.to_integer/1) 201 - {from..(from + len - 1), to..(to + len - 1)} 132 + {from..(from + len - 1), to} 202 133 end) 203 134 |> Mapping.from_list() 204 135 end) 205 - 206 - [seed2soil, soil2fert, fert2water, water2light, light2temp, temp2hum, hum2loc] = mappings 207 136 208 137 seeds = 209 138 seeds ··· 226 155 <!-- livebook:{"output":true} --> 227 156 228 157 ``` 229 - [79, 14, 55, 13] 230 - ``` 231 - 232 - ```elixir 233 - a = Mapping.from_list([{1..10, 31..40}]) 234 - b = Mapping.from_list([{25..35, 65..75}]) 235 - 236 - k = 30 237 - 238 - dbg(b[dbg(a[k])]) 239 - dbg(Mapping.squash(a, b))[k] 240 - ``` 241 - 242 - <!-- livebook:{"output":true} --> 243 - 244 - ``` 245 - 30 246 - ``` 247 - 248 - <!-- livebook:{"output":true} --> 249 - 250 - ``` 251 - 70 252 - ``` 253 - 254 - <!-- livebook:{"output":true} --> 255 - 256 - ``` 257 - foo 258 - ``` 259 - 260 - <!-- livebook:{"output":true} --> 261 - 262 - ``` 263 - %Mapping{values: [{1..5, 71..75}, {6..10, 36..40}, {25..30, 65..70}]} 264 - ``` 265 - 266 - <!-- livebook:{"output":true} --> 267 - 268 - ``` 269 - 70 158 + [1310704671, 312415190, 1034820096, 106131293, 682397438, 30365957, 2858337556, 1183890307, 159 + 665754577, 13162298, 2687187253, 74991378, 1782124901, 3190497, 208902075, 226221606, 4116455504, 160 + 87808390, 2403629707, 66592398] 270 161 ``` 271 162 272 163 ## Part 1 ··· 280 171 <!-- livebook:{"output":true} --> 281 172 282 173 ``` 283 - 35 284 - ``` 285 - 286 - ```elixir 287 - squashed = Enum.reduce(mappings, &Mapping.squash/2) 174 + 51752125 288 175 ``` 289 176 290 - <!-- livebook:{"output":true} --> 291 - 292 - ``` 293 - foo 294 - foo 295 - foo 296 - ``` 297 - 298 - <!-- livebook:{"output":true} --> 299 - 300 - ``` 301 - %Mapping{ 302 - values: [ 303 - {0..0, 27..27}, 304 - {0..5, 28..33}, 305 - {1..10, 40..49}, 306 - {6..59, 7..60}, 307 - {7..10, 59..62}, 308 - {11..14, 52..55}, 309 - {11..52, 0..41}, 310 - {15..41, 0..26}, 311 - {18..24, 90..96}, 312 - {25..55, 18..48}, 313 - {45..58, 74..87}, 314 - {49..51, 34..36}, 315 - {52..53, 37..38}, 316 - {53..60, 49..56}, 317 - {54..56, 56..58}, 318 - {56..64, 61..69}, 319 - {59..63, 95..99}, 320 - {60..80, 53..73}, 321 - {61..67, 63..69}, 322 - {64..76, 70..82}, 323 - {65..92, 69..96}, 324 - {69..69, 39..39}, 325 - {77..99, 45..67}, 326 - {81..87, 83..89}, 327 - {93..96, 49..52}, 328 - {95..97, 97..99}, 329 - {98..99, 50..51} 330 - ] 331 - } 332 - ``` 177 + ## Part 2 333 178 334 179 ```elixir 335 180 seeds 336 - |> Enum.map(&squashed[&1]) 337 - |> Enum.min() 181 + |> Enum.chunk_every(2) 182 + |> Enum.map(fn [start, length] -> start..(start + length - 1) end) 183 + |> RangeSet.new() 184 + |> then(&Enum.reduce(mappings, &1, fn map, r -> map[r] end)) 185 + |> RangeSet.min() 338 186 ``` 339 187 340 188 <!-- livebook:{"output":true} --> 341 189 342 190 ``` 343 - 14 191 + 12634632 344 192 ``` 345 193 346 - ```elixir 347 - Enum.map(seeds, &squashed[&1]) 348 - ``` 349 - 350 - <!-- livebook:{"output":true} --> 351 - 352 - ``` 353 - [72, 15, 56, 14] 354 - ``` 355 - 356 - ```elixir 357 - seeds = 358 - Enum.chunk_every(seeds, 2) 359 - |> Enum.map(fn [a, b] -> a..(a + b) end) 360 - |> RangeSet.new() 361 - 362 - mappings 363 - |> Enum.reduce(seeds, fn map, curr -> 364 - IO.puts("") 365 - IO.inspect(map, label: :map) 366 - IO.inspect(curr, label: :curr) 367 - inputs = RangeSet.new(for {from, _} <- map.values, do: from) 368 - mapped = IO.inspect(RangeSet.intersection(inputs, curr), label: :inter) 369 - left = IO.inspect(RangeSet.difference(curr, mapped), label: :diff) 370 - 371 - mapped = 372 - mapped.ranges 373 - |> Enum.map(fn a..b -> map[a]..map[b]//1 end) 374 - |> RangeSet.new() 375 - |> IO.inspect(label: :mapped) 376 - 377 - IO.inspect(RangeSet.union(left, mapped)) 378 - end) 379 - ``` 380 - 381 - <!-- livebook:{"output":true} --> 382 - 383 - ``` 384 - 385 - map: %Mapping{values: [{50..97, 52..99}, {98..99, 50..51}]} 386 - curr: RangeSet.new([55..68, 79..93]) 387 - inter: RangeSet.new([55..68, 79..93]) 388 - diff: RangeSet.new([]) 389 - mapped: RangeSet.new([57..70, 81..95]) 390 - RangeSet.new([57..70, 81..95]) 391 - 392 - map: %Mapping{values: [{0..14, 39..53}, {15..51, 0..36}, {52..53, 37..38}]} 393 - curr: RangeSet.new([57..70, 81..95]) 394 - inter: RangeSet.new([]) 395 - diff: RangeSet.new([57..70, 81..95]) 396 - mapped: RangeSet.new([]) 397 - RangeSet.new([57..70, 81..95]) 398 - 399 - map: %Mapping{ 400 - values: [{0..6, 42..48}, {7..10, 57..60}, {11..52, 0..41}, {53..60, 49..56}] 401 - } 402 - curr: RangeSet.new([57..70, 81..95]) 403 - inter: RangeSet.new([57..60]) 404 - diff: RangeSet.new([61..70, 81..95]) 405 - mapped: RangeSet.new([53..56]) 406 - RangeSet.new([53..56, 61..70, 81..95]) 407 - 408 - map: %Mapping{values: [{18..24, 88..94}, {25..94, 18..87}]} 409 - curr: RangeSet.new([53..56, 61..70, 81..95]) 410 - inter: RangeSet.new([53..56, 61..70, 81..94]) 411 - diff: RangeSet.new([95..95]) 412 - mapped: RangeSet.new([46..49, 54..63, 74..87]) 413 - RangeSet.new([46..49, 54..63, 74..87, 95..95]) 414 - 415 - map: %Mapping{values: [{45..63, 81..99}, {64..76, 68..80}, {77..99, 45..67}]} 416 - curr: RangeSet.new([46..49, 54..63, 74..87, 95..95]) 417 - inter: RangeSet.new([46..49, 54..63, 74..76, 77..87, 95..95]) 418 - diff: RangeSet.new([]) 419 - mapped: RangeSet.new([45..55, 63..63, 78..80, 82..85, 90..99]) 420 - RangeSet.new([45..55, 63..63, 78..80, 82..85, 90..99]) 421 - 422 - map: %Mapping{values: [{0..68, 1..69}, {69..69, 0..0}]} 423 - curr: RangeSet.new([45..55, 63..63, 78..80, 82..85, 90..99]) 424 - inter: RangeSet.new([45..55, 63..63]) 425 - diff: RangeSet.new([78..80, 82..85, 90..99]) 426 - mapped: RangeSet.new([46..56, 64..64]) 427 - RangeSet.new([46..56, 64..64, 78..80, 82..85, 90..99]) 428 - 429 - map: %Mapping{values: [{56..92, 60..96}, {93..96, 56..59}]} 430 - curr: RangeSet.new([46..56, 64..64, 78..80, 82..85, 90..99]) 431 - ``` 432 - 433 - ```elixir 434 - light2temp[74] 435 - ``` 436 - 437 - <!-- livebook:{"output":true} --> 438 - 439 - ``` 440 - 78 441 - ``` 442 - 443 - <!-- livebook:{"offset":13391,"stamp":{"token":"XCP.YBvV3LijXOIMnujrbQ1UcVgKkKIgzTxWiEVKN6_kRQO7Z54rqDRPZT7cgjsENw1cakYqdxjdW8l0ZieLojSPU1k_oMLqBh0-YpWLbT9dUfZRNKIxmeQgwwCEGOzZ2hdsVw","version":2}} --> 194 + <!-- livebook:{"offset":8450,"stamp":{"token":"XCP.9I0OWZix2U9jQ5DLHq6aPMZLzaSvoWmFrdBbv9pxQfaL_IHSsv0UiMHQgeLV96EpUjfWS_hLXKNfPjSWsmdceQyf2OEIe1gAC7o2oOp3S4I9UlfKFypRqLfs3Jo6p-UtGQ","version":2}} -->