높이가 서로 다른 나무들이 모인 숲이 있을 때, 높이가 높은 다른 나무들에 가려져 숲 밖에서 볼 수 없는 위치를 찾아 집을 지으려고 한단다. 숲에 있는 나무들의 높이가 주어졌을 때 조건에 맞는 위치가 몇 곳인지 찾는 것이 첫 번째 문제, 그 중에서도 가장 전망이 좋은(밖의 나무들을 가장 많이 볼 수 있는) 위치를 찾는 것이 두 번째 문제였다. 처음에는 한 행, 한 열에서 가장 작은 값을 찾으면 되겠구나! 했는데 그것이 그렇지도 않아서, 그냥 다 내려놓고 모든 경우의 수를 다 찾는 코드를 짰다. 실행 시간이 생각보다 좀 걸리지만 아무튼 결과는 나온다.
defmodule Omicron.Day8 do
@dir "data/day8/"
def q1(file_name \\ "q.txt") do
row_size = 99
col_size = 99
grid = parse_grid(file_name)
0..(row_size - 1)
|> Enum.flat_map(fn i ->
0..(col_size - 1)
|> Enum.map(fn j ->
if i in 1..(row_size - 2) and j in 1..(col_size - 2) do
{row_left, row_right} = get_row(grid, i, j)
{col_up, col_down} = get_col(grid, j, i)
{{i, j},
any_big_element?(row_left, grid[{i, j}]) and
any_big_element?(row_right, grid[{i, j}]) and
any_big_element?(col_up, grid[{i, j}]) and
any_big_element?(col_down, grid[{i, j}])}
else
{{i, j}, false}
end
end)
end)
|> Enum.into(%{})
|> Enum.filter(fn {_, v} -> v == false end)
|> length
end
def q2(file_name \\ "q.txt") do
row_size = 99
col_size = 99
grid = parse_grid(file_name)
0..(row_size - 1)
|> Enum.flat_map(fn i ->
0..(col_size - 1)
|> Enum.map(fn j ->
if i in 1..(row_size - 2) and j in 1..(col_size - 2) do
{row_left, row_right} = get_row(grid, i, j)
{col_up, col_down} = get_col(grid, j, i)
left_dist =
viewing_distance(Enum.sort_by(row_left, fn {{_, c}, _} -> c end, :desc), grid[{i, j}])
right_dist =
viewing_distance(Enum.sort_by(row_right, fn {{_, c}, _} -> c end), grid[{i, j}])
up_dist =
viewing_distance(Enum.sort_by(col_up, fn {{r, _}, _} -> r end, :desc), grid[{i, j}])
down_dist =
viewing_distance(Enum.sort_by(col_down, fn {{r, _}, _} -> r end), grid[{i, j}])
{{i, j}, left_dist * right_dist * up_dist * down_dist}
else
{{i, j}, 0}
end
end)
end)
|> Enum.into(%{})
|> Map.values()
|> Enum.max()
end
defp parse_grid(file_name) do
File.read!(@dir <> file_name)
|> String.split("\n", trim: true)
|> Enum.with_index()
|> Enum.flat_map(fn {row, i} ->
String.graphemes(row)
|> Enum.with_index()
|> Enum.map(fn {col, j} ->
{{i, j}, col}
end)
end)
|> Enum.into(%{})
end
defp get_row(grid, row_num, split_col_num) do
grid
|> Map.delete({row_num, split_col_num})
|> Enum.filter(fn {{i, _}, _} -> row_num == i end)
|> Enum.split_with(fn {{_, j}, _} -> j <= split_col_num end)
|> then(fn {a, b} ->
{Enum.into(a, %{}), Enum.into(b, %{})}
end)
end
defp get_col(grid, col_num, split_row_num) do
grid
|> Map.delete({split_row_num, col_num})
|> Enum.filter(fn {{_, j}, _} -> col_num == j end)
|> Enum.split_with(fn {{i, _}, _} -> i <= split_row_num end)
|> then(fn {a, b} ->
{Enum.into(a, %{}), Enum.into(b, %{})}
end)
end
defp any_big_element?(line, compare_to) do
Enum.any?(line, fn {_, v} -> v >= compare_to end)
end
defp viewing_distance(sorted_line, compare_to) do
Enum.reduce_while(sorted_line, 0, fn {_, v}, acc ->
cond do
v < compare_to -> {:cont, acc + 1}
v == compare_to -> {:halt, acc + 1}
true -> {:halt, acc + 1}
end
end)
end
end
'호두나무 공방 > Advent of Code' 카테고리의 다른 글
Advent of Code 2022 Day 10 in Elixir - Cathode-Ray Tube 풀이 (0) | 2022.12.11 |
---|---|
Advent of Code 2022 Day 9 in Elixir - Rope Bridge 풀이 (0) | 2022.12.11 |
Advent of Code 2022 Day 7 in Elixir - No Space Left On Device 풀이 (0) | 2022.12.11 |
Advent of Code 2022 Day 6 in Elixir - Tuning Trouble 풀이 (0) | 2022.12.10 |
Advent of Code 2022 Day 5 in Elixir - Supply Stacks 풀이 (0) | 2022.12.10 |