Water Bottles II
Source: leetcode
Difficulty: Medium
Tags: math, simulation

You are given two integers `numBottles` and `numExchange`.


`numBottles` represents the number of full water bottles that you initially have. In one operation, you can perform one of the following operations:


- Drink any number of full water bottles turning them into empty bottles.
- Exchange `numExchange` empty bottles with one full water bottle. Then, increase `numExchange` by one.


Note that you cannot exchange multiple batches of empty bottles for the same value of `numExchange`. For example, if `numBottles == 3` and `numExchange == 1`, you cannot exchange `3` empty water bottles for `3` full bottles.


Return *the **maximum** number of water bottles you can drink*.


 


**Example 1:**


![](https://assets.leetcode.com/uploads/2024/01/28/exampleone1.png)

```

Input: numBottles = 13, numExchange = 6
Output: 15
Explanation: The table above shows the number of full water bottles, empty water bottles, the value of numExchange, and the number of bottles drunk.

```

**Example 2:**


![](https://assets.leetcode.com/uploads/2024/01/28/example231.png)

```

Input: numBottles = 10, numExchange = 3
Output: 13
Explanation: The table above shows the number of full water bottles, empty water bottles, the value of numExchange, and the number of bottles drunk.

```

 


**Constraints:**


- `1 <= numBottles <= 100`
- `1 <= numExchange <= 100`




C++ solution:
class Solution {
public:
    int maxBottlesDrunk(int numBottles, int numExchange) {
        int ans = 0;  
        int empty = 0;
        ans += numBottles;
        empty += numBottles; 
        int fullBottles = 0;
      while(numExchange <= empty){
        while(empty >= numExchange){
      empty -= numExchange;
       numExchange++;
       fullBottles++;
        }
        ans += fullBottles;
        empty += fullBottles;
        fullBottles = 0;
      }
        
        return ans;
    }
};

Go solution:
func maxBottlesDrunk(numBottles int, numExchange int) int {
    // before iteration set full bottles as empty
    emptyBottles := numBottles
    numberOfBottlesDrank := numBottles
    numBottles = 0
    // if there is enough bottles to exchange iteration continue
    for emptyBottles >= numExchange{
        // exchange bottles on by one while incrementing numExchange
        for emptyBottles >= numExchange{
            numBottles++
            emptyBottles -= numExchange
            numExchange++
        }
        // and drinking them again
        numberOfBottlesDrank += numBottles
        emptyBottles += numBottles
        numBottles = 0
    }
    return numberOfBottlesDrank
}

Java solution:
class Solution {
    public int maxBottlesDrunk(int numBottles, int numExchange) {
        int sum=numBottles,bottle=numBottles;
        while(bottle >= numExchange)
        {
            bottle-=numExchange;
            numExchange++;
            sum++;
            bottle++;
        }
        return sum;
    }
}

JavaScript solution:
/**
 * @param {number} numBottles
 * @param {number} numExchange
 * @return {number}
 */
var maxBottlesDrunk = function(numBottles, numExchange) {
        let eb = numBottles;
        let bd = numBottles;
        numBottles = 0;
        while (eb >= numExchange) {
            eb -= numExchange;
            numExchange += 1;
            eb += 1;
            bd += 1;
            console.log(eb, numExchange, bd);
        }
        return bd;
    }

Python solution:
class Solution:
    def maxBottlesDrunk(self, numBottles: int, numExchange: int) -> int:

        def rec(n,r):
            if n < r:
                return n
            
            return r + rec(n-r+1,r+1)
        return rec(numBottles,numExchange)

Ruby solution:
def max_bottles_drunk(num_bottles, num_exchange)
    total = 0
    full = num_bottles
    empty = 0
    exchange_rate = num_exchange

    loop do
        total += full
        empty += full
        full = 0

        exchanged = 0
        while empty >= exchange_rate
            exchanged += 1
            empty -= exchange_rate
            exchange_rate += 1
        end

        full = exchanged

        break if full == 0
    end

    total
end