···
-
Mix.install([:kino_aoc, {:range_set, path: "../range_set"}])
···
-
soil-to-fertilizer map:
-
fertilizer-to-water map:
-
light-to-temperature map:
-
temperature-to-humidity map:
-
humidity-to-location map:
<!-- livebook:{"output":true} -->
···
-
# true = Enum.all?(lst, fn {a, b} -> Range.size(a) == Range.size(b) end)
%__MODULE__{values: Enum.sort(lst)}
-
def squash(%__MODULE__{values: from}, %__MODULE__{values: to}) do
-
from_list(do_squash(from, to))
-
defp do_squash([], rest), do: rest
-
defp do_squash(rest, []), do: rest
-
defp do_squash([{_src, a.._b} | _] = xs, [{_c..d, _out} = v | ys]) when d < a do
-
[v | do_squash(xs, ys)]
-
defp do_squash([{_src, _a..b} = v | xs], [{c.._d, _out} | _] = ys) when b < c do
-
[v | do_squash(xs, ys)]
-
defp do_squash([{src, range} | xs], [{range, out} | ys]) do
-
[{src, out} | do_squash(xs, ys)]
-
defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a <= c and b >= d do
-
|> Enum.concat(do_squash(xs, ys))
-
defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a >= c and b <= d do
-
|> Enum.concat(do_squash(xs, ys))
-
defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when c in a..b and b in c..d do
-
{s1, s2} = Range.split(src, Range.size(a..c) - 1)
-
{o1, o2} = Range.split(out, Range.size(c..b))
-
|> Enum.concat(do_squash(xs, ys))
-
defp do_squash([{src, a..b} | xs], [{c..d, out} | ys]) when a > c and b > d do
-
{of, ol} = Range.split(out, Range.size(c..a) - 1)
-
{sf, sl} = Range.split(src, Range.size(a..d))
-
|> Enum.concat(do_squash(xs, ys))
-
defp range_match(list, a.._) when is_list(list) do
-
Enum.reduce(list, {[], a}, fn
-
_.._//1 = range, {acc, s} ->
-
to = s + Range.size(range) - 1
-
{[{range, s..to} | acc], to + 1}
-
defp range_match(_.._ = range, list) when is_list(list) do
-
for {a, b} <- range_match(list, range), do: {b, a}
-
def fetch(%__MODULE__{values: list}, key) when is_integer(key) do
-
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)
-
{from..(from + len - 1), to..(to + len - 1)}
-
[seed2soil, soil2fert, fert2water, water2light, light2temp, temp2hum, hum2loc] = mappings
···
<!-- livebook:{"output":true} -->
-
a = Mapping.from_list([{1..10, 31..40}])
-
b = Mapping.from_list([{25..35, 65..75}])
-
dbg(Mapping.squash(a, b))[k]
-
<!-- livebook:{"output":true} -->
-
<!-- livebook:{"output":true} -->
-
<!-- livebook:{"output":true} -->
-
<!-- livebook:{"output":true} -->
-
%Mapping{values: [{1..5, 71..75}, {6..10, 36..40}, {25..30, 65..70}]}
-
<!-- livebook:{"output":true} -->
···
<!-- livebook:{"output":true} -->
-
squashed = Enum.reduce(mappings, &Mapping.squash/2)
-
<!-- livebook:{"output":true} -->
-
<!-- livebook:{"output":true} -->
-
|> Enum.map(&squashed[&1])
<!-- livebook:{"output":true} -->
-
Enum.map(seeds, &squashed[&1])
-
<!-- livebook:{"output":true} -->
-
Enum.chunk_every(seeds, 2)
-
|> Enum.map(fn [a, b] -> a..(a + b) end)
-
|> Enum.reduce(seeds, fn map, curr ->
-
IO.inspect(map, label: :map)
-
IO.inspect(curr, label: :curr)
-
inputs = RangeSet.new(for {from, _} <- map.values, do: from)
-
mapped = IO.inspect(RangeSet.intersection(inputs, curr), label: :inter)
-
left = IO.inspect(RangeSet.difference(curr, mapped), label: :diff)
-
|> Enum.map(fn a..b -> map[a]..map[b]//1 end)
-
|> IO.inspect(label: :mapped)
-
IO.inspect(RangeSet.union(left, mapped))
-
<!-- livebook:{"output":true} -->
-
map: %Mapping{values: [{50..97, 52..99}, {98..99, 50..51}]}
-
curr: RangeSet.new([55..68, 79..93])
-
inter: RangeSet.new([55..68, 79..93])
-
mapped: RangeSet.new([57..70, 81..95])
-
RangeSet.new([57..70, 81..95])
-
map: %Mapping{values: [{0..14, 39..53}, {15..51, 0..36}, {52..53, 37..38}]}
-
curr: RangeSet.new([57..70, 81..95])
-
inter: RangeSet.new([])
-
diff: RangeSet.new([57..70, 81..95])
-
mapped: RangeSet.new([])
-
RangeSet.new([57..70, 81..95])
-
values: [{0..6, 42..48}, {7..10, 57..60}, {11..52, 0..41}, {53..60, 49..56}]
-
curr: RangeSet.new([57..70, 81..95])
-
inter: RangeSet.new([57..60])
-
diff: RangeSet.new([61..70, 81..95])
-
mapped: RangeSet.new([53..56])
-
RangeSet.new([53..56, 61..70, 81..95])
-
map: %Mapping{values: [{18..24, 88..94}, {25..94, 18..87}]}
-
curr: RangeSet.new([53..56, 61..70, 81..95])
-
inter: RangeSet.new([53..56, 61..70, 81..94])
-
diff: RangeSet.new([95..95])
-
mapped: RangeSet.new([46..49, 54..63, 74..87])
-
RangeSet.new([46..49, 54..63, 74..87, 95..95])
-
map: %Mapping{values: [{45..63, 81..99}, {64..76, 68..80}, {77..99, 45..67}]}
-
curr: RangeSet.new([46..49, 54..63, 74..87, 95..95])
-
inter: RangeSet.new([46..49, 54..63, 74..76, 77..87, 95..95])
-
mapped: RangeSet.new([45..55, 63..63, 78..80, 82..85, 90..99])
-
RangeSet.new([45..55, 63..63, 78..80, 82..85, 90..99])
-
map: %Mapping{values: [{0..68, 1..69}, {69..69, 0..0}]}
-
curr: RangeSet.new([45..55, 63..63, 78..80, 82..85, 90..99])
-
inter: RangeSet.new([45..55, 63..63])
-
diff: RangeSet.new([78..80, 82..85, 90..99])
-
mapped: RangeSet.new([46..56, 64..64])
-
RangeSet.new([46..56, 64..64, 78..80, 82..85, 90..99])
-
map: %Mapping{values: [{56..92, 60..96}, {93..96, 56..59}]}
-
curr: RangeSet.new([46..56, 64..64, 78..80, 82..85, 90..99])
-
<!-- livebook:{"output":true} -->
-
<!-- livebook:{"offset":13391,"stamp":{"token":"XCP.YBvV3LijXOIMnujrbQ1UcVgKkKIgzTxWiEVKN6_kRQO7Z54rqDRPZT7cgjsENw1cakYqdxjdW8l0ZieLojSPU1k_oMLqBh0-YpWLbT9dUfZRNKIxmeQgwwCEGOzZ2hdsVw","version":2}} -->
···
+
Mix.install([:kino_aoc, {:range_set, github: "hauleth/range_set"}])
···
+
soil-to-fertilizer map:
+
fertilizer-to-water map:
+
light-to-temperature map:
+
temperature-to-humidity map:
+
humidity-to-location map:
<!-- livebook:{"output":true} -->
···
+
import Kernel, except: [apply: 2]
%__MODULE__{values: Enum.sort(lst)}
+
defp apply({a.._, to}, v), do: v - a + to
+
def fetch(%__MODULE__{values: list}, key) when is_integer(key) do
+
{:ok, sorted_find(list, key)}
+
def fetch(%__MODULE__{values: map}, %RangeSet{ranges: ranges}) do
+
|> Enum.flat_map(&map_range(&1, map))
+
defp sorted_find([], n), do: n
+
defp sorted_find([{a..b, _} = result | _], n) when n in a..b, do: apply(result, n)
+
defp sorted_find([{a.._, _} | _], n) when n < a, do: n
+
defp sorted_find([_ | rest], n), do: sorted_find(rest, n)
+
defp map_range(range, []), do: [range]
+
defp map_range(_..hi = range, [{lo.._, _} | _]) when lo > hi, do: [range]
+
defp map_range(lo.._ = range, [{_..hi, _} | rest]) when lo > hi, do: map_range(range, rest)
+
defp map_range(arg_range, [{fun_range, _} = fun_def | maps]) do
+
fun_lo..fun_hi = fun_range
+
arg_lo..arg_hi = arg_range
+
lo = max(fun_lo, arg_lo)
+
hi = min(fun_hi, arg_hi)
+
apply(fun_def, lo)..apply(fun_def, hi)
+
| if(hi < arg_hi, do: map_range((hi + 1)..arg_hi, maps), else: [])
···
|> Enum.map(&String.split/1)
[to, from, len] = Enum.map(line, &String.to_integer/1)
+
{from..(from + len - 1), to}
···
<!-- livebook:{"output":true} -->
+
[1310704671, 312415190, 1034820096, 106131293, 682397438, 30365957, 2858337556, 1183890307,
+
665754577, 13162298, 2687187253, 74991378, 1782124901, 3190497, 208902075, 226221606, 4116455504,
+
87808390, 2403629707, 66592398]
···
<!-- livebook:{"output":true} -->
+
|> Enum.map(fn [start, length] -> start..(start + length - 1) end)
+
|> then(&Enum.reduce(mappings, &1, fn map, r -> map[r] end))
<!-- livebook:{"output":true} -->
+
<!-- livebook:{"offset":8450,"stamp":{"token":"XCP.9I0OWZix2U9jQ5DLHq6aPMZLzaSvoWmFrdBbv9pxQfaL_IHSsv0UiMHQgeLV96EpUjfWS_hLXKNfPjSWsmdceQyf2OEIe1gAC7o2oOp3S4I9UlfKFypRqLfs3Jo6p-UtGQ","version":2}} -->