0

In the following code snippet, I intended to exit the while loop when the value of m becomes 0 or less than 0. But my while loop is still running even after the value of m finally decrements to 0. What is the reason for this infinite loop? Does it have anything to do with my else statement? If it does, why so?

NOTE: The reason I need the while loop here is because I need the for loop to run afresh when it terminates but the value of m is greater than 0.

Here is my code:

n, m = input().split()
n = int(n)
m = int(m)

while m>=0:
    for i in range(n+1):
        if m >= i:
            m -= i
        else:
            break
   
        
print(m)
JackPot
  • 25
  • 4
  • 3
    "while loop is still running even after the value of `m` finally decrements to 0" - this makes sense because the code will loop `while` `m` is greater _or equal_ to zero. – ForceBru Jun 13 '22 at 16:15
  • 2
    If `m >= i`, then `m -= i` will never make `m` negative. – chepner Jun 13 '22 at 16:17
  • 2
    As long as the initial value of `m` is >= 0, the loop will never end. The inner loop will never make `m` negative, so the outer loop will never exit. Note that the `break` statement only applies to the inner loop. – Tom Karzes Jun 13 '22 at 16:18
  • @ForceBru you are very right. But now that I have changed the condition to while m<0, the program is not even entering the inner for loop. Why is that? – JackPot Jun 13 '22 at 16:20
  • 1
    See https://stackoverflow.com/q/189645/6744133 for breaking out of the outer while loop – Oli Jun 13 '22 at 16:20
  • @JackPot, "I have changed the condition to `while m<0`" - why? This condition is the opposite of what you have in the post, so it makes sense for it to do the opposite of what the original code did... – ForceBru Jun 13 '22 at 16:25
  • What are you really attempting to do here? It seems like you want to repeatedly decrement `m` so long as it's larger than `i`, at which point you want to reset `i` to 0 and keep reducing `m` until it hits zero. But to what end? Because this feels very much like you're trying to do something simple in a complicated. What is your expected input/output for these numbers? – Nathaniel Ford Jun 13 '22 at 16:25
  • @Nathaniel Ford https://codeforces.com/problemset/problem/92/A I am attempting to solve this problem from codeforces. – JackPot Jun 13 '22 at 16:26
  • Paste the problem description into the question. – Barmar Jun 13 '22 at 16:33

1 Answers1

1

This is solved more clearly by recursion. Imagine a function f that determines how many chips are left to the presenter:

def f(chips: int, walruses: int, position: int = 1) -> int:
    # Base case, there are fewer chips than the current position number
    if chips < position:
        return chips
    else:  # Iterative case; decrement chips and recalculate position
        chips = chips - position
        position = position + 1 if position < walruses else 1
        return f(chips, walruses, position)

walrus_count, starting_chips = input().split()
print(f(int(starting_chips), int(walrus_count)))

That said, if you really want to use a while loop:

def f(chips: int, walruses:int) -> int:
    position = 1
    # Quit if we don't have enough chips
    while chips > position:
        # Decrement chips
        chips = chips - position
        # Reset position if we've gone around the circle
        position = 1 if position >= walruses else position + 1
    return chips

The problem you are having is that you're nesting loops.

while m >= 0: # Loop until you run out of chips -> but that is not what the problem calls for
    for i in range(0, n+1):  # i is position, and you're looking to loop once you run out of walruses. Alas, you're zero-indexing here!
        if m >= i:  # Check to see if there are enough chips, which is a half-overlap of the outer loop
            m -= i  # Decrement chips, correct
        else:
            break  # Breaks out of for-loop, but not while-loop
     # No extra check here to see if you need to break out of while loop. Need to add one, or fix the while loop check.
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102