Friday, February 12, 2016

Three ice water buckets challenge

This problem is found here: http://learningandtheadolescentmind.org/resources_02_bucket.html

I called it three "Ice Bucket Challenge" for fun. ;) Here is the problem description.

There are an 8-liter bucket filled with ice water and empty 3-liter and 5-liter buckets. You solve the puzzle by using the three buckets to divide the 8 liters of water into two equal parts of 4 liters. Try to solve the puzzle in the fewest number of moves.

Although to find a fewest number of moves is not easy, but I can design depth first search to find the necessary moves to distribute the waters.
Here is the code
public static boolean threeBuckets(Integer[] curr, Integer[] max, List<List<Integer>> visited){
//skip the ones we already try
if(visited.contains(Arrays.asList(curr)))
return false;
visited.add(Arrays.asList(curr));
if(isDone(curr)){
//print out the solution
System.out.println(visited);
return true;
}
for(int i = 0; i<3; i++){
if(curr[i]>0){
//transfer water to other buckets
for(int j = 0; j<3; j++){
//skip itself and the bucket is already full
if(j==i || curr[j] == max[j])
continue;
//we are going to dump as much water as we can
//make a copy of the buckets so we can retry later on
Integer[] copy = Arrays.copyOf(curr, 3);
if(copy[i] + copy[j] <= max[j]){
copy[j] = copy[i] + copy[j];
copy[i] = 0;
}else{
int t = copy[i] + copy[j];
copy[j] = max[j];
copy[i] = t - copy[j];
}
if(threeBuckets(copy, max, visited))
return true;
}
}
}
return false;
}
private static boolean isDone(Integer[] curr){
return curr[0] == 4 || curr[1] == 4 || curr[2] == 4;
}
view raw 3buckets.java hosted with ❤ by GitHub

The idea here is to for each possible case, we find the all possible cases which can be derived from it. For example, from 8, 0, 0, it could be 5, 0, 3 or 3, 5, 0. And we use a list keep track of the cases we already visited. Think of all possible cases as a graph, we essentially do a depth first search until we find the case contains 4. A potential solution to find the fewest moves is to use the breath first search. We can use a Queue to contain the list of cases we already visited, then generate the queue of next level based on that, also keep track of the parent case for each case in the queue until we find the case.

3 comments:

  1. It's also called waterjug problem, a classical AI problem. One thing we need to know is that it is necessary to calculate gcd of 3 numbers to see if it is divisible by 4 to ensure it has an answer.

    ReplyDelete
    Replies
    1. gcd(3,5,8) is 1 is not divisible by 4. i guess you mean the other way around.

      Delete