Skip to content

Commit

Permalink
Day 18: Everything is fine
Browse files Browse the repository at this point in the history
This might be some of the ugliest code I've ever written, but it gets
the job done! Took me ~4 hours and there was a point about halfway
through that I started to wish I had just built out the binary tree
structure instead of trying to manipulate the strings.

Oh well.
  • Loading branch information
adammathys committed Dec 19, 2021
1 parent 0e2285a commit fa90b4d
Show file tree
Hide file tree
Showing 4 changed files with 319 additions and 0 deletions.
100 changes: 100 additions & 0 deletions 2021/18/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
[[1,[8,[5,8]]],[[4,4],[8,[8,8]]]]
[[[3,[2,3]],[[8,0],2]],[0,[[8,1],[7,0]]]]
[4,[[0,3],[[6,6],[3,8]]]]
[[[7,[6,4]],[[0,6],[2,0]]],[[[5,6],[0,4]],[[8,1],[9,1]]]]
[[[6,3],[[6,9],4]],[[1,[4,2]],[[0,0],1]]]
[[2,0],[3,[0,8]]]
[[0,[5,5]],[[4,2],[3,[6,4]]]]
[[[[9,9],[8,5]],[7,4]],[[6,9],[8,[0,8]]]]
[[[[7,1],[2,9]],[[9,3],0]],[3,[[0,6],[7,6]]]]
[[[[3,7],[7,1]],[[5,8],[0,1]]],3]
[[[[4,6],[6,2]],[[9,1],7]],[[9,1],[8,0]]]
[[[[2,7],0],[[9,4],[2,6]]],[0,[[7,4],[0,3]]]]
[[5,[[0,2],[8,8]]],[[[4,1],9],3]]
[[[7,1],[[3,7],[3,4]]],[[[0,7],[1,6]],1]]
[[[6,5],[[1,8],[8,8]]],[[4,5],[3,7]]]
[[[1,[3,3]],[[3,2],[5,7]]],[[8,[9,3]],[[5,3],4]]]
[[[4,[2,7]],9],[9,[[5,6],4]]]
[[[9,1],3],[[1,2],9]]
[[[[0,0],[2,3]],[[7,8],[1,5]]],[[[8,6],7],[[8,3],9]]]
[6,[[5,[0,8]],1]]
[4,[[[3,0],[2,0]],[[7,2],[1,4]]]]
[[[[4,3],[4,1]],8],[[[9,4],[1,9]],[4,[0,6]]]]
[4,[5,6]]
[[[0,[6,1]],[[6,1],3]],[[0,[7,8]],[1,0]]]
[[5,[[8,7],8]],8]
[[5,[[5,2],0]],[[1,[4,7]],[[0,9],[2,3]]]]
[[7,[2,2]],[[6,3],[5,8]]]
[[[0,9],5],[1,[[5,7],1]]]
[[8,[3,[0,3]]],[[[2,2],2],[[8,8],[8,9]]]]
[[6,[[3,2],[2,6]]],[5,1]]
[[[[9,8],[6,8]],[0,7]],7]
[[[7,2],[[6,3],4]],2]
[[[5,2],[[1,6],[8,3]]],[6,5]]
[[5,2],[0,5]]
[[[[4,5],5],[[4,6],[1,2]]],[[[3,6],[4,9]],[1,9]]]
[[1,[4,1]],[[9,[5,5]],[[9,0],[5,7]]]]
[[[[8,9],[7,7]],2],[8,1]]
[[[8,1],[8,[9,5]]],3]
[[[2,[3,9]],[[5,4],[7,9]]],[9,8]]
[8,[[2,[0,9]],[[5,0],4]]]
[[[6,[4,8]],[0,6]],[[8,[1,8]],1]]
[[6,[[1,0],[6,2]]],[[9,[3,7]],[5,[4,0]]]]
[[8,[0,[9,1]]],8]
[7,[4,[7,2]]]
[[1,[[5,7],[5,4]]],[[5,[8,0]],[1,6]]]
[[[[0,6],[6,2]],3],[[[9,3],7],[7,[1,2]]]]
[[[6,[4,9]],8],[6,5]]
[[[0,[1,9]],[[1,9],[3,9]]],[[[3,4],[7,5]],3]]
[[[[9,3],5],[[0,5],[2,7]]],9]
[[[6,[7,5]],5],[1,[[7,0],[3,4]]]]
[[[2,1],[[1,3],[1,5]]],[4,[9,[7,9]]]]
[[[[7,9],4],[[8,8],7]],[[[3,5],2],[[4,4],[6,5]]]]
[[1,1],[1,1]]
[[8,[0,2]],8]
[[[2,[2,1]],[[1,7],[1,2]]],[[1,6],5]]
[6,[0,[[1,0],[0,9]]]]
[6,[[2,[8,0]],[8,[8,8]]]]
[4,[[3,[0,3]],4]]
[[[5,3],3],[[0,[7,6]],[2,[5,8]]]]
[[[[8,1],[4,1]],[[5,8],[4,8]]],[[[1,7],[7,2]],[0,[2,7]]]]
[[[2,[3,5]],3],5]
[[7,[[9,5],[8,2]]],[[[1,8],8],5]]
[[3,5],[[4,[9,3]],5]]
[[[[4,6],2],[2,2]],[0,[0,4]]]
[[[[5,8],[6,6]],[2,0]],[[[2,3],9],[[4,5],2]]]
[[[[1,9],3],[[3,4],6]],[[3,6],[6,[0,7]]]]
[[[0,[5,5]],[2,6]],[[[7,4],4],2]]
[0,[[8,[6,2]],[5,[1,5]]]]
[[[[5,5],[9,6]],[[5,2],2]],[[4,7],[[5,5],[1,6]]]]
[[4,7],[[[1,8],[9,6]],[2,3]]]
[5,[5,4]]
[[[[2,1],[7,0]],[5,[7,8]]],[6,[3,1]]]
[[[3,1],[[2,4],6]],[[[1,8],[2,1]],[[1,7],4]]]
[[[5,[3,3]],6],[[[0,0],9],[1,[7,4]]]]
[[[6,5],[[7,3],4]],[[9,[0,3]],[3,[6,0]]]]
[[[3,4],7],[8,[[1,7],[9,9]]]]
[[[[2,1],6],[2,6]],[[[8,1],[6,2]],[9,0]]]
[[8,4],[5,2]]
[[4,[[4,5],9]],[[3,[5,2]],[4,2]]]
[[[8,8],[[8,0],[5,3]]],4]
[[1,8],[0,2]]
[[[[7,2],[9,0]],[[9,2],[1,2]]],[[[4,0],3],0]]
[[[[1,2],[1,8]],[[4,3],[8,6]]],[[[5,1],8],[8,1]]]
[[[[5,3],[7,2]],7],[[6,[7,9]],[[3,8],[9,4]]]]
[[[[3,1],[2,5]],6],[[[3,2],[8,8]],[4,6]]]
[9,[[3,[2,3]],6]]
[[[[4,0],[5,6]],[5,4]],[[[9,0],[1,8]],[5,[3,6]]]]
[[[[9,5],[9,4]],[[5,7],5]],[[[1,4],7],[6,1]]]
[[2,[6,[8,2]]],[7,[1,[3,3]]]]
[[[9,1],[0,[6,3]]],[[5,[1,5]],[7,[1,0]]]]
[1,6]
[[0,[2,[8,9]]],[[[4,5],[5,4]],1]]
[[[1,[4,1]],8],[[2,[7,0]],[7,[9,9]]]]
[[[[5,7],[3,5]],[[6,6],2]],[2,[8,[9,0]]]]
[6,[[[3,9],8],[[4,3],[6,1]]]]
[[[[6,7],[7,6]],[2,8]],[[9,[4,1]],6]]
[[[[4,5],[4,5]],[[0,6],5]],[[[6,5],[7,0]],1]]
[[[[6,7],9],[[5,5],[6,6]]],[[7,1],[[8,2],[3,1]]]]
[[[9,6],7],[[[1,8],8],[1,7]]]
[[5,2],[[1,9],[2,2]]]
9 changes: 9 additions & 0 deletions 2021/18/run.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require_relative "snailfish"

