RosettaCodeData/Task/Zebra-puzzle/C-sharp/zebra-puzzle-1.cs
2023-07-01 13:44:08 -04:00

85 lines
4.1 KiB
C#

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();
}
}