-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathday_15.ex
93 lines (77 loc) · 2.35 KB
/
day_15.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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
defmodule AdventOfCode.Y2021.Day15 do
@moduledoc """
--- Day 15: Chiton ---
Problem Link: https://adventofcode.com/2021/day/15
Difficulty: l
Tags: graph graph-route slow
"""
alias AdventOfCode.Helpers.{InputReader, Transformers}
def input, do: InputReader.read_from_file(2021, 15)
def run(input \\ input()) do
input = parse(input)
task_1 = Task.async(fn -> run_1(input) end)
task_2 = Task.async(fn -> run_2(input) end)
{Task.await(task_1, :infinity), Task.await(task_2, :infinity)}
end
def run_1(grid) do
grid
|> to_graph()
|> Graph.dijkstra({0, 0}, get_destination(grid))
|> tl()
|> Enum.sum_by(&Map.get(grid, &1))
end
def run_2(grid) do
grid = multiply(grid)
grid
|> to_graph()
|> Graph.dijkstra({0, 0}, get_destination(grid))
|> tl()
|> Enum.sum_by(&Map.get(grid, &1))
end
def parse(input) do
input
|> Transformers.lines()
|> Enum.with_index()
|> Enum.flat_map(fn {line, y} ->
line
|> String.graphemes()
|> Enum.with_index()
|> Enum.map(fn {column, x} -> {{x, y}, String.to_integer(column)} end)
end)
|> Map.new()
end
def to_graph(grid) do
graph =
Enum.reduce(grid, Graph.new(), fn {{x, y}, _}, graph ->
nbs =
[{x - 1, y}, {x + 1, y}, {x, y - 1}, {x, y + 1}]
|> Enum.filter(&Map.has_key?(grid, &1))
|> Enum.map(fn point -> {{x, y}, point, [weight: Map.get(grid, point)]} end)
Graph.add_edges(graph, nbs)
end)
invalid_edges =
graph
|> Graph.edges()
|> Enum.filter(fn %Graph.Edge{v1: {x1, y1}, v2: {x2, y2}} ->
abs(x1 - x2) > 1 and abs(y1 - y2) > 1
end)
Graph.delete_edges(graph, invalid_edges)
end
defp multiply(grid) do
{max_x, max_y} = get_destination(grid)
grid =
grid
|> Enum.reduce(grid, fn {{x, y}, risk}, grid ->
Enum.reduce(1..4, grid, fn index, grid ->
Map.put(grid, {x + index * (max_x + 1), y}, increment(risk + index))
end)
end)
Enum.reduce(grid, grid, fn {{x, y}, risk}, grid ->
Enum.reduce(1..4, grid, fn index, grid ->
Map.put(grid, {x, y + index * (max_y + 1)}, increment(risk + index))
end)
end)
end
defp increment(weight), do: (weight > 9 && weight - 9) || weight
defp get_destination(grid), do: grid |> Map.keys() |> Enum.max()
end