For part 1 I rotates the matrix instead of looking in differente directions.
And for part 2, I went with a sliding window using Enum,chunks =)
defmodule Smaoc.Solution.Day4 do
def solve(:part1, input) do
matrix = parse_input(input)
[
[],
[:reverse],
[:transpose],
[:transpose, :reverse],
[:rotate45],
[:rotate45, :reverse],
[:reverse, :rotate45],
[:reverse, :rotate45, :reverse]
]
|> Enum.map(
&(matrix
|> apply_operations(&1)
|> count_XMAS)
)
|> Enum.sum()
end
def solve(:part2, input) do
valid_patterns = [
~r/M.M.A.S.S/,
~r/M.S.A.M.S/,
~r/S.M.A.S.M/,
~r/S.S.A.M.M/
]
input
|> parse_input()
|> Enum.chunk_every(3, 1, :discard)
|> Enum.map(fn row ->
row
|> transpose()
|> Enum.chunk_every(3, 1, :discard)
|> Enum.count(fn chunk ->
Enum.any?(valid_patterns, &Regex.match?(&1, to_string(chunk)))
end)
end)
|> Enum.sum()
end
defp parse_input(input) do
input
|> String.split("\n", trim: true)
|> Enum.map(&String.split(&1, "", trim: true))
end
def reverse(matrix), do: Enum.map(matrix, &Enum.reverse/1)
def transpose(matrix) do
matrix
|> Enum.zip()
|> Enum.map(&Tuple.to_list/1)
end
def rotate45(matrix) do
for(
{row, i} <- Enum.with_index(matrix),
{v, j} <- Enum.with_index(row),
do: {i + j, v}
)
|> Enum.group_by(&elem(&1, 0), &elem(&1, 1))
|> Enum.sort()
|> Enum.map(&elem(&1, 1))
end
def count_XMAS(matrix) do
matrix
|> Enum.map(fn l ->
~r/XMAS/
|> Regex.scan(to_string(l))
|> Enum.count()
end)
|> Enum.sum()
end
defp apply_operations(matrix, ops) do
Enum.reduce(ops, matrix, fn op, m -> apply(__MODULE__, op, [m]) end)
end
end






















