I think I first heard of Kdb (precursor to kdb+) back in 1998 thanks to my friend PX. It claimed to be the fastest database in the block, but the K language and the fact that it aimed an industry not close to my interests made me download it a couple of times, fire up the 32bit interpreter and then go on with life. Fast forward some years and I learn that KX was aquired and that in the mean time Q was in the system to make it more accessible. In fact Q is written in K and you can read the implementation if you download the evaluation version. My interest was rekindled thanks to this arraycast episode and I ordered Fun Q. While waiting for the book, I watched the nine first videos from “An introduction to Kdb+” and tried to think whether I can write anything fancy with so little study.
Two simple and basic programs came to mind, FizzBuzz and the Collatz conjecture function. Could I do it with this little exposure to the language and some googling around? It turns that there are more articles about Q/Kdb+ than I expected on the net, so it was possible to figure things out. Let’s see:
Here is my take on the FizzBuzz:
{f:0=x mod 3;b:0=x mod 5;fb:f&b;$[1=fb;"fizzbuzz";1=f;"fizz";1=b;"buzz";x]} '[1+til 35]
1
2
"fizz"
4
"buzz"
"fizz"
7
8
"fizz"
"buzz"
11
"fizz"
13
14
"fizzbuzz"
16
17
"fizz"
19
"buzz"
"fizz"
22
..
I wanted to make a version like this in Python print(((x mod 3 == 0) * "fizz") + ((x mod 5 == 0) * "buzz") or x)
but you can’t multiply strings with booleans in Q (or you can, but I have not figured it out yet). So I worked it out with a switch statement instead. The difficult part for me was figuring out the “execute the function for each of the numbers from 1 to 100” (the '[1+til 100]
part of the expression).
To write the Collatz function, you do something like {$[0 = x mod 2; x%2; (1+3*x)]}[45]
which finds the next term in the sequence starting from 45. But we want to make it run recursively. Q has the /
and \
operators for this, and thus a run could be like {$[0 = x mod 2; x%2; (1+3*x)]}\[45]
which is supposed to feed each run’s output to the next run and also print the intermediate returns so that we see the sequence build. However, since the run does not converge we will never see an ouput and we need something to limit the runs to a finite number, which allows us to see the sequence:
q){$[0 = x mod 2; x%2; (1+3*x)]}\[18;45]
45
136
68f
34f
17f
52f
26f
13f
40f
20f
10f
5f
16f
8f
4f
2f
1f
4f
2f
q)
I do boolean expression comparisons with 0 = x mod 2
instead of x mod = 0
because q has no precedence and evaluates from right to left. So the x mod 2 = 0
is equal to x mod (2 = 0)
which is definitely not the comparison I wanted. That is why this gives 0N
as a result. In Q you’re supposed to code golf a bit and I believe that is why 0 = x mod 2
is preferred to (x mod 2)=0
.
I really do not know the proper idiomatic way to write this stuff yet, but I hope I stay engaged long enough to find out.
Update: After posting this blog, I googled “q language fizzbuzz” and came accross the Kx solution. I read it between the TV commercials and here is what I came up with:
{fb:sum 1 2*0=x mod/:3 5;$[fb=0;x;fb=1;"fizz";fb=2;"buzz";"fizzbuzz"]}'[1+til 17]
Update 2: Assuming we consider reaching to 1 a stop condition for the Collatz function, then using the convergence feature for scanning we can have the following function in order to compute the sequence: -1 _ {$[1=x;1;0=x mod 2;x%2;1+3*x]}\[18]
. We use the drop last item (-1 _
) because the scan prints the 1
twice (since convergence stops the iteration until two consecutive iterations return the same result; plus or minus some delta I think).
PS: You may also want to read about the new data platform from the reclusive genius of banking IT
Here’s how Kx are solving it https://code.kx.com/q/learn/reading/fizzbuzz/