|
1 | 1 | defmodule AdventOfCode.Day16 do |
2 | 2 | def part1(args) do |
3 | 3 | bitlist = Base.decode16!(args) |
4 | | - decode_packet(bitlist) |
| 4 | + {data, _} = decode_packet(bitlist) |
| 5 | + total_versions(data) |
5 | 6 | end |
6 | 7 |
|
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 |
9 | 14 |
|
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} |
14 | 21 | end |
15 | 22 |
|
16 | | - # TODO |
17 | 23 | @doc """ |
18 | 24 | iex> AdventOfCode.Day16.literal_value(<<191, 138, 0::size(2)>>) |
19 | | - 2021 |
| 25 | + {2021, <<0::3>>} |
20 | 26 | """ |
21 | 27 | 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 |
37 | 62 | 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 |
50 | 112 | end |
51 | 113 |
|
52 | 114 | def part2(args) do |
|
0 commit comments