-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathday_09.ex
73 lines (65 loc) · 1.75 KB
/
day_09.ex
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
defmodule AdventOfCode.Y2021.Day09 do
@moduledoc """
--- Day 9: Smoke Basin ---
Problem Link: https://adventofcode.com/2021/day/9
Difficulty: m
Tags: graph scc
"""
alias AdventOfCode.Helpers.{InputReader, Transformers}
def input, do: InputReader.read_from_file(2021, 9)
def run(input \\ input()) do
input = parse(input)
{risk_point(input), basin_multiplier(make_graph(input))}
end
def parse(data) do
data
|> Transformers.lines()
|> Enum.with_index()
|> Enum.flat_map(fn {line, x} ->
line
|> String.graphemes()
|> Enum.with_index()
|> Enum.map(fn {value, y} -> {{x, y}, String.to_integer(value)} end)
end)
|> Map.new()
end
defp risk_point(map) do
Enum.reduce(
map,
[],
fn {{x, y}, weight}, lowest_list ->
{x, y}
|> adjacent_points()
|> Enum.reduce(true, &(&2 && map[&1] > weight))
|> then(&((&1 && [weight + 1 | lowest_list]) || lowest_list))
end
)
|> Enum.sum()
end
defp make_graph(input) do
map = Map.filter(input, fn {_, w} -> w != 9 end)
map
|> Enum.reduce(
Graph.add_vertices(%Graph{}, Map.keys(map)),
fn {{x, y} = vertex, weight}, g_1 ->
{x, y}
|> adjacent_points()
|> Enum.reduce(g_1, fn {new_x, new_y}, g_2 ->
Graph.add_edge(g_2, vertex, {new_x, new_y}, weight: weight)
end)
end
)
end
defp adjacent_points({x, y}) do
[{x + 1, y}, {x - 1, y}, {x, y + 1}, {x, y - 1}]
|> Enum.filter(fn {x, y} -> x >= 0 and y >= 0 and (x <= 99 and y <= 99) end)
end
defp basin_multiplier(graph) do
graph
|> Graph.strong_components()
|> Enum.map(&length/1)
|> Enum.sort(:desc)
|> Enum.take(3)
|> Enum.reduce(&Kernel.*/2)
end
end