Write integer_sqrt(x: int) -> int that returns the largest whole number r with r * r <= x, the square root of x rounded down.
Work it out with integer arithmetic only: don't call math.isqrt, math.sqrt or any other square-root routine, and don't raise to the power 0.5. (At this size floating point isn't exact anyway: int((10**18 - 1) ** 0.5) gives 1000000000, one too many.)
integer_sqrt(8) # 2 (2 * 2 = 4 <= 8 < 9)
integer_sqrt(16) # 4
integer_sqrt(0) # 0
integer_sqrt(10**18) # 1000000000
integer_sqrt(10**18 - 1) # 999999999
Constraints: 0 <= x <= 10^18. A single test makes 20,000 calls with large x, so counting r up one at a time (up to a billion steps per call) is far too slow. Aim for O(log x) per call.
In C++ or Java, r * r overflows a 64-bit integer once r passes about 3 * 10^9, so keep candidates below that or compare r <= x / r instead.
Show hint
If r * r > x, every number above r is too big as well; if r * r <= x, every number below r works. So one comparison rules out a whole side of the range.