input = File.readlines("input.txt")
fish = input.map{Snailfish.new(_1.chomp)}

puts "Magnitude: #{fish.reduce(:+).magnitude}"

magnitudes = fish.permutation(2).map{ _1.reduce(:+).magnitude }
puts "Largest of any two: #{magnitudes.max}"
93 changes: 93 additions & 0 deletions 2021/18/snailfish.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
require "json"

class Snailfish
attr_reader :number

# Convenience constructor to help make tests easier to read.
def self.[](number)
self.new(number)
end

def initialize(number)
@number = number
end

def +(other)
Snailfish["[#{number},#{other.number}]"].reduce!
end

def ==(other)
number == other.number
end

def inspect
number
end

def magnitude
a, b = JSON.parse(number)

a = a.is_a?(Array) ? Snailfish[a.to_json].magnitude : a
b = b.is_a?(Array) ? Snailfish[b.to_json].magnitude : b

3*a + 2*b
end

def reduce!
true while explode! || split!
self
end

def explode!
return false if max_depth <= 4

head, pair, tail = find_exploding_pair(JSON.parse(number))

if (left = head.scan(/\d{1,}/).last)
idx = head.rindex(left)
head[idx...(idx+left.length)] = (left.to_i + pair[0]).to_s
end

if (right = tail.scan(/\d{1,}/).first)
idx = tail.index(right)
tail[idx...(idx+right.length)] = (right.to_i + pair[1]).to_s
end

