1
0
Fork 0

solve 2021 day 16

This commit is contained in:
Sloane Perrault 2022-09-21 09:19:53 -04:00
parent 9b8558c65f
commit f478284da5
2 changed files with 103 additions and 1 deletions

View file

@ -16,7 +16,7 @@
| :-: | :-: | :-: | :-: | :-: | :-: | :-: | | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| | | | [1] | [2] | [3] | [4] | | | | | [1] | [2] | [3] | [4] |
| [5] | [6] | [7] | [8] | [9] | [10] | [11]| | [5] | [6] | [7] | [8] | [9] | [10] | [11]|
| [12]| [13]| [14]| [15] | 16 | 17 | 18 | | [12]| [13]| [14]| [15] | [16] | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 | | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
<!-- links --> <!-- links -->
@ -36,3 +36,4 @@
[13]: ./lib/2021/13.ex [13]: ./lib/2021/13.ex
[14]: ./lib/2021/14.ex [14]: ./lib/2021/14.ex
[15]: ./lib/2021/15.ex [15]: ./lib/2021/15.ex
[16]: ./lib/2021/16.ex

101
2021/lib/2021/16.ex Normal file
View file

@ -0,0 +1,101 @@
import AOC
aoc 2021, 16 do
def to_binary_digits(?0), do: [0, 0, 0, 0]
def to_binary_digits(?1), do: [0, 0, 0, 1]
def to_binary_digits(?2), do: [0, 0, 1, 0]
def to_binary_digits(?3), do: [0, 0, 1, 1]
def to_binary_digits(n) when n in ?4..?7, do: [0 | Integer.digits(n - ?0, 2)]
def to_binary_digits(n) when n in ?8..?9, do: Integer.digits(n - ?0, 2)
def to_binary_digits(n) when n in ?A..?F, do: Integer.digits(n - ?A + 10, 2)
def input_bitstring(input_string \\ input_string()) do
input_string
|> String.trim()
|> String.to_charlist()
|> Enum.flat_map(&to_binary_digits/1)
|> Enum.into(<<>>, &<<&1::1>>)
end
def decode_packets(bits) do
case decode_packet(bits) do
{:ok, packet, rest} -> [packet | decode_packets(rest)]
_ -> []
end
end
def decode_packets(bits, 0) do
{[], bits}
end
def decode_packets(bits, n) do
{:ok, packet, rest} = decode_packet(bits)
{packets, rest} = decode_packets(rest, n - 1)
{[packet | packets], rest}
end
def decode_packet(<<version::3, 4::3, rest::bits>>) do
{value, rest} = decode_value(rest)
{:ok, [version, 4, Integer.undigits(value, 16)], rest}
end
def decode_packet(<<version::3, id::3, 0::1, subpacket_length::15, rest::bits>>) do
<<subpackets::size(subpacket_length), rest::bits>> = rest
{:ok, [version, id, decode_packets(<<subpackets::size(subpacket_length)>>)], rest}
end
def decode_packet(<<version::3, id::3, 1::1, number_of_subpackets::11, rest::bits>>) do
{packets, rest} = decode_packets(<<rest::bits>>, number_of_subpackets)
{:ok, [version, id, packets], rest}
end
def decode_packet(_), do: :error
def decode_value(<<0::1, chunk::4, rest::bits>>), do: {[chunk], rest}
def decode_value(<<1::1, chunk::4, rest::bits>>) do
{bits, rest} = decode_value(rest)
{[chunk | bits], rest}
end
def versions([version, _, subpackets]) when is_list(subpackets) do
[version | Enum.map(subpackets, &versions/1)]
end
def versions([version, _, _]), do: [version]
def eval([_, 4, v]), do: v
def eval([_, op, args]) do
case {op, Enum.map(args, &eval/1)} do
{0 = _sum, args} -> Enum.sum(args)
{1 = _prod, args} -> Enum.product(args)
{2 = _min, args} -> Enum.min(args)
{3 = _max, args} -> Enum.max(args)
{5 = _gt, [a, b]} -> if a > b, do: 1, else: 0
{6 = _lt, [a, b]} -> if a < b, do: 1, else: 0
{7 = _eq, [a, b]} -> if a == b, do: 1, else: 0
end
end
def p1 do
{:ok, packet, _rest} =
input_bitstring()
|> decode_packet()
versions(packet)
|> List.flatten()
|> Enum.sum()
end
def p2 do
{:ok, packet, _rest} =
input_bitstring()
|> decode_packet()
eval(packet)
end
end