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

Advent of Code 2021 day 13

2021/priv/day-13.livemd

Advent of Code 2021 day 13

Setup

Mix.install([
  {:kino, "~> 0.4.1"},
  {:vega_lite, "~> 0.1.1"}
])
input = Kino.Input.textarea("Paste inputs here:")
[dots, folds] =
  input
  |> Kino.Input.read()
  |> String.split("\n\n")
  |> Enum.map(&String.split(&1, "\n", trim: true))

dots =
  dots
  |> Enum.map(&String.split(&1, ","))
  |> Enum.map(&Enum.map(&1, fn i -> String.to_integer(i) end))
  |> Enum.map(fn [row, col] -> {row, col} end)

folds =
  Enum.map(folds, fn "fold along " <> fold ->
    [dir, line] = String.split(fold, "=")
    {String.to_atom(dir), String.to_integer(line)}
  end)

Part 1

defmodule Day13 do
  def fold(:x, line), do: fn {x, y} -> {line - abs(x - line), y} end

  def fold(:y, line), do: fn {x, y} -> {x, line - abs(y - line)} end
end

folds
|> Enum.take(1)
|> Enum.reduce(dots, fn {dir, line}, dots ->
  Enum.map(dots, Day13.fold(dir, line))
end)
|> Enum.uniq()
|> Enum.count()

Part 2

defmodule Day13Part2 do
  def draw(grid) do
    {width, _} = Enum.max_by(grid, &amp;elem(&amp;1, 0))
    {_, height} = Enum.max_by(grid, &amp;elem(&amp;1, 1))

    for y <- 0..height do
      for x <- 0..width do
        if {x, y} in grid, do: "X", else: " "
      end
      |> Enum.join(" ")
      |> IO.puts()
    end
  end
end

paper =
  folds
  |> Enum.reduce(dots, fn {dir, line}, dots ->
    Enum.map(dots, Day13.fold(dir, line))
  end)
  |> Enum.uniq()
  |> Day13Part2.draw()

Visualization

> source: https://github.com/miladamilli/Advent_of_Code_2021/blob/master/day13.livemd

alias VegaLite, as: Vl

dots_to_paper = fn dots ->
  Enum.map(dots, fn {x, y} -> %{x: x, y: -y} end)
end

graph =
  Vl.new(width: 800, height: 150)
  |> Vl.config(view: [stroke: :transparent])
  |> Vl.mark(:square, opacity: 0.4, size: 200)
  |> Vl.data_from_values(dots_to_paper.(dots))
  |> Vl.encode_field(:x, "x", type: :quantitative, axis: false)
  |> Vl.encode_field(:y, "y", type: :quantitative, axis: false)
  |> Vl.encode_field(:color, "x",
    type: :quantitative,
    scale: [range: ["#27e3c8", "#b25ae7"]],
    legend: false
  )
  |> Kino.VegaLite.new()
  |> Kino.render()

Enum.reduce(folds, dots, fn {dir, fold}, dots ->
  dots = Enum.map(dots, Day13.fold(dir, fold))

  Process.sleep(500)
  Kino.VegaLite.clear(graph)
  Kino.VegaLite.push_many(graph, dots_to_paper.(dots))

  dots
end)

:ok