Advent of Code 2021 - Day 3
Mix.install([
{:kino, "~> 0.6.1"}
])
Instructions
https://adventofcode.com/2021/day/3
Get input
Paste the test input from the Day 3 instructions, your own input from Advent of Code, or copy from sdball 2021 Advent of Code Day 3 input
input = Kino.Input.textarea("Please paste your input:")
input = input |> Kino.Input.read() |> String.split()
Part 1
[sample | _] = input
bit_count = sample |> String.length()
frequencies =
for x <- 0..(bit_count - 1) do
input
|> Enum.map(fn number ->
String.at(number, x) |> String.to_integer()
end)
end
|> Enum.map(fn bits ->
bits |> Enum.frequencies()
end)
gamma =
frequencies
|> Enum.map(fn freq ->
if freq[0] < freq[1], do: 1, else: 0
end)
|> Enum.join()
|> String.to_integer(2)
epsilon =
frequencies
|> Enum.map(fn freq ->
if freq[0] < freq[1], do: 0, else: 1
end)
|> Enum.join()
|> String.to_integer(2)
power_consumption = gamma * epsilon
Part 2
defmodule LifeSupport do
def oxygen_generator_rating(report) do
oxygen_generator_rating(report, 0) |> String.to_integer(2)
end
def oxygen_generator_rating([result], _position), do: result
def oxygen_generator_rating(report, position) do
most_frequent = most_frequent_at(report, position) |> Integer.to_string()
report
|> Enum.filter(fn number -> String.at(number, position) == most_frequent end)
|> oxygen_generator_rating(position + 1)
end
def co2_scrubber_rating(report) do
co2_scrubber_rating(report, 0) |> String.to_integer(2)
end
def co2_scrubber_rating([result], _position), do: result
def co2_scrubber_rating(report, position) do
most_frequent = most_frequent_at(report, position) |> Integer.to_string()
report
|> Enum.filter(fn number -> String.at(number, position) != most_frequent end)
|> co2_scrubber_rating(position + 1)
end
defp most_frequent_at(list, position) do
freq = frequencies(list, position)
if freq[0] <= freq[1], do: 1, else: 0
end
defp frequencies(report, position) do
report
|> Enum.map(fn number ->
String.at(number, position) |> String.to_integer()
end)
|> Enum.frequencies()
end
end
LifeSupport.oxygen_generator_rating(input) * LifeSupport.co2_scrubber_rating(input)
Scratch
frequencies = [
%{0 => 5, 1 => 7},
%{0 => 7, 1 => 5},
%{0 => 4, 1 => 8},
%{0 => 5, 1 => 7},
%{0 => 7, 1 => 5}
]
gamma_digits =
frequencies
|> Enum.map(fn freq ->
if freq[0] < freq[1], do: 1, else: 0
end)
gamma_digits
|> Integer.undigits(2)