The Utils class is composed of some common methods:
The test class is as follows:
The testing is a little hard because of the recursion. Any change requires a full test. The testing checks whether the status flags we set matches the weights from the input and the times of weighings stays inside the limit.
java 代码
- package solve;
- import scale.Ball;
- import scale.Scale;
- import java.util.Iterator;
- import java.util.Set;
- /**
- * utility class, shared common methods.
- */
- public class Utils
- {
- public static Ball findGoodBall(Set ballSet)
- {
- for (Iterator it=ballSet.iterator(); it.hasNext();)
- {
- Ball ball = (Ball)it.next();
- if (ball.getStatus().equals(Ball.NORMAL)) return ball;
- }
- return null;
- }
- public static String convertToBallStatus(int scaleResult)
- {
- if (scaleResult == Scale.EVEN) return Ball.NORMAL;
- else if (scaleResult == Scale.HEAVIER) return Ball.HEAVIER;
- else return Ball.LIGHTER;
- }
- public static void markStatus(Set ballSet, String status)
- {
- for (Iterator it=ballSet.iterator(); it.hasNext();)
- {
- Ball ball = (Ball)it.next();
- if (!ball.getStatus().equals(Ball.NORMAL))
- {
- ball.setStatus(status);
- }
- }
- }
- }
The test class is as follows:
java 代码
- package solve;
- import junit.framework.TestCase;
- import java.util.Set;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.math.BigDecimal;
- import scale.Ball;
- import scale.Weight;
- import scale.Scale;
- /**
- *
- */
- public class SolverTest extends TestCase
- {
- public void test12Balls()
- {
- Set ballSet = createBallSet(12, 4, Ball.WEIGHT_HEAVIER);
- ProblemSolver solver = new ProblemSolver(ballSet);
- solver.findWeight();
- print(ballSet);
- System.out.println("scale usage=" + solver.getScale().getNumOfTrials());
- verifyResult(ballSet, solver.getScale());
- }
- public void test13Balls()
- {
- Set ballSet = createBallSet(13, 5, Ball.WEIGHT_HEAVIER);
- ProblemSolver solver = new ProblemSolver(ballSet);
- solver.findWeight();
- print(ballSet);
- System.out.println("scale usage=" + solver.getScale().getNumOfTrials());
- verifyResult(ballSet, solver.getScale());
- }
- public void testLoops()
- {
- int start = 500;
- int end = 1000;
- for (int i=start; i
- {
- for (int j=0; j
- {
- Set ballSet = createBallSet(i, j, Ball.WEIGHT_HEAVIER);
- ProblemSolver solver = new ProblemSolver(ballSet);
- solver.findWeight();
- System.out.println("num of balls=" + ballSet.size());
- //print(ballSet);
- System.out.println("scale usage=" + solver.getScale().getNumOfTrials());
- System.out.println("-------------------------------------------------");
- verifyResult(ballSet, solver.getScale());
- }
- }
- }
- private Set createBallSet(int size, int badBallIndex, Weight weight)
- {
- Set ballSet = new HashSet();
- for (int i=0; i
- {
- Weight weight1;
- if (i == badBallIndex) weight1 = weight;
- else weight1 = Ball.WEIGHT_NORNAL;
- Ball ball = new Ball("" + i, weight1);
- ballSet.add(ball);
- }
- return ballSet;
- }
- private void verifyResult(Set ballSet, Scale scale)
- {
- for (Iterator it=ballSet.iterator(); it.hasNext();)
- {
- Ball ball = (Ball)it.next();
- assertTrue(ball.validate());
- }
- // now computer the theoretic limit number of balls <=(3^n-3)/2, upper limit.
- // Number of balls 3 12 39 120 363 1092 3279 .....
- // Number of trials 2 3 4 5 6 7 8
- BigDecimal aa = new BigDecimal(Math.log(2 * ballSet.size() + 3));
- BigDecimal bb = aa.divide(new BigDecimal(Math.log(3)), BigDecimal.ROUND_UP);
- int limit = (int)Math.ceil(bb.floatValue());
- assertTrue("limit=" + limit + ", trials=" + scale.getNumOfTrials(), limit >= scale.getNumOfTrials());
- }
- private void print(Set ballSet)
- {
- for (Iterator it=ballSet.iterator(); it.hasNext();)
- {
- Ball ball = (Ball)it.next();
- System.out.println(ball.toString());
- }
- }
- }
The testing is a little hard because of the recursion. Any change requires a full test. The testing checks whether the status flags we set matches the weights from the input and the times of weighings stays inside the limit.