0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Advent of Code 2025 Day 4を解いてみます。
できるだけGenerative AIsの力を使わずに解いてみます。

今年はDay 12までなのかな? あとで増えるのかな。

GitHub

Livebookのnotebook集を公開しておきます。
livebooks

参考記事

Advent of Code 2025 Day 4: Printing Department をRustで解いた

Day 4: Printing Department

問題文は、Day 4: Printing Departmentを読んでください。
Part 1を汎用的につくれば、Part 2も解ける形です。私にとっては解きやすかったです。これまでのところDay 1が一番苦戦しました。個人の感想です。

eight adjacent positions = 8マス隣接。
これの意味がわかりませんでした。これがわかってからはすんなり解けました。以下の図ではっきりわかりました💡 Don't think. Feelです。

↖ ↑ ↗
← @ →
↙ ↓ ↘

私の解答は折りたたんでおきます。

Part 1

Part 1
  • グリッド上の各@(紙ロール)について、周囲8マスにある@の数をカウント
  • 4個未満ならフォークリフトがアクセス可能としてカウントする
  • reduce_whileで4個以上見つかった時点で早期終了し、効率化している
defmodule AdventOfCode2025Day4Part1Solver do
  def solve(map) do
    map
    |> Enum.reduce({0, map}, &fun/2)
    |> elem(0)
  end

  def fun({{_i, _j}, ?.}, {acc, map}), do: {acc, map}
  def fun({{i, j}, ?@}, {acc, map}) do
    directions = [
      {-1, -1}, {0, -1}, {1, -1},
      {-1,  0},          {1,  0},
      {-1,  1}, {0,  1}, {1,  1}
    ]

    new_acc = directions
    |> Enum.reduce_while(0, fn {x, y}, cnt ->
      v = Map.get(map, {i + x, j + y}, ?.)
      
      (if v == ?@, do: cnt + 1, else: cnt)
      |> do_fun()
    end)
    |> Kernel.<(4)
    |> if(do: acc + 1, else: acc)

    {new_acc, map}
  end

  defp do_fun(new_cnt) when new_cnt >= 4, do: {:halt, new_cnt}
  defp do_fun(new_cnt), do: {:cont, new_cnt}
end

defmodule AdventOfCode2025Day4Part1 do
  def run(input) do
    input
    |> parse_input()
    |> AdventOfCode2025Day4Part1Solver.solve()
  end

  defp parse_input(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.with_index()
    |> Enum.reduce(%{}, fn {line, i}, acc ->
      line
      |> String.to_charlist()
      |> Enum.with_index()
      |> Enum.reduce(acc, fn {c, j}, acc ->
        Map.put(acc, {i, j}, c)
      end)
    end)
  end
end

input = """
..@@.@@@@.
@@@.@.@.@@
@@@@@.@.@@
@.@@@@..@.
@@.@@@@.@@
.@@@@@@@.@
.@.@.@.@@@
@.@@@.@@@@
.@@@@@@@@.
@.@.@@@.@.
"""

AdventOfCode2025Day4Part1.run(input)

Part 2

Part 2
  • Part 1のロジックを繰り返し適用する。アクセス可能なロールを見つけたら?xでマークして削除扱いにし、再度チェック
  • ロールが減ると周囲の密度が下がり、新たにアクセス可能になるロールが出現する
  • 削除対象がなくなるまで再帰し、累積削除数が答え
defmodule AdventOfCode2025Day4Part2Solver do
  def solve(map) do
    do_solve(map, 0)
  end

  defp do_solve(map, cnt) do
    removes = map |> Enum.reduce({[], map}, &fun/2) |> elem(0)
    if Enum.count(removes) == 0 do
      cnt
    else
      new_cnt = cnt + Enum.count(removes)
      new_map = removes
        |> Enum.reduce(map, fn {i, j}, acc ->
          Map.put(acc, {i, j}, ?x)
        end)

      do_solve(new_map, new_cnt)
    end
  end

  defp fun({{_i, _j}, ?.}, {acc, map}), do: {acc, map}
  defp fun({{_i, _j}, ?x}, {acc, map}), do: {acc, map}
  defp fun({{i, j}, ?@}, {acc, map}) do
    directions = [
      {-1, -1}, {0, -1}, {1, -1},
      {-1,  0},          {1,  0},
      {-1,  1}, {0,  1}, {1,  1}
    ]

    new_acc = directions
    |> Enum.reduce_while(0, fn {x, y}, cnt ->
      v = Map.get(map, {i + x, j + y}, ?.)
      
      (if v == ?@, do: cnt + 1, else: cnt)
      |> do_fun()
    end)
    |> Kernel.<(4)
    |> if(do: [{i, j} | acc], else: acc)

    {new_acc, map}
  end

  defp do_fun(new_cnt) when new_cnt >= 4, do: {:halt, new_cnt}
  defp do_fun(new_cnt), do: {:cont, new_cnt}
end

defmodule AdventOfCode2025Day4Part2 do
  def run(input) do
    input
    |> parse_input()
    |> AdventOfCode2025Day4Part2Solver.solve()
  end

  defp parse_input(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.with_index()
    |> Enum.reduce(%{}, fn {line, i}, acc ->
      line
      |> String.to_charlist()
      |> Enum.with_index()
      |> Enum.reduce(acc, fn {c, j}, acc ->
        Map.put(acc, {i, j}, c)
      end)
    end)
  end
end

input = """
..@@.@@@@.
@@@.@.@.@@
@@@@@.@.@@
@.@@@@..@.
@@.@@@@.@@
.@@@@@@@.@
.@.@.@.@@@
@.@@@.@@@@
.@@@@@@@@.
@.@.@@@.@.
"""

AdventOfCode2025Day4Part2.run(input)

さいごに

今回は自力で全部解けました。力技で解けました。よかった :tada:

どこまでできるかわかりませんが、たまには自分で書くこともしたほうがよさそうなので、Advent of Code 2025を引き続き解いて行くことを楽しみたいと思います。

Advent of Code 2025を解くことは、闘魂活動だと思います。
あなたもぜひお好きなプログラミング言語で解いてみてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?