What are some useful tips for golfing in MATL? (As always, one tip per answer, please!)
Know the predefined literals
Although some of them keep information when copied to the clipboard, they all have a predefined value.
F, pushes 0 (actually False)
T, pushes 1 (actually True)
H, pushes 2 (predefined clipboard value)
I, pushes 3 (predefined clipboard value)
K, pushes 4 (predefined clipboard value)
J, pushes 0 + 1j (predefined clipboard value)
Not sure if I have covered all predefined values though.
& Meta-Function (Alternative Input / Output Specification)
The traditional way to specify the number of input arguments to pass to a function is to use the
2$: % Two-input version of :
Similarly, to specify the number of output arguments you can use the
# meta-function specifying either the number of output arguments,
2#S % Two-output version of sort
or if you pass a number that is greater than the number of output arguments defined for a function, only the
mod(N, numberOfOutputs) + 1 output is supplied.
4#S % Get only the second output of sort
You can additionally specify a logical array as the input to
# to retrieve only specific output arguments.
TFT#u % Three output version of unique and discard the second output
All of these input / output specifications are handy but they drive up your byte-count very quickly. To deal with this, MATL introduced the
& meta-function in the 17.0.0 release. This
& meta-function acts as a shortcut for a particular input or output specification for a function. Let's see what that means.
In our example above, we wanted to use the two-input version of
: (creates a vector of equally-spaced values). While the default number of input arguments to
1 (creates an array from
[1...N]), it is very common that a user would want to specify the start value of the range which requires the second input. So for
:, we have defined
& to be a shortcut for
10 % Push 10 to the stack 12 % Push 12 to the stack 2$: % Create an array: [10, 11, 12]
Now becomes the following, saving a byte!
10 12 &:
How can we determine what the alternate number of arguments is?
The input / output specification that
& translates to is function specific such that we optimize the byte-savings.
The input / output argument section of the help description for each function has been updated to indicate what this alternative number of inputs / outputs is (if any). The possible number of input or output arguments are displayed as a range and the default values for each are shown in parentheses. The input / output spec that can be substituted with
& is shown after the
/ character within the parentheses.
Here is the input / output argument section of the help description for
+- Min-Max range of # of inputs | +----- Alt. Default # of inputs | | V V 1--3 (1 / 2); 1 <--- Possible / Default # of outputs ^ | Default # of inputs
How did you determine what
& means for each function?
Very carefully. Using the StackExchange API, we were able to download all MATL answers that have ever been used in a PPCG challenge. By parsing each of the answers, we were then able to determine the frequency with which each input / output spec was used for each function. Using this information we were then able to objectively identify the input / output specification the
& meta-function should represent for each function. Sometimes there was no clear winner, so many functions currently don't have
And here is an example of the histogram of
Get familiar with MATL's truthy/falsy definitions
F) clearly represent truthy and falsy output, respectively, the widely agreed upon definition of truthy/falsy gives us a little bit more flexibility in MATL.
The definition states:
if (x) disp("x is truthy"); else disp("x is falsy"); end
So we can write a quick MATL truthy/falsy test which will loop through all inputs and display whether they were considered to be truthy or falsy
` ? 'truthy' } 'falsey' ]DT
What this means in MATL
What this actually translates to in MATL (and therefore in MATLAB and Octave) is that a condition is considered to be true if if it is non-empty and real components of all its values are non-zero. There are two parts to this that should be emphasized.
Non-zero: This means precisely that, not equal to zero (
==). This includes positive numbers, negative numbers, non-null characters, etc. You can easily check by converting a given value to a
g) or you can use
F % Falsy T % Truthy 0 % Falsy 1 % Truthy 2 % Truthy -1 % Truthy 'a' % Truthy ' ' % Truthy (ASCII 32) char(0) % Falsy (ASCII 0)
All values: Typically we think of scalars as being true or false, but in MATL, we can evaluate scalars, row vectors, column vectors, or even multi-dimensional matrices and they are considered to be truthy if and only if every single value is non-zero (as defined above), otherwise they are falsy. Here are a few examples to demonstrate
[1, 1, 1] % Truthy [1, 0, 0] % Falsey [1, 1, 1; 1, 1, 1] % Truthy [1, 0, 1; 1, 1, 1] % Falsey 'Hello World' % Truthy
The one edge case, as mentioned above, is an empty array
, which is always considered to be falsy (example)
How can I use this to golf better?
If the challenge simply mentions that your output should be truthy or falsy, you can likely exploit the definition above to shave a few bytes off of your answer. To save confusion, it is recommended that you include a link to the online truthy/falsy test above in your answer to help explain how MATL truthy/falsy values work.
A couple of specific examples:
An answer ending in
A. If the challenge requires a truthy or falsy output and you end your answer in
A) to create a scalar, you can remove this last byte and your answer will remain correct (unless the output is
Ensuring that an array contains only one unique value: Uses
&=in place of
un1=. If all values in an array are equal, a broadcasted element-wise equality comparison will yield an
N x Nmatrix of all ones. If all values are not equal, this matrix will contain some
0values and therefore be considered falsy.
Most functions accept some number of input. These inputs are taken from the top of the stack. If the top of the stack does not contain enough arguments, it will draw the remaining argument from the input. (See Section 7.3 in the documentation) I'd like to cite the original explanation:
Implicit inputs can be viewed as follows: the stack is indefinitely extended below the bottom, that is, at positions 0, −1, −2, ...with values that are not initially defined, but are resolved on the fly via implicit input. These inputs are asked from the user only when they are needed, in the order in which they are needed. If several inputs are required at the same time they follow the normal stack order, that is, the input that is deepest in the (extended) stack is entered first.
Logical arrays can often be used as numeric arrays
You can often use "
TF" notation instead of array literals of zeros and ones. For example,
FTF is the same as
[0,1,0], only that
logical values, not
double values. This is usually not a problem, as any arithmetical operation will treat logical values as numbers. For example,
Q is "increase by 1").
In some cases, conversion of a number to binary may be shorter. For example,
5B are the same; again with the caution that the latter two are
A case where the difference between
TF (logical) and
[1 0] (numeric) matters is when used as indices. An array of type
logical used as an index means: pick elements corresponding to
T, discard those corresponding to
[10 20]TF) produces
10 (select the first element), whereas
[10 20][1 0]) produces
[10 20] (the index
[1 0] has the interpretation of
1:end, that is, pick all elements of the array).
For loop of size n-1
to save up to an entire byte or more.
Move things from after the loop to within the loop, to exploit implicit end
], can be left out if there is no code after them. They are filled by the MATL parser implicitly.
So if you can move things from after the loop to within the loop you can to save the final
As a specific example, the following code finds how many trailing zeros there are in the factorial of a number
N (see it here):
- The code loops from
- For each of those numbers it computes its prime factors, and determines how many times
- The answer is the accumulated number of times
5appears (this works because for each
5there is at least one
The first idea was
:"@Yf5=]vs (note that there are statements after the loop):
: % Range from 1 to implicit input " % For each number in that vector @ % Push that number Yf % Vector of prime factors (with repetitions) 5= % True for entries that equal `5`, and `false` for the rest ] % End for v % Concatenate all vectors as a column vector s % Sum. Implicitly display
v by default concatenates all stack contents, it can be moved into the loop. And since addition is associative,
s can be moved too. That leaves
] at the end of the code, and thus it can be omitted:
: % Range from 1 to implicit input " % For each number in that vector @ % Push that number Yf % Vector of prime factors (with repetitions) 5= % True for entries that equal `5`, and `false` for the rest v % Concatenate all vectors so far as a column vector s % Sum. Inplicitly end loop and display
Shorter way to define an empty numeric array, if the stack is empty
To push an empty numeric array you normally use
. However, if the stack is empty you can save a byte using
v. This function by default concatenates all stack contents vertically, so if the stack is empty it produces the empty array.
You can see it in action for example here.
Some functions are extended compared with MATLAB or Octave
If you come from MATLAB or Octave, you'll find many MATL functions are similar to functions in those languages. But in quite a few of them functionality has been extended.
As an example, consider MATLAB's
reshape function, which in MATL corresponds to
e. The code snippets
reshape([10 20 30 40 50 60], 2, 3) and
reshape([10 20 30 40 50 60], 2, ) respectively mean "reshape the row vector
[10 20 30 40 50 60 into a 2×3 matrix", or "into a 2-row matrix with as many columns as needed". So the result, in both cases, is the 2D array
10 30 50 20 40 60
reshape([10 20 30 40 50 60], 2, 2) or
reshape([10 20 30 40 50 60], 5, ) would give an error because of incompatible sizes. However, MATL will remove elements in the first case (try it online!) or fill with zeros in the second (try it online!) to produce, respectively,
10 30 20 40
10 60 20 0 30 0 40 0 50 0
Other functions that have extended functionality in comparison with their MATLAB counterparts are (non-exhaustive list)
Efficiently defining numeric array literals
Here are a few ways that can be used to save bytes when defining numeric array literals. Links are given to example answers that use them. These have been obtained using the analytics script created by @Suever.
Concatenation and predefined literals
For arrays with small numbers you can sometimes use concatenation (functions
v), as well as predefined literals to avoid using spaces as separators: compare
2 4h and
2Kh, all of which define the array
[2 4]. Similarly,
2K1v with an empty stack defines
[2; 4; 1]. Example.
Letters within numeric array literals
For slightly larger numbers you can save spaces exploiting the fact that some letters have numeric meanings within array literals. So instead of
[3 5 2 7;-4 10 12 5] you can use
Specifically, within array literals,
Khave their usual meanings
String and consecutive differences
For larger numbers, defining a string and computing its consecutive differences (with
d) can help: instead of
[20 10 35 -6] you can use
'!5?b\'d. This works because
d uses the code points of the chars for computing the differences. Example.
Get the index of the first non-zero element, if any
f function gives the indices of all non-zero elements of an array. Often you want the index of the first nonzero element. That would be
f and pick its first element. But if the original array doesn't contain any non-zero value
f will output an empty array (
), and trying to pick its first element will give an error.
A common, more robust requirement is to obtain the index of the first element if there is at least one, and
 otherwise. This could be done with an
if branch after
f, but that's byte-expensive. A better way is
fX<, that is, apply the minimum function
X< to the output of
X< returns an empty array when its input is an empty array.
Generate a range as long as a given array
f instead of
n: if the array only has nonzero elements.
It is often the case that one needs to generate an array
[1 2 ... L] where
L is the number of elements of a given array. The standard way to do that is
n:. For example, the code
tn:* takes a numeric vector as input and computes each entry multiplied by its index.
If the given array is guaranteed to only contain nonzero entries (for example, it is formed by positive integers, or is a string with printable characters),
n: can be replaced by
f, which produces an array with the indices of nonzero entries. So the above code becomes
tf*, which saves 1 byte.