Skip to content

Rhaptos Software Development

Personal tools
You are here: Home » Development » Tuesday Python Challenge » Challenge #1: Squares, 17 July 2006

Challenge #1: Squares, 17 July 2006

Document Actions
This is the first Python Challenge. It starts easy, but has some bonuses that may make you think (and do some research!)
Write some Python to generate a list of the first ten square numbers, starting at 0.

  Bonus 1: write it in one line.

  Bonus 2: write it in one line again in an entirely different way.

Post your solutions in the comments; I'll provide some answers at the end of the day.

Solutions and commentary

First, since this challenge involved a lot of creating squares, let's look at the actual calculation of squares. The most obvious way is clearly::

  x*x

Which is fine if we're always doing squares. But with cubes or other exponents (including roots) we can't rely on this. Python has an operator for exponents::

 x**2

works the same. There is also an equivalent built-in::

 pow(x,2)

Note that these can work to find square roots and similar::

 x**0.5

Several people used the operator; I don't think anyone used 'pow'.

Now for the list part of the challenge. The most straightforward answer is something like this::

  ans = []
  for i in range(10):
    ans.append(i*i)

But as most people managed, we can do this in one line. One way (probably the most obvious) is list comprehension::

  [i**2 for i in range(10)]

"List comprehension" lets us create an output list based on iteration over some other list (or other iteratable object). The expression before the 'for' is added to the output list for each iteration of the expression after 'in'. There's another optional part to list comprehensions; adding an 'if' to the end allows us to decide if we evaluate the output expression and include it in the result. We may look at that in another challenge.

The other standard way is to use the built-in function 'map' which applies a given function to each element of a sequence and returns the results in a list. We need a function to apply in this case. We could do it like so::

  def square(x): return x**2

  map(square, range(10))

But this isn't one line. Python allows us to create "anonymous" functions with the 'lambda' keyword. It creates a function object without use of the special 'def' structure we usually see. This is equivalent to the above::

  square = lambda x:x**2

  map(square, range(10))

But we don't have to bind a lambda-created function to a name, and can simply include it in the expression::

  map(lambda x:x**2, range(10))

We also had some more clever entries. Winning the computationally-inefficient category, Stefan examines all numbers up to 100 and only keeps the ones that are squares::

  filter(lambda x:int(x**(0.5))==x**(0.5),range(100))

The 'filter' method is rather like map, except that it is conditional (rather like the 'if' part of list comprehension.)

Also, he uses 'reduce' as a 'map' workalike::

  reduce(lambda l,x:l+[x*x],range(0,10),[])

Michael provides a very mathematical solution::

  l = []
  a = 0
  l.append(a)
  for i in range(1,10):
    a = a+(2*i-1)
    l.append(a)


Created by jccooper
Last modified 2006-07-24 15:30

Submissions here!

Posted by jccooper at 2006-07-17 11:24
Please place your answers in reply to this comment, so they don't appear in full on the main page. Sort of a spoiler saver.

Re: Submissions here!

Posted by reedstrm at 2006-07-17 13:22
Hmm, My two ansers are basicaly just differnt spellnigs of the samea thing:

[n*n for n in range(0,10)]

map(lambda x: x*x,range(10))

Re: Submissions here!

Posted by cbearden at 2006-07-17 15:33
>>> map(lambda i: i * i, range(0,10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> [n*n for n in range(0,10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>>

Not sure if these count as completely different, but there it is.

Re: Submissions here!

Posted by jenn at 2006-07-17 16:26
Wasn't sure what was meant by "completely different" for the second bonus...I'm sure there's something cleverer than just a syntactic variation, but that's what you're getting anyway. :)

[x**2 for x in range(10)]

map(lambda x: x**2, range(10))

Re: Submissions here!

Posted by jqmichael at 2006-07-17 16:37
(1)for i in range(0,10):
print i*i,
(2)# square numbers must be the sum of the odd numbers from 1.
print 0,
a=0
for i in range(1,10):
a=a+(2*i-1)
print a,

Something different

Posted by sanca at 2006-07-18 17:38
I wanted to do something more than the standard map and list comprehension so I cheated a little bit with one-liner reduce and filter :)

reduce(lambda l,x:l+[x*x],range(0,10),[])

filter(lambda x:int(x**(0.5))==x**(0.5),range(100))

Re: Challenge #1: Squares, 17 July 2006

Posted by jccooper at 2006-07-24 16:16
I'll also note that Python 2.5 provides an option to lambdas for the mapped function. We can fill in one of the arguments to 'pow' with the 'partial' function, and provide that instead. See http://www.python.org/dev/peps/pep-0309/