Powered by AppSignal & Oban Pro

Day 3

2021/day03.livemd

Day 3

Input

stream =
  File.stream!("day3.txt")
  |> Enum.map(&String.trim/1)
  |> Enum.map(&String.to_charlist/1)

defmodule Day3 do
  def count(list) do
    Enum.reduce(list, List.duplicate(0, 12), fn input, acc ->
      for {value, counter} <- Enum.zip(input, acc) do
        case value do
          ?1 -> counter + 1
          ?0 -> counter
        end
      end
    end)
  end
end
{:module, Day3, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:count, 1}}

Task 1

half = div(length(stream), 2)

{a, b} =
  stream
  |> Day3.count()
  |> Enum.reduce({0, 0}, fn elem, {a, b} ->
    if elem > half do
      {a * 2 + 1, b * 2}
    else
      {a * 2, b * 2 + 1}
    end
  end)

a * b
3847100

Task 2

defmodule Day3.Task2 do
  def reduce(list, cb), do: reduce(list, 0, cb)

  defp reduce([elem], _, _), do: elem

  defp reduce(list, at, cb) do
    counts = Day3.count(list)

    half = div(length(list), 2)
    count = Enum.at(counts, at)

    bit =
      cond do
        count == half and cb.(count + 1, half) -> ?1
        count != half and cb.(count, half) -> ?1
        true -> ?0
      end

    reduce(Enum.filter(list, &(Enum.at(&1, at) == bit)), at + 1, cb)
  end
end

co2 = List.to_integer(Day3.Task2.reduce(stream, &</2), 2)
o2 = List.to_integer(Day3.Task2.reduce(stream, &>/2), 2)

co2 * o2
4105235