-
Notifications
You must be signed in to change notification settings - Fork 0
/
03b.exs
74 lines (67 loc) · 2.13 KB
/
03b.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# elixir 03b.exs
defmodule Solution do
def is_digit(x) do
x in ?0..?9
end
def is_symbol(x) do
!is_digit(x) && x != ?. && x != nil
end
def find_gears(a, x, y0, result) do
if x == map_size(a) do
result
else
m = map_size(a[x]) - 1
y1 = Enum.find(y0..m, fn y -> is_digit(a[x][y]) end)
if y1 == nil do
find_gears(a, x + 1, 0, result)
else
y2 = Enum.find(y1..m, fn y -> !is_digit(a[x][y]) end) - 1
number = List.foldl(Enum.to_list(y1..y2), 0, fn y, acc -> acc * 10 + (a[x][y] - 48) end)
pairs = Enum.flat_map((y1 - 1)..(y2 + 1), fn y ->
Enum.map(max(x - 1, 0)..min(x + 1, map_size(a) - 1), fn x ->
{x, y}
end)
end)
gears = Enum.filter(pairs, fn xy ->
{x, y} = xy
a[x][y] == ?*
end)
result = List.foldl(gears, result, fn gear, map ->
prev = map[gear]
if prev == nil do
Map.put(map, gear, [number])
else
Map.put(map, gear, prev ++ [number])
end
end)
find_gears(a, x, y2 + 1, result)
end
end
end
def solve(a) do
gears = find_gears(a, 0, 0, %{})
List.foldl(Map.values(gears), 0, fn ratios, result ->
if length(ratios) == 2 do
result + Enum.product(ratios)
else
result
end
end)
end
def to_array(line) do
line
|> String.to_charlist
|> Enum.with_index
|> Enum.map(fn({char, index}) -> {index, char} end)
|> Map.new
end
def main() do
input = IO.read(:stdio, :all)
|> String.split("\n")
|> Enum.with_index
|> Enum.map(fn({line, index}) -> {index, to_array("." <> line <> ".")} end)
|> Map.new
IO.inspect(solve(input))
end
end
Solution.main()