[Tutor] nested "for" loops

John Miller jmillr@umich.edu
Mon May 5 15:07:01 2003


I found this explanation of how to use list comprehensions instead of 
for loops very useful; thanks!

However, I'd like to ask two questions that arise from this.

First, the results from both Peter and Pan (hmmmm...) give, for 
example, 5,12,13 AND 12,5,13. For my purposes, I would like to exclude 
one or the other since I consider them symmetric. I can write a 
solution using nested ifs, but I was wondering if it could be done 
using list comprehensions?

Second, the solution I give below results in a '''RuntimeError: maximum 
recursion depth exceeded''' after the first three Pythagorean triples. 
What am I doing that causes this, and how can I avoid it? Thanks!

John Miller

#!/usr/local/bin/python
limit=20
def findtriples(i,j,k):
	if i <= j:
		if j <= k:
			if k <= limit:
				if (i * i) + (j * j) == (k * k):
					print "Pythagorean triple: %d, %d, %d" % (i, j, k)
				k += 1
				findtriples(i,j,k)
			elif j < limit:
				j += 1
				k = j + 1
				findtriples(i,j,k)
			elif i < limit:
				i += 1
				j = i
				k = j + 1
				findtriples(i,j,k)
findtriples(1,1,1)


On Saturday, May 3, 2003, pan@uchicago.edu wrote:

> Peter,
>
>
>> for i in range(1, 21):
>>     for j in range(1, 21):
>>         for k in range(1, 21):
>>             if (i * i) + (j * j) == (k * k):
>>                 print "Pythagorean triple: %d, %d, %d" % (i, j, k)
>
>
>
> For this sort of operation, you might wanna learn a little bit of the
> 'list comprehension'...
>
> First of all lets do some tests:
>
>>>> [x for x in range(1,4)]   # build a list using list comprehension
> [1, 2, 3]
>
>>>> [x*x for x in range(1,4)]   # another one
> [1, 4, 9]
>
> The following is more interesting. You can get ALL the possible
> 'cross-pairs' between two lists using just one liner:
>
>>>> [(x,y) for x in range(1,4) for y in range(1,4)]
> [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 
> 3)]
>
> More:
>
>>>> [(x*x,y*y) for x in range(1,4) for y in range(1,4)]
> [(1, 1), (1, 4), (1, 9), (4, 1), (4, 4), (4, 9), (9, 1), (9, 4), (9, 
> 9)]
>
> Now add some conditional check:
>
>>>> [(x*x,y*y) for x in range(1,4) for y in range(1,4) if y*y == 9]
> [(1, 9), (4, 9), (9, 9)]
>
> Now get the square sums instead:
>
>>>> [x*x+y*y for x in range(1,4) for y in range(1,4) if y*y == 9]
> [10, 13, 18]
>
> So, we are getting close to your question, which can actually be solved
> in one line:
>
>>>> [(x,y, x*x+y*y) \
> .. for x in range(1,21) \
> .. for y in range(1,21) \
> .. if (x*x+y*y) in [z*z for z in range(1,21)]]
> [(3, 4, 25), (4, 3, 25), (5, 12, 169), (6, 8, 100), (8, 6, 100), (8, 
> 15, 289),
> (9, 12, 225), (12, 5, 169), (12, 9, 225), (12, 16, 400), (15, 8, 289), 
> (16, 12,
> 400)]
>>>>
>
> It must be harder to comprehend at first, but after you get yourself
> familiar with this type of functional programming, the coding life will
> be much easier.
>
> Besides, the list comprehension is MUCH faster than the for loops.

<snip>

> pan