# Basic programs¶

From GeeksforGeeks Python Programming Examples

Many of the published examples have been rewritten to use Python techniques more likely to illuminate the q solution. Where practical, the solutions are shown as expressions evaluated in the REPL, which better allows for experimenting.

Follow links to the originals for more details on the problem and Python solutions.

### Factorial of a number¶

>>> def factorial(n): return 1 if (n==1 or n==0) else n * factorial(n - 1)
...
>>> factorial(5)
120
q)factorial:{$[x<2;1;x*.z.s x-1]} q)factorial 5 120 Above .z.s refers to the running function; it can be assigned any name. Factorial 5 is defined non-recursively as the product of the integers 1-5. >>> math.prod(map(1 ._add_, range(5))) # in Python 3.8 >>> 120 q)prd 1+til 5 120 ### Simple interest¶ >>> p=10000 # principal >>> r=5 # rate >>> t=5 # time periods >>> (p*r*t)/100 # simple interest 2500.0 q)p:10000 / principal q)r:5 / rate q)t:5 / time periods q)(p*r*t)%100 / simple interest 2500f Q programs tend to prefer vectors. q)(prd 10000 5 5)%100 2500f Iteration is implicit in most q operators. Here we have three principals and corresponding time periods. The rate is the same for all three. q)p:1000 1500 1750 / principals q)r:3 / rate q)t:5 6 7 / time periods q)(p*r*t)%100 / simple interest 150 270 367.5 ### Compound interest¶ >>> p = 1200 # principal >>> r = 5.4 # rate >>> t = 2 # time periods >>> p*(pow((1+r/100),t)) # compound interest 1333.0992 q)p:1200 / principal q)r:5.4 / rate q)t:2 / time periods q)p*(1+r%100)xexp t / compound interest 1333.099 Again, iteration through lists is implicit. q)p:1200 1500 1800 / principals q)r:5.4 / rate q)t:2 2 3 / time periods q)p*(1+r%100)xexp t / compound interest 1333.099 1666.374 2107.63 ### Whether an Armstrong number¶ import numpy as np def is_armstrong(x): s = 0 t = x while t: s += (t % 10) ** len(str(x)) t //= 10 return s == x >>> [is_armstrong(x) for x in (153, 120, 1253, 1634)] [True, False, False, True] isArmstrong:{x=sum{x xexp count x}10 vs x} q)isArmstrong each 153 120 1253 1634 1001b The steps of isArmstrong explain themselves. q)10 vs 153 / decode base-10 integer 1 5 3 q)1 5 3 xexp 3 / raise to 3rd power 1 125 27f q)sum 1 5 3 xexp 3 153f ### Area of a circle¶ The area of a circle of radius $$r$$ is $$\pi r^2$$, where $$\pi$$ is the arc-cosine of -1. >>> import numpy as np >>> np.arccos(-1)*5*5 # area of circle of radius 5 78.53981633974483 q)(acos -1)*5*5 / area of circle of radius 5 78.53982 ### Prime numbers in an interval¶ >>> from sympy import sieve >>> list(sieve.primerange(11, 25)) [11, 13, 17, 19, 23] range:{x+til y-x-1} sieve_primerange:{ c:range[x;y]; / candidates lmt:"j"$sqrt last c;                / highest divisor to test
c where all 0<c mod/:range[2;lmt] }
q)sieve_primerange[11;25]
11 13 17 19 23

No q primitive for this, but range is a useful starting point.

q)show c:range[11;25]           / candidates
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
q)"j"$sqrt last c / need test modulo only to here 5 q)range[2;]"j"$sqrt last c
2 3 4 5

q)c mod/:2 3 4 5                / modulo each c against all of them
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
2 0 1 2 0 1 2 0 1 2 0 1 2 0 1
3 0 1 2 3 0 1 2 3 0 1 2 3 0 1
1 2 3 4 0 1 2 3 4 0 1 2 3 4 0

q)show f:0<c mod/:2 3 4 5       / flag remainders
101010101010101b
101101101101101b
101110111011101b
111101111011110b
q)all f                         / AND the flag vectors
101000101000100b
q)where all f                   / index the hits
0 2 6 8 12
q)c where all f                 / select from range
11 13 17 19 23

### Whether a number is prime¶

>>> from sympy import isprime
>>> [isprime(x) for x in (11, 15, 1)]
[True, False, False]

No q primitive for this either.

range:{x+til y-x-1}
isPrime:{(x>1)and all 0<x mod range[2;"j"$sqrt x]} q)isPrime each 11 15 1 100b ### Nth Fibonacci number¶ # next Fibonacci pair def nfp(x): return [x[1], sum(x)] # Nth Fibonacci pair def fibp(n): if n<2: return [0, 1] return nfp(fibp(n-1)) def fib(n): return fibp(n)[0] >>> fib(9) 21 nfp:{(x 1),sum x} fib:{first(x-1)nfp/0 1} q)fib 9 21 Above we see nfp applied with the Do iterator /. The Python solution recurses down from n to reach the initial state of [0, 1], while the q solution iterates n-1 times on an initial state of 0 1. ### Whether a Fibonacci number¶ import math def is_fibonacci(n): phi = 0.5 + 0.5 * math.sqrt(5.0) a = phi * n return n == 0 or abs(round(a) - a) < 1.0 / n >>> [is_fibonacci(x) for x in (8, 34, 41)] [True, True, False] $$x$$ is a Fibonacci number if either of $$5x^{2}\pm 4$$ is a perfect square. is_ps:{x={x*x}"j"$sqrt x}                       / is perfect square?
is_fibonacci:{.[or]is_ps flip 4 -4+/:5*x*x}
q)is_fibonacci 8 34 41
110b

The iteration implicit in q’s operators means that is_fibonacci also iterates implicitly.

### Sum of squares of first N natural numbers¶

def squaresum(n): return (n * (n + 1) / 2) * (2 * n + 1) / 3
>>> [squaresum(x) for x in (4,5)]
[30.0, 55.0]

squaresum:{(x*(x+1)%2)*(1+x*2)%3}
q)squaresum 4 5
30 55f

The q solution mirrors the Python, but the primitives iterate implicitly.

### Cube sum of first N natural numbers¶

def sum_cubes(x): return (x * (x + 1) // 2) ** 2
>>> [sum_cubes(x) for x in (5, 7)]
[225, 784]

sum_cubes:{(x*(x+1)div 2)xexp 2}
q)sum_cubes 5 7
225 784f

Once again, the q operators iterate implicitly.