Powered by AppSignal & Oban Pro

Advent of Code 2021 - Day 6

2021/day06.livemd

Advent of Code 2021 - Day 6

Setup

Mix.install([
  {:kino, "~> 0.4.1"}
])
:ok
example_input = Kino.Input.textarea("Please enter the example input:")
my_input = Kino.Input.textarea("Please enter your input:")
defmodule Parser do
  def parse_input(input) do
    input
    |> String.split(",", trim: true)
    |> Enum.map(&String.to_integer/1)
  end
end

example_input =
  example_input
  |> Kino.Input.read()
  |> Parser.parse_input()

my_input =
  my_input
  |> Kino.Input.read()
  |> Parser.parse_input()

:ok
:ok

Part 1

defmodule Day6.Part1 do
  def solve(input, days) do
    input
    |> simulate(days)
    |> Enum.count()
  end

  defp simulate(fish, 0), do: fish

  defp simulate(fish, days) do
    baby_fish =
      fish
      |> Enum.filter(fn days_left -> days_left == 0 end)
      |> Enum.map(fn _ -> 8 end)

    older_fish =
      Enum.map(fish, fn days_left ->
        if days_left == 0, do: 6, else: days_left - 1
      end)

    simulate(older_fish ++ baby_fish, days - 1)
  end
end

Day6.Part1.solve(my_input, 80)
390011

Part 2

Part 2 just asks you to run for 256 days. The part 1 solution takes way too long to solve.

Instead of modelling each individual fish in a list of fishes, we should keep map of how many fish are at the next number of days to reproduce.

So instead of storing data like this: [1, 5, 4, 8, 7, 1, 3, 5]

Store it like this: %{1 => 2, 5 => 2, 4 => 1, 8 => 1, 7 => 1, 3 => 1}.

defmodule Day6.Part2 do
  def solve(input, days) do
    input
    |> Enum.frequencies()
    |> simulate(days)
    |> Enum.reduce(0, fn {_, count}, sofar -> count + sofar end)
  end

  defp simulate(fish, 0), do: fish

  defp simulate(fish, days) do
    baby_fish = Map.get(fish, 0)

    older_fish =
      Enum.reduce(fish, %{}, fn {days_left, n}, sofar ->
        days_left = if days_left == 0, do: 6, else: days_left - 1
        Map.update(sofar, days_left, n, fn v -> n + v end)
      end)

    fish = if baby_fish, do: Map.put_new(older_fish, 8, baby_fish), else: older_fish

    simulate(fish, days - 1)
  end
end

Day6.Part2.solve(my_input, 256)
1746710169834