Example #1
0
        public void PourFrom_LargeToSmallOverflow_VolumeIsCorrect()
        {
            var bottleA = new Bottle {Capacity = 5, Volume = 5};
            var bottleB = new Bottle {Capacity = 3};

            bottleA.PourInto(bottleB);

            Assert.That(bottleA.Volume, Is.EqualTo(2));
            Assert.That(bottleB.Volume, Is.EqualTo(3));
        }
Example #2
0
        public void PourFrom_SmallToLargeOverflow_VolumeIsCorrect()
        {
            var bottleA = new Bottle {Capacity = 5, Volume = 3};
            var bottleB = new Bottle {Capacity = 3, Volume = 3};

            bottleB.PourInto(bottleA);

            Assert.That(bottleA.Volume, Is.EqualTo(5));
            Assert.That(bottleB.Volume, Is.EqualTo(1));
        }
Example #3
0
 public void PourInto(Bottle b)
 {
     var free = b.Capacity - b.Volume;
     if (free >= Volume)
     {
         b.Volume += Volume;
         Volume = 0;
         return;
     }
     b.Volume = b.Capacity;
     Volume -= free;
 }
Example #4
0
        public static List<string> Solve(int capacityBottleA, int capacityBottleB, int desiredVolume)
        {
            var bottleA = new Bottle {Capacity = capacityBottleA};
            var bottleB = new Bottle {Capacity = capacityBottleB};

            var solution = string.Empty;
            for (var i = 1; i < 8; i++)
            {
                var s = Solve(solution, 0, i, bottleA, bottleB, desiredVolume);
                if (s.Any()) return s;
            }
            return new List<string>();
        }
Example #5
0
        static void Main(string[] args)
        {
            while (true)
            {
                Console.WriteLine("Set first bottles capacity:");
                var cap1    = Console.ReadLine();
                var bottle1 = new Bottle(Convert.ToInt32(cap1));

                Console.WriteLine();
                Console.WriteLine("Set second bottles capacity:");
                var cap2    = Console.ReadLine();
                var bottle2 = new Bottle(Convert.ToInt32(cap2));

                Console.WriteLine();
                Console.WriteLine("Set target value:");
                var targ   = Console.ReadLine();
                var target = Convert.ToInt32(targ);


                if (target > bottle1.Capacity && target > bottle2.Capacity || target <= 0)
                {
                    throw new ArgumentException("Unreachable target value");
                }

                var path = new List <Tuple <string, int, int> >();
                path.Add(new Tuple <string, int, int>("Start. " + bottle1.Name + ": " + bottle1.Ammount + "/" + bottle1.Capacity + ". "
                                                      + bottle2.Name + ": " + bottle2.Ammount + "/" + bottle2.Capacity + ". ", 0, 0));

                path = FindPath(bottle1, bottle2, target, path);

                Console.WriteLine();
                foreach (var step in path)
                {
                    Console.WriteLine(step.Item1);
                }

                Console.ReadLine();
            }
        }
Example #6
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);
        }
Example #7
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), ");
     }
 }
Example #8
0
 public Bottle(Bottle b)
 {
     Capacity = b.Capacity;
     Volume = b.Volume;
 }
Example #9
0
 private static List<string> Solve(string path, int depth, int limit, Bottle bottleA, Bottle bottleB, int desiredVolume)
 {
     if (bottleA.Volume == desiredVolume)
         return new List<string> {path + "A ;"};
     if (bottleB.Volume == desiredVolume)
         return new List<string> {path + "B ;"};
     if (depth > limit)
         return new List<string> { path + ";" };
     var actions = new Dictionary<string, Action<Bottle, Bottle>>
     {
         {"A -> B, ", (a, b) => a.PourInto(b)},
         {"B -> A, ", (a, b) => b.PourInto(a)},
         {"E(A), ", (a, b) => a.Empty()},
         {"E(B), ", (a, b) => b.Empty()},
         {"F(A), ", (a, b) => a.Fill()},
         {"F(B), ", (a, b) => b.Fill()},
     };
     PruneActions(bottleA, bottleB, actions);
     return actions.Select(action =>
     {
         var newBottleA = new Bottle(bottleA);
         var newBottleB = new Bottle(bottleB);
         action.Value(newBottleA, newBottleB);
         var s = Solve(path + action.Key, depth+1, limit, newBottleA, newBottleB, desiredVolume);
         return s;
     }).Aggregate(new List<string>(), (x, y) => x.Concat(y).ToList()).Where(s => s.EndsWith("A ;") || s.EndsWith("B ;")).ToList();
 }