Created
December 18, 2021 19:26
-
-
Save sarahzrf/57510e7b1a19241732bca02b5e8345ad to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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