Open In App

# Water Jug problem using BFS

You are given an m liter jug and a n liter jug. Both the jugs are initially empty. The jugs don’t have markings to allow measuring smaller quantities. You have to use the jugs to measure d liters of water where d is less than n.

(X, Y) corresponds to a state where X refers to the amount of water in Jug1 and Y refers to the amount of water in Jug2
Determine the path from e initial state (xi, yi) to the final state (xf, yf), where (xi, yi) is (0, 0) which indicates both Jugs are initially empty and (xf, yf) indicates a state which could be (0, d) or (d, 0).

The operations you can perform are:

1. Empty a jug (X, 0)->(0, 0) Empty Jug 1.
2. Fill a Jug, (0, 0)->(X, 0) Fill Jug 1
3. Pour water from one jug to the other until one of the jugs is either empty or full, (X, Y) -> (X-d, Y+d)

Examples:

`Input : 4 3 2Output : {( 0,0),(0,3),(3,0),(3,3),(4,2),(0,2)}`

We have discussed the optimal solution in The Two Water Jug Puzzle. In this post, a BFS based solution is discussed.

Here, we keep exploring all the different valid cases of the states of water in the jug simultaneously until and unless we reach the required target water.

As provided in the problem statement, at any given state we can do either of the following operations:

1. Fill a jug
2. Empty a jug
3. Transfer water from one jug to another until either of them gets completely filled or empty.

Examples:

`      Input: X = 4, Y = 3, Z = 2      Output: {(0, 0), (0, 3), (3, 0), (3, 3), (4, 2), (0, 2)}Explanation:     Step 1:- First we will fill the 4 litre jug completely with water.     Step 2:- Then optimal approach would be to empty water from 4-litre jug into 3-litre  (leaving 1L water in 4L jug and 3L completely full). Hence we got 1L water.    Step 3:- Now, Empty water from 3L.    Step 4:- Pour the water from 4L jug into 3L jug Now 4L container is completely empty and 1L water in present in 3L litre jug.    Step 5:- Fill the 4L jug with water completely again.    Step 6:- On transferring  water from 4L jug to 3L jug, we will get 2L water in 4L jug which was our required quantity. `
`       Input:  X = 3, Y = 5, Z = 4       Output: 6Explanation:    Step 1:- First we will fill the 5-litres jug to its maximum capacity.    Step 2:- Then optimal approach would be to transfer 3-litres from 5-litres jug to 3-litres jugs.     Step 3:- Now, Empty the 3-litres jug.    Step 4:- Transfer 2L from 5L jug to 3-L jug.    Step 5:- Now, Fill 5-litres jug to its maximum capacity.    Step 6:- On Pouring water from 5L jug to 3L jug until it’s full we will get 4L water in 5-litre jug which was our required quantity. `

Running of the algorithm:

We start at an initial state in the queue where both the jugs are empty. We then continue to explore all the possible intermediate states derived from the current jug state using the operations provided.

We also, maintain a visited matrix of states so that we avoid revisiting the same state of jugs again and again.

Cases

Jug 1

Jug 2

Is Valid

Case 1

Fill it

Empty it

?

Case 2

Empty it

Fill it

?

Case 3

Fill it

Fill it

Redundant case

Case 4

Empty it

Empty it

Already visited (Initial State)

Case 5

Unchanged

Fill it

?

Case 6

Fill it

Unchanged

?

Case 7

Unchanged

Empty

?

Case 8

Empty

Unchanged

?

Case 9

Transfer water from this

Transfer water into this

?

Case 10

Transfer water into this

Transfer water from this

?

From the table above, we can observe that the state where both the jugs are filled is redundant as we won’t be able to continue ahead / do anything with this state in any possible way.

So, we proceed, keeping in mind all the valid state cases (as shown in the table above) and we do a BFS on them.

In the BFS, we first skip the states which was already visited or if the amount of water in either of the jugs exceeded the jug quantity.

If we continue further, then we first mark the current state as visited and check if in this state, if we have obtained the target quantity of water in either of the jugs, we can empty the other jug and return the current state’s entire path.

