# Tips for golfing in K

K is a programming language in the APL family designed by Arthur Whitney. While the official interpreter is closed-source and commercial, a trial version with a workspace limit of 32 bits of addressing space (which shouldn't pose problems for code golf) can be found at the Kx Systems website. This version bundled as part of the kdb+ database is colloquially known as "K4". There are also open-source K implementations available, including Kona, which is based on K3, and my own interpreter called oK, which is based on K5 and has a browser based REPL.

Kx Systems has a wiki with K4/kdb+/Q information, and the Kona GitHub page also has an excellent collection of reference materials. I have begun writing a manual for oK/k5 which may be a useful reference.

Like J and APL, K is a very terse and powerful language, and can often make a good showing in code golf. Please share tips, tricks and idioms you discover, and if you haven't tried K before consider giving it a spin! Post one tip per answer, please!

# Calling a Dyad

Assuming you had a dyadic (2-argument) function f:

f: {x+2*y}


You would ordinarily call it like so:

f[3;47]


You can save a character by instead currying in the first argument and then applying the resulting partial function to the second argument by juxtaposition:

f[3]47


The same naturally works for array indexing:

  z: (12 17 98;90 91 92)
(12 17 98
90 91 92)

z[1;2]
92

z[1]2
92


# Ranges

Normally if you want to create a vector of sequential numbers you use !:

  !5
0 1 2 3 4


If you want to create a range that starts at a number other than zero, you'd then add an offset to the resulting vector:

  10+!5
10 11 12 13 14


There are a few unusual approaches which could work better for a particular situation. For example, if your base and offset are already members of a list, you could use "where" twice:

  &10 5
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
&&10 5
10 11 12 13 14


For slower-growing sequences, consider combining "where" with "take":

  5#2
2 2 2 2 2
&5#2
0 0 1 1 2 2 3 3 4 4


If you want to create a range of multiples, you could multiply the result of ! or you could scan (\) a list of copies of the step size:

  2*!5
0 2 4 6 8
+\5#2
2 4 6 8 10


If you're trying to avoid parentheses, the former is better if the length of the sequence is variable and the step size is fixed, while the latter is better if the step size is what tends to vary. Picking the right variation can save 1 or 2 characters. The off-by-one difference could also work in your favor.

• Another clever trick from @ngn with situational usefulness is to use e.g. 2|^x instead of (#x)#2. Dec 3, 2020 at 20:48

# Printing newlines

If your output must have a newline, you may be tempted to do this:

0:whatever,"\n"


Don't. K2 (and likely other versions) has a neat feature where you can print a list of lines:

  0:("abc";"def")
abc
def


So, if you need to append a newline to the output, just do:

0:,whatever


# Trainify (x;f x) and x f g x

Works in ngn/k

You can use "n-times-scan" 1 f\x for this. It is slightly (likely just 1 byte) longer but more reliable than converge scan f\x because it is guaranteed to return the two-item list (x;f x) even if x~f x or ~x~f f x.

For example, if you want to extract the first and last items of a list:

{(*x;*|x)}   /10 bytes
{*'(x;|x)}
{*'1|:\x}    /9 bytes
*'1|:\       /6 bytes (8 if you need enclosing parens)


Note that *'|:\ doesn't always work because the reverse might be identical to itself, in which case a 1-item list is returned instead of two.

This trick extends to the case x f g x, which can be translated to f/(x;g x) and then f/1 g\x, though it actually saves bytes only if g does not require (...) in g\.

For sorting a list of lists by the result of -/ of each row:

{<x!-/'x}   /9 bytes, or 10 with @
<!/1-/'\    /8 bytes, or 10 with (...)


Both are real examples from this answer.

Sometimes f\ works unconditionally in place of 1 f\.

/absolute value
{x|-x}
|/-:\


x f x is shorter to trainify as f/2#, than f/1::\.

/equality table
{x=/:x}
=/:/2#,


(f x)g x is only one byte longer than x g (f x) as a train: g/|1 f\.

/extract first interval based on the indices computed by f
{*(f x)_x}
{*f[x]_x}
*_/|1 f\


Casts from strings are expensive. Just use eval. This:

## Lists of Strings

Some challenges call for a hardcoded list of strings, e.g.:

("qwertyuiop";"asdfghjkl";"zxcvbnm")


Sometimes, a few bytes can be saved using an alternative form, i.e.:

";"\:"qwertyuiop;asdfghjkl;zxcvbnm"


k4 (and several other variants) can take advantage of the symbol datatype, so long as the hardcoded strings lack spaces. For example:

$qwertyuiopasdfghjklzxcvbnm  # Avoid Conditionals K has a conditional construct (:[) which is equivalent to a Lisp-style cond: :[cond1;result1; cond2;result2; cond3;result3; default]  You can have as many conditions as you like, and if none match the default value is returned. Sometimes (as in recursive programs or programs that otherwise rely on a sequence of side effects), there's no getting around using one of these. However, in situations where you can afford to do a bit of extra work, you can often replace a "cond" with list indexing. Consider the infamous fizzbuzz program. Written in a conventional imperative programming style, we might go with: {:[~x!15;"FizzBuzz";~x!3;"Fizz";~x!5;"Buzz";x]}'1+!100  There's quite a bit of repetition here in the divisibility tests. A different approach recognizes that there are 4 cases (a number, divisibility by only 3, divisibility by only 5, divisibility by 3 and 5) and attempts to directly compute an index which chooses one of these cases from a list: {(x;"Fizz";"Buzz";"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100  Two characters shorter, and a better use of the language. Knowing that list literals are evaluated right to left, we also gain some additional golfing opportunities for combining reused subexpressions. We couldn't have easily done this in the cond-based version, since the string cases aren't evaluated at all if they aren't selected: {(x;4#t;4_ t;t:"FizzBuzz")@+/1 2*~x!/:3 5}'1+!100  Now we've saved 5 characters overall. Incidentally, this particular example works out even nicer in k5, since we have the "pack" overload for / to handle the step of multiplying by a vector of coefficients and summing: {(x;4_t;4#t;t:"FizzBuzz")@2 2/~3 5!\:x}'1+!100  Also note that the behavior of "find" (?), which produces an index past the end of the key list if the item is not found, is specifically designed to support handling a "default" case in this kind of indexing. Consider this fragment to convert vowels to uppercase: {("AEIOU",x)"aeiou"?x}'  Versus one of: {t:"aeiou"?x;:[t<5;"AEIOU"t;x]}' {:[~4<t:"aeiou"?x;"AEIOU"t;x]}'  (I know which I'd rather read, too!) # Uses of $

This tip is written with ngn/k in mind, parts might apply to other versions

• $x string applied on a string converts each character into its own string, making $x one byte shorter than ,'x or ++x.

This transformation can be useful when replacing some characters with spaces in a string: Given a string x and a boolean vector y of the same length, ($x)@'y inserts spaces at the indices of 1's in the boolean vector.  ($"Hello")@'0 1 1 0 1
"H  l "

• i$C truncates strings if i is less than the length of string. On strings that case is identical to i#C, but when given lists of strings, $ always applies to individual strings, potentially saving some 's.
  3\$("Hello, ";"World")
("Hel";"Wor")