2022.11.04 11:00 AM
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.
This is close to trivial in q.
nnt:1+til@ / natural numbers to x
sqr:{x*x}
{(sqr sum x)-sum sqr x} nnt 100
We can explore some alternatives.
The square of the sums, the sum of the squares – two compositions?
(-).(sqr sum@;sum sqr@)@\:nnt 100
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)1 reverse\(sqr;sum)
{x*x} sum
sum {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)'[;]./:1 reverse\(sqr;sum)
{x*x}sum
sum{x*x}
It remains only to Apply At Each Left @\:
the compositions to the vector and take the difference.
.[-] ('[;] ./: 1 reverse\(sqr;sum) ) @\: nnt 100
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
2022.11.26 05:13 PM - edited 2022.11.26 05:20 PM
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:{(x*x:sum x)-sum x*x:1+til x} / sum square difference
2022.11.05 08:42 AM
Great work! Thanks, Stephen and Alex. 👏
2022.11.26 05:13 PM - edited 2022.11.26 05:20 PM
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:{(x*x:sum x)-sum x*x:1+til x} / sum square difference
2022.11.28 04:41 AM
Two practices I try to avoid!
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”
2022.11.28 06:03 AM
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](si*si:sum i)-sum i*i:1+til n} / sum square difference
2022.11.28 08:29 AM - edited 2022.11.28 08:29 AM
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:{(s*s:sum x)-sum x*x} 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.
EMEA
Tel: +44 (0)28 3025 2242
AMERICAS
Tel: +1 (212) 447 6700
APAC
Tel: +61 (0)2 9236 5700
KX. All Rights Reserved.
KX and kdb+ are registered trademarks of KX Systems, Inc., a subsidiary of FD Technologies plc.