Challenge #1: Squares, 17 July 2006
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.
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)
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)
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/

[n*n for n in range(0,10)]
map(lambda x: x*x,range(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.
[x**2 for x in range(10)]
map(lambda x: x**2, range(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,
reduce(lambda l,x:l+[x*x],range(0,10),[])
filter(lambda x:int(x**(0.5))==x**(0.5),range(100))