Advent of Code 2021 - Day 16

Nice!

I propose to use a different way of iterating on values. Instead of having Enum.reduce/3 everywhere you could to this:

  defp ast_helper(values, type_id) do
    case type_id do
      0 -> quote(do: Enum.sum(unquote(values)))
      1 -> quote(do: Enum.product(unquote(values)))
      2 -> quote(do: Enum.min(unquote(values)))
      3 -> quote(do: Enum.max(unquote(values)))
      5 -> ast_if(values, :>)
      6 -> ast_if(values, :<)
      7 -> ast_if(values, :==)
    end
  end

  defp ast_if([val_a, val_b], op) do
    quote do
      if unquote(op)(unquote(val_a), unquote(val_b)),
        do: 1,
        else: 0
    end
  end

Oh and note that you can directly use len in the function head!

  defp make_ast(<<_version::3, type_id::3, 0::1, len::15, values::bitstring-size(len), rest::bitstring>>) do
    ast =
      values
      |> parse_values()
      |> ast_helper(type_id)

    {ast, rest}
  end

Magic :smiley:

3 Likes

Busy week with my real life so I’ve fallen a bit behind. Finally got to this one and I like the type specs. I’ve been meaning to try and use them more consistently and this seemed like a good opportunity. Dialyzer also worked a charm alerting me to an error I had in defining the packet type using a different field name for the values than I did in function calls.