Zebra puzzle

You are encouraged to solve this task according to the task description, using any language you may know.
The Zebra puzzle, a.k.a. Einstein's Riddle,
is a logic puzzle which is to be solved programmatically.



It has several variants, one of them this:

   There are five houses.
   The English man lives in the red house.
   The Swede has a dog.
   The Dane drinks tea.
   The green house is immediately to the left of the white house.
   They drink coffee in the green house.
   The man who smokes Pall Mall has birds.
   In the yellow house they smoke Dunhill.
   In the middle house they drink milk.
   The Norwegian lives in the first house.
   The man who smokes Blend lives in the house next to the house with cats.
   In a house next to the house where they have a horse, they smoke Dunhill.
   The man who smokes Blue Master drinks beer.
   The German smokes Prince.
   The Norwegian lives next to the blue house.
   They drink water in a house next to the house where they smoke Blend. 

The question is, who owns the zebra?

Additionally, list the solution for all the houses.

Optionally, show the solution is unique.



Related tasks

   Dinesman's multiple-dwelling problem
   Twelve statements


 
PROGRAM ZEBRA_PUZZLE
 
DIM DRINK$[4],NATION$[4],COLR$[4],SMOKE$[4],ANIMAL$[4]
DIM PERM$[120],X$[4]
 
PROCEDURE PERMUTATION(X$[]->X$[],OK)
    LOCAL I%,J%
    FOR I%=UBOUND(X$,1)-1 TO 0 STEP -1 DO
       EXIT IF X$[I%]<X$[I%+1]
    END FOR
    IF I%<0 THEN OK=FALSE  EXIT PROCEDURE END IF
    J%=UBOUND(X$,1)
    WHILE X$[J%]<=X$[I%] DO
         J%=J%-1
    END WHILE
    SWAP(X$[I%],X$[J%])
    I%=I%+1
    J%=UBOUND(X$,1)
    WHILE I%<J% DO
        SWAP(X$[I%],X$[J%])
        I%=I%+1
        J%=J%-1
    END WHILE
    OK=TRUE
END PROCEDURE
 
BEGIN
 
! The names (only used for printing the results)
 
    DATA("Beer","Coffee","Milk","Tea","Water")
    DATA("Denmark","England","Germany","Norway","Sweden")
    DATA("Blue","Green","Red","White","Yellow")
    DATA("Blend","BlueMaster","Dunhill","PallMall","Prince")
    DATA("Birds","Cats","Dog","Horse","Zebra")
 
    FOR I%=0 TO 4 DO READ(DRINK$[I%])   END FOR
    FOR I%=0 TO 4 DO READ(NATION$[I%])  END FOR
    FOR I%=0 TO 4 DO READ(COLR$[I%])    END FOR
    FOR I%=0 TO 4 DO READ(SMOKE$[I%])   END FOR
    FOR I%=0 TO 4 DO READ(ANIMAL$[I%])  END FOR
 
! Some single-character tags:
    A$="A"  B$="B"  c$="C"  d$="D"  e$="E"
 
! ERRE doesn't have enumerations!
    Beer$=A$  Coffee$=B$  Milk$=c$  TeA$=d$  Water$=e$
    Denmark$=A$  England$=B$  Germany$=c$  Norway$=d$  Sweden$=e$
    Blue$=A$  Green$=B$  Red$=c$  White$=d$  Yellow$=e$
    Blend$=A$  BlueMaster$=B$  Dunhill$=c$  PallMall$=d$  Prince$=e$
    Birds$=A$  Cats$=B$  Dog$=c$  Horse$=d$  ZebrA$=e$
 
    PRINT(CHR$(12);)
 
! Create the 120 permutations of 5 objects:
 
    X$[0]=A$  X$[1]=B$  X$[2]=C$  X$[3]=D$  X$[4]=E$
 
    REPEAT
       P%=P%+1
       PERM$[P%]=X$[0]+X$[1]+X$[2]+X$[3]+X$[4]
       PERMUTATION(X$[]->X$[],OK)
    UNTIL NOT OK
 
! Solve:
    SOLUTIONS%=0
    T1=TIMER
    FOR NATION%=1 TO 120 DO
        NATION$=PERM$[NATION%]
        IF LEFT$(NATION$,1)=Norway$ THEN
             FOR COLR%=1 TO 120 DO
                COLR$=PERM$[COLR%]
                IF INSTR(COLR$,Green$+White$)<>0 AND INSTR(NATION$,England$)=INSTR(COLR$,Red$) AND ABS(INSTR(NATION$,Norway$)-INSTR(COLR$,Blue$))=1 THEN
                    FOR DRINK%=1 TO 120 DO
                       DRINK$=PERM$[DRINK%]
                       IF MID$(DRINK$,3,1)=Milk$ AND INSTR(NATION$,Denmark$)=INSTR(DRINK$,TeA$) AND INSTR(DRINK$,Coffee$)=INSTR(COLR$,Green$) THEN
                           FOR SmOKe%=1 TO 120 DO
                              SmOKe$=PERM$[SMOKE%]
                              IF INSTR(NATION$,Germany$)=INSTR(SmOKe$,Prince$) AND INSTR(SmOKe$,BlueMaster$)=INSTR(DRINK$,Beer$) AND ABS(INSTR(SmOKe$,Blend$)-INSTR(DRINK$,Water$))=1 AND INSTR(SmOKe$,Dunhill$)=INSTR(COLR$,Yellow$) THEN
                                  FOR ANIMAL%=1 TO 120 DO
                                     ANIMAL$=PERM$[ANIMAL%]
                                     IF INSTR(NATION$,Sweden$)=INSTR(ANIMAL$,Dog$) AND INSTR(SmOKe$,PallMall$)=INSTR(ANIMAL$,Birds$) AND ABS(INSTR(SmOKe$,Blend$)-INSTR(ANIMAL$,Cats$))=1 AND ABS(INSTR(SmOKe$,Dunhill$)-INSTR(ANIMAL$,Horse$))=1 THEN
                                         PRINT("House    Drink  Nation Colour Smoke  Animal")
                                         PRINT("---------------------------------------------------------------------------")
                                         FOR house%=1 TO 5 DO
                                            PRINT(house%;)
                                            PRINT(TAB(10);DRINK$[ASC(MID$(DRINK$,house%))-65];)
                                            PRINT(TAB(25);NATION$[ASC(MID$(NATION$,house%))-65];)
                                            PRINT(TAB(40);COLR$[ASC(MID$(COLR$,house%))-65];)
                                            PRINT(TAB(55);SMOKE$[ASC(MID$(SmOKe$,house%))-65];)
                                            PRINT(TAB(70);ANIMAL$[ASC(MID$(ANIMAL$,house%))-65])
                                         END FOR
                                         SOLUTIONS%=SOLUTIONS%+1
                                     END IF
                                  END FOR ! ANIMAL%
                              END IF
                           END FOR ! SmOKe%
                       END IF
                    END FOR ! DRINK%
                END IF
             END FOR ! COLR%
        END IF
    END FOR ! NATION%
    PRINT("Number of solutions=";SOLUTIONS%)
    PRINT("Solved in ";TIMER-T1;" seconds")
END PROGRAM