[SOLVED] Finding prime numbers kdb, discussion about projection and functions

Issue

So I am trying to create a function that finds all the prime numbers below a certain number.

This is the code I have written which doesn’t work, but will help me explain how I am trying to solve it. I will fix the manual checking for 0,1,2 later.

primes: enlist 2
g: h[;primes]
g'[3 + til 100-2]

h:{[x;y] z: x mod/: y; bool:(0 in z)=0b; if[bool; `primes set primes,x ]; }

So what I want to do is, use the each (') operator to run this function h for each element in 3+ til 100-2. However, I want it to continue using the primes variable not in an each way. The if statement will execute if there is no 0 in z as this means x is prime. Then in the if statement, I would like to join x to the primes list.

Loop 1: x:3 y: enlist 2
In the if statement, it will join 3 to primes

loop 2: x:4 y: 2 3
if statement will not execute

loop 3: x:5 y: 2 3
In the if statement, it will join 5 to primes

loop 4: x:6 y: 2 3 5
if statement will not execute

Thanks for your help!

Solution

Your logic works, and can be tidied up a little as:

q)primes:enlist 2
q)h:{m:x mod/:primes;bool:(0 in m)=0b;if[bool;`primes set primes,x];}
q)h'[3 + til 100-2];
q)primes
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

Some differences to yours:

  1. If you project your h with input primes, e.g. g:h[;primes] then that primes input is fixed at that point in time, it will not vary for each iteration. So your y in your function is always fixed at just 2.

I got around that in this example by simply referencing the global primes variable (which isn’t fixed).

  1. I avoided using z as a variable within the function as it is generally bad practice since z is more commonly used as the default/implicit third input variable in a function.

Sticking with your logic, a more conventional iterative approach which doesn’t require a global primes variable would be:

q){$[not 0 in y mod/:x;x,y;x]}/[2;3 + til 100-2]
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

This uses over (/) to iterate.

This still isn’t the optimal way to get primes, for that this might be optimal: https://github.com/KxSystems/kdb/blob/master/greplin.q#L6

q)p:{$[x<4;enlist 2;r,1_where not any x#'not til each r:p ceiling sqrt x]}
q)p 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

Answered By – terrylynch

Answer Checked By – Terry (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.