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

Day 5

advent_of_code/2021/day-05.livemd

Day 5

Setup

Mix.install([
  {:kino, "~> 0.5.0"},
  {: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 Counter1 do
  def lines(lines) do
    lines
    |> Enum.reduce(%{}, fn
      [x, y1, x, y2], grid ->
        Enum.reduce(y1..y2, grid, fn y, grid ->
          Map.update(grid, {x, y}, 1, &(&1 + 1))
        end)

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

      _line, grid ->
        grid
    end)
    |> Enum.count(fn {_, v} -> v > 1 end)
  end
end

Counter1.lines(lines)

Part 2

defmodule Counter2 do
  def lines(lines) do
    lines
    |> Enum.reduce(%{}, fn
      [x, y1, x, y2], grid -> sum_grid(Stream.cycle([x]), y1..y2, grid)
      [x1, y, x2, y], grid -> sum_grid(x1..x2, Stream.cycle([y]), grid)
      [x1, y1, x2, y2], grid -> sum_grid(x1..x2, y1..y2, grid)
    end)
    |> Enum.count(fn {_, v} -> v > 1 end)
  end

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

Counter2.lines(lines)
lines_data =
  lines
  |> Enum.flat_map(fn
    [x, y1, x, y2] -> Enum.zip(Stream.cycle([x]), y1..y2)
    [x1, y, x2, y] -> Enum.zip(x1..x2, Stream.cycle([y]))
    [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(:circle)
|> 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, scale: [range: ["green", "red"]])