— Day 4: Ceres Search —
Mix.install([{:kino_aoc, "~> 0.1"}])
Setup
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2024", "4", System.fetch_env!("LB_AOC_SESSION_COOKIE"))
test_input = Kino.Input.textarea("test_input")
defmodule CeresSearch do
def parse_rows(input) do
String.split(input, "\n", trim: true)
end
def matrix(input) do
input
|> parse_rows()
|> Enum.map(&String.graphemes/1)
end
def parse_columns(input) do
input
|> matrix()
|> Enum.zip_with(&Enum.join/1)
end
def parse_diagonal(matrix) do
for {row, idx} <- Enum.with_index(matrix),
{col, ^idx} <- Enum.with_index(row) do
col
end
end
def xmas_counter(row) do
xmas = ~r/XMAS/ |> Regex.scan(row) |> length()
samx = ~r/SAMX/ |> Regex.scan(row) |> length()
xmas + samx
end
def count_diagonals(matrix) do
counter = fn acc, count ->
acc |> parse_diagonal() |> Enum.join() |> xmas_counter() |> Kernel.+(count)
end
down_count =
matrix
|> Enum.reduce({matrix, 0}, fn _row, {acc, count} ->
{tl(acc), counter.(acc, count)}
end)
|> elem(1)
length = matrix |> hd() |> length()
accross_count =
2..length
|> Enum.reduce({Enum.map(matrix, &tl/1), 0}, fn _i, {acc, count} ->
{Enum.map(acc, &tl/1), counter.(acc, count)}
end)
|> elem(1)
down_count + accross_count
end
def sam_or_mas?("S", "M"), do: true
def sam_or_mas?("M", "S"), do: true
def sam_or_mas?(_, _), do: false
end
Part 1
import CeresSearch
test_input = Kino.Input.read(test_input)
accross =
puzzle_input
|> parse_rows()
|> Enum.reduce(0, &(xmas_counter(&1) + &2))
vertical =
puzzle_input
|> parse_columns()
|> Enum.reduce(0, &(xmas_counter(&1) + &2))
matrix = matrix(puzzle_input)
diagonals =
(
primary = count_diagonals(matrix)
secondary = matrix |> Enum.reverse() |> count_diagonals()
primary + secondary
)
diagonals + accross + vertical
Part 2
grid =
puzzle_input
|> matrix()
|> Enum.with_index()
|> Enum.reduce(%{}, fn {row, row_i}, acc ->
for {letter, col_i} <- Enum.with_index(row), reduce: acc do
acc -> Map.put(acc, {row_i, col_i}, letter)
end
end)
for {{row, col}, "A"} <- grid, row > 0 and col > 0, reduce: 0 do
acc ->
primary = sam_or_mas?(grid[{row - 1, col - 1}], grid[{row + 1, col + 1}])
secondary = sam_or_mas?(grid[{row - 1, col + 1}], grid[{row + 1, col - 1}])
if primary and secondary, do: acc + 1, else: acc
end