Modifying one row of an array

荒凉一梦 提交于 2019-12-12 12:33:44

问题


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 gerund m to the infixes of y, extending m 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!