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

Day 9: Mirage Maintenance

day09.livemd

Day 9: Mirage Maintenance

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

Input

input = Kino.Input.textarea("Please, paste your input here:")
defmodule Day9Shared do
  def parse(input) do
    input
    |> Kino.Input.read()
    |> String.split("\n")
    |> Enum.map(fn raw_values ->
      raw_values
      |> String.split(~r/\s+/)
      |> Enum.map(&String.to_integer/1)
    end)
  end

  def extrapolate(history) do
    history
    |> Stream.unfold(fn values ->
      next = diff(values)

      if Enum.all?(values, &(&1 == 0)) do
        nil
      else
        {values, next}
      end
    end)
    |> Enum.to_list()
  end

  def diff([head | sequence]) do
    sequence
    |> Enum.reduce({[], head}, fn item, {diffs, prev} ->
      {[item - prev | diffs], item}
    end)
    |> elem(0)
    |> Enum.reverse()
  end
end

Day9Shared.parse(input)

Part 1

defmodule Day9Part1 do
  import Day9Shared, except: [parse: 1]

  def solve(values) do
    values
    |> Stream.map(&extrapolate/1)
    |> Stream.map(fn extras ->
      extras
      |> Stream.map(&List.last/1)
      |> Enum.sum()
    end)
    |> Enum.sum()
  end
end

input
|> Day9Shared.parse()
|> Day9Part1.solve()

# 1934898173 is too low
# 1934898178 is the right answer

Part 2

defmodule Day9Part2 do
  import Day9Shared, except: [parse: 1]

  def solve(values) do
    values
    |> Stream.map(&extrapolate/1)
    |> Stream.map(fn extras ->
      extras
      |> Enum.map(&hd/1)
      |> Enum.reverse()
    end)
    |> Enum.map(&[0 | &1])
    |> Enum.map(fn seqs ->
      Enum.reduce(seqs, 0, fn el, acc -> el - acc end)
    end)
    |> Enum.to_list()
    |> Enum.sum()
  end
end

input
|> Day9Shared.parse()
|> Day9Part2.solve()