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!
CodePudding user response:
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:
- If you project your
h
with inputprimes
, e.g.g:h[;primes]
then thatprimes
input is fixed at that point in time, it will not vary for each iteration. So youry
in your function is always fixed at just2
.
I got around that in this example by simply referencing the global primes
variable (which isn't fixed).
- I avoided using
z
as a variable within the function as it is generally bad practice sincez
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