func dinesman(problem) { var lines = problem.split('.') var names = lines.first.scan(/\b[A-Z]\w*/) var re_names = Regex(names.join('|'))   # Later on, search for these keywords (the word "not" is handled separately). var words = %w(first second third fourth fifth sixth seventh eighth ninth tenth bottom top higher lower adjacent) var re_keywords = Regex(words.join('|'))   # Build an array of lambda's var predicates = lines.first(-1).last(-1).map{ |line| var keywords = line.scan(re_keywords) var (name1, name2) = line.scan(re_names)...   keywords.map{ |keyword| var l = do { given(keyword) { when ("bottom") { ->(c) { c.first == name1 } } when ("top") { ->(c) { c.last == name1 } } when ("higher") { ->(c) { c.index(name1) > c.index(name2) } } when ("lower") { ->(c) { c.index(name1) < c.index(name2) } } when ("adjacent") { ->(c) { c.index(name1) - c.index(name2) -> abs == 1 } } default { ->(c) { c[words.index(keyword)] == name1 } } } } line ~~ /\bnot\b/ ? func(c) { l(c) -> not } : l; # handle "not" } }.flat   names.permutations { |*candidate| predicates.all { |predicate| predicate(candidate) } && return candidate } }