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


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static System.Console;
 
public enum Colour { Red, Green, White, Yellow, Blue }
public enum Nationality { Englishman, Swede, Dane, Norwegian,German }
public enum Pet { Dog, Birds, Cats, Horse, Zebra }
public enum Drink { Coffee, Tea, Milk, Beer, Water }
public enum Smoke { PallMall, Dunhill, Blend, BlueMaster, Prince}
 
public static class ZebraPuzzle
{
    private static (Colour[] colours, Drink[] drinks, Smoke[] smokes, Pet[] pets, Nationality[] nations) _solved;
 
    static ZebraPuzzle()
    {
        var solve = from colours in Permute<Colour>()  //r1 5 range
                    where (colours,Colour.White).IsRightOf(colours, Colour.Green) // r5
                    from nations in Permute<Nationality>()
                    where nations[0] == Nationality.Norwegian // r10
                    where (nations, Nationality.Englishman).IsSameIndex(colours, Colour.Red) //r2
                    where (nations,Nationality.Norwegian).IsNextTo(colours,Colour.Blue) // r15
                    from drinks in Permute<Drink>()
                    where drinks[2] == Drink.Milk //r9
                    where (drinks, Drink.Coffee).IsSameIndex(colours, Colour.Green) // r6
                    where (drinks, Drink.Tea).IsSameIndex(nations, Nationality.Dane) //r4
                    from pets in Permute<Pet>()
                    where (pets, Pet.Dog).IsSameIndex(nations, Nationality.Swede) // r3
                    from smokes in Permute<Smoke>()
                    where (smokes, Smoke.PallMall).IsSameIndex(pets, Pet.Birds) // r7
                    where (smokes, Smoke.Dunhill).IsSameIndex(colours, Colour.Yellow) // r8
                    where (smokes, Smoke.Blend).IsNextTo(pets, Pet.Cats) // r11
                    where (smokes, Smoke.Dunhill).IsNextTo(pets, Pet.Horse) //r12
                    where (smokes, Smoke.BlueMaster).IsSameIndex(drinks, Drink.Beer) //r13
                    where (smokes, Smoke.Prince).IsSameIndex(nations, Nationality.German) // r14
                    where (drinks,Drink.Water).IsNextTo(smokes,Smoke.Blend) // r16
                    select (colours, drinks, smokes, pets, nations);
 
        _solved = solve.First();
    }
 
    private static int IndexOf<T>(this T[] arr, T obj) => Array.IndexOf(arr, obj);
 
    private static bool IsRightOf<T, U>(this (T[] a, T v) right, U[] a, U v) => right.a.IndexOf(right.v) == a.IndexOf(v) + 1;
 
    private static bool IsSameIndex<T, U>(this (T[] a, T v)x, U[] a, U v) => x.a.IndexOf(x.v) == a.IndexOf(v);
 
    private static bool IsNextTo<T, U>(this (T[] a, T v)x, U[] a,  U v) => (x.a,x.v).IsRightOf(a, v) || (a,v).IsRightOf(x.a,x.v);
 
    // made more generic from https://codereview.stackexchange.com/questions/91808/permutations-in-c
    public static IEnumerable<IEnumerable<T>> Permutations<T>(this IEnumerable<T> values)
    {
        if (values.Count() == 1)
            return values.ToSingleton();
 
        return values.SelectMany(v => Permutations(values.Except(v.ToSingleton())),(v, p) => p.Prepend(v));
    }
 
    public static IEnumerable<T[]> Permute<T>() => ToEnumerable<T>().Permutations().Select(p=>p.ToArray());
 
    private static IEnumerable<T> ToSingleton<T>(this T item){ yield return item; }
 
    private static IEnumerable<T> ToEnumerable<T>() => Enum.GetValues(typeof(T)).Cast<T>();
 
    public static new String ToString()
    {
        var sb = new StringBuilder();
        sb.AppendLine("House Colour Drink    Nationality Smokes     Pet");
        sb.AppendLine("───── ────── ──────── ─────────── ────────── ─────");
        var (colours, drinks, smokes, pets, nations) = _solved;
        for (var i = 0; i < 5; i++)
            sb.AppendLine($"{i+1,5} {colours[i],-6} {drinks[i],-8} {nations[i],-11} {smokes[i],-10} {pets[i],-10}");
        return sb.ToString();
    }
 
    public static void Main(string[] arguments)
    {
        var owner = _solved.nations[_solved.pets.IndexOf(Pet.Zebra)];
        WriteLine($"The zebra owner is {owner}");
        Write(ToString());
        Read();
    }
}