Most concise J syntax for creating a numeric matrix - j

Imagine that I want to take the numbers from 1 to 3 and form a matrix such that each possible pairing is represented, e.g.,
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Here is the monadic verb I formulated in J to do this:
($~ (-:## , 2:)) , ,"0/~ 1+i.y
Originally I had thought that ,"0/~ 1+i.y would be sufficient, but unfortunately that produces the following output:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
In other words, its shape is 3 3 2 and I want something whose shape is 9 2. The only way I could think of to fix it is to pour all of the data into a new shape. I'm convinced there must be a more concise way to do this. Anyone know?

Reshaping your intermediate result can be simplified. Removing the topmost axis is commonly done with ,/ so in your case the completed phrase could be ,/ ,"0/~ 1+i.y

One way (which uses { as a monad in its capacity for permutation cataloguing):
>,{ 2#<1+i.y
EDIT:
Some fun to be had with this scheme:
All possible permutations:
>,{ y#<1+i.y
Configurable number in sequence:
>,{ x#<1+i.y

I realize this question is old, but there is a simpler way to do it: count to 9 in trinary, and add 1.
1 + 3 3 #: i.9
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
The 3 3 & #: gives you two digits. The general 'base 3' verb is 3 & #.^:_1.

Related

Average from different columns in shell script

I have a datafile with 10 columns as given below
ifile.txt
2 4 4 2 1 2 2 4 2 1
3 3 1 5 3 3 4 5 3 3
4 3 3 2 2 1 2 3 4 2
5 3 1 3 1 2 4 5 6 8
I want to add 11th column which will show the average of each rows along 10 columns. i.e. AVE(2 4 4 2 1 2 2 4 2 1) and so on. Though my following script is working well, but I would like to make it more simpler and short. I appreciate, in advance, for any kind help or suggestions in this regard.
awk '{for(i=1;i<=NF;i++){s+=$i;ss+=$i}m=s/NF;$(NF+1)=ss/NF;s=ss=0}1' ifile.txt
This should work
awk '{for(i=1;i<=NF;i++)x+=$i;$(NF+1)=x/NF;x=0}1' file
For each field you add the value to x in the loop.
Next you set field 11 to the sum in xdivided by the number of fields NF.
Reset x to zero for the next line.
1 equates to true and performs the default action in awk which is to print the line.
is this helping
awk '{for(i=1;i<=NF;i++)s+=$i;print $0,s/NF;s=0}' ifile.txt
or
awk '{for(i=1;i<=NF;i++)ss+=$i;$(NF+1)=ss/NF;ss=0}1' ifile.txt

How to remove an element from a list in J by index?

The rather verbose fork I came up with is
({. , (>:#[ }. ]))
E.g.,
3 ({. , (>:#[ }. ])) 0 1 2 3 4 5
0 1 2 4 5
Works great, but is there a more idiomatic way? What is the usual way to do this in J?
Yes, the J-way is to use a 3-level boxing:
(<<<5) { i.10
0 1 2 3 4 6 7 8 9
(<<<1 3) { i.10
0 2 4 5 6 7 8 9
It's a small note in the dictionary for {:
Note that the result in the very last dyadic example, that is, (<<<_1){m , is all except the last item.
and a bit more in Learning J: Chapter 6 - Indexing: 6.2.5 Excluding Things.
Another approach is to use the monadic and dyadic forms of # (Tally and Copy). This idiom of using Copy to remove an item is something that I use frequently.
The hook (i. i.##) uses Tally (monadic #) and monadic and dyadic i. (Integers and Index of) to generate the filter string:
2 (i. i.##) 'abcde'
1 1 0 1 1
which Copy (dyadic #) uses to omit the appropriate item.
2 ((i. i.##) # ]) 0 1 2 3 4 5
0 1 3 4 5
2 ((i. i.##) # ]) 'abcde'
abde

how find unique value from Different column

A B ANSWER
1 1 1
3 3 3
1 2 1
2 4 2
4 4 4
5 5 5
6 6 6
i have used this function to get above answer "=IF(ISERROR(MATCH(A2:A8,$B$1:$B$8,0)),"",A2)"
but I need answer like this i have given below (suppose if you take value in A column "1"
Which is repeated only once in column B)
A B ANR
1 1 1
3 3 3
1 2 0
2 4 2
4 4 4
5 5 5
6 6 6
I've just wrapped your formula in a condition that returns 0 where the count of the A value from start to the current row is more than one:
=IF(COUNTIF(A$1:A2,A2)>1,0,IF(ISERROR(MATCH(A2:A8,$B$1:$B$8,0)),"",A2))
.
An alternative formula that gives the same results as above for the sample data provided but may (or may not) suit the additional requirements mentioned in a comment:
=IF(COUNTIF(A$2:A$10,A2)<=COUNTIF(B$2:B$10,A2),A2,IF(COUNTIF(A$2:A2,A2)>COUNTIF(B$2:B$10,A2),0,IF(COUNTIF(A$2:A$10,A2)>COUNTIF(B$2:B2,A2),A2,0)))

How can I implement a grouping algorithm in J?

I'm trying to implement A006751 in J. It's pretty easy to do in Haskell, something like:
concat . map (\g -> concat [show $ length g, [g !! 0]]) . group . show
(Obviously that's not complete, but it's the basic heart of it. I spent about 10 seconds on that, so treat it accordingly.) I can implement any of this fairly easily in J, but the part that eludes me is a good, idiomatic J algorithm that corresponds to Haskell's group function. I can write a clumsy one, but it doesn't feel like good J.
Can anyone implement Haskell's group in good J?
Groups are usually done with the /. adverb.
1 1 2 1 </. 'abcd'
┌───┬─┐
│abd│c│
└───┴─┘
As you can see, it's not sequential. Just make your key sequential like so (essentially determining if an item is different from the next, and do a running sum of the resulting 0's and 1's):
neq =. 13 : '0, (}. y) ~: (}: y)'
seqkey =. 13 : '+/\neq y'
(seqkey 1 1 2 1) </. 'abcd'
┌──┬─┬─┐
│ab│c│d│
└──┴─┴─┘
What I need then is a function which counts the items (#), and tells me what they are ({. to just pick the first). I got some inspiration from nubcount:
diffseqcount =. 13 : ',(seqkey y) (#,{.)/. y'
diffseqcount 2
1 2
diffseqcount 1 2
1 1 1 2
diffseqcount 1 1 1 2
3 1 1 2
If you want the nth result, just use power:
diffseqcount(^:10) 2 NB. 10th result
1 3 2 1 1 3 2 1 3 2 2 1 1 3 3 1 1 2 1 3 2 1 2 3 2 2 2 1 1 2
I agree that /. ( Key ) is the best general method for applying verbs to groups in J. An alternative in this case, where we need to group consecutive numbers that are the same, is dyadic ;. (Cut):
1 1 0 0 1 0 1 <(;.1) 3 1 1 1 2 2 3
┌─┬─────┬───┬─┐
│3│1 1 1│2 2│3│
└─┴─────┴───┴─┘
We can form the frets to use as the left argument as follows:
1 , 2 ~:/\ 3 1 1 1 2 2 3 NB. inserts ~: in the running sets of 2 numbers
1 1 0 0 1 0 1
Putting the two together:
(] <;.1~ 1 , 2 ~:/\ ]) 3 1 1 1 2 2 3
┌─┬─────┬───┬─┐
│3│1 1 1│2 2│3│
└─┴─────┴───┴─┘
Using the same mechanism as suggested previously:
,#(] (# , {.);.1~ 1 , 2 ~:/\ ]) 3 1 1 1 2 2 3
1 3 3 1 2 2 1 3
If you are looking for a nice J implementation of the look-and-say sequence then I'd suggest the one on Rosetta Code:
las=: ,#((# , {.);.1~ 1 , 2 ~:/\ ])&.(10x&#.inv)#]^:(1+i.#[)
5 las 1 NB. left arg is sequence length, right arg is starting number
11 21 1211 111221 312211

Force array instead of matrix in J for "i."

The i. primitive produces a list of integers:
i. 10
0 1 2 3 4 5 6 7 8 9
If I want to produce several short lists in a row, I do this:
;i."0 each [ 2 3 4
0 1 0 1 2 0 1 2 3
(the result I want)
Boxing (that each) is a crutch here, because without it, i."0 produces a matrix.
i."0 [ 2 3 4
0 1 0 0
0 1 2 0
0 1 2 3
(the result I don't want)
Is there a better way to not have i."0 format the output to a matrix, but an array?
No, I believe you can't do any better than your current solution. There is no way for i."0 to return a vector.
The "0 adverb forces i. to accept scalars, and i. returns vectors. i. has no way of knowing that your input was a vector rather than a scalar. According to The J primer the result shape is the concatenation of the frame of the argument and the result.
The shortest "box-less" solution I've found so far is
(*#$"0~#&,i."0) 2 3 4
which is still longer than just using ;i. each 2 3 4

Resources