Skip to content

Commit 1f9697d

Browse files
committed
got subpackets by bits and count going, mostly
1 parent d460088 commit 1f9697d

2 files changed

Lines changed: 140 additions & 41 deletions

File tree

2021/elixir/lib/advent_of_code/day_16.ex

Lines changed: 98 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,114 @@
11
defmodule AdventOfCode.Day16 do
22
def part1(args) do
33
bitlist = Base.decode16!(args)
4-
decode_packet(bitlist)
4+
{data, _} = decode_packet(bitlist)
5+
total_versions(data)
56
end
67

7-
def decode_packet(bitlist) do
8-
<<v::3, t::3, rest::bits>> = bitlist
8+
def decode_packet(<<v::3, 4::3, rest::bits>>) do
9+
IO.puts("decode")
10+
IO.puts("going to literal")
11+
{payload, remainder} = literal_value(rest)
12+
{%{version: v, type: 4, payload: payload},remainder}
13+
end
914

10-
case t do
11-
4 -> literal_value(rest)
12-
_ -> operator(rest)
13-
end
15+
def decode_packet(<<v::3, t::3, rest::bits>>) do
16+
IO.puts("decode")
17+
IO.inspect({bits_to_integer(<<v>>),bits_to_integer(<<t>>)}, label: "{v, t}")
18+
IO.puts("going to operator")
19+
{payload, remainder} = operator(rest)
20+
{%{version: v, type: t, payload: payload}, remainder}
1421
end
1522

16-
# TODO
1723
@doc """
1824
iex> AdventOfCode.Day16.literal_value(<<191, 138, 0::size(2)>>)
19-
2021
25+
{2021, <<0::3>>}
2026
"""
2127
def literal_value(bitlist) do
22-
<<a::1, b::size(4), rest::bits>> = bitlist
23-
IO.inspect({a, b}, label: "a and b")
24-
if match?(<<^a::1>>, <<0::1>>) do
25-
IO.puts("base case")
26-
<<b::4>>
27-
else
28-
IO.puts("else")
29-
n = literal_value(rest)
30-
IO.inspect(is_bitstring(<<b::4>>), label: "b is bitstring")
31-
IO.inspect(is_bitstring(n), label: "n is bitstring")
32-
<< <<b::4>>, n >>
33-
end
34-
end
35-
36-
def operator(bitlist) do
28+
IO.puts("entering literal")
29+
{v, remainder} = do_literal_value(bitlist)
30+
31+
size = bit_size(v)
32+
<<int::size(size)>> = v
33+
int
34+
35+
{int, remainder}
36+
end
37+
38+
defp do_literal_value(<<0::1, b::4, rest::bits>>) do
39+
IO.puts("literal base")
40+
{<<b::4>>, rest}
41+
end
42+
43+
defp do_literal_value(<<_::1, b::4, rest::bits>>) do
44+
IO.puts("literal recursion")
45+
{n, remainder} = do_literal_value(rest)
46+
m = <<b::4>>
47+
IO.inspect(is_bitstring(m), label: "m is bitstring")
48+
IO.inspect(bit_size(m), label: "m bit size")
49+
IO.inspect(bit_size(<< m::bits , n::bits >>), label: "full bit size")
50+
{<< m::bits , n::bits >>, remainder}
51+
end
52+
53+
def operator(<<0::1, len::15, rest::bits>> = bitlist) do
54+
IO.puts("operator")
55+
IO.puts("by length")
56+
len = bits_to_integer(<<len>>)
57+
<<subpackets::size(len)-bits, remainder::bits>> = rest
58+
{subpackets_by_bits(subpackets), <<>>} # remainder should be junk?
59+
end
60+
61+
def operator(<<1::1, subpackets::11, rest::bits>> = bitlist) do
3762
IO.puts("operator")
38-
<<mode::1, rest::bits>> = bitlist
39-
case mode do
40-
0 ->
41-
IO.puts("by length")
42-
<<len::15, rest2::bits>> = bitlist
43-
<<subpackets::size(len)>> = rest2
44-
decode_packet(subpackets)
45-
1 ->
46-
IO.puts("by number of packets")
47-
<<subpackets::11, rest2::bits>> = bitlist
48-
decode_packet(rest2)
49-
end
63+
IO.puts("by number of packets")
64+
IO.inspect(subpackets, label: "count")
65+
subpackets = subpackets_by_count(rest, subpackets)
66+
{subpackets, rest} |> IO.inspect(label: "operator return")
67+
end
68+
69+
def subpackets_by_count(remainder, 0), do: []
70+
71+
def subpackets_by_count(bitlist, count) do
72+
IO.inspect(count, label: "subpacket")
73+
{data, remainder} = decode_packet(bitlist)
74+
IO.inspect(data, label: "data in subpacket")
75+
[ data | subpackets_by_count(remainder, count - 1)]
76+
end
77+
78+
def subpackets_by_bits(<<>>) do
79+
IO.puts("ran out of bits")
80+
[]
81+
end
82+
83+
def subpackets_by_bits(bitlist) do
84+
IO.puts("inspecting a subpacket")
85+
{data, remainder} = decode_packet(bitlist)
86+
IO.inspect(data)
87+
[ data | subpackets_by_bits(remainder)] |> IO.inspect
88+
end
89+
90+
@doc """
91+
iex> packet = %{payload: [
92+
...> %{payload: 10, type: 4, version: 6},
93+
...> %{payload: 20, type: 4, version: 2}
94+
...>],
95+
...>type: 6,
96+
...>version: 1}
97+
iex> AdventOfCode.Day16.total_versions(packet)
98+
9
99+
"""
100+
def total_versions(%{version: v, payload: x } = packet) when is_integer(x), do: v
101+
102+
def total_versions(%{version: v, payload: payload} = packet) do
103+
Enum.reduce(payload, v, fn subpacket, acc ->
104+
acc + total_versions(subpacket)
105+
end)
106+
end
107+
108+
defp bits_to_integer(bs) do
109+
size = bit_size(bs)
110+
<<int::size(size)>> = bs
111+
int
50112
end
51113

