You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
5.1 KiB

  1. /* ZEBRA, Who Owns the Zebra? */
  2. /* Written in GNU MathProg by Andrew Makhorin <mao@gnu.org> */
  3. ########################################################################
  4. # The Zebra Puzzle is a well-known logic puzzle.
  5. #
  6. # It is often called "Einstein's Puzzle" or "Einstein's Riddle"
  7. # because it is said to have been invented by Albert Einstein as a boy,
  8. # with the common claim that Einstein said "only 2 percent of the
  9. # world's population can solve". It is also sometimes attributed to
  10. # Lewis Carroll. However, there is no known evidence for Einstein's or
  11. # Carroll's authorship.
  12. #
  13. # There are several versions of this puzzle. The version below is
  14. # quoted from the first known publication in Life International
  15. # magazine on December 17, 1962.
  16. #
  17. # 1. There are five houses.
  18. # 2. The Englishman lives in the red house.
  19. # 3. The Spaniard owns the dog.
  20. # 4. Coffee is drunk in the green house.
  21. # 5. The Ukrainian drinks tea.
  22. # 6. The green house is immediately to the right of the ivory house.
  23. # 7. The Old Gold smoker owns snails.
  24. # 8. Kools are smoked in the yellow house.
  25. # 9. Milk is drunk in the middle house.
  26. # 10. The Norwegian lives in the first house.
  27. # 11. The man who smokes Chesterfields lives in the house next to the
  28. # man with the fox.
  29. # 12. Kools are smoked in the house next to the house where the horse
  30. # is kept.
  31. # 13. The Lucky Strike smoker drinks orange juice.
  32. # 14. The Japanese smokes Parliaments.
  33. # 15. The Norwegian lives next to the blue house.
  34. #
  35. # Now, who drinks water? Who owns the zebra?
  36. #
  37. # In the interest of clarity, it must be added that each of the five
  38. # houses is painted a different color, and their inhabitants are of
  39. # different national extractions, own different pets, drink different
  40. # beverages and smoke different brands of American cigarettes. One
  41. # other thing: In statement 6, right means your right.
  42. #
  43. # (From Wikipedia, the free encyclopedia.)
  44. ########################################################################
  45. set HOUSE := { 1..5 };
  46. set COLOR := { "blue", "green", "ivory", "red", "yellow" };
  47. set NATIONALITY := { "Englishman", "Japanese", "Norwegian", "Spaniard",
  48. "Ukranian" };
  49. set DRINK := { "coffee", "milk", "orange_juice", "tea", "water" };
  50. set SMOKE := { "Chesterfield", "Kools", "Lucky_Strike", "Old_Gold",
  51. "Parliament" };
  52. set PET := { "dog", "fox", "horse", "snails", "zebra" };
  53. var color{HOUSE, COLOR}, binary;
  54. c1{h in HOUSE}: sum{c in COLOR} color[h,c] = 1;
  55. c2{c in COLOR}: sum{h in HOUSE} color[h,c] = 1;
  56. var nationality{HOUSE, NATIONALITY}, binary;
  57. n1{h in HOUSE}: sum{n in NATIONALITY} nationality[h,n] = 1;
  58. n2{n in NATIONALITY}: sum{h in HOUSE} nationality[h,n] = 1;
  59. var drink{HOUSE, DRINK}, binary;
  60. d1{h in HOUSE}: sum{d in DRINK} drink[h,d] = 1;
  61. d2{d in DRINK}: sum{h in HOUSE} drink[h,d] = 1;
  62. var smoke{HOUSE, SMOKE}, binary;
  63. s1{h in HOUSE}: sum{s in SMOKE} smoke[h,s] = 1;
  64. s2{s in SMOKE}: sum{h in HOUSE} smoke[h,s] = 1;
  65. var pet{HOUSE, PET}, binary;
  66. p1{h in HOUSE}: sum{p in PET} pet[h,p] = 1;
  67. p2{p in PET}: sum{h in HOUSE} pet[h,p] = 1;
  68. /* the Englishman lives in the red house */
  69. f2{h in HOUSE}: nationality[h,"Englishman"] = color[h,"red"];
  70. /* the Spaniard owns the dog */
  71. f3{h in HOUSE}: nationality[h,"Spaniard"] = pet[h,"dog"];
  72. /* coffee is drunk in the green house */
  73. f4{h in HOUSE}: drink[h,"coffee"] = color[h,"green"];
  74. /* the Ukrainian drinks tea */
  75. f5{h in HOUSE}: nationality[h,"Ukranian"] = drink[h,"tea"];
  76. /* the green house is immediately to the right of the ivory house */
  77. f6{h in HOUSE}:
  78. color[h,"green"] = if h = 1 then 0 else color[h-1,"ivory"];
  79. /* the Old Gold smoker owns snails */
  80. f7{h in HOUSE}: smoke[h,"Old_Gold"] = pet[h,"snails"];
  81. /* Kools are smoked in the yellow house */
  82. f8{h in HOUSE}: smoke[h,"Kools"] = color[h,"yellow"];
  83. /* milk is drunk in the middle house */
  84. f9: drink[3,"milk"] = 1;
  85. /* the Norwegian lives in the first house */
  86. f10: nationality[1,"Norwegian"] = 1;
  87. /* the man who smokes Chesterfields lives in the house next to the man
  88. with the fox */
  89. f11{h in HOUSE}:
  90. (1 - smoke[h,"Chesterfield"]) +
  91. (if h = 1 then 0 else pet[h-1,"fox"]) +
  92. (if h = 5 then 0 else pet[h+1,"fox"]) >= 1;
  93. /* Kools are smoked in the house next to the house where the horse is
  94. kept */
  95. f12{h in HOUSE}:
  96. (1 - smoke[h,"Kools"]) +
  97. (if h = 1 then 0 else pet[h-1,"horse"]) +
  98. (if h = 5 then 0 else pet[h+1,"horse"]) >= 1;
  99. /* the Lucky Strike smoker drinks orange juice */
  100. f13{h in HOUSE}: smoke[h,"Lucky_Strike"] = drink[h,"orange_juice"];
  101. /* the Japanese smokes Parliaments */
  102. f14{h in HOUSE}: nationality[h,"Japanese"] = smoke[h,"Parliament"];
  103. /* the Norwegian lives next to the blue house */
  104. f15{h in HOUSE}:
  105. (1 - nationality[h,"Norwegian"]) +
  106. (if h = 1 then 0 else color[h-1,"blue"]) +
  107. (if h = 5 then 0 else color[h+1,"blue"]) >= 1;
  108. solve;
  109. printf "\n";
  110. printf "HOUSE COLOR NATIONALITY DRINK SMOKE PET\n";
  111. for {h in HOUSE}
  112. { printf "%5d", h;
  113. printf{c in COLOR: color[h,c]} " %-6s", c;
  114. printf{n in NATIONALITY: nationality[h,n]} " %-11s", n;
  115. printf{d in DRINK: drink[h,d]} " %-12s", d;
  116. printf{s in SMOKE: smoke[h,s]} " %-12s", s;
  117. printf{p in PET: pet[h,p]} " %-6s", p;
  118. printf "\n";
  119. }
  120. printf "\n";
  121. end;