But, if we have not yet found the target quantity, we then derive the intermediate states from the current state of jugs i.e. we derive the valid cases, mentioned in the table above (go through the code once if you have some confusion).

We keep repeating all the above steps until we have found our target or there are no more states left to proceed with.

Implementation:

## C++

 `#include ``using` `namespace` `std;``typedef` `pair<``int``, ``int``> pii;``void` `printpath(map mp, pii u)``{``    ``if` `(u.first == 0 && u.second == 0) {``        ``cout << 0 << ``" "` `<< 0 << endl;``        ``return``;``    ``}``    ``printpath(mp, mp[u]);``    ``cout << u.first << ``" "` `<< u.second << endl;``}``void` `BFS(``int` `a, ``int` `b, ``int` `target)``{``    ``map m;``    ``bool` `isSolvable = ``false``;``    ``map mp;` `    ``queue q;` `    ``q.push(make_pair(0, 0));``    ``while` `(!q.empty()) {` `        ``auto` `u = q.front();``        ``// cout< a || u.second > b || u.first < 0``             ``|| u.second < 0))``            ``continue``;``        ``// cout< jug 2``        ``int` `d = b - u.second;``        ``if` `(u.first >= d) {``            ``int` `c = u.first - d;``            ``if` `(m[{ c, b }] != 1) {``                ``q.push({ c, b });``                ``mp[{ c, b }] = u;``            ``}``        ``}``        ``else` `{``            ``int` `c = u.first + u.second;``            ``if` `(m[{ 0, c }] != 1) {``                ``q.push({ 0, c });``                ``mp[{ 0, c }] = u;``            ``}``        ``}``        ``// transfer jug 2 -> jug 1``        ``d = a - u.first;``        ``if` `(u.second >= d) {``            ``int` `c = u.second - d;``            ``if` `(m[{ a, c }] != 1) {``                ``q.push({ a, c });``                ``mp[{ a, c }] = u;``            ``}``        ``}``        ``else` `{``            ``int` `c = u.first + u.second;``            ``if` `(m[{ c, 0 }] != 1) {``                ``q.push({ c, 0 });``                ``mp[{ c, 0 }] = u;``            ``}``        ``}` `        ``// empty the jug 2``        ``if` `(m[{ u.first, 0 }] != 1) {``            ``q.push({ u.first, 0 });``            ``mp[{ u.first, 0 }] = u;``        ``}` `        ``// empty the jug 1``        ``if` `(m[{ 0, u.second }] != 1) {``            ``q.push({ 0, u.second });``            ``mp[{ 0, u.second }] = u;``        ``}``    ``}``    ``if` `(!isSolvable)``        ``cout << ``"No solution"``;``}` `int` `main()``{``    ``int` `Jug1 = 4, Jug2 = 3, target = 2;``    ``cout << ``"Path from initial state "``            ``"to solution state ::\n"``;``    ``BFS(Jug1, Jug2, target);``    ``return` `0;``}`

