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

Day 9: Rope Bridge -- AoC 22

2022/09.livemd

Day 9: Rope Bridge – AoC 22

stream = File.stream!("/Users/pw/src/weiland/adventofcode/2022/input/09.txt")

Part One

instructions =
  stream
  |> Stream.map(&String.trim/1)
  |> Stream.map(&String.split(&1, " "))
  |> Stream.flat_map(fn [i, n] -> List.duplicate(i, String.to_integer(n)) end)

instructions
|> Enum.to_list()
defmodule Solution do
  def parse(instructions) do
    init_value = %{head: %{x: 0, y: 0}, tail: %{x: 0, y: 0}, moves: [%{x: 0, y: 0}]}

    instructions
    |> Enum.reduce(init_value, &reduce/2)
    |> then(fn value -> value.moves end)
    |> Enum.uniq()
    |> Enum.count()
  end

  def reduce(instruction, %{head: head, tail: tail, moves: moves}) do
    x =
      case instruction do
        "L" -> -1
        "R" -> 1
        _ -> 0
      end

    y =
      case instruction do
        "U" -> 1
        "D" -> -1
        _ -> 0
      end

    new_head = %{x: head.x + x, y: head.y + y}
    new_tail = if is_touching(new_head, tail), do: tail, else: head
    new_moves = if new_tail != tail, do: [new_tail | moves], else: moves

    %{head: new_head, tail: new_tail, moves: new_moves}
  end

  def is_touching(head, tail) do
    Kernel.abs(head.x - tail.x) <= 1 &amp;&amp; Kernel.abs(head.y - tail.y) <= 1
  end
end

Solution.parse(instructions)

Part Two

defmodule SolutionPartTwo do
  def parse(instructions) do
    init_value = %{
      head: %{x: 0, y: 0},
      tails: List.duplicate(%{x: 0, y: 0}, 9),
      moves: [%{x: 0, y: 0}]
    }

    instructions
    |> Enum.reduce(init_value, &amp;reduce/2)

    # |> then(fn value -> value.moves end)
    # |> Enum.uniq
    # |> Enum.count
  end

  def reduce(instruction, %{head: head, tails: tails, moves: moves}) do
    x =
      case instruction do
        "L" -> -1
        "R" -> 1
        _ -> 0
      end

    y =
      case instruction do
        "U" -> 1
        "D" -> -1
        _ -> 0
      end

    new_head = %{x: head.x + x, y: head.y + y}

    new_tails =
      tails
      |> Enum.reduce([], fn tail, acc ->
        # prev = List.last(acc)
        old_tail = if length(acc) == 0, do: new_head, else: List.last(acc)
        new_tail = if is_touching(new_head, tail), do: tail, else: old_tail

        [new_tail | acc]
      end)

    # new_moves = if new_tail != tail, do: [new_tail | moves], else: moves

    %{head: new_head, tails: new_tails, moves: moves}
  end

  def is_touching(a, b) do
    Kernel.abs(a.x - b.x) <= 1 &amp;&amp; Kernel.abs(a.y - b.y) <= 1
  end
end

SolutionPartTwo.parse(instructions)

# 6464 is too high