We have two jugs X and Y.
X can hold 4 pints.
Y can hold 3.
Permissable moves are to fill X from Y, to fill Y from X, and to empty or fill either jug completely.
The aim is to find a sequence of actions, starting from empty jugs, which achieves a state in which Y contains exactly two pints.
State representation is a data structure containing two numbers.
Successor generation will involve looking at two numbers and finding out which actions are possible.
Is it possible to transfer from one jug to another?
Is it possible to empty a jug?
Is it possible to fill a jug?
How will these actions be applied within the chosen state representation?
import java.util.*; class Node { int x = 0, y = 0; /* state variables */ Node parent = null; /* parent link */ Node (int x, int y, Node parent) { this.x = x; this.y = y; this.parent = parent; } public String toString() { return(x + " " + y); } public boolean equals(Object node) { /* argument has to be an Object */ return(((Node)node).x == x && ((Node)node).y == y); }
However, this program uses Vectors rather than ArrayLists.
Vectors are essentially the same as ArrayLists, but they have a couple of extra features which are of use here, e.g., they print out nicely and also implement a `contains' method.
Vector<Node> getPath(Vector<Node> v) { v.insertElementAt(this, 0); if (parent != null) v = parent.getPath(v); return(v); } Vector<Node> getPath() { return(getPath(new Vector<Node>())); } }
public class WaterJugsSearch { boolean isGoal(Node node) { return(node.y == 2); }
Vector<Node> getSuccessors(Node parent) { int x = parent.x, y = parent.y; Vector<Node> successors = new Vector<Node>(); if (x < 4 && y > 0) { /* transfer amount z from y to x */ int z = Math.min(y, 4-x); successors.add(new Node(x+z, y-z, parent)); } if (y < 3 && x > 0) { /* transfer amount z from x to y */ int z = Math.min(x, 3-y); successors.add(new Node(x-z, y+z, parent)); } if (x > 0) { /* empty x */ successors.add(new Node(0, y, parent)); } if (y > 0) { /* empty y */ successors.add(new Node(x, 0, parent)); } if (x < 4) { /* fill x from tap */ successors.add(new Node(4, y, parent)); } if (y < 3) { /* fill y from tap */ successors.add(new Node(x, 3, parent)); } return(successors); }
void run() { Vector<Node> open = new Vector<Node>(); open.add(new Node(0, 0, null)); while (open.size() > 0) { Node node = open.remove(0); if (isGoal(node)) { System.out.println("Solution: " + node.getPath()); } else { Vector<Node> successors = getSuccessors(node); for (int i = 0; i < successors.size(); i++) { Node child = successors.get(i); if (!node.getPath().contains((Object)child)) { open.add(child); } } } } }
public static void main(String args[]) { // do the search new WaterJugsSearch().run(); } }
Solution: [0 0, 0 3, 3 0, 3 3, 4 2] Solution: [0 0, 4 0, 1 3, 0 3, 3 0, 3 3, 4 2] Solution: [0 0, 4 0, 4 3, 0 3, 3 0, 3 3, 4 2] Solution: [0 0, 4 0, 1 3, 4 3, 0 3, 3 0, 3 3, 4 2] Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 2 0, 0 2] Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 0 3, 3 0, 3 3, 4 2] Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 0 3, 3 0, 3 3, 4 2] Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 4 1, 4 3, 0 3, 3 0, 3 3, 4 2] Solution: [0 0, 0 3, 3 0, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 2 0, 0 2] Solution: [0 0, 0 3, 4 3, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 2 0, 0 2] Solution: [0 0, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 4 3, 0 3, 3 0, 3 3, 4 2] Solution: [0 0, 0 3, 3 0, 3 3, 4 3, 4 0, 1 3, 1 0, 0 1, 4 1, 2 3, 2 0, 0 2].