## Java

 `// Java program for water jug problem``// using BFS``// Code by: Sparsh_CBS` `import` `java.util.*;` `class` `Pair {``    ``int` `j1, j2;``    ``List path;` `    ``Pair(``int` `j1, ``int` `j2)``    ``{``        ``this``.j1 = j1;``        ``this``.j2 = j2;``        ``path = ``new` `ArrayList<>();``    ``}` `    ``Pair(``int` `j1, ``int` `j2, List _path)``    ``{``        ``this``.j1 = j1;``        ``this``.j2 = j2;` `        ``path = ``new` `ArrayList<>();``        ``path.addAll(_path);``        ``path.add(``new` `Pair(``this``.j1, ``this``.j2));``    ``}``}` `public` `class` `GFG {``    ``public` `static` `void` `main(String[] args)``        ``throws` `java.lang.Exception``    ``{``        ``int` `jug1 = ``4``;``        ``int` `jug2 = ``3``;``        ``int` `target = ``2``;` `        ``getPathIfPossible(jug1, jug2, target);``    ``}` `    ``private` `static` `void``    ``getPathIfPossible(``int` `jug1, ``int` `jug2, ``int` `target)``    ``{``        ``boolean``[][] visited``            ``= ``new` `boolean``[jug1 + ``1``][jug2 + ``1``];``        ``Queue queue = ``new` `LinkedList<>();` `        ``// Initial State: Both Jugs are empty so,``        ``// initialise j1 j2 as 0 and put it in the path list``        ``Pair initialState = ``new` `Pair(``0``, ``0``);``        ``initialState.path.add(``new` `Pair(``0``, ``0``));``        ``queue.offer(initialState);` `        ``while` `(!queue.isEmpty()) {``            ``Pair curr = queue.poll();` `            ``// Skip already visited states and overflowing``            ``// water states``            ``if` `(curr.j1 > jug1 || curr.j2 > jug2``                ``|| visited[curr.j1][curr.j2])``                ``continue``;``            ``// mark current jugs state as visited``            ``visited[curr.j1][curr.j2] = ``true``;` `            ``// Check if current state has already reached``            ``// the target amount of water or not``            ``if` `(curr.j1 == target || curr.j2 == target) {``                ``if` `(curr.j1 == target) {``                    ``// If in our current state, jug1 holds``                    ``// the required amount of water, then we``                    ``// empty the jug2 and push it into our``                    ``// path.``                    ``curr.path.add(``new` `Pair(curr.j1, ``0``));``                ``}``                ``else` `{``                    ``// else, If in our current state, jug2``                    ``// holds the required amount of water,``                    ``// then we empty the jug1 and push it``                    ``// into our path.``                    ``curr.path.add(``new` `Pair(``0``, curr.j2));``                ``}``                ``int` `n = curr.path.size();``                ``System.out.println(``                    ``"Path of states of jugs followed is :"``);``                ``for` `(``int` `i = ``0``; i < n; i++)``                    ``System.out.println(``                        ``curr.path.get(i).j1 + ``" , "``                        ``+ curr.path.get(i).j2);``                ``return``;``            ``}` `            ``// If we have not yet found the target, then we``            ``// have three cases left I. Fill the jug and``            ``// Empty the other II. Fill the jug and let the``            ``// other remain untouched III. Empty the jug and``            ``// let the other remain untouched``            ``// IV. Transfer amounts from one jug to another` `            ``// Please refer to the table attached above to``            ``// understand the cases that we are taking into``            ``// consideration` `            ``// Now,``            ``// I. Fill the jug and Empty the other``            ``queue.offer(``new` `Pair(jug1, ``0``, curr.path));``            ``queue.offer(``new` `Pair(``0``, jug2, curr.path));` `            ``// II. Fill the jug and let the other remain``            ``// untouched``            ``queue.offer(``new` `Pair(jug1, curr.j2, curr.path));``            ``queue.offer(``new` `Pair(curr.j1, jug2, curr.path));` `            ``// III. Empty the jug and let the other remain``            ``// untouched``            ``queue.offer(``new` `Pair(``0``, curr.j2, curr.path));``            ``queue.offer(``new` `Pair(curr.j1, ``0``, curr.path));` `            ``// IV. Transfer water from one to another until``            ``// one jug becomes empty or until one jug``            ``// becomes full in this process` `            ``// Transferring water form jug1 to jug2``            ``int` `emptyJug = jug2 - curr.j2;``            ``int` `amountTransferred``                ``= Math.min(curr.j1, emptyJug);``            ``int` `j2 = curr.j2 + amountTransferred;``            ``int` `j1 = curr.j1 - amountTransferred;``            ``queue.offer(``new` `Pair(j1, j2, curr.path));` `            ``// Tranferring water form jug2 to jug1``            ``emptyJug = jug1 - curr.j1;``            ``amountTransferred = Math.min(curr.j2, emptyJug);``            ``j2 = curr.j2 - amountTransferred;``            ``j1 = curr.j1 + amountTransferred;``            ``queue.offer(``new` `Pair(j1, j2, curr.path));``        ``}` `        ``System.out.println(``"Not Possible to obtain target"``);``    ``}``}`

