Day 18: Snailfish
Input
input_test =
"""
[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]]
[[[5,[2,8]],4],[5,[[9,9],0]]]
[6,[[[6,2],[5,6]],[[7,6],[4,7]]]]
[[[6,[0,7]],[0,9]],[4,[9,[9,0]]]]
[[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]]
[[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]]
[[[[5,4],[7,7]],8],[[8,3],8]]
[[9,3],[[9,9],[6,[4,9]]]]
[[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]]
[[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]
"""
|> String.split("\n", trim: true)
input =
File.read!("input18.txt")
|> String.split("\n", trim: true)
Part 1
defmodule SM do
def parse(s) when is_bitstring(s), do: parse(String.graphemes(s)) |> elem(0)
def parse(["[" | t]) do
{left, ["," | t]} = parse(t)
{right, ["]" | t]} = parse(t)
{[left, right], t}
end
def parse([x | t]), do: {String.to_integer(x), t}
def inc([l, r], v, 0), do: [inc(l, v, 0), r]
def inc([l, r], v, 1), do: [l, inc(r, v, 1)]
def inc(x, v, _), do: x + v
def split([l, r]) do
{l, s} = split(l)
if not s do
{r, s} = split(r)
{[l, r], s}
else
{[l, r], s}
end
end
def split(x), do: if(x < 10, do: {x, false}, else: {[trunc(x / 2), x - trunc(x / 2)], true})
def explode([l, r], 4), do: {true, 0, l, r}
def explode([l, r], d) do
{e, l, a, b} = explode(l, d + 1)
if not e do
{e, r, a, b} = explode(r, d + 1)
if e and a > 0 do
{e, [inc(l, a, 1), r], -1, b}
else
{e, [l, r], a, b}
end
else
if b > 0 do
{e, [l, inc(r, b, 0)], a, -1}
else
{e, [l, r], a, b}
end
end
end
def explode(x, _), do: {false, x, -1, -1}
def fixup(t) do
{e, t, _a, _b} = explode(t, 0)
if not e do
{t, s} = split(t)
if s, do: fixup(t), else: t
else
fixup(t)
end
end
def mag([l, r]), do: 3 * mag(l) + 2 * mag(r)
def mag(x), do: x
def add(b, a), do: fixup([a, b])
def varsums(l), do: for(a <- l, b <- l, a != b, do: mag(add(a, b)))
end
4140 = Enum.map(input_test, &SM.parse/1) |> Enum.reduce(&SM.add/2) |> SM.mag()
3647 = Enum.map(input, &SM.parse/1) |> Enum.reduce(&SM.add/2) |> SM.mag()
Part 2
3993 = Enum.map(input_test, &SM.parse/1) |> SM.varsums() |> Enum.max()
4600 = Enum.map(input, &SM.parse/1) |> SM.varsums() |> Enum.max()