6
1

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 2015 Day 14 Part 1 & Part 2 を Livebook で楽しむ

Last updated at Posted at 2024-11-26

はじめに

Advent of code 2024 の準備として、過去回の Advent of code 2015 を Livebook で楽しみます

本記事では Day 14 の Part 1 と Part 2 を解きます

問題文はこちら

実装したノートブックはこちら

セットアップ

Kino AOC をインストールします

Mix.install([
  {:kino_aoc, "~> 0.1"}
])

Kino AOC の使い方はこちらを参照

入力の取得

"Advent of Code Helper" スマートセルを追加し、 Day 14 の入力を取得します

スクリーンショット 2024-11-26 1.17.23.png

私の答え

私の答えです。
折りたたんでおきます。
▶を押して開いてください。

Part 1

回答

入力を正規表現でパースします

Regex.named_captures(
  ~r/(?<reindeer>[a-zA-Z]+) can fly (?<speed>\d+) km\/s for (?<keep>\d+) seconds, but then must rest for (?<rest>\d+)/,
  "Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds."
)

実行結果

%{"keep" => "10", "reindeer" => "Comet", "rest" => "127", "speed" => "14"}

各トナカイのスピード、持続時間、休憩時間、走行距離のマップ配列にします

reindeer_list =
  puzzle_input
  |> String.split("\n")
  |> Enum.map(fn row ->
    Regex.named_captures(
      ~r/(?<reindeer>[a-zA-Z]+) can fly (?<speed>\d+) km\/s for (?<keep>\d+) seconds, but then must rest for (?<rest>\d+)/,
      row
    )
    |> then(fn %{"speed" => speed, "keep" => keep, "rest" => rest} ->
      %{
        speed: String.to_integer(speed),
        keep: String.to_integer(keep),
        rest: String.to_integer(rest),
        distance: 0
      }
    end)
  end)

実行結果

[
  %{speed: 19, keep: 7, rest: 124, distance: 0},
  %{speed: 3, keep: 15, rest: 28, distance: 0},
  %{speed: 19, keep: 9, rest: 164, distance: 0},
  %{speed: 19, keep: 9, rest: 158, distance: 0},
  %{speed: 13, keep: 7, rest: 82, distance: 0},
  %{speed: 25, keep: 6, rest: 145, distance: 0},
  %{speed: 14, keep: 3, rest: 38, distance: 0},
  %{speed: 3, keep: 16, rest: 37, distance: 0},
  %{speed: 25, keep: 6, rest: 143, distance: 0}
]

各秒時点で各トナカイの走行距離を計算し、 2503 秒時点での最大値を求めます

1..2503
|> Enum.reduce(reindeer_list, fn sec, acc_reindeer_list ->
  acc_reindeer_list
  |> Enum.map(fn reindeer ->
    remain = rem(sec, reindeer.keep + reindeer.rest)
    if remain > 0 and remain <= reindeer.keep do
      Map.put(reindeer, :distance, reindeer.distance + reindeer.speed)
    else
      reindeer
    end
  end)
end)
|> Enum.map(&(&1.distance))
|> Enum.max()

Part 2

回答

各トナカイに point: 0 を初期値として与えます

reindeer_list =
  puzzle_input
  |> String.split("\n")
  |> Enum.map(fn row ->
    Regex.named_captures(
      ~r/(?<reindeer>[a-zA-Z]+) can fly (?<speed>\d+) km\/s for (?<keep>\d+) seconds, but then must rest for (?<rest>\d+)/,
      row
    )
    |> then(fn %{"speed" => speed, "keep" => keep, "rest" => rest} ->
      %{
        speed: String.to_integer(speed),
        keep: String.to_integer(keep),
        rest: String.to_integer(rest),
        distance: 0,
        point: 0
      }
    end)
  end)

各秒数時点で最も走行距離が長いトナカイにポイントを加算していき、最大ポイントを求めます

1..2503
|> Enum.reduce(reindeer_list, fn sec, acc_reindeer_list ->
  acc_reindeer_list =
    acc_reindeer_list
    |> Enum.map(fn reindeer ->
      remain = rem(sec, reindeer.keep + reindeer.rest)
      if remain > 0 and remain <= reindeer.keep do
        Map.put(reindeer, :distance, reindeer.distance + reindeer.speed)
      else
        reindeer
      end
    end)

  max_distance =
    acc_reindeer_list
    |> Enum.map(&(&1.distance))
    |> Enum.max()

  acc_reindeer_list
  |> Enum.map(fn reindeer ->
    if reindeer.distance == max_distance do
       Map.put(reindeer, :point, reindeer.point + 1)
    else
      reindeer
    end
  end)
end)
|> Enum.map(&(&1.point))
|> Enum.max()

まとめ

問題文から ChatGPT に画像を生成してもらいました

reindeer.jpeg

繰り返しだけで解ける問題だったので簡単でした

今のところ、 Day 7 で一番苦労しています

6
1
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
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?