From 499a6f145d428a16ad1710b5ecc3349771bf09c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Geron?= Date: Sat, 7 Dec 2024 19:34:39 +1300 Subject: [PATCH] Solve day 4 --- lib/aoc2024/day_04.ex | 99 ++++++++++++++++++++++++++++++++++++++++--- test/aoc2024_test.exs | 19 +++++++++ 2 files changed, 113 insertions(+), 5 deletions(-) diff --git a/lib/aoc2024/day_04.ex b/lib/aoc2024/day_04.ex index d88421d..8936220 100644 --- a/lib/aoc2024/day_04.ex +++ b/lib/aoc2024/day_04.ex @@ -1,13 +1,102 @@ defmodule Aoc2024.Day04 do def parse(input) do - input |> String.split("\n", trim: true) + input |> String.split("\n", trim: true) |> Enum.map(&String.graphemes/1) end - def part1(_lines) do - :todo1 + defp size(grid) do + height = length(grid) + width = grid |> Enum.map(&length/1) |> Enum.max() + {height, width} end - def part2(_lines) do - :todo2 + def part1(grid) do + word_chars = "XMAS" |> String.graphemes() + {height, width} = grid |> size() + + -1..1 + |> Enum.map(fn dy -> + -1..1 + |> Enum.map(fn dx -> + if dx == 0 && dy == 0 do + 0 + else + 0..(height - 1) + |> Enum.map(fn y -> + 0..(width - 1) + |> Enum.map(fn x -> + all_chars_ok = + word_chars + |> Enum.with_index() + |> Enum.all?(fn {char, index} -> + cy = y + index * dy + cx = x + index * dx + + cond do + cy < 0 -> + false + + cx < 0 -> + false + + cy >= height -> + false + + true -> + row = grid |> Enum.at(cy) + + if cx >= length(row) do + false + else + row |> Enum.at(cx) == char + end + end + end) + + if all_chars_ok do + 1 + else + 0 + end + end) + |> Enum.sum() + end) + |> Enum.sum() + end + end) + |> Enum.sum() + end) + |> Enum.sum() + end + + def part2(grid) do + {height, width} = grid |> size() + + 0..(height - 3) + |> Enum.map(fn y -> + 0..(width - 3) + |> Enum.map(fn x -> + center = grid |> Enum.at(y + 1) |> Enum.at(x + 1) + upper_left = grid |> Enum.at(y) |> Enum.at(x) + lower_right = grid |> Enum.at(y + 2) |> Enum.at(x + 2) + upper_right = grid |> Enum.at(y) |> Enum.at(x + 2) + lower_left = grid |> Enum.at(y + 2) |> Enum.at(x) + + diag1? = + (upper_left == "M" && lower_right == "S") || + (upper_left == "S" && lower_right == "M") + + diag2? = + (upper_right == "M" && lower_left == "S") || + (upper_right == "S" && lower_left == "M") + + if center == "A" && diag1? && diag2? do + 1 + else + 0 + end + end) + |> Enum.sum() + end) + |> Enum.sum() end end diff --git a/test/aoc2024_test.exs b/test/aoc2024_test.exs index 5a8eaad..3d3976b 100644 --- a/test/aoc2024_test.exs +++ b/test/aoc2024_test.exs @@ -51,4 +51,23 @@ defmodule Aoc2024Test do input = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)\n+mul(32,64](mul(11,8)undo()?mul(8,5))" assert Aoc2024.Day03.part2(input) == 48 end + + test "Day 4" do + input = """ + MMMSXXMASM + MSAMXMSMSA + AMXSXMAAMM + MSAMASMSMX + XMASAMXAMM + XXAMMXXAMA + SMSMSASXSS + SAXAMASAAA + MAMMMXMMMM + MXMXAXMASX + """ + + parsed_input = Aoc2024.Day04.parse(input) + assert Aoc2024.Day04.part1(parsed_input) == 18 + assert Aoc2024.Day04.part2(parsed_input) == 9 + end end