@number = [head,0,tail].join
end

def split!
number.match(/\d{2,}/) do |split|
head, tail = number.split(split[0], 2)
m = split[0].to_i / 2.0
@number = [head, [m.floor, m.ceil].to_json, tail].join
end
end

private

def max_depth
array = JSON.parse(number)
depth = 1

until array == array.flatten
depth +=1
array = array.flatten(1)
end

depth
end

def find_exploding_pair(pair, depth = 1, head = "", tail = "")
a, b = pair

if depth == 4
return ["#{head}[", a, ",#{b.to_json}]#{tail}"] if a.is_a?(Array)
return ["#{head}[#{a.to_json},", b, "]#{tail}"] if b.is_a?(Array)
return false
end

find_exploding_pair(a, depth + 1, "#{head}[", ",#{b.to_json}]#{tail}") ||
find_exploding_pair(b, depth + 1, "#{head}[#{a.to_json},", "]#{tail}")
end
end
117 changes: 117 additions & 0 deletions 2021/18/test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
require "minitest/autorun"
require_relative "snailfish"

class SnailfishTest < Minitest::Test
def test_addition
assert_equal Snailfish["[[1,2],[[3,4],5]]"], [
Snailfish["[1,2]"],
Snailfish["[[3,4],5]"]
].reduce(:+)

assert_equal Snailfish["[[[[1,1],[2,2]],[3,3]],[4,4]]"], [
Snailfish["[1,1]"],
Snailfish["[2,2]"],
Snailfish["[3,3]"],
Snailfish["[4,4]"]
].reduce(:+)

assert_equal Snailfish["[[[[3,0],[5,3]],[4,4]],[5,5]]"], [
Snailfish["[1,1]"],
Snailfish["[2,2]"],
Snailfish["[3,3]"],
Snailfish["[4,4]"],
Snailfish["[5,5]"]
].reduce(:+)

assert_equal Snailfish["[[[[5,0],[7,4]],[5,5]],[6,6]]"], [
Snailfish["[1,1]"],
Snailfish["[2,2]"],
Snailfish["[3,3]"],
Snailfish["[4,4]"],
Snailfish["[5,5]"],
Snailfish["[6,6]"]
].reduce(:+)
end

def test_complex_addition
assert_equal Snailfish["[[[[4,0],[5,4]],[[7,7],[6,0]]],[[8,[7,7]],[[7,9],[5,0]]]]"],
Snailfish["[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]"] +
Snailfish["[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]"]

assert_equal Snailfish["[[[[6,7],[6,7]],[[7,7],[0,7]]],[[[8,7],[7,7]],[[8,8],[8,0]]]]"],
Snailfish["[[[[4,0],[5,4]],[[7,7],[6,0]]],[[8,[7,7]],[[7,9],[5,0]]]]"] +
Snailfish["[[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]]"]

assert_equal Snailfish["[[[[7,0],[7,7]],[[7,7],[7,8]]],[[[7,7],[8,8]],[[7,7],[8,7]]]]"],
Snailfish["[[[[6,7],[6,7]],[[7,7],[0,7]]],[[[8,7],[7,7]],[[8,8],[8,0]]]]"] +
Snailfish["[[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]]"]

assert_equal Snailfish["[[[[7,7],[7,8]],[[9,5],[8,7]]],[[[6,8],[0,8]],[[9,9],[9,0]]]]"],
Snailfish["[[[[7,0],[7,7]],[[7,7],[7,8]]],[[[7,7],[8,8]],[[7,7],[8,7]]]]"] +
Snailfish["[7,[5,[[3,8],[1,4]]]]"]

