Powered by AppSignal & Oban Pro

🎄 Year 2022 🔔 Day 09

elixir/notebooks/2022/day09.livemd

🎄 Year 2022 🔔 Day 09

Problem

Parse input

filename = "#{__DIR__}/../../../inputs/2022/day09.txt"

parsed_steps =
  File.stream!(filename)
  |> Enum.map(&String.trim/1)
  |> Enum.map(fn line ->
    [dir, steps] = line |> String.split()
    {dir, String.to_integer(steps)}
  end)

Shared code

Part One

defmodule Helper do
  def step({head_coords, tail_coords}, dir) do
    new_head_coords = step_head(head_coords, dir)
    new_tail_coords = step_tail(new_head_coords, tail_coords)

    {new_head_coords, new_tail_coords}
  end

  defp step_head({x, y}, "L"), do: {x - 1, y}
  defp step_head({x, y}, "R"), do: {x + 1, y}
  defp step_head({x, y}, "U"), do: {x, y + 1}
  defp step_head({x, y}, "D"), do: {x, y - 1}

  defp step_tail({hx, hy}, {tx, ty}) do
    cond do
      hx + 2 == tx ->
        {tx - 1, hy}

      hx - 2 == tx ->
        {tx + 1, hy}

      hy + 2 == ty ->
        {hx, ty - 1}

      hy - 2 == ty ->
        {hx, ty + 1}

      true ->
        {tx, ty}
    end
  end
end

parsed_steps
|> Enum.flat_map(fn {dir, steps} -> List.duplicate(dir, steps) end)
|> Enum.scan({{0, 0}, {0, 0}}, &Helper.step(&2, &1))
|> then(&[{{0, 0}, {0, 0}} | &1])
|> Enum.map(&elem(&1, 1))
|> Enum.uniq()
|> Enum.count()

Part two

hx = 54
tx = 52

div(hx - tx, abs(hx - tx))
defmodule Helper do
  def step([head_coords | tail_coords], dir) do
    new_head_coords = step_head(head_coords, dir)
    new_tail_coords = Enum.scan(tail_coords, new_head_coords, &step_tail(&2, &1))

    [new_head_coords | new_tail_coords]
  end

  defp step_head({x, y}, "L"), do: {x - 1, y}
  defp step_head({x, y}, "R"), do: {x + 1, y}
  defp step_head({x, y}, "U"), do: {x, y + 1}
  defp step_head({x, y}, "D"), do: {x, y - 1}

  defp step_tail({hx, hy}, {tx, ty}) do
    if abs(hx - tx) >= 2 || abs(hy - ty) >= 2 do
      nx = if hx != tx, do: tx + div(hx - tx, abs(hx - tx)), else: tx
      ny = if hy != ty, do: ty + div(hy - ty, abs(hy - ty)), else: ty
      {nx, ny}
    else
      {tx, ty}
    end
  end
end

parsed_steps
|> Enum.flat_map(fn {dir, steps} -> List.duplicate(dir, steps) end)
|> Enum.scan(List.duplicate({0, 0}, 10), &Helper.step(&2, &1))
|> Enum.map(&Enum.at(&1, 9))
|> Enum.uniq()
|> Enum.count()