Identity Crisis 2013-5#
Problem: An Identity Matrix is a square matrix (table) of 0 with 1’s in the main diagonal. Write an APL dfn which produces an n×n identity matrix.
Video: https://youtu.be/vVaZ3wEdmpQ
Code: abrudz/apl_quest
Example Solutions:#
A#
n←5
A←(=/¨⍤⍳,⍨) ⍝ equality of x and y in all indices
We can take that vector and use it as an input for the Index Generator.
⍳
this generates an array of shape 5 5 where the elements are the indices for each element.Equality Reduction of Each pair
=/¨
we can see where the horizontal and vertical indexes are equal. This forms our identity matrix.⍤
The Atop operatorf⍤g Y
performs performs f on the result of g on Y. This allows the expression to be Tacit.
{({(=/)⍵}¨)(⍳(⍵,⍵))} ⍝ The expression as a Dfn from tacit.help
B - Equailty Table using same indeces for both sides#
B←(∘.=⍨⍳) ⍝ equality table for one dimensional indices
∘.
Outer Product∘.
generates a table from the input vector⍨⍳
Same input vector on both sides. Uses Index Generator⍳
to create the values.=
Comparison Function = checks for eqality beween the elements.This forms our identity matrix.
C - Assign to diagonal#
{s←⍵ ⍵⍴0 ⋄ (1 1⍉s)←1 ⋄ s} ⍝ assign to diagonal
⍵ ⍵⍴0
Reshape 0 to a 5 by 5 matrix and assign it to s(1 1⍉s)←1
Giving 1 1 to dyadic transpose returns the leading diagonal. 1 replaces those values becuase dyadic transpose allows for modified assignment.s
returns the new identity matrix. Diamond is the statement seperator.
D - amend at (i,i)#
{1@(,⍨¨⍳⍵)⊢⍵ ⍵⍴0} ⍝ amend at (i,i)
E - 1s at (i,i)#
⍸⍣¯1,⍨¨⍳ ⍝ 1s at (i,i)
,⍨¨⍳
Step 1 of D (1 1) (2 2) (3 3) (4 4) (5 5)⍸⍣¯1
Where⍸
returns the indices of all ones in a Boolean array. The Power Operator with¯1
returns the inverse of the Where function. Given the indices in Step 1 it returns a boolean vector with ones at each position. The inverse of indices.This generates our identity matrix.
F#
{⎕IO←0 ⋄ d←i+⍵×i←⍳⍵ ⋄ ⍵ ⍵⍴1@d⊢0↑⍨⍵*2} ⍝ amend at (i,i)ₙ
⎕IO←0
Sets Index Origin to 0d←i+⍵×i←⍳⍵
Taking the indices⍳⍵
we can multiply by their lengthw
we get the indices for the leading axis in ravel order (0 5 10 15 20 25), adding the indices⍳⍵
returns the diagonal (0 6 12 18 24). This is then assigned tod
which we use in the next step.1@d
We then set 1s At1@d
these indices in a vector⊢
of 0s with length of⍵*2
using Overtake↑
⍵ ⍵⍴
The result is shaped into a matrix using Reshape⍴
Industrial Versions#
A#
A ←{⍵ ⍵⍴1,⍵↑0} ⍝ insert 1 before n 0s
There are n zeros to the next 1. (1 0 0 0 0 0 1) ex. n=5
1,⍵↑0
Overtake↑
A length larger than the argument length causes fills to be inserted. In this case we use it to pad zero with⍵-1
additional zeros.1,
Catenate a 1 to the result.Reshape
⍴
repeats an argument of any length, singleton or otherwise. We prefix it with⍵ ⍵
to indicate the desired final shape. A 5x5 matrix using the example in Step 1.
B#
B ←{⍵ ⍵⍴(⍵+1)↑1} ⍝ overtake
Using the concept of Overtake we saw in Step 1 of A we can pad 1 with
⍵+1
zeros and then reshape the result. Obtaining the same matrix.
C - Tacit#
C ←(,⍨⍴+∘1↑1⍨) ⍝ tacit form
,⍨⍴
Ravel the argument against itself and use it to reshape+∘1
Bind + to 1 making it monadic. Add one to the argument.↑1⍨
Use step 2 to Overtake 1. The Selfie⍨
is used as a Constant.
D - Signum#
D ←(,⍨⍴+∘1↑×) ⍝ sign gives 1 (or 0 for 0)
Signum
×A
- Sign of number - on a real argument are0
,1
, and¯1
(zero, positive and negative)
E - Tally#
E ←(,⍨⍴+∘1↑≢) ⍝ tally of scalar is 1
Tally
≢
The tally of a Scalar is 1
Expand#
A#
A ←{⍵ ⍵⍴1(-⍵)\1} ⍝ expand 1 into one 1 and n 0s
Expand
\
- copies each element of the right argument a given number of times. Positive numbers on the left also replicate like with/
but negative numbers insert that many prototypical (spaces for characters and zeros for numbers) elements at that position.1(-⍵)\1
-⍵
is the number of zeros.\1
is the number to prepend with.1(-⍵)
is the number of times to prepend with a 1.⍵ ⍵⍴
Reshape into a⍵ ⍵
matrix.
B#
B ←(,⍨⍴1\⍨1,-) ⍝ tacit
C ←{(⍵,⍵)⍴((1,(-⍵))\1)} ⍝ tacit.help
,⍨⍴1
Self concatenation of the argument reshaped by1\⍨1
1 expanded by 1 (See A step 2),-
followed by the negation of the argument (generates zeros)See C for Dfn form
Matrix - Matrix Multiplication#
A#
A ←{⌹⍨?⍵ ⍵⍴0} ⍝ M × I = M
Reshape a matrix of random numbers against it’s inverse.
?⍵ ⍵⍴0
This gives us a matrix of random floats between zero and one.Matrix Divide
⌹
Using Selfie⍨
we echo the right argument to its left. In this case the matrix generated in Step 2 is divided by itself.This produces the identity matrix using matrix multiplication
B#
B ←(⌹⍨⍤?,⍨⍴≡) ⍝ depth of simple scalar is 0
C ←{(?((⍵,⍵)⍴(≡⍵)))⌹(?((⍵,⍵)⍴(≡⍵)))} ⍝ tacit.help
Makes A a [Tacit Function](Tacit Programming)
Can be read as Matrix division
⌹
, Selfie⍨
, On⍤
, random numbers?
shaped⍴
as the self concatentation,⍨
(takes one input and makes it two) of Depth≡
- returns an array’s depth. On a scaler (our input) it reurns zero.See C for Dfn form
Base conversion#
A#
A ← (⍴∘2⊤2*⊢-⍳) ⍝ powers of two are 1 0 0 …
B ← {(⍵⍴2)⊤(2*(⍵-(⍳⍵)))} ⍝ tacit.help
Looking at our identiry matrix we can see that each column is a power of two spelled out in binary.
2*⊢-⍳
We can generate these numbers by subtracting the initial Identity⊢
from the Index Generator⍳
of the argument and raising the result to the power of 2.We can then perform a base conversion. The left argument to Encode
⊤
defines the number of digits in the new number system. In this case we are prefixing it with a 2.We Bind
∘
- the Encode⊤
with Reshape⍴
creating a derived function and a tacit result.See B for Dfn form
Overtake, Mix and Scan#
A#
A ← (-⍤⍳↑⍤0≢) ⍝ suffixes of 1
-⍤⍳
Negation of the indicesPaired with the rank operator. Take using a length which is larger than the argument length causes fills of 0’s to be inserted.
Use tally to get a 1 allows function to be tacit.
{(-(⍳⍵))(↑⍤0)(≢⍵)}
is the Dfn version
B#
B ← (↑,⍨\⍤↑∘1) ⍝ cumulative reverse-concatenations
C ← {↑(({⍵,⍺}\)(⍵↑1))} ⍝ tacit.help
,⍨\
Swapped concatentation of scan returns the reversed prefixes of a vector↑∘1
Take binded with one. Overtakes one with the arguments number of zeros. In this case n=5⍤
Atop seperates the functions returns the right and then the left.
Key Operator#
A#
A←(×⌽⍤↑⌸⍤⍳) ⍝ {×(({⌽(⍺↑⍵)}⌸)(⍳⍵))}
Signum reversal atop of the the taking of the two arguments
↑⌸⍤⍳
We use the Index Generator⍳
to produce a list of numbers. Key⌸
groups each unique element as left argument, and the indices of that element in the data as right argument. We can then Overtake↑
with a length larger than the argument length causing fills of zeros to be inserted.×⌽
Reverse⌽
reorders the elements of the argument to go in the opposite direction along a specified axis We then use Signum×
to generate 1’s, instead of the indices generated by Key in Step 2.⍤
The Atop operatorf⍤g Y
performs performs f on the result of g on Y. This allows the expression to be Tacit.See Comment for the Dfn version.
B#
B←(⍸⍣¯1⍤⊢⌸⍳) ⍝ {({(⍸⍣¯1)⍵}⌸)(⍳⍵)}
Where inverse atop the right argument. Boolean vectors with 1 in each position.
⊢⌸⍳
Same as in A we use the Index Generator⍳
to produce a list of numbers. Key⌸
groups each unique element as left argument, and the indices of that element in the data as right argument. However we use Identity⊢
to just return the indices.⍸⍣¯1
Power⍣¯1
is used to access function inverses. Where⍸
returns the indices of a boolean array. So this will pad our indices with zeros.⍤
The Atop operatorf⍤g Y
performs performs f on the result of g on Y. This allows the expression to be Tacit.See Comment for the Dfn version.
Complex Numbers#
A#
A ← {4=○÷12○⍵∘.+0j1×⍵}⍳ ⍝ π÷4 = arg(a+ai)
B ← {0=(2*÷2)||⍵∘.+0j1×⍵}⍳ ⍝ |a+ai| = 0 mod √2
⍵∘.+0j1×⍵
Using Outer Product∘.+
of the real part plus the imaginary part+0j1
and Multiplying the imaginary part0j1×⍵
by the Index⍳
to create a table.○÷12○
The Circular12○
function is the Phase of ⍵. This determines the magnitude and the direction fo a complex number.4=○÷
The diagonal values will have Phase of 45 degrees or one quarter of pi (0.785398163 radians). Dividing by pi○÷
returns 4 and we can then select all the 4’s in the matrix. Returning 1’s for true. B⍵∘.+0j1×⍵
Again using Outer Product∘.+
of the real part plus the imaginary part+0j1
and Multiplying the imaginary part0j1×⍵
by the Index⍳
to create a table.When two complex numbers are added, they form the two sides of a right triangle in the complex plane, with the resulting complex number being the hypotenuse. The magnitude of the resulting complex number is equal to the length of the hypotenuse.
Becuase the horizontal and the vertical parts of this triangle are equal to each other( the same index is used on both sides of the outer product). The diagnals length is a multiple of the square root of 2.
(2*÷2)||
The first vertial bar takes the Magnitude|
of the result of Step 1. The second bar calculates the remainder or Residue when the table is divided by the square root of two(2*÷2)
0=
Everywhere there is no remainder we are on the diagonal.
Comment:#
J←{⍵ ⍵⍴(⍵+1)↑1} ⍝ overtake to insert 1 before n 0s
=/¨ ⍝ Compare Each
∘.=⍨ ⍝ Equailty Table using same indeces for both sides
1 1⍉s ⍝ Selects the diagonal of s
,⍨¨ ⍝ Catenate each to itself
x+.×y ⍝ matrix multiplication
,\ ⍝ prefix of a vector
Glyphs Used:#
Catenate
,
Index of
⍳
Compress
/
- filters the right argument=/¨
compare eachEach
¨
Commute
⍨
- aka Selfie or SwapDyadic Transpose
x⍉y
- allows you to select diagonals by giving one or more dimensions equal mappingReshape
⍴
At
@
- What’s on its left gets done at the position indicated by its right operand.Identity
⊢
Where
⍸
- returns the indices of a boolean array - mondadicPower
⍣¯1
- used to access function inversesPower(Function)
*
-X*Y
isX
raised to the powerY
Overtake
↑
- A length larger than the argument length causes fills to be insertedBind
∘
- used to create a derived function with a single constant argumentConstant
A⍨
- always returns the operator arraySignum
×A
- Sign of number - on a real argument are0
,1
, and¯1
(zero, positive and negative)Tally
≢
Expand
\
- copies each element of the right argument a given number of timesRoll
?0
- When zero Roll chooses a floating-point number between 0 and 1Rank
⍤
- applies its left [operand](. https://aplwiki.com/wiki/Operand “Operand”) function to cells of its arguments specified by its right operand array.Depth
≡
- returns an array’s depthDecode
⊥
- aka baseEncode
⊤
- aka antibaseBind
∘
- used to create a derived function with a single constant argumentKey
⌸
- groups major cells and applies the function for each cellEnclose
⊂
- An enclosed array is a scalar, which is subject to scalar extension.Reverse
⌽
- reorders elements of the argument to go in the opposite direction along a specified axis.Circular 12○ - Phase of ⍵ (omega)
Pi Times ○
Magnitude
|
aka absolute valueResidue
|
aka remainder
Concepts Used:#
Index Origin - Generating Functions with that work with 0 or 1 origin
Transcript:#
Welcome to this episode of the apl quest see APL wiki for details. Today’s quest is generating an identity matrix of order n. It’s a very simple task, but there are a lot of interesting ways we can do this. Let’s get started with some serious solutions and then look at some more fun innovative solutions after that.
The first thing we can do is that we have a number n. Let’s, for argument, say that n is five and we want to make a matrix that is five by five. So we can calculate n to itself, giving us five by five.
Next up, we can generate all the indices of an array of shape five five, and we can take these indices and look at where the horizontal and vertical index are the same by comparing each. This gives us our identity matrix. However, we can do this in a simpler way. We only need to generate the indices until n and then make an inequality table using the outer product and the selfie or commute operator to use the same indices on both sides of the quality. In fact, this is our simplest solution. So just the outer product selfie on the indices.
It isn’t a very efficient solution, however, because we are comparing a lot of numbers in general that we have generated when we actually know where the ones are going to be in advance. So what we can do is we can start off by creating an empty matrix of zeros. So we take n and use that twice to reshape zero. This gives us a big empty vector like this, an empty matrix like this. No, it’s not empty. It has a big zero matrix like this.
Then we can use dyadic transpose, which selects the um, it can collapse dimensions so that we get diagonals. We can illustrate this by saying 5 5 reshape iota 25, and then we can use the attic transpose mapping both dimensions to a single dimension, and that gives us the compromise between them diagonal.
Now we can use this with a selective assignment. We say one one transpose of s gates one, and the one that gets distributed over the entire s. And now s has been updated to become an identity matrix. We can put this into a function as s gets omega omega reshape zero, and then the diagonal of s gets one, and then return that s. And we can now give it the argument five fine.
This is verbose, but it works. It doesn’t have the best performance necessarily, and it’s a bit awkward because we have to have this middle statement where we update s before we then return s. We can also use the add operator to do something similar. We can start off by generating all the indices that need to be set to 1.
How can we do this? Well, if we start with this iota n in our case, then we know that it is the elements of position one one, two two, three three, four four, and that need to be set to one. So what we can do is we concatenate selfie concatenate to itself each one of them, and these are the indices that we need to set to one. And then we can use this, setting one at those indices in the array that is n and reshape zero, and that will give us an identity matrix.
We could also use these indices in a different way, and namely we could say, “Give me a boolean matrix that has ones in those positions.” So where are all the ones in the boolean matrix? It’s magnetic iota underbar, and the inverse we can use power negative one on that, and that gives us an identity matrix as well.
There are even more things that we could do along these lines. Instead of using a matrix, we can use a vector. The way we can do that is by observing that this is kind of an encoding of in in a special radix. So we want ones, and then when we do things like that, we need to set coordinate to zero, otherwise, it becomes too complicated.
What we can do is we have the indices iota n here, and then we can multiply those by n, and so this corresponds to, let’s see, number zero is this element, and number five is this element, and number ten is this element in revel order. However, we need to offset one for each one, so if you take these indices and add them to this, that gives us in revel order that diagonal. We can actually see this if we say 5 5 reshape by yo to 25. We can see that 0, 6, 12, 18, 24, those are diagonals.
Once we have those, we can then use the add operator as before. So we can set the ones at that in a vector, which is zero reshaped to the shape of n squared, and this is our flattened identity matrix. Now we can take the proper shape and reshape it, and we get our identity matrix.
Let’s change back to quarter one index origin one and then actually do some of the best performing solutions. We can observe similar to what we’ve done now. We can see that there are exactly n zeros onto the next one, and then again n zeros to the next one. So what we can do is we can begin with a one followed by n zeros, and then we can reshape that cyclically into our full shape. We’ll use n here, and this is almost as good as it gets.
There’s one problem for a very large n, and we create a boolean vector of all zeros. And by inserting one at the beginning, it gives us sub-optimal performance because we need to copy this entire array one step over, shifting everything by one bit to insert that leading bit. How can we avoid that? Well, we can use overtake. So if we say n take
of one, it pads with additional zeros at the end. And the only thing we need to do here is really adding n plus one, and this gives us the full row. And now we can reshape into that shape.
This is going to be the best it gets. We can put this into a function as omega omega reshape omega plus one take one
. We can also make this into a tested form, and we can play some tricks there. Let’s split up the problem omega omega
that is the self-concatenation of the argument. Then we reshape that, and then we want the argument plus one.
So we can tie or bind a 1 to plus, making a magnetic function. So that’s an increment function, and we use that to take from. Well, we need a 1 here, but we can’t have 1 at the end of a tested function because it’s a constant, not a function. We can transform it into a function using the constant operator, so we can try this as well, and that works. And then for a little bit of trickery, we can actually avoid this construct of one constant by observing that the sine of five is one, and the problem was that we needed on the right hand to have a function, not a constant.
So this is a function applied to any number that’s relevant, and we get one. If we want the zero by zero, it doesn’t matter that the sine of zero is zero. It will still work because it becomes an empty array, so we can do this. We can say i5
like this. Another possibility is observing that how many elements are there in a single number? There’s only one, and that applies even to zero.
So we can do that as well. This is the fastest solution that we’re going to get. This is a proper solution, whether you want to use a tested form or a defend. It should be about the same performance.
Now onto some more fun and innovative solutions that we could do. Remember again that we needed a single one followed by n zeros, and we can actually do that using expand. So if we have a one representing that we want 1 1
and then we have negative n representing n fill elements, we can use that with the expand function on a single one to get the same thing, and then we can reshape that to our identity matrix.
We can write this in a tested form, and so this is again the self-concatenation, reshapes one expanded by one followed by the negation, and it works for zero as well. What happens in the zero case is negation of zero is zero, so we get 1 0
. That means we expand one as a single one with no fill elements, reshape that to 0 0
, and we have an empty numeric matrix, so that works as well.
Here’s one that almost always works. There is an astronomically small probability that it won’t work, but it is rather fun. Let’s say we have a matrix of random numbers. So with the zero as argument, ?
gives us random floats between zero and one. They won’t be zero, they won’t be one, and it’s exceedingly unlikely that we’ll have duplicates here.
Of course, now if this is a matrix, then there must exist a matrix such that m * m
(multiplication here means matrix multiplication) will give us… but in traditional mathematics, just m * m
will give us the matrix itself, and that is the identity matrix.
Now, if we move things around in this equation, we’ll find that dividing the matrix by itself should give us the identity matrix. And indeed, that is so. So we can do m matrix divide with m, and that gives us an identity matrix. We can write the whole thing as matrix division selfie on the random numbers of the self-concatenation of zero (here’s a constant zero). You can try this, and it works.
Similar to what we did with sine and tally to get a 1, there’s also a function which, for a single number (a scalar), gives 0, and that is the depth function. So we can go up and amend our function to this very obscure looking thing which works just fine and is very, very inefficient because API will have to solve an equation system every time we generate an identity matrix. But hey, it’s fun, right?
Here’s another one which is very, very inefficient. Let’s think about this: we’ve got the indices up to n. If we subtract these from n itself, that gives us descending powers from four down to zero, raised two to the power of that, and we’ve got descending powers of two. And now, if we go up and look in our identity matrix, then we can see that the first column is 16 spelled out in binary, and the second column is 8 spelled out in binary, and 4 and 2 and 1. So this means that if we represent all these numbers in base 2, then we would get the identity matrix.
So we could do something like this which auto-sizes, but we already know that we want n bits, so we can say n nreship2 encode on that, and that works as well. And then we can make the whole thing tacit by saying that it is the reshape of two. So this is a magnetic function which reshapes two encodes 2 to the power of the argument minus iota on the argument, so this works just fine but again, very inefficient doing base conversions when we just want to create an identity matrix. But fun!
Okay, a little bit more fun. We can generate the negative indices, and then we can overtake like we did before on a1, so each one of these will be used to take from a1. It takes from the rear padding, zeroes us at the front. Oops, that was too much - missing an each there. There we go. And now we just need to stack them up on top of each other, and there are various ways we could do that. We can mix or we could use the rank operator. So we want to pair these up, we need to do take pair these up with one and then it mixes everything together, so that works as well. And now we can put all this together to create a tested function.
So we have the negation of iota take rank 0 on… remember how to get a 1 without using literal one? We could use tally, for example, so this should work as well. And here’s our density matrix in the rather roundabout way.
Another thing we can use is scan. So we can get normally prefixes of a vector like this, and if we instead of concatenate (this is a cumulative concatenation), we do a cumulative swapped concatenation, then we get these reversed prefixes instead. If we can have a way to get reverse prefixes and we have a way to get one followed by a bunch of zeros, then these give us our rows, and we just need to mix.
So we can write this as an as a function the conclusion swapped scan and off the take of one so this is an end take one and then we mix that then we just need to put and a top here so we have two functions after each other and here we got our identity function in a very roundabout manner but lots of fun again.
Now let’s move over to the key operator which we can also use for this. We can generate our our indices like this and then we can ask the key operator what are the indices so let’s put it like this but now so this is saying index one is found or the number one is found at position one the number two is filter under position two only number three is found at position three that means the alpha here is one and omega is what f plus 2 omega is 2 and so on. Now we can use take here and that gives us these vectors and we can see how where we’re going with this. We can then reverse this and now we just have the problem of the sign so we can take the sign of all of this and we need to stack them on top of each other as well.
So we could mix it like this but there’s a better way but not enclosing them we already get the mix for free and now we just need to get the sign here and then we can make this tacit because it fits very nicely it is the reversal on top of the taking of these two arguments and that gives us our identity matrix. It’s not quite a function yet but we can make it so by combining the key with the indices and now we have our identity matrix generator in a totally obscure way that nobody will be able to understand.
Don’t do this in production code. Let’s make it worse. Let’s start again with this construct and here we are only interested in the right argument so that gives us these vectors of um indices one by itself two beta three beta four by five by itself and remember we used the uh iota underbar the where inverse to generate a boolean array and that has ones in those positions there’s only one position in each one but we can still do this so this gives us these vectors and yes you recognize this remove the enclosure and we’ve got our identity matrix.
We can combine this. We can make the operand test it simply by saying that it’s this where inverse on top of the right argument we have to have that because there’s a left argument as well and so this is our function and that works again don’t do this in production code but it sure is fun to look at.
Then somebody asked during the live chat event if we can’t use complex numbers for this, and of course, we can use complex numbers for this. Okay, let’s get started. So we have these indices, and let’s make a table of complex numbers. So we do the other product of the real part plus the imaginary part, so we multiply the imaginary units with these indices. Oops, there shouldn’t be n here; it should be that, and that gives us a complex number table.
So this is 1 + 1i, 2 + 1i, 1 + 2i, 1 + 3i, next row 2 + 1i, and so on. And now what we need to do is we want to find out the ones that are down the diagonal and both actually down the diagonal. We can kind of see the angle of them, but it also happens to be that in a complex plane, these will have an angle or also known as the argument, which is 45 degrees or a quarter of pi. So we can ask for the argument of that, and we can see that going down the diagonal, they all have that 0.785 and so on. Now we can multiply that by, or rather, sorry, divide pi by that, so the same thing as taking the reciprocal and multiplying by pi, and then you can see that gives four. And now we can say where is 4 equal to that, and that gives us our identity matrix.
So this is our full function. We could either do iota omega here, or we could just use omega and put iota outside that as in the top, and we’ve got our identity matrix producing function here in a terrible way using complex numbers. And as if that wasn’t enough, let’s go in and modify this a bit. Starting again from here with our table of complex numbers, we can also ask what is the absolute value or the magnitude of these numbers. And since they are on the 45-degree angle, that means that the horizontal and vertical parts in this right-angle triangle are equal to each other. That means that the diagonal’s length has to be a multiple of the square root of 2. So we can ask what is the divisional remainder when these numbers are divided by the square root of 2, and if there is no remainder, then we are on the diagonal, so we can compare this with zero, and we get our identity matrix using complex numbers.
That’s enough fun, and what you should do, of course, is use the solution where we take the argument twice, reshape with one plus the argument to take over of and of one, or you can use the tested version where it’s a self-concatenation of the reshape of the incremented number take off one or as a constant, or you can use the sign or the tally if you really want to go there. But these would be the industrial strength versions. You can also go up, and if you don’t like parentheses like I personally don’t do, then you can swap the arguments of this take as well. That’s perfectly acceptable as well. Thank you for watching.