Two water Jug problem | Practice | GeeksforGeeks

You are at the side of a river. You are given a m litre jug and a n litre jug where 0 < m < n. 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 litres of water where d < n. Determine the minimum no of operations to be performed to obtain d litres of water in one of jug.
The operations you can perform are:

Empty a Jug
Fill a Jug
Pour water from one jug to the other until one of the jugs is either empty or full.

Empty a Jug
Fill a Jug
Pour water from one jug to the other until one of the jugs is either empty or full.
 
Example 1:
Input: m = 3, n = 5, d = 4
Output: 6
Explanation: Operations are as follow-
1. Fill up the 5 litre jug.
2. Then fill up the 3 litre jug using 5 litre
   jug. Now 5 litre jug contains 2 litre water.
3. Empty the 3 litre jug.
4. Now pour the 2 litre of water from 5 litre 
   jug to 3 litre jug.
5. Now 3 litre jug contains 2 litre of water 
   and 5 litre jug is empty. Now fill up the 
   5 litre jug.
6. Now fill one litre of water from 5 litre jug 
   to 3 litre jug. Now we have 4 litre water in 
   5 litre jug.

Example 2:
Input: m = 8, n = 56, d = 46
Output: -1
Explanation: Not possible to fill any one of 
the jug with 46 litre of water.

 
Your Task:
You don't need to read or print anything. Your task is to complete the function minSteps() which takes m, n and d ans input parameter and returns the minimum number of operation to fill d litre of water in any of the two jug.
 
Expected Time Comeplxity: O(d)
Expected Space Complexity: O(1)

