Modifying one line of an array
I just started learning J and there is something I donβt know how to work correctly
Suppose I want to print a 2 character checkerboard like
baba
abab
baba
To do this, I assumed that you can simply create an array
baba
baba
baba
and flip the second line.
Creating an array of very simple 3 4 $ 'ba'
. But reversing the second line is where I am struggling.
I can get a back reference to the second line executing |. 1 { 3 4 $ 'ba'
, but that only gives me the second line, not the whole array. I can't see how to use the J syntax, I can actually keep the top and bottom line and only apply |.
to the middle line.
More generally, how would you apply to |.
just every other line?
source to share
What did you ask
To apply |.
to a single line, try something like:
x =: 3 4 $ 'ba'
(|. 1{x) 1} x
baba
abab
baba
To undo all other lines, I don't know if there is something simpler:
,/ 1 (]`(|."1))\ i. 5 4
0 1 2 3
7 6 5 4
8 9 10 11
15 14 13 12
16 17 18 19
This makes use of a relatively obscure feature in the dyad \ (Infix)
:
x m\ y
applies sequential gerund verbsm
to infixesy
, expanding cyclicallym
as needed.
Here x
is 1, so our infix is ββjust 1 Γ 4 matrices; we loop the gerund ( ] ` (|."1)
) to alternate doing nothing ( ]
) and changing one row of the submatrix ( |."1
). We then flatten the resulting 5 Γ 1 Γ 4 array back to a 5 Γ 4 matrix with ,/
.
Instead, you might want
An easier way to achieve a "checkerboard" is as follows: first, use +/
on two ranges to create a "padding table", for example:
(i.3) +/ (i.4)
0 1 2 3
1 2 3 4
2 3 4 5
Then take all of these mod 2 values ββto get a checkerboard pattern of 0s and 1s:
2 | (i.3) +/ (i.4)
0 1 0 1
1 0 1 0
0 1 0 1
Then index from the select string with {
:
(2 | (i.3) +/ (i.4)) { 'ba'
baba
abab
baba
source to share
Method 1: change }
Replace the second line with the modified line:
( 4 $ 'ab') (1 }) m =: 3 4 $ 'ba'
or in general, replace with a pattern a =: 4 $ 'ab'
for indices i =: +:i.5
:
a i } 10 4 $ 'ba'
Path 2: Gerund Cycling and Cutting ;.
You can cycle verbs by binding them to `. For every other line (rank "1
) you want to either do nothing ]
or reverse |.
:
(]"1)`(|."1) ;.1 m
Method 3: using a different template
You can see your template as 4 $ 'ba'
, followed by its inverse:
3 $ (,:|.) 4 $ 'ba'
By the way,
odd sized (3) even patterned ('ba') lets you simplify |: 4 3 $ 'ba'
.
source to share
Well, you already have many answers, but none of them were the first that popped into my head, so I'll add the following:
0 1 0 |."(0 1) 3 4$'ba'
This takes advantage of the fact that rotating the middle row by 1 looks the same as flipping. You can generalize this by calculating the longest list of 0s and 1s as needed based on the number of lines in your chessboard.
source to share
The approach I would try would not require reversing the rows of the array, but it works by rephrasing the situation in a friendly way.
I would add a column to the array to have columns of an odd number (5) with an even number of elements ('ba'), then remove the last element in each row.
4 5$'ba'
babab
ababa
babab
ababa
}:"1 (4 5$'ba')
baba
abab
baba
abab
source to share