assert_equal Snailfish["[[[[6,6],[6,6]],[[6,0],[6,7]]],[[[7,7],[8,9]],[8,[8,1]]]]"],
Snailfish["[[[[7,7],[7,8]],[[9,5],[8,7]]],[[[6,8],[0,8]],[[9,9],[9,0]]]]"] +
Snailfish["[[2,[2,2]],[8,[8,1]]]"]

assert_equal Snailfish["[[[[6,6],[7,7]],[[0,7],[7,7]]],[[[5,5],[5,6]],9]]"],
Snailfish["[[[[6,6],[6,6]],[[6,0],[6,7]]],[[[7,7],[8,9]],[8,[8,1]]]]"] +
Snailfish["[2,9]"]

assert_equal Snailfish["[[[[7,8],[6,7]],[[6,8],[0,8]]],[[[7,7],[5,0]],[[5,5],[5,6]]]]"],
Snailfish["[[[[6,6],[7,7]],[[0,7],[7,7]]],[[[5,5],[5,6]],9]]"] +
Snailfish["[1,[[[9,3],9],[[9,0],[0,7]]]]"]

assert_equal Snailfish["[[[[7,7],[7,7]],[[8,7],[8,7]]],[[[7,0],[7,7]],9]]"],
Snailfish["[[[[7,8],[6,7]],[[6,8],[0,8]]],[[[7,7],[5,0]],[[5,5],[5,6]]]]"] +
Snailfish["[[[5,[7,4]],7],1]"]

assert_equal Snailfish["[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]"],
Snailfish["[[[[7,7],[7,7]],[[8,7],[8,7]]],[[[7,0],[7,7]],9]]"] +
Snailfish["[[[[4,2],2],6],[8,7]]"]
end

def test_magnitude
assert_equal 143, Snailfish["[[1,2],[[3,4],5]]"].magnitude
assert_equal 1384, Snailfish["[[[[0,7],4],[[7,8],[6,0]]],[8,1]]"].magnitude
assert_equal 445, Snailfish["[[[[1,1],[2,2]],[3,3]],[4,4]]"].magnitude
assert_equal 791, Snailfish["[[[[3,0],[5,3]],[4,4]],[5,5]]"].magnitude
assert_equal 1137, Snailfish["[[[[5,0],[7,4]],[5,5]],[6,6]]"].magnitude
assert_equal 3488, Snailfish["[[[[8,7],[7,7]],[[8,6],[7,7]]],[[[0,7],[6,6]],[8,7]]]"].magnitude
end

def test_split
assert_equal "[[5,5],0]", Snailfish["[10,0]"].split!
assert_equal "[0,[5,6]]", Snailfish["[0,11]"].split!

assert_equal "[0,[[6,6],0]]", Snailfish["[0,[12,0]]"].split!
assert_equal "[0,[[6,7],[0,14]]]", Snailfish["[0,[13,[0,14]]]"].split!

assert_equal "[[[[0,7],4],[[7,8],[0,13]]],[1,1]]",
Snailfish["[[[[0,7],4],[15,[0,13]]],[1,1]]"].split!

refute Snailfish["[0,[1,[3,[[4,5],6]]]]"].split!
end

def test_explode
assert_equal "[[[[0,9],2],3],4]", Snailfish["[[[[[9,8],1],2],3],4]"].explode!
assert_equal "[7,[6,[5,[7,0]]]]", Snailfish["[7,[6,[5,[4,[3,2]]]]]"].explode!
assert_equal "[[6,[5,[7,0]]],3]", Snailfish["[[6,[5,[4,[3,2]]]],1]"].explode!

assert_equal "[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]",
Snailfish["[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]"].explode!
assert_equal "[[3,[2,[8,0]]],[9,[5,[7,0]]]]",

Snailfish["[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]"].explode!

assert_equal "[[[[6,7],[0,7]],[[13,0],[7,21]]],[[2,[11,10]],[[0,8],[8,0]]]]",
Snailfish["[[[[6,7],[0,7]],[[7,[6,7]],[0,21]]],[[2,[11,10]],[[0,8],[8,0]]]]"].explode!

refute Snailfish["[[[[0,7],4],[[7,8],[6,0]]],[8,1]]"].explode!
end

def test_reduce
assert_equal Snailfish["[[[[0,7],4],[[7,8],[6,0]]],[8,1]]"],
Snailfish["[[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]]"].reduce!
end
end

0 comments on commit fa90b4d

Please sign in to comment.