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

Day 5

2021/day_05.livemd

Day 5

Common

Input

Mix.install([{:kino, github: "livebook-dev/kino"}])
textarea = Kino.Input.textarea("Input:")
defmodule Day5 do
  def parse_input(raw_input) do
    raw_input
    |> String.split("\n", trim: true)
    |> Enum.map(fn line ->
      [_all | matches] = Regex.run(~r{([0-9]+),([0-9]+) -> ([0-9]+),([0-9]+)}, line)
      [x1, y1, x2, y2] = Enum.map(matches, &String.to_integer/1)
      {{x1, y1}, {x2, y2}}
    end)
  end
end
raw_input = Kino.Input.read(textarea)
input = Day5.parse_input(raw_input)

Part 1

defmodule Day5.Part1 do
  def run(input) do
    Enum.reduce(input, %{}, fn
      {{x, y1}, {x, y2}}, acc ->
        Enum.reduce(y1..y2, acc, fn y, acc ->
          Map.update(acc, {x, y}, 1, &(&1 + 1))
        end)

      {{x1, y}, {x2, y}}, acc ->
        Enum.reduce(x1..x2, acc, fn x, acc ->
          Map.update(acc, {x, y}, 1, &(&1 + 1))
        end)

      _, acc ->
        acc
    end)
    |> Enum.count(&(elem(&1, 1) >= 2))
  end
end
Day5.Part1.run(input)

Part 2

defmodule Day5.Part2 do
  def run(input) do
    Enum.reduce(input, %{}, fn
      {{x, y1}, {x, y2}}, acc ->
        Enum.reduce(y1..y2, acc, fn y, acc ->
          Map.update(acc, {x, y}, 1, &(&1 + 1))
        end)

      {{x1, y}, {x2, y}}, acc ->
        Enum.reduce(x1..x2, acc, fn x, acc ->
          Map.update(acc, {x, y}, 1, &(&1 + 1))
        end)

      {{x1, y1}, {x2, y2}}, acc when x1 < x2 and y1 < y2 ->
        Enum.reduce(0..(x2 - x1), acc, fn diff, acc ->
          Map.update(acc, {x1 + diff, y1 + diff}, 1, &amp;(&amp;1 + 1))
        end)

      {{x1, y1}, {x2, y2}}, acc when x1 > x2 and y1 < y2 ->
        Enum.reduce(0..(x1 - x2), acc, fn diff, acc ->
          Map.update(acc, {x1 - diff, y1 + diff}, 1, &amp;(&amp;1 + 1))
        end)

      {{x1, y1}, {x2, y2}}, acc when x1 < x2 and y1 > y2 ->
        Enum.reduce(0..(x2 - x1), acc, fn diff, acc ->
          Map.update(acc, {x1 + diff, y1 - diff}, 1, &amp;(&amp;1 + 1))
        end)

      {{x1, y1}, {x2, y2}}, acc when x1 > x2 and y1 > y2 ->
        Enum.reduce(0..(x1 - x2), acc, fn diff, acc ->
          Map.update(acc, {x1 - diff, y1 - diff}, 1, &amp;(&amp;1 + 1))
        end)
    end)
    |> Enum.count(&amp;(elem(&amp;1, 1) >= 2))
  end
end
Day5.Part2.run(input)