public static void Sample_Einsteins_Puzzle() { //this example shows how to solve Einstein's puzzle //go to http://en.wikipedia.org/wiki/Einstein's_Puzzle for more information on puzzle var solutions = from n in ArrayExt.Enum <Nationality>().ToConstraintList(5) from c in ArrayExt.Enum <HouseColor>().ToConstraintList(5) from s in ArrayExt.Enum <Smoke>().ToConstraintList(5) from d in ArrayExt.Enum <Drink>().ToConstraintList(5) from p in ArrayExt.Enum <Pet>().ToConstraintList(5) from i in 0.To(4).ToConstraintIndex() where Constraint.AllDifferent(n) where Constraint.AllDifferent(c) where Constraint.AllDifferent(s) where Constraint.AllDifferent(d) where Constraint.AllDifferent(p) where n[0] == Nationality.Norwegian where d[2] == Drink.Milk where (n[i] == Nationality.British) == (c[i] == HouseColor.Red) where (n[i] == Nationality.German) == (s[i] == Smoke.Prince) where (c[i] == HouseColor.Yellow) == (s[i] == Smoke.DunHill) where (n[i] == Nationality.Danish) == (d[i] == Drink.Tea) where (c[i] == HouseColor.Green) == (d[i] == Drink.Coffee) where (s[i] == Smoke.BlueMaster) == (d[i] == Drink.Beer) where (n[i] == Nationality.Swedish) == (p[i] == Pet.Dog) where (s[i] == Smoke.PallMall) == (p[i] == Pet.Bird) where (c[i] == HouseColor.Green) == (c[i + 1] == HouseColor.White) where (p[i] == Pet.Cat) ? (s[i - 1] == Smoke.Blend || s[i + 1] == Smoke.Blend) : true where ((p[i] == Pet.Horse) ? (s[i - 1] == Smoke.DunHill || s[i + 1] == Smoke.DunHill) : true) where ((n[i] == Nationality.Norwegian) ? (c[i - 1] == HouseColor.Blue || c[i + 1] == HouseColor.Blue) : true) where ((s[i] == Smoke.Blend) ? (d[i - 1] == Drink.Water || d[i + 1] == Drink.Water) : true) select 0.To(4).Select(x => new { Nationality = n[x], HouseColor = c[x], Smoke = s[x], Drink = d[x], Pet = p[x] }); //show results Console.WriteLine("\tNationality\tHouseColor\tSmoke\t\tDrink\t\tPet"); Console.WriteLine(new string('-', 80)); solutions.First().ForEach((man, i) => Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", i + 1, man.Nationality.ToString().PadRight(12), man.HouseColor.ToString().PadRight(12), man.Smoke.ToString().PadRight(12), man.Drink.ToString().PadRight(12), man.Pet.ToString().PadRight(12)) ); }
public static void Sample_River_Crossing() { //this example shows how to solve river crossing puzzle //go to http://en.wikipedia.org/wiki/River_IQ_Test for more information on puzzle //go to http://freeweb.siol.net/danej/riverIQGame.swf for the game //create some variables var allPeople = Cross.Thief | Cross.Police | Cross.Father | Cross.Mother | Cross.Son | Cross.Son2 | Cross.Daughter | Cross.Daughter2; //STEP 1 - create combination of crossing var crossing = ArrayExt.Enum <Cross>().Backtrack( //Seed - number of people, and people new { Length = 0, Value = (Cross)0 }, //Func - add number of people, add people (current, item, i) => new { Length = current.Length + 1, Value = current.Value | item }, //Yield - must contains police, father, or mother current => (current.Value & (Cross.Police | Cross.Father | Cross.Mother)) > 0 ); //thief-police is the same as police-thief, therefore skip police-thief crossing.BacktrackingModel = BacktrackingModel.Combination; //Answer can be 1 or 2 people on boat crossing.ContinueOnYielded = true; //Stop backtracking when there are more than 2 people crossing.AppendBreak(current => current.Length > 2); //Thief must be with police crossing.AppendConstraint(current => current.Value == Cross.Thief, current => item => item == Cross.Police); //Father cannot be with daughter crossing.AppendConstraint(current => current.Value == Cross.Father, current => item => item != Cross.Daughter && item != Cross.Daughter2); //Mother cannot be with son crossing.AppendConstraint(current => current.Value == Cross.Mother, current => item => item != Cross.Son && item != Cross.Son2); //shows result Console.WriteLine("below is combination of crossing"); crossing.SelectResults(c => c.Value).ForEach(c => Console.WriteLine(c)); Console.WriteLine(); //---------------------------------------------------------------------- //STEP 2 - create solutions based on combination of crossing var solutions = crossing.SelectResults(c => c.Value).Backtrack( //Seed - list of people on landA and landB new { LandA = allPeople, LandB = (Cross)0, BoatOnLandA = true, History = new[] { new { LandA = allPeople, BoatOnLandA = true } } }, //Func - add/subtract crossing people to/from LandA, LandB (last, item, i) => new { LandA = last.LandA ^ item, LandB = last.LandB ^ item, BoatOnLandA = !last.BoatOnLandA, History = last.History.Append(new { LandA = last.LandA ^ item, BoatOnLandA = !last.BoatOnLandA }) }, //Yield - all people on LandB last => last.LandB == allPeople ); //Thief cannot be with others without police solutions.AppendBreak(last => ((last.LandA & (Cross.Thief | Cross.Police)) == Cross.Thief) && //no police (last.LandA != Cross.Thief) //has others ); solutions.AppendBreak(last => ((last.LandB & (Cross.Thief | Cross.Police)) == Cross.Thief) && //no police (last.LandB != Cross.Thief) //has others ); //Son cannot be with mother without father solutions.AppendBreak(last => ((last.LandA & (Cross.Father | Cross.Mother)) == Cross.Mother) && //no father ((last.LandA & (Cross.Son | Cross.Son2)) > 0) //has sons ); solutions.AppendBreak(last => ((last.LandB & (Cross.Father | Cross.Mother)) == Cross.Mother) && //no father ((last.LandB & (Cross.Son | Cross.Son2)) > 0) //has sons ); //Daughter cannot be with father without mother solutions.AppendBreak(last => ((last.LandA & (Cross.Father | Cross.Mother)) == Cross.Father) && //no mother ((last.LandA & (Cross.Daughter | Cross.Daughter2)) > 0) //has daugthers ); solutions.AppendBreak(last => ((last.LandB & (Cross.Father | Cross.Mother)) == Cross.Father) && //no mother ((last.LandB & (Cross.Daughter | Cross.Daughter2)) > 0) //has daugthers ); //Must have people to cross solutions.AppendConstraint(last => last.BoatOnLandA, last => item => (last.LandA & item) == item); solutions.AppendConstraint(last => !last.BoatOnLandA, last => item => (last.LandB & item) == item); //Check history solutions.AppendConstraint(last => item => !last.History.Contains(new { LandA = last.LandA ^ item, BoatOnLandA = !last.BoatOnLandA })); //show result Console.WriteLine("Now start crossing"); solutions.SelectResults().First().History.ForEach(x => { Console.WriteLine(x.LandA); Console.WriteLine(allPeople ^ x.LandA); Console.WriteLine("============================================================="); }); }
public static void Sample_Einsteins_Puzzle() { //this example shows how to solve Einstein's puzzle //go to http://en.wikipedia.org/wiki/Einstein's_Puzzle for more information on puzzle //select combination of each person var men = from n in ArrayExt.Enum <Nationality>() from c in ArrayExt.Enum <HouseColor>() where (n == Nationality.British) == (c == HouseColor.Red) from s in ArrayExt.Enum <Smoke>() where (n == Nationality.German) == (s == Smoke.Prince) where (c == HouseColor.Yellow) == (s == Smoke.DunHill) from d in ArrayExt.Enum <Drink>() where (n == Nationality.Danish) == (d == Drink.Tea) where (c == HouseColor.Green) == (d == Drink.Coffee) where (s == Smoke.BlueMaster) == (d == Drink.Beer) from p in ArrayExt.Enum <Pet>() where (n == Nationality.Swedish) == (p == Pet.Dog) where (s == Smoke.PallMall) == (p == Pet.Bird) select new { Nationality = n, HouseColor = c, Smoke = s, Drink = d, Pet = p }; //Generate solution var solutions = men.Backtrack(5); //New guy must not has same properties as persons in sequence solutions.AppendConstraint(seq => seq.Any(), seq => man => seq.All(x => x.Nationality != man.Nationality && x.HouseColor != man.HouseColor && x.Smoke != man.Smoke && x.Drink != man.Drink && x.Pet != man.Pet ) ); //Norwegian lives in the first house. solutions.AppendConstraint(seq => seq.Length == 0, seq => man => man.Nationality == Nationality.Norwegian ); //Guy who drinks milk lives in the third house solutions.AppendConstraint(seq => seq.Length <= 2, seq => man => (seq.Length == 2) == (man.Drink == Drink.Milk) ); //White house is next to green house solutions.AppendConstraint(seq => seq.Any(), seq => man => (seq.Last().HouseColor == HouseColor.Green) == (man.HouseColor == HouseColor.White) ); //Guy who pets cat is neighbor with guy who smokes Blend solutions.AppendConstraint(seq => seq.Count(x => x.Pet == Pet.Cat || x.Smoke == Smoke.Blend) == 1, seq => man => (man.Pet == Pet.Cat) || (man.Smoke == Smoke.Blend) ); //Guy who pets horse is neighbor with guy who smokes DunHill solutions.AppendConstraint(seq => seq.Count(x => x.Pet == Pet.Horse || x.Smoke == Smoke.DunHill) == 1, seq => man => (man.Pet == Pet.Horse) || (man.Smoke == Smoke.DunHill) ); //Norwegian is neighbor with guy lives in blue house solutions.AppendConstraint(seq => seq.Count(x => x.Nationality == Nationality.Norwegian || x.HouseColor == HouseColor.Blue) == 1, seq => man => (man.Nationality == Nationality.Norwegian) || (man.HouseColor == HouseColor.Blue) ); //Guy who drinks water is neighbor with guy who smokes Blend solutions.AppendConstraint(seq => seq.Count(x => x.Drink == Drink.Water || x.Smoke == Smoke.Blend) == 1, seq => man => (man.Drink == Drink.Water) || (man.Smoke == Smoke.Blend) ); //show results Console.WriteLine("\tNationality\tHouseColor\tSmoke\t\tDrink\t\tPet"); Console.WriteLine(new string('-', 80)); solutions.First().ForEach((man, i) => Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", i + 1, man.Nationality.ToString().PadRight(12), man.HouseColor.ToString().PadRight(12), man.Smoke.ToString().PadRight(12), man.Drink.ToString().PadRight(12), man.Pet.ToString().PadRight(12)) ); }