Constraint Processing (#70)

Just finish my solution, I run out of time to provide an example …
define the domain as instance variable.
define the rule by using block & instance variable.
define the solution block by using instance variable.
( all block will exec on “Engine”'s instance_eval )

class Engine

def go(&solution)
solve(instance_variables, &solution)
end

private
def method_missing(name, *args, &block)
if name.to_s =~ /=$/ && block.nil?
vars(name, *args)
elsif args.size == 0 && !block.nil?
rules(name, &block)
else
super
end
end

def rules(name, &block)
self.class.send(:define_method, name, &block)
self.class.send(:protected, name)
end

def vars(name, *args)
name = name.to_s.sub(/=$/, ‘’)
self.class.class_eval(“attr_accessor :#{name}”)
args = args[0] if args.size == 1 && args[0].respond_to?(:each)
instance_variable_set("@#{name}", args)
end

def solve(vars, &solution)
if (vars.size != 0)
name = vars.shift
value = instance_variable_get(name)
value.each { |e|
instance_variable_set(name, e)
solve(vars.dup, &solution)
}
instance_variable_set(name, value)
else
protected_methods.each { |method|
return if !send(method)
}
instance_eval(&solution)
end
end

end

if FILE == $0
e = Engine.new
e.a = 0…4
e.b = 0…4
e.c = 0…4
e.rule1 { @a < @b }
e.rule2 { @a + @b == @c }
e.go { puts “a => #@a, b => #@b, c => #@c” }
end

END