[Tutor] exercise is recursion

Remco Gerlich scarblac@pino.selwerd.nl
Tue, 21 Nov 2000 14:48:06 +0100

On Mon, Nov 20, 2000 at 10:09:12PM -0600, Timothy Wilson wrote:
> I thought I would write a little progam that would factor a given integer
> into its primes. This seemed like a good time to use recursion, but I'm
> having trouble making it work. Anyone see the problem here? I've added a few
> lines of debugging code, and there's a function to determine if a number is
> prime, but I don't think I'll need it. Any suggestions would be appreciated.
> --snip--
> #!/usr/bin/python
> # This python factors a number into its primes.
> from math import *

Ick, I hate import *.

> def isPrime(number):
> 	for j in [2] + range(3, sqrt(number)+1, 2):
> 		if number in [1, 2]:
> 			return 1
> 		if  number % j == 0:
> 			return 0
> 	return 1
> def factor(factors, number, i=2):
> 	while i < sqrt(number):
> 		if number % i == 0:
> 			factor(factors, number/i, i)
> 			factors.append(i)
> #			if number/i == i:
> 		i = i + 1
> 	print str(number) + '\t' + str(i) + '\t' + str(factors) # debugging
> code
> 	return factors

I think the problem is that the while continues after you've found a factor,
and i is also increased after that. You should break after the append(i); any
other factors have already been found by the recursive call to factor().

Also, I think it should say <= not < in the while guard.

I would write it like this:

import math

def factors(n, highestsofar=2):
   for i in range(highestsofar, math.sqrt(n)+1):
      if n % i == 0:
         return [i] + factors(n/i, i)
   return [n]

I don't use a mutable list but add function results together because I
think that's a bit clearer. Instead of range(), you'd want to use a function
that only returns the primes in that range; you can adapt that from
Demo/scripts/primes.py in Python's source distribution. The highestsofar
variable is an optimization (you also use it).

Adding further optimization and unrolling it to an iterative version are
left as an excercise for the reader ;-).

Remco Gerlich