I wanted to keep it pipeline-y. I feel like there has to be a way to do something similar in one pass, but I couldn’t figure it out before Day 4.
# Part 1
"day3.txt"
|> File.stream!
|> Enum.map(fn line -> String.split(line, "", trim: true) end)
|> Enum.zip_with(&Enum.frequencies/1)
|> Enum.map(fn counts -> if counts["0"] > counts["1"], do: ["0", "1"], else: ["1", "0"] end)
|> Enum.zip_with(&Enum.join/1)
|> Enum.reduce(1, fn number, product -> String.to_integer(number, 2) * product end)
# Part 2
defmodule Day3 do
def input() do
"day3.txt"
|> File.stream!
|> Enum.map(&String.trim/1)
end
def oxygen([final_value], _position) do
String.to_integer(final_value, 2)
end
def oxygen(data, position) do
data
|> Enum.group_by(fn num -> String.at(num, position) end)
|> Enum.max_by(&number_sorter/1)
|> elem(1)
|> oxygen(position + 1)
end
def carbon([final_value], _position) do
String.to_integer(final_value, 2)
end
def carbon(data, position) do
data
|> Enum.group_by(fn num -> String.at(num, position) end)
|> Enum.min_by(&number_sorter/1)
|> elem(1)
|> carbon(position + 1)
end
defp number_sorter({target_bit, bit_list}) do
length(bit_list) + 0.1 * String.to_integer(target_bit)
end
end
data = Day3.input()
Day3.oxygen(data, 0) * Day3.carbon(data, 0)