다른 일정 탓에 조금 늦게 올리는 5일차 문제 풀이. 좌표평면상의 가로, 세로, 대각선(문제 2에서만)상에 있는 열수분출공(hydrothermal vent)에 대해, 2개 이상의 열수맥(?)이 겹치는 곳의 개수를 찾는 문제였다. 지금까지 거의 모든 문제에서 Enum.reduce
를 사용했는데, 이번에도 그 힘으로 어렵지 않게 풀 수 있었다.
신경쓴 부분이라고 하면 get_points
의 패턴 매칭 부분. 문제 1에서는 가로세로만 고려하면 되어서, get_line
함수 없이 get_points
를 4개 함수로 나누었었다.
when x1 > x2
(즉y1 == y2
)when x1 < x2
(즉y1 == y2
)when y1 > y2
(즉x1 == x2
)when y1 < y2
(즉x1 == x2
)
문제 1은 그렇게 풀었는데, 문제 2에서 대각선도 생각해야 해서 한 좌표축의 연속된 점들을 리스트로 반환하는 get_line
을 분리하고, 여기서 대소관계에 따른 처리를 모두 담당하도록 해서 get_points
를 조금 더 단순하게 다듬을 수 있었다. 두 번째 파라미터인 :q1
, :q2
아톰은 1번 문제에서 대각선 입력을 처리하지 않아야 해서 임의로 구분한 부분이다.
defmodule Day5 do
def parse_input do
path = "input/day5.txt"
File.read!(path)
|> String.split("\n")
|> Enum.map(&parse_vent/1)
end
defp parse_vent(input_line) do
input_line
|> String.split(" -> ")
|> Enum.map(fn point ->
point
|> String.split(",")
|> Enum.map(&String.to_integer/1)
|> List.to_tuple()
end)
|> List.to_tuple()
end
@spec run_q1 :: non_neg_integer
def run_q1 do
parse_input()
|> Enum.reduce(%{}, fn vent, acc ->
get_points(vent, :q1)
|> Enum.reduce(acc, fn point, tmp_acc ->
Map.update(tmp_acc, point, 1, &(&1 + 1))
end)
end)
|> Enum.filter(fn {_k, v} -> v >= 2 end)
|> Enum.count()
end
@spec run_q2 :: non_neg_integer
def run_q2 do
parse_input()
|> Enum.reduce(%{}, fn vent, acc ->
get_points(vent, :q2)
|> Enum.reduce(acc, fn point, tmp_acc ->
Map.update(tmp_acc, point, 1, &(&1 + 1))
end)
end)
|> Enum.filter(fn {_k, v} -> v >= 2 end)
|> Enum.count()
end
@spec get_points({{integer, integer}, {integer, integer}}, :q1 | :q2) ::
list({integer, integer})
def get_points({{x1, y}, {x2, y}}, _) do
get_line(x1, x2) |> Enum.map(&{&1, y})
end
def get_points({{x, y1}, {x, y2}}, _) do
get_line(y1, y2) |> Enum.map(&{x, &1})
end
def get_points({{_x1, _y1}, {_x2, _y2}}, :q1) do
[]
end
def get_points({{x1, y1}, {x2, y2}}, :q2) do
Enum.zip(get_line(x1, x2), get_line(y1, y2))
end
@spec get_line(integer, integer) :: list
def get_line(a, b) when a < b, do: a..b |> Enum.to_list()
def get_line(a, b) when a > b, do: a..b//-1 |> Enum.to_list()
end
'호두나무 공방 > Advent of Code' 카테고리의 다른 글
Advent of Code 2021 Day 7 in Elixir - The Treachery of Whales (0) | 2021.12.07 |
---|---|
Advent of Code 2021 Day 6 in Elixir - Lanternfish (0) | 2021.12.06 |
Advent of Code 2021 Day 4 in Elixir - Giant Squid (0) | 2021.12.04 |
Advent Of Code 2021 Day 3 in Elixir - Binary Diagnostic (0) | 2021.12.03 |
Advent of Code 2021 Day 2 in Elixir - Dive! (0) | 2021.12.02 |