Skip to content

Instantly share code, notes, and snippets.

@sarahzrf
Created December 18, 2021 19:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sarahzrf/57510e7b1a19241732bca02b5e8345ad to your computer and use it in GitHub Desktop.
Save sarahzrf/57510e7b1a19241732bca02b5e8345ad to your computer and use it in GitHub Desktop.
require 'json'
class Atom
attr_accessor :val, :prv, :nxt, :become
def initialize(val)
@val = val
end
def leftmost
self
end
def rightmost
self
end
def split
return false unless val >= 10
val_l = val / 2
val_r = val - val_l
become.(Pair.new(Atom.new(val_l), Atom.new(val_r)))
true
end
def explode(depth=0)
false
end
def to_nomber
val
end
def magnitude
val
end
def inspect
"#<Atom: #{to_nomber.inspect}>"
end
end
class Pair
attr_reader :left, :right
attr_accessor :become
def initialize(l, r)
l.rightmost.nxt = r.leftmost
r.leftmost.prv = l.rightmost
l.become = method(:left=)
r.become = method(:right=)
@left = l
@right = r
end
def leftmost
left.leftmost
end
def rightmost
right.rightmost
end
def left=(l)
l.leftmost.prv = leftmost.prv
leftmost.prv.nxt = l.leftmost if leftmost.prv
l.rightmost.nxt = right.leftmost
right.leftmost.prv = l.rightmost
l.become = method(:left=)
@left = l
end
def right=(r)
r.rightmost.nxt = rightmost.nxt
rightmost.nxt.prv = r.rightmost if rightmost.nxt
r.leftmost.prv = left.rightmost
left.rightmost.nxt = r.leftmost
r.become = method(:right=)
@right = r
end
def explode(depth=0)
if depth >= 4
left.prv.val += left.val if left.prv
right.nxt.val += right.val if right.nxt
become.(Atom.new(0))
true
else
left.explode(depth + 1) or right.explode(depth + 1)
end
end
def split
left.split or right.split
end
def normalize
loop do
progress = false
while explode
progress = true
end
if split
progress = true
end
break if !progress
end
self
end
def to_nomber
[left.to_nomber, right.to_nomber]
end
def magnitude
3 * left.magnitude + 2 * right.magnitude
end
def inspect
"#<Pair: #{to_nomber.inspect}>"
end
end
def construct(nomber)
case nomber
when Integer
Atom.new(nomber)
when Array
nl, nr = nomber
Pair.new(construct(nl), construct(nr))
else
raise "malformed nomber"
end
end
ns = $<.map {|l| construct(JSON.parse(l))}
final = ns.reduce {|n1, n2| Pair.new(n1, n2).normalize}
puts final.magnitude
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment