4
\$\begingroup\$

This is a very simple task, but I'm curious if there is a better, more 'Pythonic' way to solve this.

"""The sum of the squares of the first ten natural numbers is,

1^2 + 2^2 + ... + 10^2 = 385
The square of the sum of the first ten natural numbers is,

(1 + 2 + ... + 10)^2 = 552 = 3025
Hence the difference between the sum of the squares of the first ten natural numbers
and the square of the sum is 3025 − 385 = 2640.

Find the difference between the sum of the squares of the first one hundred natural
numbers and the square of the sum."""

square = 0
s = 0

for i in range(1, 101):
    square += i**2
    s += i

s = s**2

print(s - square)
\$\endgroup\$
5
\$\begingroup\$

This would be good practice for list comprehension, especially since sum() is a builtin function.

sequence = range(1, 11)
sum_of_squares = sum([i**2 for i in sequence])
square_of_sum = sum(sequence)**2
print(square_of_sum - sum_of_squares) # 2640

For even more fanciness, you can use this expression for the sum_of_squares:

sum_of_squares = sum(i**2 for i in sequence) # No square brackets

This sums over a generator expression instead of creating a new list, saving memory, especially if the sequence is something ridiculous like range(1, 1000000001).

\$\endgroup\$
  • 1
    \$\begingroup\$ Note that OP seems to be using python 3, so sequence is actually a generator and will be exhausted after the first time it's used \$\endgroup\$ – smac89 Dec 15 '16 at 4:56
  • 5
    \$\begingroup\$ @smac89 In the latest Python3, range() returns a special range object that acts like a list without taking up memory. It can be iterated multiple times. ideone.com/qJC8Nj \$\endgroup\$ – Mark H Dec 15 '16 at 10:20
  • \$\begingroup\$ Gotcha! Makes sense seeing as xrange behaved the same way in python 2 \$\endgroup\$ – smac89 Dec 15 '16 at 22:53
2
\$\begingroup\$

Separation of Concerns

What you have here looks nice...

for i in range(1, 101):
    square += i**2
    s += i

Seems like you were really shooting for that extra bit of performance by doing two totally unrelated things in one loop. Please don't do this, it's confusing! Especially when coupled with these last two lines:

s = s**2

print(s - square)

Now you are taking the square of one of the things you were incrementing. Wait, What, Why??

Now the reader of your code has to go back and examine the first loop to understand why s is squared but square isn't. But when they go back, they are also trying to understand what square has to do with all this and this just leads to someone scanning back and forth...

Here it is fixed:

for i in range(1, 101):
    square += i ** 2

for i in range(1, 101):
    s += i

Naming for Humans

Another source of confusion might arise from the naming scheme you have chosen. Python will understand any random name you give it because it has no notion of context, but if a human was reading your code, it would help to use names that contain more information of what they represent.

  • i kinda looks like 1 if someone was quickly looking through your code. To fix, choose pretty much anything but i. x, n, v seem like fine choices to me.
  • square seems like a name you will give something that should be squared. To fix, choose a name that identifies what the variable is holding; sum_of_squares is pretty Ok.
  • s doesn't really tell you much about what it holds. To fix, use something like nsum.

Applying the fixes and putting it all together

sum_of_squares = 0
nsum = 0

for x in range(1, 101):
    sum_of_squares += x ** 2

for n in range(1, 101):
    nsum += n

print(nsum ** 2 - sum_of_squares)

Note the names I have chosen were completely arbitrary and I've only suggested them to draw your attention to using correct variable names.

More "Pythonic"

I find that when people use that phrase, they are essentially asking for someone to replace their loops with list-comprehension or just make the code shorter by whatever python wizardry they can muster. Well before I go on and blast your code with my shrink ray (which I keep handy for such occasions as these), I must say that the code the way it currently looks is quite "Pythonic" (whatever that means). It just looks readable and nice and very to-the-point, so why muck with it any further?

Anyways, as you wish

r = range(1, 101)
print (sum(r) ** 2 - sum(x ** 2 for x in r))
\$\endgroup\$
  • 1
    \$\begingroup\$ Did you intentionally go for the most convoluted example to not use iteration? There's no need for abs and starmap, and you can move the range into a variable. Your 'Pythonic code' is not Pythonic. You can reduce it to r = range(1, 101);print(sum(x ** 2 for x in r) - sum(r)**2). \$\endgroup\$ – Peilonrayz Dec 15 '16 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.