diff --git a/2021/ruby/day_18.rb b/2021/ruby/day_18.rb new file mode 100644 index 0000000..879b0f0 --- /dev/null +++ b/2021/ruby/day_18.rb @@ -0,0 +1,79 @@ +require "strscan" + +def add(a, b) + reduced("[#{a},#{b}]") +end + +def reduced(s) + last_s = "" + until s == last_s + last_s = s + + to_explode = find_nested(s) + if to_explode + s = explode(s, to_explode) + next + end + + s = s.sub(/[1-9]\d+/) {|n| + half = n.to_i / 2.0 + pair = [half.floor, half.ceil] + "[#{pair.join(?,)}]" + } + end + s +end + +def find_nested(s) + ss = StringScanner.new(s) + + depth = 0 + until ss.eos? + case + when ss.scan(/\[/) + if depth == 4 + a = ss.pos-1 + ss.scan(/\d+,\d+\]/) + b = ss.pos-1 + return [a, b] + end + depth += 1 + when ss.scan(/\]/) + depth -= 1 + when ss.scan(/\d+|,/) + # no-op + else + fail + end + end + + nil +end + +def explode(s, pair_range) + a, b = pair_range + pair = s[a..b].scan(/\d+/).map(&:to_i) + + [ + s[0...a].reverse.sub(/\d+/) { (_1.reverse.to_i + pair[0]).to_s.reverse }.reverse, + 0, + s[b+1..].sub(/(\d+)/) { _1.to_i + pair[1] }, + ].join +end + +class Array + def magnitude + 3*self[0].magnitude + 2*self[1].magnitude + end +end + +class Integer + def magnitude + self + end +end + +# sum = ARGF.read.split("\n").reject(&:empty?).inject {|sum,num| add(sum, num) } +# p eval(sum).magnitude + +p ARGF.read.split("\n").reject(&:empty?).permutation(2).map { eval(add(*_1)).magnitude }.max