<pre>
<verbatim>
/*
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 (S[[1]] = S[[0]], ==== 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->tmat[[t1]][[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 {						
	char	tmat[[TOT''TOKEN]][[TOT''TOKEN]];		
	jmp_buf jb;					
} States[[100]], *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
");
		exit(0);
	END_EITHER
}

no(a1, a2)
{
	int	non1, non2, token;

	if (Val(a1, a2) <code></code> T_YES)
		REJECT;
	else if (Val(a1, a2) <code></code> T_UNK) {
		Val(a1, a2) = T_NO;
		no(a2, a1);
		non1 <code> non2 </code> -1;

		for EVERY_ITEM(token, a1)
			if (Val(token, a2) ===== T_NO)
====
				if (non1 <code></code> -1)
					non1 = token;
				else
					break;
		if (non1 <code></code> -1)
			REJECT;
		else if (token <code></code> CLASS(a1) + NUM_ITEM)
			yes(non1, a2);

		for EVERY_TOKEN(token)
			if (Val(token, a1) <code></code> T_YES)
				no(a2, token);
	}
}

yes(a1, a2)
{
	int	token;

	if (Val(a1, a2) <code></code> T_NO)
		REJECT;
	else if (Val(a1, a2) <code></code> 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) <code></code> T_YES)
				yes(a2, token);
			else if (Val(token, a1) <code></code> T_NO)
				no(a2, token);
	}
}

solveit()
{
	int	token, tok2;

	for EVERY_TOKEN(token)
		for (tok2 = token; tok2 < TOT_TOKEN; tok2++)
			if (Val(token, tok2) <code></code> T_UNK) {
				EITHER
					yes(token, tok2);
				OR
					no(token, tok2);
				END_EITHER;
				return solveit();
			}
	printf("Solution:
");
	for EVERY_ITEM(token, 0) {
		for (tok2 = NUM''ITEM; tok2 < TOT''TOKEN; tok2++)
			if (Val(token, tok2) <code></code> T_YES)
				printf("	%s %s
",names[[token]],names[[tok2]]);
		printf("
");
	}
	REJECT;
}

---
james@crc.ricoh.com (James Allen)
</verbatim>
</pre>
