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

--- Day 13: Transparent Origami ---

2021/day13.livemd

— Day 13: Transparent Origami —

Setup

defmodule Setup do
  def get_input(prompt) do
    case IO.gets(prompt) do
      :eof -> ""
      line -> line <> get_input(prompt)
    end
  end

  def parse(binary) do
    [dots, folds] = binary |> String.split("\n\n")

    {parse_dots(dots), parse_folds(folds)}
  end

  defp parse_dots(binary) do
    binary
    |> String.split([",", "\n"], trim: true)
    |> Enum.chunk_every(2)
    |> MapSet.new(fn [x, y] ->
      {String.to_integer(x), String.to_integer(y)}
    end)
  end

  defp parse_folds(binary) do
    binary
    |> String.split("\n", trim: true)
    |> Enum.map(&amp;parse_fold/1)
  end

  defp parse_fold("fold along x=" <> x), do: {:x, String.to_integer(x)}
  defp parse_fold("fold along y=" <> y), do: {:y, String.to_integer(y)}
end
defmodule Manual do
  def fold({:y, fold}, dots) do
    for {x, y} <- dots, reduce: MapSet.new() do
      acc ->
        cond do
          y < fold ->
            MapSet.put(acc, {x, y})

          y == fold ->
            acc

          y > fold ->
            MapSet.put(acc, {x, fold - y + fold})
        end
    end
  end

  def fold({:x, fold}, dots) do
    for {x, y} <- dots, reduce: MapSet.new() do
      acc ->
        cond do
          x < fold ->
            MapSet.put(acc, {x, y})

          x == fold ->
            acc

          x > fold ->
            MapSet.put(acc, {fold - x + fold, y})
        end
    end
  end
end

Part1

Setup.get_input("input")
|> Setup.parse()
|> then(fn {dots, [fold | _folds]} ->
  Manual.fold(fold, dots)
end)
|> Enum.count()

Part2

Setup.get_input("input")
|> Setup.parse()
|> then(fn {dots, folds} ->
  Enum.reduce(folds, dots, &amp;Manual.fold/2)
end)
|> then(fn dots ->
  dots
  |> Enum.unzip()
  |> Tuple.to_list()
  |> Enum.map(&amp;Enum.max/1)
  |> then(fn [max_x, max_y] ->
    Enum.map(0..max_y, fn y ->
      Enum.map(0..max_x, fn x ->
        if {x, y} in dots, do: "#", else: " "
      end)
      |> Enum.join()
    end)
  end)
end)
|> Enum.join("\n")
|> IO.puts()