52114
def part2(args) do

2021/elixir/test/advent_of_code/day_16_test.exs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,55 @@ defmodule AdventOfCode.Day16Test do
44

55
import AdventOfCode.Day16
66

7-
@tag :skip
7+
# @tag :skip
88
test "literal number packet" do
99
input = "D2FE28"
10-
result = part1(input)
10+
{result, _} = Base.decode16!(input) |> decode_packet()
1111

12-
assert result
12+
assert result[:version] == 6
13+
assert result[:type] == 4
1314
end
1415

15-
@tag :skip
16-
test "operator packet" do
16+
# @tag :skip
17+
test "operator packet with length" do
1718
input = "38006F45291200"
19+
{result, _} = Base.decode16!(input) |> decode_packet()
20+
21+
assert result[:version] == 1
22+
assert result[:type] == 6
23+
end
24+
25+
# @tag :skip
26+
test "operator packet with count" do
27+
input = "EE00D40C823060"
28+
{result, _} = Base.decode16!(input) |> decode_packet()
29+
30+
assert result[:version] == 7
31+
assert result[:type] == 3
32+
end
33+
34+
test "example 1" do
35+
input = "8A004A801A8002F478"
36+
result = part1(input)
37+
assert result == 16
38+
end
39+
40+
test "example 2" do
41+
input = "620080001611562C8802118E34"
42+
result = part1(input)
43+
assert result == 12
44+
end
45+
46+
test "example 3" do
47+
input = "C0015000016115A2E0802F182340"
48+
result = part1(input)
49+
assert result == 23
50+
end
51+
52+
test "example 4" do
53+
input = "A0016C880162017C3686B18A3D4780"
1854
result = part1(input)
55+
assert result == 31
1956
end
2057

2158
@tag :skip

0 commit comments

Comments
 (0)