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

Advent of Code 2021 day 05

2021/priv/day-05.livemd

Advent of Code 2021 day 05

Setup

Mix.install([
  {:kino, "~> 0.4.1"},
  {:vega_lite, "~> 0.1.1"}
])
input = Kino.Input.textarea("Please type your input:")
lines =
  input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.map(fn line ->
    line
    |> String.split([",", " -> "])
    |> Enum.map(&String.to_integer/1)
  end)

Part 1

defmodule Day4 do
  def to_grid(lines) do
    Enum.reduce(lines, %{}, &update_line/2)
  end

  defp update_line([x, y1, x, y2], grid) do
    Enum.reduce(y1..y2, grid, fn y, grid ->
      Map.update(grid, {x, y}, 1, &(&1 + 1))
    end)
  end

  defp update_line([x1, y, x2, y], grid) do
    Enum.reduce(x1..x2, grid, fn x, grid ->
      Map.update(grid, {x, y}, 1, &(&1 + 1))
    end)
  end

  defp update_line(_line, grid), do: grid
end

lines
|> Day4.to_grid()
|> Enum.filter(fn {_k, v} -> v > 1 end)
|> Enum.count()

Part 2

defmodule Day4Part2 do
  def to_grid(lines) do
    Enum.reduce(lines, %{}, fn
      [x, y1, x, y2], grid -> update_grid(Stream.cycle([x]), y1..y2, grid)
      [x1, y, x2, y], grid -> update_grid(x1..x2, Stream.cycle([y]), grid)
      [x1, y1, x2, y2], grid -> update_grid(x1..x2, y1..y2, grid)
    end)
  end

  defp update_grid(xs, ys, grid) do
    xs
    |> Enum.zip(ys)
    |> Enum.reduce(grid, fn key, grid ->
      Map.update(grid, key, 1, &(&1 + 1))
    end)
  end
end

lines
|> Day4Part2.to_grid()
|> Enum.filter(fn {_k, v} -> v > 1 end)
|> Enum.count()

Visualization

lines_data =
  lines
  |> Enum.flat_map(fn
    [x1, y, x2, y] -> Enum.zip(x1..x2, Stream.cycle([y]))
    [x, y1, x, y2] -> Enum.zip(Stream.cycle([x]), y1..y2)
    [x1, y1, x2, y2] -> Enum.zip(x1..x2, y1..y2)
  end)
  |> Enum.map(fn {x, y} -> %{x: x, y: y} end)

alias VegaLite, as: Vl

Vl.new(width: 400, height: 400, background: "white")
|> Vl.data_from_values(lines_data)
|> Vl.mark(:rect)
|> Vl.encode_field(:x, "x", axis: [title: "x"], bin: [maxbins: 50])
|> Vl.encode_field(:y, "y", axis: [title: "y"], bin: [maxbins: 50])
# |> Vl.encode(:size, aggregate: :count)
|> Vl.encode(:color, aggregate: :count)
|> Vl.config(view: [stroke: :transparent])