Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Advent 2023 - Day 5

day5.livemd

Advent 2023 - Day 5

Mix.install([
  {:kino, "~> 0.11.3"}
])

Section

input = Kino.Input.textarea("Please paste your input file")
[seeds | mappings] =
  input
  |> Kino.Input.read()
  |> String.split("\n\n")
  |> Enum.map(fn category ->
    category
    |> String.split(":")
    |> Enum.at(1)
    |> String.trim()
    |> String.split("\n")
    |> Enum.map(fn chain ->
      chain
      |> String.split(" ")
      |> Enum.map(&Integer.parse/1)
      |> Enum.map(&elem(&1, 0))
    end)
  end)
[
  [[79, 14, 55, 13]],
  [[50, 98, 2], ~c"420"],
  [[0, 15, 37], [37, 52, 2], [39, 0, 15]],
  [~c"15\b", [0, 11, 42], [42, 0, 7], [57, 7, 4]],
  [[88, 18, 7], [18, 25, 70]],
  [[45, 77, 23], [81, 45, 19], ~c"D@\r"],
  [[0, 69, 1], [1, 0, 69]],
  [~c"<8%", [56, 93, 4]]
]
seeds = List.flatten(seeds)
[79, 14, 55, 13]
mappings =
  for mapping <- mappings do
    for [dest, src, range] <- mapping do
      {src..(src + range), dest - src}
    end
  end
[
  [{98..100, -48}, {50..98, 2}],
  [{15..52, -15}, {52..54, -15}, {0..15, 39}],
  [{53..61, -4}, {11..53, -11}, {0..7, 42}, {7..11, 50}],
  [{18..25, 70}, {25..95, -7}],
  [{77..100, -32}, {45..64, 36}, {64..77, 4}],
  [{69..70, -69}, {0..69, 1}],
  [{56..93, 4}, {93..97, -37}]
]

Part 1

for seed <- seeds do
  Enum.reduce(mappings, seed, fn mapping, value ->
    map =
      Enum.find(mapping, fn {range, _} ->
        Enum.member?(range, value)
      end)

    if is_nil(map) do
      value
    else
      {_, to_add} = map
      value + to_add
    end
  end)
end
|> Enum.min()
35

Part 2

seed_ranges =
  seeds
  |> Enum.chunk_every(2)
  |> Enum.map(fn [start, range] ->
    start..(start + range - 1)
  end)
[79..92, 55..67]

if we have: 30..50

outside range:

  • 10..20 -> {nil, [30..50]}
  • 60..80 -> {nil, [30..50]}

corner of range:

  • 10..40 -> {30..40<-remap range, [41..50]<-leftover}
  • 40..60 -> {40..50<-remap range, [30..39]<-leftover}

within_range:

  • 35..45 -> {35..45<-remap range, [30..34,46..50]<-leftover}

entire_range:

  • 30..50 -> {30..50<-remap range, []<-leftover}
  • 0..100 -> {30..50<-remap range, []<-leftover}
defmodule Almanac do
  # outside of range / disjoint
  def dice(sl..sr//1 = src, ml..mr//1) when sr < ml or sl > mr, do: {nil, [src]}
  # corner to the left
  def dice(sl..sr//1, ml..mr//1) when sl >= ml and sr > mr, do: {sl..mr, [(mr + 1)..sr]}
  # corner to the right
  def dice(sl..sr//1, ml..mr//1) when sl < ml and sr <= mr, do: {ml..sr, [sl..(ml - 1)]}
  # within range
  def dice(sl..sr//1, ml..mr//1) when sl < ml and sr > mr,
    do: {ml..mr, [sl..(ml - 1), (mr + 1)..sr]}

  # entire range
  def dice(sl..sr//1, ml..mr//1) when sl >= ml and sr <= mr, do: {sl..sr, []}
end

example = 30..50

# outside
{nil, [30..50]} = Almanac.dice(example, 10..20)
# corner to the left
{30..40, [41..50]} = Almanac.dice(example, 10..40)
# corner to the right
{40..50, [30..39]} = Almanac.dice(example, 40..60)
# within range
{35..45, [30..34, 46..50]} = Almanac.dice(example, 35..45)
# entire range
{30..50, []} = Almanac.dice(example, 30..50)
# also entire range
{30..50, []} = Almanac.dice(example, 0..100)
{30..50, []}
example = 50..150

Almanac.dice(example, 60..70)
{60..70, [50..59, 71..150]}
Almanac.dice(example, 100..120)
{100..120, [50..99, 121..150]}
for seed_range <- seed_ranges do
  Enum.reduce(mappings, [seed_range], fn mapping, values ->
    values
    |> Enum.map(fn value ->
      IO.puts("value")
      IO.inspect(value)

      Enum.map_reduce(mapping, [value], fn {range, to_add}, leftovers ->
        leftovers
        |> Enum.map(fn leftover ->
          {to_be_mapped, leftover} = Almanac.dice(leftover, range)
        end)
        |> IO.inspect()

        raise "fuck"
      end)

      mapping
      |> Enum.map(fn {range, to_add} ->
        IO.inspect("what")
        IO.inspect(range)
        IO.inspect(value)
        map_first..map_last//_step = range
        val_first..val_last//_step = value

        first = if map_first < val_first, do: val_first, else: map_first
        last = if map_last > val_last, do: val_last, else: map_last

        first..last
        # (first + to_add)..(last + to_add)
      end)
    end)
    |> List.flatten()
    |> IO.inspect()

    raise "aaa"
  end)
end
warning: variable "leftover" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)
  advent2023/day5.livemd#cell:auevw3s4pafeeggwj3ttbo6gjyez65mo:11

warning: variable "to_be_mapped" is unused (if the variable is not meant to be used, prefix it with an underscore)
  advent2023/day5.livemd#cell:auevw3s4pafeeggwj3ttbo6gjyez65mo:11

warning: variable "to_add" is unused (if the variable is not meant to be used, prefix it with an underscore)
  advent2023/day5.livemd#cell:auevw3s4pafeeggwj3ttbo6gjyez65mo:8

warning: variable "to_add" is unused (if the variable is not meant to be used, prefix it with an underscore)
  advent2023/day5.livemd#cell:auevw3s4pafeeggwj3ttbo6gjyez65mo:19

value
79..92
[nil: [79..92]]