# The Number of Full Rounds You Have Played
**Difficulty:** MEDIUM
[External](https://leetcode.com/problems/the-number-of-full-rounds-you-have-played)
Canonical: https://scaleengineer.com/dsa/problems/the-number-of-full-rounds-you-have-played
**Patterns:** [Math](https://scaleengineer.com/dsa/patterns/math)
**Data structures:** String
**Companies:** [General Motors](https://scaleengineer.com/companies/general-motors)
---
## Problem
You are participating in an online chess tournament. There is a chess round that starts every `15` minutes. The first round of the day starts at `00:00`, and after every `15` minutes, a new round starts.

* For example, the second round starts at `00:15`, the fourth round starts at `00:45`, and the seventh round starts at `01:30`.

You are given two strings `loginTime` and `logoutTime` where:

* `loginTime` is the time you will login to the game, and
* `logoutTime` is the time you will logout from the game.

If `logoutTime` is **earlier** than `loginTime`, this means you have played from `loginTime` to midnight and from midnight to `logoutTime`.

Return _the number of full chess rounds you have played in the tournament_.

**Note:** All the given times follow the 24-hour clock. That means the first round of the day starts at `00:00` and the last round of the day starts at `23:45`.

**Example 1:**

**Input:** loginTime = "09:31", logoutTime = "10:14"
**Output:** 1
**Explanation:** You played one full round from 09:45 to 10:00.
You did not play the full round from 09:30 to 09:45 because you logged in at 09:31 after it began.
You did not play the full round from 10:00 to 10:15 because you logged out at 10:14 before it ended.

**Example 2:**

**Input:** loginTime = "21:30", logoutTime = "03:00"
**Output:** 22
**Explanation:** You played 10 full rounds from 21:30 to 00:00 and 12 full rounds from 00:00 to 03:00.
10 + 12 = 22.

**Constraints:**

* `loginTime` and `logoutTime` are in the format `hh:mm`.
* `00 <= hh <= 23`
* `00 <= mm <= 59`
* `loginTime` and `logoutTime` are not equal.

# Approaches
## Iterative Simulation of Rounds
This approach simulates the process of playing through the tournament. It first determines the actual playable time window, then iterates through all possible 15-minute round start times within that window, counting each one that can be fully completed.
**Time:** O(1). Although there is a loop, the maximum number of iterations is fixed and small. A day has `24 * 4 = 96` rounds. An overnight session can span at most two days, so the loop runs at most `2 * 96 = 192` times, which is considered constant time. · **Space:** O(1). We only use a few integer variables to store the times and the count.
**Pros:** Easy to understand and implement as it directly models the problem statement.; Correct for all cases and handles edge cases like overnight sessions properly.
**Cons:** Slightly less performant than a direct mathematical calculation due to the explicit loop.; The logic can be simplified into a single formula, making this approach more verbose than necessary.
### Explanation
The core idea is to model the problem directly. We first convert the time strings into a more usable format, like total minutes from midnight. A key step is to handle sessions that cross midnight by adding 24 hours to the logout time, creating a single continuous timeline. Then, we find the first round we could possibly play by rounding our login time up to the next 15-minute mark. From this adjusted start time, we loop in 15-minute increments, checking if each full round (from `t` to `t+15`) ends before or at our logout time. We count every such round until they start extending past our logout time.

```java
class Solution {
    public int numberOfRounds(String loginTime, String logoutTime) {
        int loginH = Integer.parseInt(loginTime.substring(0, 2));
        int loginM = Integer.parseInt(loginTime.substring(3, 5));
        int logoutH = Integer.parseInt(logoutTime.substring(0, 2));
        int logoutM = Integer.parseInt(logoutTime.substring(3, 5));

        int loginTotalMinutes = loginH * 60 + loginM;
        int logoutTotalMinutes = logoutH * 60 + logoutM;

        if (logoutTotalMinutes < loginTotalMinutes) {
            logoutTotalMinutes += 24 * 60; // Add a day for overnight session
        }

        // Round login time up to the next 15-minute mark
        int startRoundMinutes = (int) Math.ceil(loginTotalMinutes / 15.0) * 15;

        int count = 0;
        for (int t = startRoundMinutes; t + 15 <= logoutTotalMinutes; t += 15) {
            count++;
        }

        return count;
    }
}
```
### Algorithm
*   Parse the `loginTime` and `logoutTime` strings to get the total minutes from midnight for each.
*   Handle the case where the session spans midnight. If `logoutTime` is earlier than `loginTime`, add a full day's worth of minutes (24 * 60 = 1440) to the `logoutTime`'s minute representation.
*   Calculate the start time of the first potential full round. This is done by rounding the `loginTime` (in minutes) *up* to the next 15-minute mark. For example, a login at 09:31 means the first possible round starts at 09:45.
*   Initialize a counter for full rounds to zero.
*   Iterate from the calculated start time, incrementing by 15 minutes in each step.
*   In each iteration, check if the current round can be completed. A round starting at time `t` ends at `t + 15`. This round is complete if `t + 15` is less than or equal to the `logoutTime` (in minutes).
*   If the round is complete, increment the counter.
*   Continue the loop until the round can no longer be completed.
*   Return the final count.

## Direct Mathematical Calculation
This approach avoids iteration by directly calculating the number of full rounds using a mathematical formula. It converts the times to minutes, adjusts the start and end times to the nearest playable round boundaries, and then calculates the number of 15-minute intervals between them.
**Time:** O(1). The solution involves a fixed number of arithmetic operations, regardless of the input times. String parsing and calculations are all constant time operations. · **Space:** O(1). Only a few variables are used to store the calculated minute values. No additional data structures are needed.
**Pros:** Most efficient solution as it uses direct calculation without any loops.; Concise and elegant, reducing the problem to a few arithmetic operations.
**Cons:** The mathematical logic, especially the rounding using integer arithmetic, might be slightly less intuitive at first glance compared to an iterative approach.
### Explanation
The most efficient way to solve this problem is to transform the time-based logic into a pure arithmetic problem. We convert both login and logout times into total minutes from midnight. To handle overnight sessions, if logout is earlier than login, we add a full day's minutes (1440) to the logout time. 

The crucial step is to determine the actual interval of playable rounds. The first possible round must start at or after we log in. We find this by rounding the login time *up* to the next 15-minute mark. The last possible round must end at or before we log out, so we find this by rounding the logout time *down* to the previous 15-minute mark. 

Once we have the adjusted start and end times in minutes, the number of rounds is simply the duration of this adjusted interval divided by 15. This entire process can be done with a few lines of code without any loops.

```java
class Solution {
    public int numberOfRounds(String loginTime, String logoutTime) {
        // Helper to convert "hh:mm" to minutes from midnight
        int loginMinutes = toMinutes(loginTime);
        int logoutMinutes = toMinutes(logoutTime);

        // Handle overnight session
        if (logoutMinutes < loginMinutes) {
            logoutMinutes += 24 * 60;
        }

        // Round login time up to the nearest 15-minute interval
        // Example: 09:31 (571) -> (571 + 14) / 15 = 39. This is the 39th 15-min block.
        int startBlock = (loginMinutes + 14) / 15;

        // Round logout time down to the nearest 15-minute interval
        // Example: 10:14 (614) -> 614 / 15 = 40. This is the 40th 15-min block.
        int endBlock = logoutMinutes / 15;

        // The number of rounds is the difference in these 15-minute blocks
        int rounds = endBlock - startBlock;

        return Math.max(0, rounds);
    }

    private int toMinutes(String time) {
        int hours = Integer.parseInt(time.substring(0, 2));
        int minutes = Integer.parseInt(time.substring(3, 5));
        return hours * 60 + minutes;
    }
}
```
### Algorithm
*   Convert `loginTime` and `logoutTime` strings into total minutes from midnight.
*   If `logoutMinutes < loginMinutes`, add `1440` (24 * 60) to `logoutMinutes` to handle the overnight case.
*   Calculate the effective start time (`start`) by rounding `loginMinutes` *up* to the nearest multiple of 15. This can be done with integer arithmetic: `start = (loginMinutes + 14) / 15`.
*   Calculate the effective end time (`end`) by rounding `logoutMinutes` *down* to the nearest multiple of 15. This can be done with integer arithmetic: `end = logoutMinutes / 15`.
*   The number of rounds is the difference between these two 15-minute block indices: `end - start`.
*   Return the result, ensuring it's not negative (e.g., using `Math.max(0, result)`).

# Solutions
### Java

```java
class Solution {
public
  int numberOfRounds(String loginTime, String logoutTime) {
    int a = f(loginTime), b = f(logoutTime);
    if (a > b) {
      b += 1440;
    }
    return Math.max(0, b / 15 - (a + 14) / 15);
  }
private
  int f(String s) {
    int h = Integer.parseInt(s.substring(0, 2));
    int m = Integer.parseInt(s.substring(3, 5));
    return h * 60 + m;
  }
}

```

### CPP

```cpp
class Solution {
public:
  int numberOfRounds(string loginTime, string logoutTime) {
    auto f = [](string &s) {
      int h, m;
      sscanf(s.c_str(), "%d:%d", &h, &m);
      return h * 60 + m;
    };
    int a = f(loginTime), b = f(logoutTime);
    if (a > b) {
      b += 1440;
    }
    return max(0, b / 15 - (a + 14) / 15);
  }
};

```

### Python

```python
class Solution:
    def numberOfRounds(self, loginTime: str, logoutTime: str) -> int: def f(s: str) -> int: return int(s[: 2]) * 60 + int(s[3:]) a, b = f(loginTime), f(logoutTime) if a > b: b += 1440 a, b = (a + 14) // 15, b // 15 return max(0, b - a)

```
