craftApprentice
craftApprentice

Reputation: 2777

Why two while loops one after the other (not inside the other) in Python don't work?

I wrote the code below and I was expecting that, when the first loop ends and doesn't return False, the flow would follow to the second while loop. However, the flow skips the second while loop and simply returns True. Why is that? How can I fix this problem, making the flow after the first while loop go to the second while loop?

square = [[1,2,3,4],[4,3,1,4],[3,1,2,4],[2,4,4,3]]
# this is an auxiliary function
def getSum(lis):
sum = 0
for e in lis:        
    sum = sum + e
return sum

# here is where the problem is
def check_game(square):
standardSum = getSum(range(1, len(square)+1))    

while square: #this is the first while loop
    row = square.pop()
    print row, 'row', 'sum of row=', getSum(row)
    if standardSum != getSum(row):
        return False
m = 0
while m < len(square): # the second while loop, which the flow skips 
    n = 0
    col = []
    while n < len(square):
        col.append(square[n][m])
        n = n + 1
    print col, 'column'
    if standardSum != getSum(col):
        print standardSum, ' and sum of col =', getSum(col)
        return False            
    m = m + 1
return True 

Upvotes: 0

Views: 2132

Answers (6)

Katriel
Katriel

Reputation: 123632

FYI your code is very (very very very) un-idiomatic Python -- it's written much more like C.

Here's a rewrite which is much more like Python is normally written.

square = [[1,2,3,4],[4,3,1,4],[3,1,2,4],[2,4,4,3]]
transpose = lambda i: zip(*i)

def is_magic(square):
    n = len(square)
    s = n*(n+1)/2

    return all(sum(row) == s for row in square) and \
           all(sum(col) == s for col in transpose(square))

You may wish to look into numpy, which is a Python module for handling matrices. With it:

def is_magic(square):
    n = len(square)
    s = n*(n+1)/2

    return all(m.sum(0) == s) and all(m.sum(1) == s)

Upvotes: 2

Burhan Khalid
Burhan Khalid

Reputation: 174624

You can avoid your error by replacing your first while with this:

for row in square:
  print row, 'row', 'sum of row=', getSum(row)
  if standardSum != getSum(row):
     return False

Upvotes: 0

Aram Kocharyan
Aram Kocharyan

Reputation: 20421

You know how many times you plan to iterate because you check a length and an increment variable. Use a for loop instead, as it will allow you to initialize the increment and adjust it each loop on the same line. This will avoid issues resulting in infinite loops in the future (even though thisn't the problem here, I consider it relevant to point out).

Upvotes: 0

Mark Tolonen
Mark Tolonen

Reputation: 177564

square.pop() returns a row from square and removes the row, therefore len(square) is zero in the second loop.

There is also a built-in function sum that does the same thing as your getSum function.

Upvotes: 1

Marcin
Marcin

Reputation: 49816

while square: will terminate when square is empty; it follows that len(square) == 0, and thus m < len(square) evaluates to false when m=0.

Upvotes: 1

Sven Marnach
Sven Marnach

Reputation: 601529

The first loop only terminates when there are no more items left in square. After the first loop, len(square) will be 0, so the entry condition for the second loop m < len(square) will be False.

Upvotes: 5

Related Questions