| 
 | 1 | +#!/usr/bin/env ruby  | 
 | 2 | + | 
 | 3 | +$monkeys = {}  | 
 | 4 | + | 
 | 5 | +class IsHuman < ::StandardError  | 
 | 6 | +end  | 
 | 7 | + | 
 | 8 | +class Monkey  | 
 | 9 | +  def initialize(name, operation)  | 
 | 10 | +    number_format = /^(?<num>[[:digit:]]+)$/  | 
 | 11 | +    calc_format = /^(?<m1>[[:alpha:]]+) (?<op>[-+*\/=]) (?<m2>[[:alpha:]]+)$/  | 
 | 12 | + | 
 | 13 | +    @operation = operation  | 
 | 14 | +    @name = name  | 
 | 15 | +    @value = nil  | 
 | 16 | + | 
 | 17 | +    if m = number_format.match(@operation)  | 
 | 18 | +      @value = m['num'].to_i  | 
 | 19 | +    else  | 
 | 20 | +      m = calc_format.match(@operation)  | 
 | 21 | +      @m1 = m['m1']  | 
 | 22 | +      @op = m['op']  | 
 | 23 | +      @op = '==' if @name == 'root'  | 
 | 24 | +      @m2 = m['m2']  | 
 | 25 | +    end  | 
 | 26 | +  end  | 
 | 27 | + | 
 | 28 | +  def value  | 
 | 29 | +    raise IsHuman if setting? and @name == 'humn'  | 
 | 30 | +    return @value if @value  | 
 | 31 | + | 
 | 32 | +    @value = $monkeys[@m1].value.send(@op, $monkeys[@m2].value)  | 
 | 33 | +  end  | 
 | 34 | + | 
 | 35 | +  def set_equal!(value)  | 
 | 36 | +    if @name == 'humn'  | 
 | 37 | +      @value = value  | 
 | 38 | +      return  | 
 | 39 | +    end  | 
 | 40 | + | 
 | 41 | +    begin  | 
 | 42 | +      left = $monkeys[@m1].value  | 
 | 43 | +    rescue IsHuman  | 
 | 44 | +      left = nil  | 
 | 45 | +    end  | 
 | 46 | +    begin  | 
 | 47 | +      right = $monkeys[@m2].value  | 
 | 48 | +    rescue IsHuman  | 
 | 49 | +      right = nil  | 
 | 50 | +    end  | 
 | 51 | + | 
 | 52 | +    case @op  | 
 | 53 | +    when '=='  | 
 | 54 | +      $monkeys[@m1].set_equal!(right) if right  | 
 | 55 | +      $monkeys[@m2].set_equal!(left) if left  | 
 | 56 | +    when '+'  | 
 | 57 | +      $monkeys[@m1].set_equal!(value - right) if right  | 
 | 58 | +      $monkeys[@m2].set_equal!(value - left) if left  | 
 | 59 | +    when '-'  | 
 | 60 | +      $monkeys[@m1].set_equal!(value + right) if right  | 
 | 61 | +      $monkeys[@m2].set_equal!(left - value) if left  | 
 | 62 | +    when '*'  | 
 | 63 | +      $monkeys[@m1].set_equal!(value / right) if right  | 
 | 64 | +      $monkeys[@m2].set_equal!(value / left) if left  | 
 | 65 | +    when '/'  | 
 | 66 | +      $monkeys[@m1].set_equal!(value * right) if right  | 
 | 67 | +      $monkeys[@m2].set_equal!(left / value) if left  | 
 | 68 | +    end  | 
 | 69 | +  end  | 
 | 70 | + | 
 | 71 | +  def to_s  | 
 | 72 | +    "<#{self.class}: #{@name} = #{@operation} (#{@value})>"  | 
 | 73 | +  end  | 
 | 74 | + | 
 | 75 | +  alias inspect to_s  | 
 | 76 | + | 
 | 77 | +  def self.setting=(maybe)  | 
 | 78 | +    @@setting = maybe  | 
 | 79 | +  end  | 
 | 80 | + | 
 | 81 | +  def self.setting  | 
 | 82 | +    @@setting ||= false  | 
 | 83 | +  end  | 
 | 84 | + | 
 | 85 | +  private  | 
 | 86 | + | 
 | 87 | +  def setting?  | 
 | 88 | +    self.class.setting  | 
 | 89 | +  end  | 
 | 90 | +end  | 
 | 91 | + | 
 | 92 | + | 
 | 93 | +input = File.read('21.input').lines  | 
 | 94 | + | 
 | 95 | +monkey_format = /^(?<name>[[:alpha:]]+): (?<op>.*)$/  | 
 | 96 | + | 
 | 97 | +input.each do |line|  | 
 | 98 | +  m = monkey_format.match line  | 
 | 99 | +  $monkeys[m['name']] = Monkey.new(m['name'], m['op'])  | 
 | 100 | +end  | 
 | 101 | + | 
 | 102 | +Monkey.setting = true  | 
 | 103 | +$monkeys['root'].set_equal! nil  | 
 | 104 | +Monkey.setting = false  | 
 | 105 | +print $monkeys['humn'].value, "\n"  | 
0 commit comments