## Python3

 `from` `collections ``import` `deque`  `def` `BFS(a, b, target):` `    ``m ``=` `{}``    ``isSolvable ``=` `False``    ``path ``=` `[]` `  ` `    ``q ``=` `deque()` `    ``q.append((``0``, ``0``))` `    ``while` `(``len``(q) > ``0``):``        ``u ``=` `q.popleft()``# If this state is already visited``        ``if` `((u[``0``], u[``1``]) ``in` `m):``            ``continue``        ``if` `((u[``0``] > a ``or` `u[``1``] > b ``or``             ``u[``0``] < ``0` `or` `u[``1``] < ``0``)):``            ``continue` `        ``# Filling the vector for constructing``        ``# the solution path``        ``path.append([u[``0``], u[``1``]])` `        ``# Marking current state as visited``        ``m[(u[``0``], u[``1``])] ``=` `1` `        ``# If we reach solution state, put ans=1``        ``if` `(u[``0``] ``=``=` `target ``or` `u[``1``] ``=``=` `target):``            ``isSolvable ``=` `True` `            ``if` `(u[``0``] ``=``=` `target):``                ``if` `(u[``1``] !``=` `0``):` `                    ``# Fill final state``                    ``path.append([u[``0``], ``0``])``            ``else``:``                ``if` `(u[``0``] !``=` `0``):` `                    ``# Fill final state``                    ``path.append([``0``, u[``1``]])` `            ``# Print the solution path``            ``sz ``=` `len``(path)``            ``for` `i ``in` `range``(sz):``                ``print``(``"("``, path[i][``0``], ``","``,``                      ``path[i][``1``], ``")"``)``            ``break` `        ``# If we have not reached final state``        ``# then, start developing intermediate``        ``# states to reach solution state``        ``q.append([u[``0``], b])  ``# Fill Jug2``        ``q.append([a, u[``1``]])  ``# Fill Jug1` `        ``for` `ap ``in` `range``(``max``(a, b) ``+` `1``):` `            ``# Pour amount ap from Jug2 to Jug1``            ``c ``=` `u[``0``] ``+` `ap``            ``d ``=` `u[``1``] ``-` `ap` `            ``# Check if this state is possible or not``            ``if` `(c ``=``=` `a ``or` `(d ``=``=` `0` `and` `d >``=` `0``)):``                ``q.append([c, d])` `            ``# Pour amount ap from Jug 1 to Jug2``            ``c ``=` `u[``0``] ``-` `ap``            ``d ``=` `u[``1``] ``+` `ap` `            ``# Check if this state is possible or not``            ``if` `((c ``=``=` `0` `and` `c >``=` `0``) ``or` `d ``=``=` `b):``                ``q.append([c, d])` `        ``# Empty Jug2``        ``q.append([a, ``0``])` `        ``# Empty Jug1``        ``q.append([``0``, b])` `    ``# No, solution exists if ans=0``    ``if` `(``not` `isSolvable):``        ``print``(``"No solution"``)`  `# Driver code``if` `__name__ ``=``=` `'__main__'``:` `    ``Jug1, Jug2, target ``=` `4``, ``3``, ``2``    ``print``(``"Path from initial state "``          ``"to solution state ::"``)` `    ``BFS(Jug1, Jug2, target)` `# This code is contributed by mohit kumar 29`

