[Tutor] New at Python
Steven D'Aprano
steve at pearwood.info
Mon Oct 6 04:08:48 CEST 2014
On Sun, Oct 05, 2014 at 06:40:39PM -0400, Mike Spaulding wrote:
> Given that n refers to a positive int use a while loop to compute the sum of
> the cubes of the first n counting numbers, and associate this value with
> total . Use no
> <http://pearson.turingscraft.com/codelab/jsp/tutor.jsp?glIndex=1&lang=PYTHON
> 3> variables other than n , k , and total .
Here is the thought process I would use to convert this into code.
Actually writing code happens quite late in the process, first I try to
understand the problem, and then and only then do I write code.
We want to "compute the sum of ...", associating that value with total.
So write it out in English (or whatever your native language is):
total = sum of ...
What do the ... represent? The cubes of the first n counting numbers. Do
you remember the definition of "counting numbers"? If not, google for
it. Understanding the problem, and the language used in the problem, is
critical to solving the problem.
https://duckduckgo.com/html/?q=counting+numbers
The counting numbers are simply 1, 2, 3, 4, 5, ... which goes on
forever, but fortunately for this problem we only want "the first n"
of them. If you're familiar with mathematics, that's obvious, but what
if you're not? Let's reason inductively.
If we wanted the first *three* numbers, we would have:
1, 2, 3.
If we wanted the first *four* numbers, we would have:
1, 2, 3, 4.
If we wanted the first *ten* numbers, we would have:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10.
I'm seeing a pattern here. So if you use a pronumeral "n" to represent
the, er, number of numbers we want, we'll have something like this:
1, 2, 3, 4, ... n.
and we want the *cubes* of those numbers:
1**3, 2**3, 3**3, 4**3, ... n**3.
and they go into our sum:
total = sum of 1**3, 2**3, 3**3, 4**3, ... n**3
We're told to solve this with a while loop, using variables n, k and
total. Let's ignore the part about the while loop for now, and
concentrate on the variables. n and total are obviously the input and
the output: n is the number we're working on, total is the number we
calculate. What's k? That gives us a strong hint that we need a third
variable.
What could it be? Since we can only add two numbers at a time (a + b)
and we know that total is going to be one of them (total + ???) and n is
*not* going to be the other one, that gives us a clue that k will be the
other one:
k = 1
total = total + k**3
k = 2
total = total + k**3
etc.
Let's start with a simpler problem: ignore the requirement to cube the
numbers, and let's just sum the natural numbers themselves:
total = sum of 1, 2, 3, 4, ... n
We can write that as:
total = 0 # We start with nothing.
total = total + 1 # Add the first number.
total = total + 2 # Add the second number.
total = total + 3 # Add the third number.
total = total + 4 # I'm starting to see a pattern here.
and so on. Whenever you see repeated code like that, you should think of
a loop. A for loop is actually the right solution here, but the question
insists you use a while loop, so let's start with a little bit of
almost-but-not-quite Python code. We use k as the loop variable, it will
start at the first number we want to add, and increase by one each time
through the loop:
total = 0
k = 1 # The number we're going to add to the total, starting at 1.
while there are still numbers to be added:
total = total + k
k = k + 1 # Go on to the next number to be added.
There's a shorter way to add an increment to a variable:
total = 0
k = 1
while there are still numbers to be added:
total += k
k += 1
Obviously "while there are still numbers to be added" is not Python
code. In Python, we need "while condition". What is the condition that
decides whether there are still numbers to be added or not?
Let's take a concrete example: n = 4. We're going to loop with:
k = 1 is used.
k = 2 is used.
k = 3 is used.
k = 4 is used. <-- n = 4
k = 5 is NOT used.
So our condition is that k is less than or equal to n. So now we can
insert that condition into the Python code:
total = 0
k = 1
while k <= n:
total += k
k += 1
Don't forget that we actually want to sum the cubes!
total = 0
k = 1
while k <= n:
total += k**3
k += 1
And we're done here and can move on to the next exercise. Or, we can
continue on this one and do it *right*.
Earlier, I said that a for loop was the right solution for this, rather
than a while loop. Using a for loop simplifies the management of the k
variable:
total = 0
for k in (1, 2, 3, 4, ..., n) # not quite legal Python!
total = total + k**3
To get the values (1, 2, 3, 4, ..., n) we use the built-in Python
function "range", which returns a sequence of numbers, given an optional
starting value, a stopping value, and an optional stepsize or stride:
range(6) -> 0, 1, 2, 3, 4, 5
range(1, 6) -> 1, 2, 3, 4, 5
range(1, 6, 2) -> 1, 3, 5
So in this case, we want to start at 1, and end with n *included*, so
our stopping value is n+1, and the step is just the default 1:
total = 0
for k in range(1, n+1):
total = total + k**3
That can be simplified using a generator expression and the built-in
sum() function:
total = sum(k**3 for k in range(1, n+1))
only you probably haven't learned about them yet. But you can probably
see the similarity between the explicit for-loop and the generator
expression:
for k in range(1, n+1):
<blah blah blah> k**3
vs.
<blah blah blah>(k**3 for k in range(1, n+1))
The order is slightly different, but I hope you can see the similarity.
Can we improve this solution? Here it is again:
total = sum(k**3 for k in range(1, n+1))
Yes, we can improve it, thanks to mathematics! Can we find a simple
equation that gives us the sum of the first n cubes? Googling for
"sum of first n cubes" gets me to here:
https://en.wikipedia.org/wiki/Squared_triangular_number
which simplifies my code to:
total = sum(k for k in range(1, n+1))**2
I can simplify that even more, since there is a marvelous
equation that gives the sum of the first n counting numbers. These two
pages will give you a good feel for how to think like a mathematician
and find patterns, which is an excellent skill for programmers too:
http://www.comfsm.fm/~dleeling/math/cogapp/sumofn.html
http://proofsfromthebook.com/2013/01/29/first-n-positive-integers/
Using that formula gives us:
total = (n*(n+1)//2)**2 # sum of the first n cubes.
which requires no other variables, no loops, and only four maths
operations: one each addition, multiplication, division and power. For
large values of n it will be *much* faster than summing them by hand.
The only downside is that it isn't *obvious* that it is the sum of the
first n cubes, but that's why # comments are available.
--
Steven
More information about the Tutor
mailing list