package com.freetymekiyan.algorithms.level.medium;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. You
* need to determine whether it is possible to measure exactly z litres using these two jugs.
* <p>
* If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end.
* <p>
* Operations allowed:
* <p>
* Fill any of the jugs completely with water.
* Empty any of the jugs.
* Pour water from one jug into another till the other jug is completely full or the first jug itself is empty.
* Example 1: (From the famous "Die Hard" example)
* <p>
* Input: x = 3, y = 5, z = 4
* Output: True
* Example 2:
* <p>
* Input: x = 2, y = 6, z = 5
* Output: False
* <p>
* Tags: Math
*/
public class WaterAndJugProblem {
private WaterAndJugProblem w;
/**
* Math, Bézout's identity.
* Let a and b be nonzero integers and let d be their greatest common divisor.
* Then there exist integers x and y such that ax+by=d, linear combination of x and y.
*/
public boolean canMeasureWater(int x, int y, int z) {
if (x + y < z) {
return false;
}
if (x == z || y == z || x + y == z) {
return true;
}
int gcd = gcd(x, y);
return z % gcd == 0;
}
/**
* Euclid's Algorithm.
* gcd(a, 0) = a
* gcd(a, b) = gcd(b, a mod b)
* a mod b = a - b * floor(a / b)
*/
private int gcd(int x, int y) {
return y == 0 ? x : gcd(y, x % y);
}
@Before
public void setUp() {
w = new WaterAndJugProblem();
}
@Test
public void testExamples() {
Assert.assertTrue(w.canMeasureWater(3, 5, 4));
Assert.assertFalse(w.canMeasureWater(0, 0, 1));
Assert.assertTrue(w.canMeasureWater(0, 0, 0));
Assert.assertFalse(w.canMeasureWater(2, 6, 5));
}
@After
public void tearDown() {
w = null;
}
}