Constraints:
1 ≤ n ≤ m ≤ 100
1 ≤ d ≤ 100
0
yashmandaviya7021 week ago
in case any one want to print the path of operations as in explanation :
vector<string> bfsfill(int a,int b,int c){    queue<string> q;    unordered_map<string,int> level;    unordered_map<string,string> parent;    string f = "0_0";    parent[f] = "-1";    level[f] = 0;    q.push(f);       while(!q.empty()){     auto cv = q.front();     q.pop();     stringstream ss(cv);     string s1,s2;     getline(ss,s1,'_');     getline(ss,s2,'_');     int x = stoi(s1),y = stoi(s2);     if((x==c && y==0)||(x==0 && y==c)) break;       //  /*    //  x,y -> a,y    //  x,y -> x,b    //  x,y -> 0,y    //  x,y -> x,0    //  x,y -> a,y-(a-x) if(x+y>=a)    //  x,y -> x-(b-y),b if(x+y>=b)    //  x,y -> x+y,0 if(x+y<=a)    //  x,y -> 0,x+y if(x+y<=b)    //  */        if(x<a && level.find(to_string(a)+"_"+to_string(y))==level.end()){      level[to_string(a)+"_"+to_string(y)] = level[cv]+1;      parent[to_string(a)+"_"+to_string(y)] = cv;      q.push(to_string(a)+"_"+to_string(y));     }     if(y<b && level.find(to_string(x)+"_"+to_string(b))==level.end()){      level[to_string(x)+"_"+to_string(b)] = level[cv]+1;      parent[to_string(x)+"_"+to_string(b)] = cv;      q.push(to_string(x)+"_"+to_string(b));     }     if(level.find(to_string(0)+"_"+to_string(y))==level.end()){      level[to_string(0)+"_"+to_string(y)] = level[cv]+1;      parent[to_string(0)+"_"+to_string(y)] = cv;      q.push(to_string(0)+"_"+to_string(y));     }     if(level.find(to_string(x)+"_"+to_string(0))==level.end()){      level[to_string(x)+"_"+to_string(0)] = level[cv]+1;      parent[to_string(x)+"_"+to_string(0)] = cv;      q.push(to_string(x)+"_"+to_string(0));     }     if(x+y>=a && level.find(to_string(a)+"_"+to_string(y-a+x))==level.end()){      level[to_string(a)+"_"+to_string(y-a+x)] = level[cv]+1;      parent[to_string(a)+"_"+to_string(y-a+x)] = cv;      q.push(to_string(a)+"_"+to_string(y-a+x));     }     if(x+y>=b && level.find(to_string(x-b+y)+"_"+to_string(b))==level.end()){      level[to_string(x-b+y)+"_"+to_string(b)] = level[cv]+1;      parent[to_string(x-b+y)+"_"+to_string(b)] = cv;      q.push(to_string(x-b+y)+"_"+to_string(b));     }     if(x+y<=a && level.find(to_string(x+y)+"_"+to_string(0))==level.end()){      level[to_string(x+y)+"_"+to_string(0)] = level[cv]+1;      parent[to_string(x+y)+"_"+to_string(0)] = cv;      q.push(to_string(x+y)+"_"+to_string(0));     }     if(x+y<=b && level.find(to_string(0)+"_"+to_string(x+y))==level.end()){      level[to_string(0)+"_"+to_string(x+y)] = level[cv]+1;      parent[to_string(0)+"_"+to_string(x+y)] = cv;      q.push(to_string(0)+"_"+to_string(x+y));     }    }       vector<string> ans;    int l1 = INT_MAX,l2 = INT_MAX;    if(level.find(to_string(0)+"_"+to_string(c))!=level.end()) l1 = level[to_string(0)+"_"+to_string(c)];    if(level.find(to_string(c)+"_"+to_string(0))!=level.end()) l2 = level[to_string(c)+"_"+to_string(0)];    if(l1<l2){     string aa = to_string(0)+"_"+to_string(c);     while(level[aa]!=0){      ans.push_back(aa);      aa=parent[aa];     }    }    else{     string aa = to_string(c)+"_"+to_string(0);     while(level[aa]!=0){      ans.push_back(aa);      aa=parent[aa];      }    }    reverse(ans.begin(),ans.end());    return ans;   }
+2
putyavka3 weeks ago
Time: 0.02/1.12 sec
int minSteps(int m, int n, int d) {
    if (d == m || d == n) return 1;
    if (m == n) return -1;
    int k = m, c = 2, c1 = 0, c2 = 0;
    while (k) { // pour from small to big
        if (d == k) { c1 = c; break; }
        if (k < m) c += 4; else c += 2;
        k += m;
        if (k >= n) k -= n;
    }
    if (!c1) return -1;
    k = n - m, c = 2;
    while (k) { // pour from big to small
        if (d == k) { c2 = c; break; }
        c += 2; k -= m;
        if (k < 0) { c += 2; k += n; }
    }
    return min(c1, c2);
}
0
rp213 weeks ago
There may be an issue with the given time complexity. Nonetheless most intuitive and easiest approach is BFS(for shortest paths in unweighted graph).
-1
subhamkumar0321 month ago
class Solution{
	public:
	int gcd(int a, int b)
	{
	    if (b==0)
	       return a;
	    return gcd(b, a%b);
	}
	int pour(int fromCap, int toCap, int d)
	{
	    int from = fromCap;
	    int to = 0;
	    int step = 1;
	    while (from != d && to != d)
	    {
	        int temp = min(from, toCap - to);
	        to   += temp;
	        from -= temp;
	        step++;
	 
	        if (from == d || to == d)
	            break;
	        if (from == 0)
	        {
	            from = fromCap;
	            step++;
	        }
	        if (to == toCap)
	        {
	            to = 0;
	            step++;
	        }
	    }
	    return step;
	}
	int minSteps(int m, int n, int d)
	{
	    if (m > n)
	        swap(m, n);
	    if (d > n)
	        return -1;
	    if ((d % gcd(n,m)) != 0)
	        return -1;
        return min(pour(n,m,d),pour(m,n,d));
	}
};
0
prabhxjott2 months ago
38 78 100
Why is it giving -1 for this testCase ?
0
agrimjain2411
This comment was deleted.
0
diptendunandi5 months ago
	int m,n,N;
	int get_index(int i, int j){
	    return i*N+j;
	}
	pair<int,int> get_cor(int index){
	    return {index/N,index%N};
	}
	void check(queue <int> &q, unordered_map<int,bool> &vis, int i ,int j){
	    if (i<0 || j<0 || i>m || j>n) return;
	    int idx = get_index(i,j);
	    if(vis.find(idx)!=vis.end()) return ;
	    vis[idx] = true;
	    q.push(idx);
	}
	int minSteps(int m, int n, int d)
	{
	    if(m > n) swap(m,n);
	    if(d>n) return -1;
	    this->m = m;
	    this-> n = n;
	    this-> N = n+10;
	    unordered_map<int,bool> mp;
	    mp[0] = true;
	    queue<int> q;
	    q.push(0);
	    int level = 0;
	    while(!q.empty()){
	        int t = q.size();
	        for(int k =0;k<t;k++){
	            auto p =get_cor(q.front());
	            q.pop();
	            int i = p.first, j = p.second;
	            if(i==d || j==d) return level;
	            check(q,mp,i,0);
	            check(q,mp,0,j);
	            check(q,mp,m,j);
	            check(q,mp,i,n);
	            check(q,mp,0,i+j);
	            check(q,mp,i+j,0);
	            check(q,mp,i - (n-j),n);
	            check(q,mp,m, j - (m - i));
	        }
	        level++;
	    }
	    return -1;
 
	}
0
himanshujain4576 months ago
Very Simple Approach:
int minSteps(int m, int n, int d){    int c1=m,c2=0,cnt=1,cnt2=1;    if(d>m and d>n)    return -1;    map<pair<int,int>,int>mp;
//CASE1:always  pour water from jug 1 to jug2 if at any stage jug1 become empty fill it again or if jug2 fill fully empty it again until one of the jug have d litre of water    while(c1!=d and c2!=d)    {        mp[{c1,c2}]++;        int remain=n-c2;        if(remain>=c1)        {                    cnt++;        c2+=c1;        c1=0;        }        else       {           c2+=remain;           c1-=remain;            cnt++;       }
//if at any stage c1 or c2 become equals to d then break the loop        if(c1==d||c2==d)       break;        if(c1==0)        {        c1=m;        cnt++;        }        if(c2==n)        {        c2=0;        cnt++;        }
//if at any stage same procedure starts following  again then break the loop        if(mp.find({c1,c2})!=mp.end())       {           cnt=-1;           break;       }            }
//CASE2:always  pour water from jug 2  to jug1 if at any stage jug2 become empty fill it again or if jug1 fill fully empty it again until one of the jug have d litre of water    mp.clear();    c1=0;    c2=n;       while(c1!=d and c2!=d)    {          mp[{c1,c2}]++;        int remain=m-c1;        if(remain>=c2)        {                    cnt2++;        c1+=c2;;        c2=0;        }        else       {           cnt2++;           c1+=remain;           c2-=remain;       }
//if at any stage c1 or c2 become equals to d then break the loop          if(c1==d||c2==d)       break;        if(c1==m)        {        c1=0;        cnt2++;        }        if(c2==0)        {        c2=n;        cnt2++;        }
 
//if at any stage same procedure starts following  again then break the loop          if(mp.find({c1,c2})!=mp.end())       {           cnt2=-1;           break;       }            }    if(cnt==-1 and cnt2==-1)return -1;    if(cnt==-1)return cnt2;    if(cnt2==-1)return cnt;    return min(cnt,cnt2);    }
0
perumallayaswanth20008 months ago
Can some one help me to answer this question.
For this test case i am getting answer as 108 but i am getting 110
46 65 23
This is my code. Please do read comments for better understanding.My approach is starting with both empty jugs performing all operations on each jug and bfs. If i got the required water in any jug at any point of time i return the bfs call count.
class Solution
{
    public int  minSteps(int m, int n, int d){
        Pair pair=new Pair(0,0);
        Queue<Pair>q= new LinkedList<>();
        q.add(pair);
        return bfs(q,m,n,d,-1);
    }
    
    int bfs(Queue<Pair>q,int m,int n,int d,int c){
        ArrayList<String>al=new ArrayList<>();
        while(!q.isEmpty()){
            int size=q.size();
            c++;
            while(size-->0){
                Pair popped=q.poll();
                if(popped.u==d || popped.v==d)
                return c;
                
                //empty jug1
                Pair emptyu=new Pair(0,popped.v);
                String eu=Integer.toString(emptyu.u)+Integer.toString(emptyu.v);
                if(popped.u!=0 && !al.contains(eu)){
                q.add(emptyu);
                al.add(eu);
                }
                
                //empty jug2
                Pair emptyv=new Pair(popped.u,0);
                String ev=Integer.toString(emptyv.u)+Integer.toString(emptyv.v);
                if(popped.v!=0 && !al.contains(ev)){
                q.add(emptyv);
                al.add(ev);
                }
                
                //fill jug1
                Pair fillu=new Pair(m,popped.v);
                String fu=Integer.toString(fillu.u)+Integer.toString(fillu.v);
                if(popped.u!=m && !al.contains(fu)){
                q.add(fillu);
                al.add(fu);
                }
                
                //fill jug2
                Pair fillv=new Pair(popped.u,n);
                String fv=Integer.toString(fillv.u)+Integer.toString(fillv.v);
                if(popped.v!=n && !al.contains(fv)){
                q.add(fillv);
                al.add(fv);
                }
                
                
                //transfer from jug1 to jug2
                int vremain=n-popped.v;
                if(popped.u!=0 && vremain>0){
                String su1=Integer.toString(0)+Integer.toString(popped.v+popped.u);
                String su2=Integer.toString(popped.u-vremain)+Integer.toString(n); 
                    //if jug2 has more space than jug1
                    if(vremain>popped.u && !al.contains(su1)){
                    q.add(new Pair(0,popped.v+popped.u));
                     al.add(su1);
                    }
                    //if jug1 has more space than jug2
                    else if(vremain<popped.u && !al.contains(su2)){
                    q.add(new Pair(popped.u-vremain,n));
                        al.add(su2);
                    }
                }
                
                //transfer from jug2 to jug1
                int uremain=m-popped.u;
                if(popped.v!=0 && uremain>0){
                String su3=Integer.toString(popped.v+popped.u)+Integer.toString(0);
                String su4=Integer.toString(m)+Integer.toString(popped.v-uremain);    
                    if(uremain>popped.v && !al.contains(su3)){
                    q.add(new Pair(popped.v+popped.u,0));
                     al.add(su3);
                    }
                
                    else if(uremain<popped.v && !al.contains(su4)){
                    q.add(new Pair(m,popped.v-uremain));
                        al.add(su4);
                    }
                }
            }
        }
        return -1;
    }
}

class Pair{
    int u;
    int v;
    Pair(int u,int v){
        this.u=u;
        this.v=v;
    }
}
 
0
geminicode9 months ago
Was anyone able to submit in python??
We strongly recommend solving this problem on your own before viewing its editorial. Do you still
                    want to view the editorial?
 Login to access your submissions. 

Problem


Contest

Reset the IDE using the second button on the top right corner.
Avoid using static/global variables in your code as your code is tested 
                                    against multiple test cases and these tend to retain their previous values.
Passing the Sample/Custom Test cases does not guarantee the correctness of code.
                                    On submission, your code is tested against multiple test cases consisting of all
                                        possible corner cases and stress constraints.
You can access the hints to get an idea about what is expected of you as well as
                                        the final solution code.
You can view the solutions submitted by other users from the submission tab.
Make sure you are not using ad-blockers.
Disable browser extensions.
We recommend using latest version of your browser for best experience.
Avoid using static/global variables in coding problems as your code is tested 
                                against multiple test cases and these tend to retain their previous values.
Passing the Sample/Custom Test cases in coding problems does not guarantee the 
                                correctness of code. On submission, your code is tested against multiple test cases
                                    consisting of all possible corner cases and stress constraints.