번식 주기가 있는 피보나치 토끼 문제. 10년쯤 전에 '피보나치 토끼에 수명이 있다면 어떻게 번식할까'를 소재로 코드를 쫌쫌 짜본 기억도 나고 해서 재밌게 풀었다.
1번 문제는 그냥 리스트 처리로 무작정 풀어도 금방 됐는데, 2번 문제를 같은 방식으로 돌려보니 영 소식이 없어서 급하게 방향을 틀었다. 생각해보니 다음 번식까지 남은 일자별 마릿수만 계산하면 됐지 순서까지 생각할 필요는 없겠어서 %{번식까지 남은 날(일 단위) => 마릿수}
형식의 맵 처리로 변경. 리스트 처리를 이용한 기존 버전이 run_q1_old
, 고친 버전이 run_q1
, run_q2
이다. 제법 만족스럽게 풀렸다.
defmodule Day6 do
@period 6
@first_period @period + 2
def parse_input do
path = "input/day6.txt"
File.read!(path)
|> String.split(",")
|> Enum.map(&String.to_integer/1)
end
@spec run_q1 :: non_neg_integer
def run_q1 do
parse_input()
|> Enum.frequencies()
|> step(80)
|> Map.values()
|> Enum.sum()
end
@spec run_q1_old :: non_neg_integer
def run_q1_old do
parse_input()
|> step_old(80)
|> Enum.count()
end
def run_q2 do
parse_input()
|> Enum.frequencies()
|> step(256)
|> Map.values()
|> Enum.sum()
end
@spec step(%{integer() => integer()}, integer()) :: %{integer() => integer()}
defp step(fishes, 0) do
fishes
end
defp step(fishes, remain_day) do
fishes
|> Enum.reduce(%{}, fn
{0, fish_count}, acc_fishes ->
acc_fishes
|> Map.update(@period, fish_count, &(&1 + fish_count))
|> Map.update(@first_period, fish_count, &(&1 + fish_count))
{day, fish_count}, acc_fishes ->
acc_fishes
|> Map.update(day - 1, fish_count, &(&1 + fish_count))
end)
|> step(remain_day - 1)
end
@spec step_old(list(integer), integer) :: list(integer)
defp step_old(fishes, 0) do
fishes
end
defp step_old(fishes, remain_day) do
{existing_fishes, count_of_new_fishes} =
fishes
|> Enum.reduce({[], 0}, fn
0, {fishes, count_of_new_fishes} ->
{[6 | fishes], count_of_new_fishes + 1}
day, {acc, count_of_new_fishes} ->
{[day - 1 | acc], count_of_new_fishes}
end)
1..count_of_new_fishes//1
|> Enum.map(fn _ -> @first_period end)
|> Kernel.++(existing_fishes)
|> Enum.reverse()
# |> IO.inspect(label: remain_day)
|> step_old(remain_day - 1)
end
end
'호두나무 공방 > Advent of Code' 카테고리의 다른 글
Advent of Code 2021 Day 8 in Elixir - Seven Segment Search (0) | 2021.12.08 |
---|---|
Advent of Code 2021 Day 7 in Elixir - The Treachery of Whales (0) | 2021.12.07 |
Advent of Code 2021 Day 5 in Elixir - Hydrothermal Venture (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 |