## C#

 `using` `System;``using` `System.Collections.Generic;` `class` `GFG {` `    ``static` `void` `BFS(``int` `a, ``int` `b, ``int` `target)``    ``{` `        ``// Map is used to store the states, every``        ``// state is hashed to binary value to``        ``// indicate either that state is visited``        ``// before or not``        ``Dictionary, ``int``> m``            ``= ``new` `Dictionary, ``int``>();``        ``bool` `isSolvable = ``false``;``        ``List > path``            ``= ``new` `List >();``        ``// Queue to maintain states``        ``List > q``            ``= ``new` `List >();` `        ``// Initializing with initial state``        ``q.Add(``new` `Tuple<``int``, ``int``>(0, 0));` `        ``while` `(q.Count > 0) {` `            ``// Current state``            ``Tuple<``int``, ``int``> u = q[0];` `            ``// Pop off used state``            ``q.RemoveAt(0);` `            ``// If this state is already visited``            ``if` `(m.ContainsKey(u) && m[u] == 1)``                ``continue``;` `            ``// Doesn't met jug constraints``            ``if` `((u.Item1 > a || u.Item2 > b || u.Item1 < 0``                 ``|| u.Item2 < 0))``                ``continue``;` `            ``// Filling the vector for constructing``            ``// the solution path``            ``path.Add(u);` `            ``// Marking current state as visited``            ``m[u] = 1;` `            ``// If we reach solution state, put ans=1``            ``if` `(u.Item1 == target || u.Item2 == target) {``                ``isSolvable = ``true``;` `                ``if` `(u.Item1 == target) {``                    ``if` `(u.Item2 != 0)` `                        ``// Fill final state``                        ``path.Add(``new` `Tuple<``int``, ``int``>(``                            ``u.Item1, 0));``                ``}``                ``else` `{``                    ``if` `(u.Item1 != 0)` `                        ``// Fill final state``                        ``path.Add(``new` `Tuple<``int``, ``int``>(``                            ``0, u.Item2));``                ``}` `                ``// Print the solution path``                ``int` `sz = path.Count;``                ``for` `(``int` `i = 0; i < sz; i++)``                    ``Console.WriteLine(``"("` `+ path[i].Item1``                                      ``+ ``", "` `+ path[i].Item2``                                      ``+ ``")"``);``                ``break``;``            ``}` `            ``// If we have not reached final state``            ``// then, start developing intermediate``            ``// states to reach solution state``            ``// Fill Jug2``            ``q.Add(``new` `Tuple<``int``, ``int``>(u.Item1, b));` `            ``// Fill Jug1``            ``q.Add(``new` `Tuple<``int``, ``int``>(a, u.Item2));` `            ``for` `(``int` `ap = 0; ap <= Math.Max(a, b); ap++) {` `                ``// Pour amount ap from Jug2 to Jug1``                ``int` `c = u.Item1 + ap;``                ``int` `d = u.Item2 - ap;` `                ``// Check if this state is possible or not``                ``if` `(c == a || (d == 0 && d >= 0))``                    ``q.Add(``new` `Tuple<``int``, ``int``>(c, d));` `                ``// Pour amount ap from Jug 1 to Jug2``                ``c = u.Item1 - ap;``                ``d = u.Item2 + ap;` `                ``// Check if this state is possible or not``                ``if` `((c == 0 && c >= 0) || d == b)``                    ``q.Add(``new` `Tuple<``int``, ``int``>(c, d));``            ``}` `            ``// Empty Jug2``            ``q.Add(``new` `Tuple<``int``, ``int``>(a, 0));` `            ``// Empty Jug1``            ``q.Add(``new` `Tuple<``int``, ``int``>(0, b));``        ``}` `        ``// No, solution exists if ans=0``        ``if` `(!isSolvable)``            ``Console.WriteLine(``"No solution"``);``    ``}` `    ``// Driver code``    ``static` `void` `Main()``    ``{``        ``int` `Jug1 = 4, Jug2 = 3, target = 2;``        ``Console.WriteLine(``"Path from initial state "``                          ``+ ``"to solution state ::"``);` `        ``BFS(Jug1, Jug2, target);``    ``}``}` `// This code is contributed by divyeshrabadiya07`

## Javascript

 ``

Output

```Path of states of jugs followed is :
0 , 0
0 , 3
3 , 0
3 , 3
4 , 2
0 , 2
```

Time Complexity: O(n*m).
Space Complexity: O(n*m). Where n and m are the quantity of jug1 and jug2, respectively. This article has been improved by Sparsh Sharma