|
1 | 1 | defmodule Day3 do
|
| 2 | + # Part 1 |
2 | 3 | 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 |
7 | 35 |
|
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)) |
9 | 38 | end
|
10 | 39 |
|
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) |
17 | 42 | end
|
18 | 43 |
|
19 | 44 | 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 |
21 | 46 | end
|
22 | 47 |
|
23 | 48 | 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 |
25 | 50 | end
|
26 | 51 | end
|
0 commit comments