aboutsummaryrefslogtreecommitdiff
path: root/day07/part2
diff options
context:
space:
mode:
authorNat Lasseter <Nat Lasseter nathan@bytemark.co.uk>2017-12-14 19:18:21 +0000
committerNat Lasseter <Nat Lasseter nathan@bytemark.co.uk>2017-12-14 19:18:21 +0000
commit1a0e17e9d8551f1866642e3feb3e76c1f4890108 (patch)
tree89e92e25eb2ef2ad471111aa12816d1049399def /day07/part2
parent3454670e13fb38d3821420b377a8abaa8c7ee472 (diff)
Day07 Part2
Diffstat (limited to 'day07/part2')
-rwxr-xr-xday07/part289
1 files changed, 89 insertions, 0 deletions
diff --git a/day07/part2 b/day07/part2
new file mode 100755
index 0000000..46245ae
--- /dev/null
+++ b/day07/part2
@@ -0,0 +1,89 @@
+#!/usr/bin/env ruby
+
+class Array
+ def to_empty_hash
+ h = {}
+ self.each do |el|
+ h[el] = nil
+ end
+ return h
+ end
+end
+
+input = $stdin.readlines.map(&:chomp)
+
+hash = {}
+
+input.each do |line|
+ me, them = line.split(" -> ")
+ _, name, weight = me.match(/([a-z]+) \((\d+)\)/).to_a
+ children = them.nil? ? [] : them.split(", ")
+
+ hash[name.intern] = {
+ :weight => weight.to_i,
+ :remove => false,
+ :children => children.map(&:intern).to_empty_hash
+ }
+end
+
+hash.each do |key, value|
+ value[:children].each do |ckey, cvalue|
+ if cvalue.nil? then
+ value[:children][ckey] = hash[ckey].dup
+ hash[ckey][:remove] = true
+ end
+ end
+end
+
+hash = hash.reject { |key, value|
+ value[:remove]
+}
+
+here = nil
+newhere = hash[hash.keys.first]
+
+def weight(prog)
+ return prog[:weight] if prog[:children].empty?
+ chilweight = 0
+ prog[:children].each do |k, v|
+ chilweight += weight(v)
+ end
+ return prog[:weight] + chilweight
+end
+
+def is_balanced?(tower)
+ ws = []
+ tower[:children].each do |k, v|
+ ws << weight(v)
+ end
+ return ws.uniq.length == 1
+end
+
+while here != newhere do
+ here = newhere
+ here[:children].each do |key, value|
+ unless is_balanced?(value) then
+ newhere = value
+ end
+ end
+end
+
+ws = []
+here[:children].each do |k, v|
+ ws << weight(v)
+end
+
+goodweight = nil
+ws.each do |w|
+ goodweight = w if ws.count(w) != 1
+end
+
+here[:children].each do |k, v|
+ if weight(v) == goodweight then
+ next
+ else
+ diff = weight(v) - goodweight
+ puts v[:weight] - diff
+ break
+ end
+end