Comments on the “Three Piles” Problem

Download Report

Transcript Comments on the “Three Piles” Problem

Comments on the “Three Piles”
Problem
29-Mar-16
My timings
Solved 10000 problems of size 5 in 15 milliseconds.
Average time per problem: 0.0015 ms.
Solved 200 problems of size 10 in 16 milliseconds.
Average time per problem: 0.08 ms.
Solved 200 problems of size 15 in 718 milliseconds.
Average time per problem: 3.59 ms.
Solved 200 problems of size 20 in 34719 milliseconds.
Average time per problem: 173.595 ms.
Solved 100 problems of size 25 in 43797 milliseconds.
Average time per problem: 437.97 ms.
Timing graph
General approach


The “Three Piles” problem can be solved by a
backtracking algorithm
Roughly, the algorithm goes like this:

boolean solve(int numbersPlaced) {
if (numbersPlaced== all the numbers)
return true;
for (each pile p) {
if can put the next number, numbersPlaced+1, into pile p {
put it in pile p
if (solve(numbersPlaced+1)) return true
else take the number out again
}
return false
}
Problems with this algorithm


It’s much easier for the programmer if the method
returns a boolean, but the user demands a solution
The method requires some data structures (say, arrays
or stacks) to keep working information in



We can’t set this information up inside a recursive method
We don’t want to hassle the user with extra junk that is only
needed to make the algorithm work
Solution: Provide a facade method to:



Provide a simplified interface to the user
Initialize any needed data structures
Call the “real” recursive method with whatever parameters
are convenient for the programmer, not the user
The facade method

The user wants to do this:



solution = solve(problem)
where solution is some data structure containing your results
In the code below, I called this data structure a “Solution,” but
it might be implemented by (for example) an int[][]
So you do this:

Solution solve(int[] problem) {
Solution solution; // maybe an int[][]
// Create the “Solution” data structure and any other data
// structures and initializations that you need
put problem[0] into your solution pile 0
if (reallySolve(problem, solution, 0, other stuff)) {
return solution;
} else return null; // Much better than returning a bad solution!
}
The real recursive method


boolean reallySolve(problem, solution, nextNumber, ...) {
if nextNumber == problem size, return true**
for each pile p,
if we can put nextNumber into pile p {
put it in the pile
if (reallySolve(problem, solution,
nextNumber+1, ...)) return true;
else take the number back out again
}
}
return false
}
** If some problems may be unsolvable , you should check the
“solution” at this point and return false if it doesn’t work
Backtracking in general


Solution solve(Problem p) {
create object to hold solution;
do any other initializations you need;
if (solve(p, solution, other stuff)) return solution;
else return null;
}
private boolean solve(Problem p, Solution s, other stuff) {
if problem is already solved, return true;
for each of the choices available to you {
make a choice;
if (solve(simpler version of p, s, other stuff)) return true;
else undo this choice; // can sometimes be implicit
}
return false;
}
Summary

The notion of a facade is this:



The code has a complex interface and requires lots of
initializations and global structures
The user wants a simple and easy to use interface
Create a facade to stand between the user and the ugly code
and present a simpler interface
The End