はじめに
Advent of code 2024 の準備として、過去回の Advent of code 2015 を Livebook で楽しみます
本記事では Day 5 の Part 1 と Part 2 を解きます
問題文はこちら
実装したノートブックはこちら
セットアップ
Kino AOC をインストールします
Mix.install([
{:kino_aoc, "~> 0.1"}
])
Kino AOC の使い方はこちらを参照
入力の取得
"Advent of Code Helper" スマートセルを追加し、 Day 5 の入力を取得します
私の答え
私の答えです。
折りたたんでおきます。
▶を押して開いてください。
Part 1
回答
条件を実装しやすい内容に読み替えます
- 母音を3文字以上含むか: 各文字のうち、母音であるものの数が 2 を超えているか
- 繰り返しを含むか: 正規表現で
(.)\1
(何らかの文字の直後に同じ文字がある)に該当する部分があるか - NGワードを含んでいないか: 各 NG ワードについて含んでいる回数が 0 になっているか
puzzle_input
|> String.split("\n")
|> Enum.count(fn word ->
has_three_vowels =
word
|> String.codepoints()
|> Enum.map(fn char ->
["a", "e", "i", "o", "u"]
|> Enum.count(&(&1 == char))
end)
|> Enum.sum()
|> Kernel.>(2)
has_twice =
Regex.run(~r/(.)\1/, word)
|> then(&!is_nil(&1))
no_ng =
["ab", "cd", "pq", "xy"]
|> Enum.count(fn ng -> String.contains?(word, ng) end)
|> Kernel.==(0)
(has_three_vowels and has_twice and no_ng)
end)
Part 2
回答
正規表現の問題です
-
(.{2,}).*\1
: 2文字以上の文字列が繰り返されている -
(.).{1}\1
: 同じ文字の間に違う文字が1文字ある
puzzle_input
|> String.split("\n")
|> Enum.count(fn word ->
has_repeat =
Regex.run(~r/(.{2,}).*\1/, word)
|> then(&!is_nil(&1))
has_between =
Regex.run(~r/(.).{1}\1/, word)
|> then(&!is_nil(&1))
(has_repeat and has_between)
end)
まとめ
問題文から ChatGPT に画像を生成してもらいました
以前、 AtCoder でやった問題と似ていたのですんなり解けました
やはり正規表現はしっかり習得しておかないといけませんね