Skip to content

Commit 20672dc

Browse files
committed
Solve day 3 - part 2
1 parent 864f8de commit 20672dc

File tree

2 files changed

+80
-34
lines changed

2 files changed

+80
-34
lines changed

lib/day3.ex

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,51 @@
11
defmodule Day3 do
2+
# Part 1
23
def power_consumption(report) do
3-
frequencies =
4-
report
5-
|> Enum.zip_with(& &1)
6-
|> Enum.map(&Enum.frequencies/1)
4+
integer_of(common_bits(report, :most)) * integer_of(common_bits(report, :least))
5+
end
6+
7+
# Part 2
8+
def life_support_rating(report, size) do
9+
oxygen_rating(report, size) * co2_scrubber_rating(report, size)
10+
end
11+
12+
def oxygen_rating(report, size), do: report |> rating(:most, size)
13+
14+
def co2_scrubber_rating(report, size), do: report |> rating(:least, size)
15+
16+
# Private functions
17+
defp rating(report, strategy, bit_length) do
18+
Enum.to_list(0..bit_length)
19+
|> Enum.reduce(report, fn i, acc -> filter(acc, i, strategy) end)
20+
|> List.first()
21+
|> integer_of()
22+
end
23+
24+
# Filters if list has more than one elements
25+
defp filter([x], _, _), do: [x]
26+
27+
defp filter(report, index, strategy) do
28+
bits = report |> common_bits(strategy) |> List.to_tuple()
29+
report |> Enum.filter(fn item -> elem(List.to_tuple(item), index) == elem(bits, index) end)
30+
end
31+
32+
defp integer_of(common_bits) do
33+
common_bits |> Enum.join() |> Integer.parse(2) |> elem(0)
34+
end
735

8-
calculate(:most, frequencies) * calculate(:least, frequencies)
36+
def common_bits(report, strategy) do
37+
report |> transpose() |> Enum.map(&Enum.frequencies/1) |> Enum.map(&common_bit(strategy, &1))
938
end
1039

11-
defp calculate(strategy, frequencies) do
12-
frequencies
13-
|> Enum.map(&common_bit(strategy, &1))
14-
|> Enum.join()
15-
|> Integer.parse(2)
16-
|> elem(0)
40+
defp transpose(list_of_lists) do
41+
list_of_lists |> Enum.zip_with(& &1)
1742
end
1843

1944
defp common_bit(:most, map) do
20-
if map[0] > map[1], do: 0, else: 1
45+
if map[1] >= map[0], do: 1, else: 0
2146
end
2247

2348
defp common_bit(:least, map) do
24-
if map[0] > map[1], do: 1, else: 0
49+
if map[0] <= map[1], do: 0, else: 1
2550
end
2651
end

test/day3_test.exs

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,51 @@ defmodule Day3Test do
22
use ExUnit.Case
33
import Parser
44

5-
def parse_report(lines) do
6-
lines
7-
|> Enum.map(&String.split(&1, "", trim: true))
8-
|> Enum.map(fn a -> a |> Enum.map(&String.to_integer/1) end)
5+
setup do
6+
example_input = [
7+
[0, 0, 1, 0, 0],
8+
[1, 1, 1, 1, 0],
9+
[1, 0, 1, 1, 0],
10+
[1, 0, 1, 1, 1],
11+
[1, 0, 1, 0, 1],
12+
[0, 1, 1, 1, 1],
13+
[0, 0, 1, 1, 1],
14+
[1, 1, 1, 0, 0],
15+
[1, 0, 0, 0, 0],
16+
[1, 1, 0, 0, 1],
17+
[0, 0, 0, 1, 0],
18+
[0, 1, 0, 1, 0]
19+
]
20+
21+
puzzle_input =
22+
lines_to_list("inputs/day3")
23+
|> Enum.map(&String.split(&1, "", trim: true))
24+
|> Enum.map(fn a -> a |> Enum.map(&String.to_integer/1) end)
25+
26+
{:ok, example_input: example_input, puzzle_input: puzzle_input}
27+
end
28+
29+
test "part 1 - works for given example", context do
30+
assert Day3.power_consumption(context[:example_input]) == 198
31+
end
32+
33+
test "part 1 - solves the puzzle", context do
34+
assert Day3.power_consumption(context[:puzzle_input]) == 852_500
35+
end
36+
37+
test "oxygen_rating - works for given example", context do
38+
assert Day3.oxygen_rating(context[:example_input], 4) == 23
39+
end
40+
41+
test "co2_scrubber_rating - works for given example", context do
42+
assert Day3.co2_scrubber_rating(context[:example_input], 4) == 10
943
end
1044

11-
test "part 1 - works for given example" do
12-
assert Day3.power_consumption([
13-
[0, 0, 1, 0, 0],
14-
[1, 1, 1, 1, 0],
15-
[1, 0, 1, 1, 0],
16-
[1, 0, 1, 1, 1],
17-
[1, 0, 1, 0, 1],
18-
[0, 1, 1, 1, 1],
19-
[0, 0, 1, 1, 1],
20-
[1, 1, 1, 0, 0],
21-
[1, 0, 0, 0, 0],
22-
[1, 1, 0, 0, 1],
23-
[0, 0, 0, 1, 0],
24-
[0, 1, 0, 1, 0]
25-
]) == 198
45+
test "part 2 - works for given example", context do
46+
assert Day3.life_support_rating(context[:example_input], 4) == 230
2647
end
2748

28-
test "part 1 - solves the puzzle" do
29-
assert Day3.power_consumption(lines_to_list("inputs/day3") |> parse_report) == 852_500
49+
test "part 2 - solves the puzzle", context do
50+
assert Day3.life_support_rating(context[:puzzle_input], 11) == 1_007_985
3051
end
3152
end

0 commit comments

Comments
 (0)