Quick followup on previous notes. It's possible to generate a rotation matrix in K without any list appending functions. No idea if it's faster, and don't particularly care, but this way just feels righter.

I rewrote `rots`

to be a matrix of indices that can be projected across a real array, rather than a direct rotation of it. `rots[x;y]`

generates y rows of rightward rotations of a x-sized array. I also made an inclusive `rotsi`

function which leaves the first row unchanged. Maybe that one is easier to visualize.

```
rotsi[5;6]
0 1 2 3 4
4 0 1 2 3
3 4 0 1 2
2 3 4 0 1
1 2 3 4 0
0 1 2 3 4
rots[5;6]
4 0 1 2 3
3 4 0 1 2
2 3 4 0 1
1 2 3 4 0
0 1 2 3 4
4 0 1 2 3
```

`rotsi`

is implemented in terms of `rots`

, which is implemented with the enumeration `!`

operator.

Since the resulting matrix will be y×x items long, it makes sense to begin by enumerating that many.

```
{!x*y}[5;6]
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
```

Then cut it into y rows.

```
{y^!x*y}[5;6]
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
25 26 27 28 29
```

The shape is there. A modulo operation against x will give the indices of 0…x-1. K has a builtin `mod`

function, but it gives me weird errors when currying, so here's my (stackoverflow's) version.

```
md:{y-x*_y%x }
{(md[x])'y^!x*y}[5;6]
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
```

Getting there, just gotta spin it. The order of each row is the same at the moment, but it wouldn't be if we added a different amount to each one before the modulo. There are six rows, so what about adding 0…5?

```
{(md[x])'(!y)+y^!x*y}[5;6]
0 1 2 3 4
1 2 3 4 0
2 3 4 0 1
3 4 0 1 2
4 0 1 2 3
0 1 2 3 4
```

Almost. Would work if the matrix were a perfect square. Try it with a larger offset of 1…6.

```
{(md[x])'(1+!y)+y^!x*y}[5;6]
1 2 3 4 0
2 3 4 0 1
3 4 0 1 2
4 0 1 2 3
0 1 2 3 4
1 2 3 4 0
```

Definitely spinning now, just not in the right order. Generalized, we need to add an iteration vector of the difference between x and y to apply the correct offset.

```
{(md[x])'((x-y)+!y)+y^!x*y}[5;4]
1 2 3 4 0
2 3 4 0 1
3 4 0 1 2
4 0 1 2 3
```

Reversing this offset vector changes the rotation direction.

```
rots:{(md[x])'(|(x-y)+!y)+y^!x*y};rots[5;6]
4 0 1 2 3
3 4 0 1 2
2 3 4 0 1
1 2 3 4 0
0 1 2 3 4
4 0 1 2 3
```

The inclusive rotation matrix is self-explanatory.

```
rotsi:{(,!x),rots[x;y-1]};rotsi[5;6]
0 1 2 3 4
4 0 1 2 3
3 4 0 1 2
2 3 4 0 1
1 2 3 4 0
0 1 2 3 4
```

- The order of arguments should be flipped to allow for better currying.
- Both left/right rotations can be implemented from a cross summation of arrays
`+/:\:`

`rots`

and`rotsi`

should be general functions where a negative x rotates left, and a positive right.- There should be a direct array rotation function
`rot`

.

Observe.

```
rotsli:{md[y]'(!x)+/:\:!y}
rotsl:{1_rotsli[x+1;y]}
rotsr:{md[y]'(|(y-x)+!x)+/:\:!y}
rotsri:{(,!y),rotsr[x-1;y]}
rots:{$[x<0;rotsl[abs x;y];rotsr[x;y]]}
rotsi:{$[x<0;rotsli[abs x;y];rotsri[x;y]]}
rot:{y[,/((abs x)-1)_(rots[x;#y])]}
rotsi[-8;5]
0 1 2 3 4
1 2 3 4 0
2 3 4 0 1
3 4 0 1 2
4 0 1 2 3
0 1 2 3 4
1 2 3 4 0
2 3 4 0 1
rotsi[8;5]
0 1 2 3 4
4 0 1 2 3
3 4 0 1 2
2 3 4 0 1
1 2 3 4 0
0 1 2 3 4
4 0 1 2 3
3 4 0 1 2
xs:"hello"
rot[-1;xs]
"elloh"
rot[1;xs]
"ohell"
```

See my kool repo for these procedures, among others.