Project Euler #6

6. Sum square difference

https://projecteuler.net/problem=6

The sum of the squares of the first ten natural numbers is 385. The square of the sum of the first ten natural numbers is 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.

Solutions

This is close to trivial in q.

nnt:1+til@ / natural numbers to xsqr:{x*x} {(sqrsumx)-sumsqrx}nnt100

Alternatives

We can explore some alternatives.

The square of the sums, the sum of the squares – two compositions?

(-).(sqrsum@;sumsqr@)@\:nnt100

We can factor out the repetitions. The Zen monks will give us sqr and sum both reversed and not; 1 reverse\(sqr;sum), a 2×2 matrix.

q)1reverse\(sqr;sum) {x*x}sumsum{x*x}

Compose '[;] is binary (composes two functions) so can be applied by Apply Each Right ./: to each row of the matrix to produce the two compositions.

q)'[;]./:1reverse\(sqr;sum) {x*x}sumsum{x*x}

It remains only to Apply At Each Left @\: the compositions to the vector and take the difference.

.[-] ('[;]./:1reverse\(sqr;sum) )@\:nnt100

Composition rocks – and opens the way for cases where the functions (here sqr and sum) are determined at runtime.

Improving readability here… not so much.


Contributors

  • Stephen Taylor
  • Alex Unterrainer

From https://github.com/qbists/studyq/blob/main/euler/06.md

Great work! Thanks, Stephen and Alex. 

though less well-known, i prefer to build compositions with :: instead of @.``

@ adds an extra operator in the train of functions:

q)1+til@ +[1]@[k){$[0>@x;!x;'type]}] q)1+til:: +[1]k){$[0>@x;!x;'type]}

your solution introduces many new concepts. but as you indicate, it reduces readability.

a shorter, faster and more readable solution would be:

ssd:{(xx:sum x)-sum xx:1+til x} / sum square difference

Two practices I try to avoid!

  • setting a variable twice (I know, the clue is in the name, but I find it better to treat them as immutable) – A man with two watches never knows what time it is.
  • destroying the function argument value

And yet – what an elegant outcome. Only goes to show, whether writing code or writing English:

I’ve found many useful rules, but none so useful that I haven’t also found an occasion when it seemed right to break it.
— “Three Principles of Coding Clarity”

great quote and great article!

by adding an explicit function argument and introducing two new variables, we avoid setting a variable twice and destroying the function argument – in the process improving code clarity.

ssd:{[n](sisi:sum i)-sum ii:1+til n} / sum square difference

Oooooh… I don’t know. Nothing wrong with implicit arguments to simple functions. And listing the natural number sequence could stand aside from the rest of it…

ssd:{(ss:sum x)-sum xx} 1+til:: / sum square difference

Glad you liked the article. Arthur seems to mention it whenever I (rarely) see him. Something about the concept of ‘code distance’ seems to have struck a chord.