/* Who Owns the Zerba?
On a city block there are five houses in a row, numbered from left to right, each of a different color and inhabited by men of different nationalities, with different pets, drinks and cigarettes. You are given the following clues:
1. The Englishman lives in the red house. 2. The Spaniard owns the dog. 3. Coffee is drunk in the green house. 4. The Ukrainian drinks tea. 5. The green house is immediately to the right of the ivory house. 6. The Old Gold smoker owns snails. 7. Kools are smoked in the yellow house. 8. Milk is drunk in house #3. 9. The Norwegian lives in house #1. 10. The man who smokes Chesterfields lives in the house next to the man
with the fox.
11. Kools are smoked in the house next to the house where the horse is kept. 12. The Lucky Strike smoker drinks orange juice. 13. The Japanese smokes Parliaments. 14. The Norwegian lives next to the blue house.
Who drinks water? And who owns the zebra?
This puzzle was in the International Edition of Life Magazine in 1962.
- /
- include <setjmp.h>
- define EITHER if (S1? = S0?, ! setjmp((S++)->jb)) {
- define OR } else EITHER
- define REJECT longjmp((--S)->jb, 1)
- define END_EITHER } else REJECT;
/* values in tmat: */
- define T_UNK
- define T_YES 1
- define T_NO 2
- define Val(t1,t2) (S->tmatt1?t2?)
define CLASS(x) \
(((x) / NUM_ITEM) * NUM_ITEM)
define EVERY_TOKEN(x) \
(x = 0; x < TOT_TOKEN; x++)
define EVERY_ITEM(x, class) \
(x = CLASS(class); x < CLASS(class) + NUM_ITEM; x++)
- define BEGIN \
struct state { \
} States100?, *S = States; \
\
main() \ { \
int token; \
\
for EVERY_TOKEN(token) \
yes(token, token); \
EITHER
/* Here is the problem-specific data */
- define NUM_ITEM 5
- define NUM_CLASS 6
- define TOT_TOKEN (NUM_ITEM * NUM_CLASS)
- define HOUSE_0
- define HOUSE_1 1
- define HOUSE_2 2
- define HOUSE_3 3
- define HOUSE_4 4
- define ENGLISH 5
- define SPANISH 6
- define NORWEG 7
- define UKRAIN 8
- define JAPAN 9
- define GREEN 10
- define RED 11
- define IVORY 12
- define YELLOW 13
- define BLUE 14
- define COFFEE 15
- define TEA 16
- define MILK 17
- define OJUICE 18
- define WATER 19
- define DOG 20
- define SNAIL 21
- define FOX 22
- define HORSE 23
- define ZEBRA 24
- define OGOLD 25
- define PLAYER 26
- define CHESTER 27
- define LSTRIKE 28
- define PARLIA 29
char *names[] = {
"HOUSE_0", "HOUSE_1", "HOUSE_2", "HOUSE_3", "HOUSE_4", "ENGLISH", "SPANISH", "NORWEG", "UKRAIN", "JAPAN", "GREEN", "RED", "IVORY", "YELLOW", "BLUE", "COFFEE", "TEA", "MILK", "OJUICE", "WATER", "DOG", "SNAIL", "FOX", "HORSE", "ZEBRA", "OGOLD", "PLAYER", "CHESTER", "LSTRIKE", "PARLIA",
};
BEGIN
yes(ENGLISH, RED); /* Clue 1 / yes(SPANISH, DOG); / Clue 2 / yes(COFFEE, GREEN); / Clue 3 / yes(UKRAIN, TEA); / Clue 4 */
EITHER /* Clue 5 */
yes(IVORY, HOUSE_0); yes(GREEN, HOUSE_1);
OR
yes(IVORY, HOUSE_1); yes(GREEN, HOUSE_2);
OR
yes(IVORY, HOUSE_2); yes(GREEN, HOUSE_3);
OR
yes(IVORY, HOUSE_3); yes(GREEN, HOUSE_4);
END_EITHER
yes(OGOLD, SNAIL); /* Clue 6 / yes(PLAYER, YELLOW); / Clue 7 / yes(MILK, HOUSE_2); / Clue 8 / yes(NORWEG, HOUSE_0); / Clue 9 */
EITHER /* Clue 10 */
yes(CHESTER, HOUSE_0); yes(FOX, HOUSE_1);
OR
yes(CHESTER, HOUSE_4); yes(FOX, HOUSE_3);
OR
yes(CHESTER, HOUSE_1); EITHER yes(FOX, HOUSE_0); OR yes(FOX, HOUSE_2); END_EITHER
OR
yes(CHESTER, HOUSE_2); EITHER yes(FOX, HOUSE_1); OR yes(FOX, HOUSE_3); END_EITHER
OR
yes(CHESTER, HOUSE_3); EITHER yes(FOX, HOUSE_2); OR yes(FOX, HOUSE_4); END_EITHER
END_EITHER
EITHER /* Clue 11 */
yes(PLAYER, HOUSE_0); yes(HORSE, HOUSE_1);
OR
yes(PLAYER, HOUSE_4); yes(HORSE, HOUSE_3);
OR
yes(PLAYER, HOUSE_1); EITHER yes(HORSE, HOUSE_0); OR yes(HORSE, HOUSE_2); END_EITHER
OR
yes(PLAYER, HOUSE_2); EITHER yes(HORSE, HOUSE_1); OR yes(HORSE, HOUSE_3); END_EITHER
OR
yes(PLAYER, HOUSE_3); EITHER yes(HORSE, HOUSE_2); OR yes(HORSE, HOUSE_4); END_EITHER
END_EITHER
yes(LSTRIKE, OJUICE); /* Clue 12 / yes(JAPAN, PARLIA); / Clue 13 */
EITHER /* Clue 14 */
yes(NORWEG, HOUSE_0); yes(BLUE, HOUSE_1);
OR
yes(NORWEG, HOUSE_4); yes(BLUE, HOUSE_3);
OR
yes(NORWEG, HOUSE_1); EITHER yes(BLUE, HOUSE_0); OR yes(BLUE, HOUSE_2); END_EITHER
OR
yes(NORWEG, HOUSE_2); EITHER yes(BLUE, HOUSE_1); OR yes(BLUE, HOUSE_3); END_EITHER
OR
yes(NORWEG, HOUSE_3); EITHER yes(BLUE, HOUSE_2); OR yes(BLUE, HOUSE_4); END_EITHER
END_EITHER
/* End of problem-specific data */
solveit();
OR
printf("All solutions found\n"); exit(0);
END_EITHER
}
no(a1, a2) {
int non1, non2, token;
if (Val(a1, a2) == T_YES)
REJECT;
else if (Val(a1, a2) == T_UNK) {
Val(a1, a2) = T_NO; no(a2, a1); non1 = non2 = -1;
for EVERY_ITEM(token, a1)
if (Val(token, a2) != T_NO)
if (non1 == -1)
non1 = token;
else
break;
if (non1 == -1)
REJECT;
else if (token == CLASS(a1) + NUM_ITEM)
yes(non1, a2);
for EVERY_TOKEN(token)
if (Val(token, a1) == T_YES)
no(a2, token);
}
}
yes(a1, a2) {
int token;
if (Val(a1, a2) == T_NO)
REJECT;
else if (Val(a1, a2) == T_UNK) {
Val(a1, a2) = T_YES; yes(a2, a1); for EVERY_ITEM(token, a1)
if (token != a1)
no(token, a2);
for EVERY_TOKEN(token)
if (Val(token, a1) == T_YES)
yes(a2, token);
else if (Val(token, a1) == T_NO)
no(a2, token);
}
}
solveit() {
int token, tok2;
for EVERY_TOKEN(token)
for (tok2 = token; tok2 < TOT_TOKEN; tok2++)
if (Val(token, tok2) == T_UNK) {
EITHER
yes(token, tok2);
OR
no(token, tok2);
END_EITHER; return solveit();
}
printf("Solution:\n"); for EVERY_ITEM(token, 0) {
for (tok2 = NUM_ITEM; tok2 < TOT_TOKEN; tok2++)
if (Val(token, tok2) == T_YES)
printf("\n");
} REJECT;
}
--- james@crc.ricoh.com (James Allen)
