Skip to content

Latest commit

 

History

History
111 lines (92 loc) · 1.92 KB

day3.livemd

File metadata and controls

111 lines (92 loc) · 1.92 KB

Advent 2021 - Day 3

Setup

Mix.install([
  {:kino, github: "livebook-dev/kino"}
])
input = Kino.Input.textarea("Please paste your input file:")
input =
  input
  |> Kino.Input.read()
  |> String.trim()
  |> String.split("\n")

Part 1

epsilon =
  input
  |> Enum.reduce(nil, fn line, acc ->
    result_of_line =
      String.graphemes(line)
      |> Enum.map(fn char ->
        if char == "0" do
          {1, 0}
        else
          {0, 1}
        end
      end)

    if acc == nil do
      result_of_line
    else
      Enum.zip(result_of_line, acc)
      |> Enum.map(fn {r, a} ->
        {r0, r1} = r
        {a0, a1} = a
        {r0 + a0, r1 + a1}
      end)
    end
  end)
  |> Enum.map(fn {zeros, ones} ->
    if zeros > ones do
      "0"
    else
      "1"
    end
  end)

{gamma, _} =
  epsilon
  |> Enum.map(fn value ->
    if value == "1" do
      "0"
    else
      "1"
    end
  end)
  |> Enum.join()
  |> Integer.parse(2)

{epsilon, _} =
  epsilon
  |> Enum.join()
  |> Integer.parse(2)

epsilon * gamma

Part 2

defmodule Part2 do
  def invoke(list, index, condition) do
    if length(list) == 1 do
      List.first(list)
    else
      %{"0" => zeros, "1" => ones} =
        list
        |> Enum.reduce(%{}, fn line, acc ->
          char =
            String.graphemes(line)
            |> Enum.at(index)

          Map.update(acc, char, 1, &(&1 + 1))
        end)

      keep = if condition.(zeros, ones), do: "0", else: "1"

      list = Enum.filter(list, fn line -> String.graphemes(line) |> Enum.at(index) == keep end)

      invoke(list, index + 1, condition)
    end
  end
end

oxygen_generator = Part2.invoke(input, 0, fn zeros, ones -> zeros > ones end)
c02_scrubber = Part2.invoke(input, 0, fn zeros, ones -> zeros <= ones end)

(Integer.parse(oxygen_generator, 2) |> elem(0)) * (Integer.parse(c02_scrubber, 2) |> elem(0))