Exemplo n.º 1
0
        public Step Fill(Bottle targetBottle)
        {
            if (IsEmpty() || targetBottle.IsFull())
            {
                return(null);
            }

            if (!IsBottle && !targetBottle.IsBottle)
            {
                return(null);
            }

            var sourceAmount = Amount();
            var targetUllage = targetBottle.Ullage();

            if (sourceAmount <= targetUllage)
            {
                targetBottle.AddWater(sourceAmount);
                Empty();
                return(new Step(_index, targetBottle._index, sourceAmount));
            }
            else
            {
                targetBottle.AddWater(targetUllage);
                AddWater(-targetUllage);
                return(new Step(_index, targetBottle._index, targetUllage));
            }
        }
Exemplo n.º 2
0
        public static List <Tuple <string, int, int> > FindPath(Bottle bottle1, Bottle bottle2, int target, List <Tuple <string, int, int> > path)
        {
            if (bottle1.Ammount == target || bottle2.Ammount == target)
            {
                return(path);
            }

            var bestPath            = new List <Tuple <string, int, int> >(path);
            var subSteps            = Int32.MaxValue;
            var bottle1StartAmmount = bottle1.Ammount;
            var bottle2StartAmmount = bottle2.Ammount;

            //Never fill a bottle if the other is full
            if (!bottle2.IsFull() && bottle1.Fill())
            {
                //Check if we have a duplicate state. Only proceed if we are in a unique state
                var ammount1 = bottle1.Ammount;
                var ammount2 = bottle2.Ammount;
                if (!path.Exists(x => x.Item2 == ammount1 && x.Item3 == ammount2))
                {
                    //Copy path
                    var subPath = new List <Tuple <string, int, int> >(path);
                    subPath.Add(new Tuple <string, int, int>("Fill " + bottle1.Name + ". " + bottle1.Name + ": " + bottle1.Ammount + "/" + bottle1.Capacity + ". "
                                                             + bottle2.Name + ": " + bottle2.Ammount + "/" + bottle2.Capacity + ". ", bottle1.Ammount, bottle2.Ammount));

                    //Continue recursive search
                    var p = FindPath(bottle1, bottle2, target, subPath);
                    if (p.Count < subSteps)
                    {
                        subSteps = p.Count;
                        bestPath = p;
                    }
                }
            }

            //Reset bottles for new branch
            bottle1.Ammount = bottle1StartAmmount;
            bottle2.Ammount = bottle2StartAmmount;

            if (!bottle1.IsFull() && bottle2.Fill())
            {
                var ammount1 = bottle1.Ammount;
                var ammount2 = bottle2.Ammount;
                if (!path.Exists(x => x.Item2 == ammount1 && x.Item3 == ammount2))
                {
                    var subPath = new List <Tuple <string, int, int> >(path);
                    subPath.Add(new Tuple <string, int, int>("Fill " + bottle2.Name + ". " + bottle1.Name + ": " + bottle1.Ammount + "/" + bottle1.Capacity + ". "
                                                             + bottle2.Name + ": " + bottle2.Ammount + "/" + bottle2.Capacity + ". ", bottle1.Ammount, bottle2.Ammount));

                    var p = FindPath(bottle1, bottle2, target, subPath);
                    if (p.Count < subSteps)
                    {
                        subSteps = p.Count;
                        bestPath = p;
                    }
                }
            }

            bottle1.Ammount = bottle1StartAmmount;
            bottle2.Ammount = bottle2StartAmmount;

            //Never empty a bottle if the other is empty
            if (bottle2.Ammount != 0 && bottle1.Pour())
            {
                var ammount1 = bottle1.Ammount;
                var ammount2 = bottle2.Ammount;
                if (!path.Exists(x => x.Item2 == ammount1 && x.Item3 == ammount2))
                {
                    var subPath = new List <Tuple <string, int, int> >(path);
                    subPath.Add(new Tuple <string, int, int>("Pour " + bottle1.Name + ". " + bottle1.Name + ": " + bottle1.Ammount + "/" + bottle1.Capacity + ". "
                                                             + bottle2.Name + ": " + bottle2.Ammount + "/" + bottle2.Capacity + ". ", bottle1.Ammount, bottle2.Ammount));

                    var p = FindPath(bottle1, bottle2, target, subPath);
                    if (p.Count < subSteps)
                    {
                        subSteps = p.Count;
                        bestPath = p;
                    }
                }
            }

            bottle1.Ammount = bottle1StartAmmount;
            bottle2.Ammount = bottle2StartAmmount;

            if (bottle2.Ammount != 0 && bottle2.Pour())
            {
                var ammount1 = bottle1.Ammount;
                var ammount2 = bottle2.Ammount;
                if (!path.Exists(x => x.Item2 == ammount1 && x.Item3 == ammount2))
                {
                    var subPath = new List <Tuple <string, int, int> >(path);
                    subPath.Add(new Tuple <string, int, int>("Pour " + bottle2.Name + ". " + bottle1.Name + ": " + bottle1.Ammount + "/" + bottle1.Capacity + ". "
                                                             + bottle2.Name + ": " + bottle2.Ammount + "/" + bottle2.Capacity + ". ", bottle1.Ammount, bottle2.Ammount));

                    var p = FindPath(bottle1, bottle2, target, subPath);
                    if (p.Count < subSteps)
                    {
                        subSteps = p.Count;
                        bestPath = p;
                    }
                }
            }

            bottle1.Ammount = bottle1StartAmmount;
            bottle2.Ammount = bottle2StartAmmount;

            if (bottle1.Transfer(ref bottle2))
            {
                var ammount1 = bottle1.Ammount;
                var ammount2 = bottle2.Ammount;
                if (!path.Exists(x => x.Item2 == ammount1 && x.Item3 == ammount2))
                {
                    var subPath = new List <Tuple <string, int, int> >(path);
                    subPath.Add(new Tuple <string, int, int>("Transfer " + bottle1.Name + " into " + bottle2.Name + ". " + bottle1.Name + ": " + bottle1.Ammount + "/" + bottle1.Capacity + ". "
                                                             + bottle2.Name + ": " + bottle2.Ammount + "/" + bottle2.Capacity + ". ", bottle1.Ammount, bottle2.Ammount));

                    var p = FindPath(bottle1, bottle2, target, subPath);
                    if (p.Count < subSteps)
                    {
                        subSteps = p.Count;
                        bestPath = p;
                    }
                }
            }

            bottle1.Ammount = bottle1StartAmmount;
            bottle2.Ammount = bottle2StartAmmount;

            if (bottle2.Transfer(ref bottle1))
            {
                var ammount1 = bottle1.Ammount;
                var ammount2 = bottle2.Ammount;
                if (!path.Exists(x => x.Item2 == ammount1 && x.Item3 == ammount2))
                {
                    var subPath = new List <Tuple <string, int, int> >(path);
                    subPath.Add(new Tuple <string, int, int>("Transfer " + bottle2.Name + " into " + bottle1.Name + ". " + bottle1.Name + ": " + bottle1.Ammount + "/" + bottle1.Capacity + ". "
                                                             + bottle2.Name + ": " + bottle2.Ammount + "/" + bottle2.Capacity + ". ", bottle1.Ammount, bottle2.Ammount));

                    var p = FindPath(bottle1, bottle2, target, subPath);
                    if (p.Count < subSteps)
                    {
                        subSteps = p.Count;
                        bestPath = p;
                    }
                }
            }

            return(bestPath);
        }
Exemplo n.º 3
0
 private static void PruneActions(Bottle bottleA, Bottle bottleB, Dictionary<string, Action<Bottle, Bottle>> actions)
 {
     if (bottleA.IsEmpty())
     {
         actions.Remove("A -> B, ");
         actions.Remove("E(A), ");
     }
     if (bottleB.IsEmpty())
     {
         actions.Remove("B -> A, ");
         actions.Remove("E(B), ");
     }
     if (bottleA.IsFull())
     {
         actions.Remove("B -> A, ");
         actions.Remove("F(A), ");
     }
     if (bottleB.IsFull())
     {
         actions.Remove("A -> B, ");
         actions.Remove("F(B), ");
     }
 }