dinesman_problem_parsing.sf 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/Dinesman%27s_multiple-dwelling_problem
  4. #
  5. func dinesman(problem) {
  6. var lines = problem.split('.')
  7. var names = lines.first.scan(/\b[A-Z]\w*/)
  8. var re_names = Regex(names.join('|'))
  9. # Later on, search for these keywords (the word "not" is handled separately).
  10. var words = %w(first second third fourth fifth sixth seventh eighth ninth tenth
  11. bottom top higher lower adjacent);
  12. var re_keywords = Regex(words.join('|'))
  13. # Build an array of lambda's
  14. var predicates = lines.slice(1,-1).map{ |line|
  15. var keywords = line.scan(re_keywords)
  16. var (name1, name2) = line.scan(re_names)...
  17. keywords.map{ |keyword|
  18. var l = do {
  19. given(keyword) {
  20. when ("bottom") { ->(c) { c.first == name1 } }
  21. when ("top") { ->(c) { c.last == name1 } }
  22. when ("higher") { ->(c) { c.index(name1) > c.index(name2) } }
  23. when ("lower") { ->(c) { c.index(name1) < c.index(name2) } }
  24. when ("adjacent") { ->(c) { c.index(name1) - c.index(name2) -> abs == 1 } }
  25. default { ->(c) { c[words.index(keyword)] == name1 } }
  26. }
  27. }
  28. line ~~ /\bnot\b/ ? func(c) { l(c) -> not } : l; # handle "not"
  29. }
  30. }.flat
  31. names.permutations { |*candidate|
  32. predicates.all { |predicate| predicate(candidate) } && return candidate;
  33. }
  34. }
  35. var demo1 = "Abe Ben Charlie David. Abe not second top. not adjacent Ben Charlie.
  36. David Abe adjacent. David adjacent Ben. Last line."
  37. var demo2 = "A B C D. A not adjacent D. not B adjacent higher C. C lower D. Last line"
  38. var problem1 = "Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that
  39. contains only five floors. Baker does not live on the top floor. Cooper does not live on the bottom floor.
  40. Fletcher does not live on either the top or the bottom floor. Miller lives on a higher floor than does Cooper.
  41. Smith does not live on a floor adjacent to Fletcher's. Fletcher does not live on a floor adjacent to Cooper's.
  42. Where does everyone live?"
  43. var problem2 = "Baker, Cooper, Fletcher, Miller, Guinan, and Smith
  44. live on different floors of an apartment house that contains
  45. only seven floors. Guinan does not live on either the top or the third or the fourth floor.
  46. Baker does not live on the top floor. Cooper
  47. does not live on the bottom floor. Fletcher does not live on
  48. either the top or the bottom floor. Miller lives on a higher
  49. floor than does Cooper. Smith does not live on a floor
  50. adjacent to Fletcher's. Fletcher does not live on a floor
  51. adjacent to Cooper's. Where does everyone live?"
  52. [demo1, demo2, problem1, problem2].each{|problem| say dinesman(problem).join("\n"); say '' };