-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday3.exs
More file actions
61 lines (50 loc) · 1.66 KB
/
day3.exs
File metadata and controls
61 lines (50 loc) · 1.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
input =
File.stream!("day/3/input", [], :line)
|> Stream.map(&String.trim/1)
|> Stream.map(&String.to_integer(&1, 2))
|> Enum.to_list()
defmodule Day3 do
use Bitwise
# Set to 4 if you want to use sample data, 11 for input.
@high_bit 11
def gamma_epsilon(numbers) do
Enum.reduce(@high_bit..0, {0, 0}, fn bit, {gamma, epsilon} ->
if Day3.bit_delta(numbers, bit) > 0 do
{gamma ||| 1 <<< bit, epsilon}
else
{gamma, epsilon ||| 1 <<< bit}
end
end)
end
def oxygen_generator_rating(numbers),
do: find_rating(numbers, fn delta -> if(delta >= 0, do: 1, else: 0) end)
def co2_scrubber_rating(numbers),
do: find_rating(numbers, fn delta -> if(delta >= 0, do: 0, else: 1) end)
defp bit_delta(numbers, bit) do
mask = 1 <<< bit
Enum.reduce(numbers, 0, fn num, delta ->
if (num &&& mask) > 0 do
delta + 1
else
delta - 1
end
end)
end
defp find_rating(numbers, keep_func) do
Enum.reduce_while(@high_bit..0, numbers, fn bit, numbers ->
keep_value = keep_func.(bit_delta(numbers, bit)) <<< bit
keep_mask = 1 <<< bit
keep_list = Enum.filter(numbers, fn number -> (number &&& keep_mask) == keep_value end)
if length(keep_list) == 1 do
{:halt, hd(keep_list)}
else
{:cont, keep_list}
end
end)
end
end
{gamma, epsilon} = Day3.gamma_epsilon(input)
IO.puts("Gamma: #{gamma}, Epsilon: #{epsilon}, Power Consumption: #{gamma * epsilon}")
ogr = Day3.oxygen_generator_rating(input)
csr = Day3.co2_scrubber_rating(input)
IO.puts("Oxygen Generator Rating: #{ogr}, CO₂ Scrubber Rating: #{csr}, Life Support Rating: #{ogr * csr}")