···
6
-
Mix.install([:kino_aoc, {:range_set, path: "../range_set"}])
6
+
Mix.install([:kino_aoc, {:range_set, github: "hauleth/range_set"}])
···
34
-
soil-to-fertilizer map:
34
+
soil-to-fertilizer map:
39
-
fertilizer-to-water map:
39
+
fertilizer-to-water map:
49
-
light-to-temperature map:
49
+
light-to-temperature map:
54
-
temperature-to-humidity map:
54
+
temperature-to-humidity map:
58
-
humidity-to-location map:
58
+
humidity-to-location map:
<!-- livebook:{"output":true} -->
···
75
+
import Kernel, except: [apply: 2]
78
-
# true = Enum.all?(lst, fn {a, b} -> Range.size(a) == Range.size(b) end)
%__MODULE__{values: Enum.sort(lst)}
82
-
def squash(%__MODULE__{values: from}, %__MODULE__{values: to}) do
83
-
from_list(do_squash(from, to))
86
-
defp do_squash([], rest), do: rest
87
-
defp do_squash(rest, []), do: rest
91
-
defp do_squash([{_src, a.._b} | _] = xs, [{_c..d, _out} = v | ys]) when d < a do
92
-
[v | do_squash(xs, ys)]
97
-
defp do_squash([{_src, _a..b} = v | xs], [{c.._d, _out} | _] = ys) when b < c do
98
-
[v | do_squash(xs, ys)]
103
-
defp do_squash([{src, range} | xs], [{range, out} | ys]) do
104
-
[{src, out} | do_squash(xs, ys)]
83
+
defp apply({a.._, to}, v), do: v - a + to
109
-
defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a <= c and b >= d do
115
-
|> Enum.concat(do_squash(xs, ys))
86
+
def fetch(%__MODULE__{values: list}, key) when is_integer(key) do
87
+
{:ok, sorted_find(list, key)}
120
-
defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a >= c and b <= d do
129
-
|> Enum.concat(do_squash(xs, ys))
90
+
def fetch(%__MODULE__{values: map}, %RangeSet{ranges: ranges}) do
92
+
|> Enum.flat_map(&map_range(&1, map))
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)
143
-
|> Enum.concat(do_squash(xs, ys))
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)
148
-
defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a > c and b > d do
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)
113
+
apply(fun_def, lo)..apply(fun_def, hi)
114
+
| if(hi < arg_hi, do: map_range((hi + 1)..arg_hi, maps), else: [])
158
-
|> Enum.concat(do_squash(xs, ys))
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}
173
-
defp range_match(_.._ = range, list) when is_list(list) do
174
-
for {a, b} <- range_match(list, range), do: {b, a}
178
-
def fetch(%__MODULE__{values: list}, key) when is_integer(key) do
180
-
with {a.._, b.._} <- Enum.find(list, key, fn {range, _} -> key in range end) do
···
|> Enum.map(&String.split/1)
[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}
206
-
[seed2soil, soil2fert, fert2water, water2light, light2temp, temp2hum, hum2loc] = mappings
···
<!-- livebook:{"output":true} -->
233
-
a = Mapping.from_list([{1..10, 31..40}])
234
-
b = Mapping.from_list([{25..35, 65..75}])
239
-
dbg(Mapping.squash(a, b))[k]
242
-
<!-- livebook:{"output":true} -->
248
-
<!-- livebook:{"output":true} -->
254
-
<!-- livebook:{"output":true} -->
260
-
<!-- livebook:{"output":true} -->
263
-
%Mapping{values: [{1..5, 71..75}, {6..10, 36..40}, {25..30, 65..70}]}
266
-
<!-- livebook:{"output":true} -->
158
+
[1310704671, 312415190, 1034820096, 106131293, 682397438, 30365957, 2858337556, 1183890307,
159
+
665754577, 13162298, 2687187253, 74991378, 1782124901, 3190497, 208902075, 226221606, 4116455504,
160
+
87808390, 2403629707, 66592398]
···
<!-- livebook:{"output":true} -->
287
-
squashed = Enum.reduce(mappings, &Mapping.squash/2)
290
-
<!-- livebook:{"output":true} -->
298
-
<!-- livebook:{"output":true} -->
336
-
|> Enum.map(&squashed[&1])
181
+
|> Enum.chunk_every(2)
182
+
|> Enum.map(fn [start, length] -> start..(start + length - 1) end)
184
+
|> then(&Enum.reduce(mappings, &1, fn map, r -> map[r] end))
<!-- livebook:{"output":true} -->
347
-
Enum.map(seeds, &squashed[&1])
350
-
<!-- livebook:{"output":true} -->
358
-
Enum.chunk_every(seeds, 2)
359
-
|> Enum.map(fn [a, b] -> a..(a + b) end)
363
-
|> Enum.reduce(seeds, fn map, curr ->
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)
373
-
|> Enum.map(fn a..b -> map[a]..map[b]//1 end)
375
-
|> IO.inspect(label: :mapped)
377
-
IO.inspect(RangeSet.union(left, mapped))
381
-
<!-- livebook:{"output":true} -->
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])
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])
400
-
values: [{0..6, 42..48}, {7..10, 57..60}, {11..52, 0..41}, {53..60, 49..56}]
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])
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])
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])
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])
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])
437
-
<!-- livebook:{"output":true} -->
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}} -->