diff --git a/.gitignore b/.gitignore index a1c2a23..6a6e872 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +.idea/ +class/ \ No newline at end of file diff --git a/src/main/java/org/waterpouring/Action.java b/src/main/java/org/waterpouring/Action.java new file mode 100644 index 0000000..5dd0983 --- /dev/null +++ b/src/main/java/org/waterpouring/Action.java @@ -0,0 +1,42 @@ +package org.waterpouring; + +import java.util.Arrays; + +/** + * Defines a single action that can be taken to proceed in solving a water-pouring problem. + * One or more actions will combine to create the total solution if it can be solved. + */ +public class Action { + Integer[] glassIndex; + MoveType moveType; + Integer[] endState; + + /** + * Create an action + * @param JUGS The jugs, in gallon size, that we are working with + * @param startState The state at the time of taking this action + * @param moveType + * @param jugIndex The indices of the jugs we are working with. Depending on the move type this can + * be 1 or 2 values + * @return + */ + public static Action of(Integer[] JUGS, Integer[] startState, MoveType moveType, Integer... jugIndex) { + return new Action(JUGS, startState, moveType, jugIndex); + } + + private Action(Integer[] GLASSES, Integer[] startState, MoveType moveType, Integer... glassIndex) { + this.glassIndex = glassIndex; + this.moveType = moveType; + this.endState = moveType==null ? + startState : moveType.move.doMove(GLASSES, startState, glassIndex); + } + + @Override + public String toString() { + return "Action{" + + "glassIndex=" + Arrays.toString(glassIndex) + + ", moveType=" + moveType + + ", endState=" + Arrays.toString(endState) + + '}'; + } +} diff --git a/src/main/java/org/waterpouring/Move.java b/src/main/java/org/waterpouring/Move.java new file mode 100644 index 0000000..8b83f27 --- /dev/null +++ b/src/main/java/org/waterpouring/Move.java @@ -0,0 +1,16 @@ +package org.waterpouring; + +/** + * A move describes some action taken on one or more jugs + */ +@FunctionalInterface +public interface Move { + /** + * + * @param JUGS the jugs, defined by their gallon capacity, for the problem + * @param state The current capacity of each jug + * @param jugIndex The indices of the various jugs to be operated on + * @return the new state of the jugs after performing the given move + */ + Integer[] doMove(final Integer[] JUGS, Integer[] state, Integer[] jugIndex); +} diff --git a/src/main/java/org/waterpouring/MoveType.java b/src/main/java/org/waterpouring/MoveType.java new file mode 100644 index 0000000..291bd03 --- /dev/null +++ b/src/main/java/org/waterpouring/MoveType.java @@ -0,0 +1,34 @@ +package org.waterpouring; + + +/** + * An enumeration of all possible moves + */ +public enum MoveType { + /** Dump a jug out so that it is empty. Receives a single index parameter in its associated move */ + EMPTY(new Move() { + @Override + public Integer[] doMove(Integer[] JUGS, Integer[] state, Integer[] jugIndex) { + return new Integer[0]; + } + }), //TODO: + /** Pour water into a jug up so that it is full. Receives a single index parameter in its move */ + FILL(new Move() { + @Override + public Integer[] doMove(Integer[] JUGS, Integer[] state, Integer[] jugIndex) { + return new Integer[0]; + } + }), //TODO: + /** Pour the contents from one jug to another. Receives two index parameters: 0 = the from jug, 1 = the to jug */ + POUR(new Move() { + @Override + public Integer[] doMove(Integer[] JUGS, Integer[] state, Integer[] jugIndex) { + return new Integer[0]; + } + }); //TODO: + + public final Move move; + MoveType(Move move) { + this.move = move; + } +} diff --git a/src/main/java/org/waterpouring/Solver.java b/src/main/java/org/waterpouring/Solver.java new file mode 100644 index 0000000..aabee48 --- /dev/null +++ b/src/main/java/org/waterpouring/Solver.java @@ -0,0 +1,84 @@ +package org.waterpouring; + +import java.util.*; + +public class Solver { + final Integer[] JUGS; + final Integer GOAL; + + // The initial state we begin with (all jugs empty) + final Integer[] startState; + + /** + * + * @param jugs The capacity, in gallons, of the jugs we are working with + * @param goal in gallons, of the desired amount + */ + public Solver(final Integer[] jugs, final Integer goal) { + this.JUGS = jugs; + this.GOAL = goal; + this.startState = new Integer[]{JUGS.length}; + for(int i=0; i createActions(Integer[] state) { + //TODO: + return null; + } + + /** + * Look within the tree of all possible actions to see if a goal solution exists + * @param actions + * @return + */ + public boolean solutionExists(List> actions) { + //TODO: + return false; + } + + /** + * For the given trail, take all the possible actions in the next list and create + * a new list for each one where the trail of actions becomes the head of the list, + * and the next element is appended to the end. + * @param trail of actions + * @param next possible next actions from the end of the trail. + * @return For example:

+ * trail = "A", "B", "C" and next = "D", "E", "F" + *

yields: + *

+ */ + public List> combineTrails(List trail, List next) { + //TODO: + return null; + } + + /** + * For the given parameters, find a solution where the Glass capacities can produce + * the goal amount. + * @return A list of actions that yield the goal amount, or null if no solution exists + */ + public List findSolution() { + //TODO: + return null; + } + + public static void main(String[] args) { + List solution = new Solver(new Integer[]{5, 3}, 4).findSolution(); + if(solution != null) { + System.out.println("Solution found: " + solution); + } else { + System.out.println("No solution found for the given parameters"); + } + } +} \ No newline at end of file