问题
I've only just started learning J and there's something I have no idea how to do properly
Suppose i want to print a checkerboard of 2 symbols, for example
baba
abab
baba
To do this, I assumed you could just generate an array
baba
baba
baba
and reverse the second line.
Generating the array is easy: 3 4 $ 'ba'
. But reversing the second row is where I struggle.
I can get the reverse of the second row doing |. 1 { 3 4 $ 'ba'
but that only gives me the second row, not the entire array. I don't see how using J syntax I can actually keep the top and bottom row and only apply |.
to the middle row.
More generally, how would you apply |.
only every other row?
回答1:
What you asked
To apply |.
to one row, try something like:
x =: 3 4 $ 'ba'
(|. 1{x) 1} x
baba
abab
baba
To reverse every other row, I don't know if there's something simpler than this:
,/ 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 uses a relatively obscure feature of the dyad \ (Infix)
:
x m\ y
applies successive verbs from the gerundm
to the infixes ofy
, extendingm
cyclically as required.
Here, x
is 1, so our "infixes" are just 1×4 matrices; we cycle through a gerund (] ` (|."1)
) to alternate between doing nothing (]
) and reversing the single row of the submatrix (|."1
). Then, we flatten the resulting 5×1×4 array back to a 5×4 matrix with ,/
.
What you maybe want instead
A much simpler way to achieve a "checkerboard" is as follows: first, use +/
on two ranges to create an "addition table", like so:
(i.3) +/ (i.4)
0 1 2 3
1 2 3 4
2 3 4 5
Then take all of these values mod 2, 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 a string of choice with {
:
(2 | (i.3) +/ (i.4)) { 'ba'
baba
abab
baba
回答2:
Way 1: Amending }
Replace the second line with the changed line:
( 4 $ 'ab') (1 }) m =: 3 4 $ 'ba'
or generally, replace with pattern a =: 4 $ 'ab'
, at indices i =: +:i.5
:
a i } 10 4 $ 'ba'
Way 2: Cycling with gerund and cut ;.
You can cyclically apply verbs by tying them with `. For every other row (rank "1
) you want to either do nothing ]
or reverse |.
:
(]"1)`(|."1) ;.1 m
Way 3: Using a different pattern
You can see your pattern as 4 $ 'ba'
followed by its inverse:
3 $ (,:|.) 4 $ 'ba'
Incidentally,
having an odd dimension (3) with an even pattern ('ba') allows you the simpler |: 4 3 $ 'ba'
.
回答3:
Well, you already have a lot of answers, but none of them was the first thing that popped into my head, so I'll add this one:
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 it. You can generalize this by computing as long a list of 0 and 1 as you need based on the number of rows in your checkerboard.
回答4:
The approach that I would try would not require reversing lines of the array, but works by reframing the situation in a J friendly way.
I would add a column to the array so that I have an odd number columns (5) with an even number of elements ('ba'), then strip off the last item in each row.
4 5$'ba'
babab
ababa
babab
ababa
}:"1 (4 5$'ba')
baba
abab
baba
abab
回答5:
Here's yet another way of re-framing this specific problem in a "J friendly way", as bob put it. It doesn't "modify one row" but achieves the desired result in a different way.
|: 4 3 $ 'ba' NB. transpose a 4x3 matrix
baba
abab
baba
来源:https://stackoverflow.com/questions/31339471/modifying-one-row-of-an-array