[2021][ruby][18.x]
change zyqnxlpmqsuqqvqrzzyumvpmopqrnwus
commit c25cb405c11f7217ddb4f1ce8ea85dccc4817437
author Alpha Chen <alpha@kejadlen.dev>
date
parent vnoznxvk
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