1
defmodule FourEnum do
2
defstruct [:grid, :row, :col]
3
end
4
5
defmodule Four do
6
defstruct [:map, :width, :height]
7
8
def parse(input) do
9
lines = input |> String.trim() |> String.split("\n")
10
width = lines |> Enum.at(0) |> String.length()
11
height = lines |> Enum.count()
12
map =
13
lines
14
|> Enum.with_index()
15
|> Enum.map(fn {line, row} ->
16
{row,
17
line
18
|> String.to_charlist()
19
|> Enum.with_index()
20
|> Enum.map(fn {char, col} ->
21
{col, char == ?@}
22
end)
23
|> Enum.into(%{})}
24
end)
25
|> Enum.into(%{})
26
%Four{map: map, width: width, height: height}
27
end
28
29
def enum(%Four{} = grid),
30
do: %FourEnum{grid: grid, row: 0, col: 0}
31
32
def at_position(%Four{map: map, width: width, height: height}, r, c)
33
when r >= 0 and c >= 0 and r < height and c < height,
34
do: map[r][c]
35
36
def at_position(_, _, _),
37
do: nil
38
end
39
40
defimpl Enumerable, for: FourEnum do
41
def count(_),
42
do: {:error, __MODULE__}
43
44
def member?(_, _),
45
do: {:error, __MODULE__}
46
47
def reduce(_enum, {:halt, acc}, _fun), do: {:halted, acc}
48
def reduce(enum, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(enum, &1, fun)}
49
def reduce(%FourEnum{grid: %Four{map: map, width: width, height: height} = grid, row: row, col: col}, {:cont, acc}, fun) do
50
cond do
51
row == height ->
52
{:done, acc}
53
col == width - 1 ->
54
reduce(%FourEnum{grid: grid, row: row + 1, col: 0}, fun.({row, col, map[row][col]}, acc), fun)
55
true ->
56
reduce(%FourEnum{grid: grid, row: row, col: col + 1}, fun.({row, col, map[row][col]}, acc), fun)
57
end
58
end
59
60
def slice(_),
61
do: {:error, __MODULE__}
62
end
63
64
input = """
65
..@@.@@@@.
66
@@@.@.@.@@
67
@@@@@.@.@@
68
@.@@@@..@.
69
@@.@@@@.@@
70
.@@@@@@@.@
71
.@.@.@.@@@
72
@.@@@.@@@@
73
.@@@@@@@@.
74
@.@.@@@.@.
75
"""
76
77
input = File.read!("4.input")
78
79
grid = Four.parse(input)
80
Enum.sum_by(Four.enum(grid), fn {row, col, set} ->
81
if set and Enum.sum_by(row - 1..row + 1, fn r -> Enum.sum_by(col - 1..col + 1, fn c -> if(!(r == row and c == col) and Four.at_position(grid, r, c) == true, do: 1, else: 0) end) end) < 4 do
82
1
83
else
84
0
85
end
86
end) |> IO.inspect()
87