Advent of Code Day 3
Setup
test_data = """
00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010
"""
data = File.read!("day_03/input.txt")
"000010000011\n001010000111\n011010000010\n000011111110\n101101000101\n000100010100\n111101111110\n111111000010\n000011010011\n100011100000\n101110110001\n111011111101\n111011011001\n010101000010\n000010001000\n101010011111\n010000111101\n011010111100\n101111010110\n000110110101\n001010000001\n110101100110\n111110010100\n001000001011\n100111101001\n000010010001\n100100101010\n011010110111\n000001100100\n101111000111\n010101101100\n001111010010\n010001011100\n110101011011\n000010101000\n011011101101\n101001000011\n101111000000\n001111101111\n001101110111\n110110110101\n100011001011\n010110110011\n001010001110\n110110100100\n001001111111\n100111011100\n101101001010\n011110000011\n010101111000\n001101000101\n100011001100\n110000110001\n011101010001\n000110001101\n110001101101\n011001000110\n011101010101\n110110011010\n001000011001\n100101100101\n010110001100\n110100011001\n001011000010\n101011110101\n011101001010\n011011000111\n000101000001\n100001010110\n111101000011\n111010111011\n000011101001\n011111110000\n110011100101\n110011100110\n101011001011\n100110110111\n010001111100\n101010011001\n111001111011\n111001000011\n010010111010\n011011011110\n101000010000\n000010011111\n000101110000\n101010000110\n101100000100\n110000110000\n000010100010\n010001111001\n001000001111\n010110000011\n010000111110\n001011001010\n011010100001\n001001000110\n011010001101\n100111011101\n011101010000\n100111010100\n100101001101\n111010101001\n011001011101\n010011000000\n000001100110\n110101011100\n000110101000\n011110001000\n010011000001\n100011011111\n100100001111\n010011101010\n001011000001\n111101011000\n011101000110\n111011001101\n110110010110\n111011000110\n111111010101\n101110100111\n011110010001\n010100011111\n001111000101\n101100010011\n111101000010\n100001110100\n110001110011\n011011110101\n100110111101\n110010011010\n111001000110\n100010111111\n100010101110\n011110111001\n011100101100\n010101111101\n101010111011\n111111110100\n010111100110\n111010101111\n011001110000\n101011100011\n101000000110\n111100011011\n001001010010\n001010110001\n000111101101\n100010000101\n010001101110\n000100100001\n010100011000\n001100011011\n111111110011\n111010010000\n001100101001\n000101001110\n111100111010\n111110010000\n010111001000\n011100001100\n000010011010\n101010101011\n110100011011\n010110101101\n000001000101\n111111010011\n110000000110\n110100111111\n111000000010\n000101010111\n001110110110\n111111111011\n010010100100\n110000010011\n010111110111\n111000010010\n111011100000\n010100000101\n010011011001\n000110101111\n110111101111\n101001001011\n101111110111\n111010101011\n100100010101\n100100011100\n000011010111\n011010101011\n101000111010\n010101011101\n101101000001\n010111110010\n111101011010\n000001010100\n011010101000\n010000110010\n101000011100\n010001010000\n000001001101\n100101110001\n001101010010\n001100111110\n011101010111\n111110011100\n100011000101\n101111100100\n111011001000\n010111000110\n001010111100\n011011110001\n111010011110\n101011100110\n001100010111\n111110110111\n101011010001\n011110100011\n110000001110\n101011101011\n101101000111\n110111111111\n010000011000\n001110001000\n111000000101\n010111101100\n000100000101\n001111100101\n101001111101\n010111110101\n100110010101\n111101101100\n111100010010\n110011111110\n011100010101\n111001001100\n101010110000\n010100010010\n111100110000\n111100001000\n111100110110\n101101110010\n010001101100\n010110010000\n100000100101\n000000001110\n011001100110\n100101000010\n011111100010\n010010100010\n100101011001\n011100100100\n010111110000\n100111000110\n111110011011\n011111000011\n101001100101\n000110101110\n111001111110\n011110011101\n101011111111\n010110101010\n100001100111\n000101001111\n110100011101\n111110100111\n101000111110\n010010011110\n100110100111\n000111010011\n110101110110\n101101000000\n110110111110\n001100111111\n000010101010\n001001001001\n101000110110\n010011111000\n000101110011\n011100001111\n000001101110\n100001010010\n001100000011\n011100101110\n111000111000\n110010110111\n100100000010\n010101100100\n100111001101\n011101100100\n110010001010\n100111000000\n111011001100\n010010010011\n110110100001\n001011110001\n010000100110\n001111100100\n100110001000\n101000010001\n001000001000\n110001001011\n001010010101\n101001111011\n011101110010\n101000100110\n010000101110\n000110010110\n001111010001\n011010100111\n101110011001\n001010001100\n010001011010\n110010100010\n100001111001\n001001010001\n0" <> ...
Part 1
# What is the power consumption of the submarine?
# gamma rate
# epsilon rate
defmodule Day3Part1 do
def parse_raw_data(data) when is_binary(data) do
String.split(data, "\n", trim: true)
end
def zero_one_counts(data) when is_list(data) do
for i <- 0..(String.length(hd(data)) - 1) do
Enum.reduce(data, {0, 0}, fn element, {zero_count, one_count} ->
case String.at(element, i) do
"1" ->
{zero_count, one_count + 1}
"0" ->
{zero_count + 1, one_count}
end
end)
end
end
def most_common(zero_one_counts) when is_list(zero_one_counts) do
Enum.map(zero_one_counts, fn
{zero_count, one_count} when zero_count > one_count -> "0"
{zero_count, one_count} when one_count > zero_count -> "1"
end)
end
def least_common(zero_one_counts) when is_list(zero_one_counts) do
Enum.map(zero_one_counts, fn
{zero_count, one_count} when zero_count > one_count -> "1"
{zero_count, one_count} when one_count > zero_count -> "0"
end)
end
end
zero_one_counts =
data
|> Day3Part1.parse_raw_data()
|> Day3Part1.zero_one_counts()
gamma_rate =
zero_one_counts
|> Day3Part1.most_common()
|> Enum.join()
|> Integer.parse(2)
|> elem(0)
epsilon_rate =
zero_one_counts
|> Day3Part1.least_common()
|> Enum.join()
|> Integer.parse(2)
|> elem(0)
gamma_rate * epsilon_rate
3242606
Part 2
# oxygen generator rating by the CO2 scrubber rating
defmodule Day3Part2 do
def process_ratings(data, fun) when is_list(data) and is_function(fun, 2) do
0..(String.length(hd(data)) - 1)
|> Enum.reduce_while(data, fn index, acc ->
case fun.(index, acc) do
[answer] -> {:halt, String.to_integer(answer, 2)}
ratings -> {:cont, ratings}
end
end)
end
def keep_oxygen_generator_rating?(index, ratings) do
{zeros, ones} =
ratings
|> Day3Part1.zero_one_counts()
|> Enum.at(index)
Enum.filter(ratings, fn rating ->
case String.at(rating, index) do
"1" when ones == zeros -> true
"1" when ones > zeros -> true
"0" when zeros > ones -> true
_ -> false
end
end)
end
def keep_co2_scrubber_rating?(index, ratings) do
{zeros, ones} =
ratings
|> Day3Part1.zero_one_counts()
|> Enum.at(index)
Enum.filter(ratings, fn rating ->
case String.at(rating, index) do
"0" when zeros < ones -> true
"1" when ones < zeros -> true
"0" when ones == zeros -> true
_ -> false
end
end)
end
end
data = Day3Part1.parse_raw_data(data)
oxygen_generator_rating =
Day3Part2.process_ratings(
data,
&Day3Part2.keep_oxygen_generator_rating?/2
)
co2_scrubber_rating =
Day3Part2.process_ratings(
data,
&Day3Part2.keep_co2_scrubber_rating?/2
)
oxygen_generator_rating * co2_scrubber_rating
4856080