RosettaCodeData/Task/Dinesmans-multiple-dwelling.../Ruby/dinesmans-multiple-dwelling...

28 lines
1.1 KiB
Ruby

def solve( problem )
lines = problem.split(".")
names = lines.first.scan( /[A-Z]\w*/ )
re_names = Regexp.union( names )
# Later on, search for these keywords (the word "not" is handled separately).
words = %w(first second third fourth fifth sixth seventh eighth ninth tenth
bottom top higher lower adjacent)
re_keywords = Regexp.union( words )
predicates = lines[1..-2].flat_map do |line| #build an array of lambda's
keywords = line.scan( re_keywords )
name1, name2 = line.scan( re_names )
keywords.map do |keyword|
l = case keyword
when "bottom" then ->(c){ c.first == name1 }
when "top" then ->(c){ c.last == name1 }
when "higher" then ->(c){ c.index( name1 ) > c.index( name2 ) }
when "lower" then ->(c){ c.index( name1 ) < c.index( name2 ) }
when "adjacent" then ->(c){ (c.index( name1 ) - c.index( name2 )).abs == 1 }
else ->(c){ c[words.index(keyword)] == name1 }
end
line =~ /\bnot\b/ ? ->(c){not l.call(c) } : l # handle "not"
end
end
names.permutation.detect{|candidate| predicates.all?{|predicate| predicate.(candidate)}}
end