Alternate approach

Hi,

I am trying to learn q by creating different scripts. I am trying to solve below problem.

"If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. 

Find the sum of all the multiples of 3 or 5 below 1000."

One of the solution of this problem I developed is


sum ((til ceiling 1000%3)3) union (til ceiling 1000%5)5


I have achieved the same with loop and if-else as well.

Please let me know if you guys know any other approach or may be better solutions.


Thank you.

try doing that in constant time

Well, you can use the fact that 3+6+9+12 is 3*(1+2+3+4) and the fact that the sum of integers is 0.5*n*(n+1) to get something of the form (excluding shared multiples of 15 and excluding 1000 itself):

q)sum k*.5*n*1+n:floor 999%abs k:3 5 -15
233168f

More generally,

q)\ts a:{sum ((til ceiling x%y)*y) union (til ceiling x%z)*z}[100000000;3;5]
1018 1207960160

q)\ts b:{sum k*.5*n*1+n:floor x%abs k:y,z,neg y*z}[100000000-1;3;5]
0 3392

q)a~`long$b
1b

The first solution blows up - both in terms of speed and memory usage - as the number increases.
 

Terry

Hi TerryLynch,

Thank you. Your suggestion seems great.

I understood the logic you suggested but I am not able to understand the Q expression you wrote, specially the use of “k” in the expression/function. Can you please elaborate?

@Yan Yan,

Please tell me what do you mean by constant time.

thank you.

This is problem #1 from https://projecteuler.net
Once you have the correct answer (using any algorithm) you can go to the “thread” for the problem and see how 206 other people have solved it using a variety of languages.

You can also download the the “overview” that discusses an “efficient” solution.

Constant time means the run time of the algorithm does not change, no matter the input size is 1k, 10k or 1M. The sum of the arithmetic sequence takes constant time to calculate using the formula given by @TerryLynch. A fixed number of multiplications and additions are faster than looping 1k, 10k or 1M times.

https://en.wikipedia.org/wiki/Time\_complexity

https://en.wikipedia.org/wiki/Arithmetic\_progression

As you know, q executes from left to right, or better “left of right”.
the “k” in Terry’s functions stores and intermediate value for use later in the execution stream.

Another way of expressing this in q (without the “k” variable) based on the “efficient” solution reported in the Project Euler overview is:

q)f:{floor .5*y*prd 0 1+(x-1) div y}

q){f[x;y]+f[x;z]-f[x;y*z]}[1000;3;5]

233168

q)\ts {f[x;y]+f[x;z]-f[x;y*z]}[100;3;5]

0 2144

q)\ts {f[x;y]+f[x;z]-f[x;y*z]}[100000000;3;5]

0 2144

The \ts reports the time (0 milliseconds) and the space (2144 bytes) used.

The time (0 milliseconds) is “constant” for inputs of 100 and of 100000000.  The space is also constant.

OOPS … typo (again)
q executes from right to left, or better “left of right”.

@Terry, Yan and Tom,
You guys are great. Thank you.