34 lines
1.3 KiB
Text
34 lines
1.3 KiB
Text
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.ft(1, lines.end-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
|
||
}
|
||
}
|