How do I use argument twice in a function in J? - arrays

I want to write prime function for purposes of learning J.
So far I've come up with this:
=&0+/(=&0)(2+i.(-&2)y)|y
It's working great except that I should store number in y variable.
y=.5
=&0+/(=&0)(2+i.(-&2)y)|y NB. prime cheker
1
y=.13
=&0+/(=&0)(2+i.(-&2)y)|y NB. prime cheker
1
y=.14
=&0+/(=&0)(2+i.(-&2)y)|y NB. prime cheker
0
How do I write a function that works what takes argument? i.e. f 13 -> 1

You can just define a verb using : 3.
f =: 3 :'=&0+/(=&0)(2+i.(-&2)y)|y'
f 5
1
f 13
1
f 10
0
When using : 3, y always refers to the right hand argument of the verb.
If you want to define a dyadic verb, use : 4 and x for the left argument.
Btw, you can set the value of a variable anywhere:
=&0+/(=&0)(2+i.(-&2)y)|y=.5
1
=&0+/(=&0)(2+i.(-&2)y)|y=.10
0

You might find the Defining Verbs Guide on the J Wiki useful.
As has already been mentioned you can take your sentence and define it as a verb using the following syntax:
isPrime0=: 3 : '=&0+/(=&0)(2+i.(-&2)y)|y'
However it is probably more natural to write it like this:
isPrime1=: 3 : '0 = (+/ 0 = (2 + i. y - 2) | y)'
You could also define a tacit version (doesn't refer to the arguments) like any of the following:
isPrime2=: 0 = [: +/ 0 = ] |~ 2 + [: i. 2 -~ ]
isPrime3=: 0 = [: +/ 0 = ] |~ 2 + i.#:-&2 NB. replace train with verb composed using conjunctions
isPrime4=: 0 = [: +/ 0 = ] |~ i.&.(-&2) NB. use Under to re-add the 2 after Integers
isPrime5=: 0 -.#e. i.&.(-&2) | ] NB. check no zero in result

Related

Inserting an element into an array in J

What is the best practice for inserting an element into an array at an arbitrary position in J?
I guess this is sort of a double question: my main issue is figuring out how to provide three arguments to the verb I want to create. The gist of the code that I want to write is
insert =. dyad : '(n {. y) , x , (n }. y)'
for a position n. The best solution to this that I can think of is taking a two-length array of boxes as the right argument and the position as the left, but that seems a bit clunky
insert =. dyad : 0
NB. the array to be inserted is the first argument
i =. > {. y
NB. the original array is the second argument
a =. > {: y
(x {. a) , i , (x }. a)
)
EDIT: Furthermore, would it be possible to take an array of indices to insert the item at and an array of items to be inserted at those indices -- i.e. inserting multiple items at a time? It seems to me like this is something J would be good at, but I'm not sure how it would be done.
Boxing the arguments is an often used technique. You can use multiple assignment for cleaner code:
f =: 3 : 0
'arg1 arg2' =: y
)
f (i.5);(i.9) NB. arg1 is i.5, arg2 is i.9
To insert array a at position n in L, you can more compactly write:
n ({., a, }.) L
Another way to insert an element into an array is to fill with #!.. Some examples:
1 1 1j2 1 (#!.999) 1 2 3 4
1 2 3 999 999 4
1j1 1 1j1 1 (#!.999) 1 2 3 4
1 999 2 3 999 4
1 1 0j1 1 (#!.999) 1 2 3 4
1 2 999 4
Depending on your needs, there are many other tricks you can use, like shifting by n n |. and then undoing the shift with dual &.:
a,&. (n |. ]) L
(reply to the comment that got too long)
Both from readability and performance standpoint the two methods are about the same. I would slightly favor the first as more readable but would probably use the second.
You can use timespacex verb to check the performance: eg.
NB. define the different methods
f1 =: 4 :'x ({., a, }.) y
f2 =: 4 :' a,&. (x |. ]) y'
NB. set some parameters
a =: 1000 $ 9
L =: 1e6 $ 5
n =: 333456
NB. check if the too methods give identical results
(n f1 L) -: (n f2 L)
1
NB. iterate 100 times to get performance averages
100 timespacex'n f1 L'
0.00775349 2.09733e7
100 timespacex'n f2 L'
0.00796431 1.67886e7

Octave group statistic computation with accumarray and user defined function returning a third column's value

To be clear the following is not my original problem which has data that is much larger and this code is in the context of a larger application and code base. I have reduced my work to the simplest example that’s now at toy or didactic size for clarity and dev and unit testing because that helps a lot for these purposes as well as for sharing on stackexchange. I am experienced in R but not in octave (Matlab). This is code for octave version 4.0.0. I seem to be stuck on translating group computations such as R’s tapply() or by() as well as writing and calling user defined functions (plus a bit of additional processing than those built-ins), but now written in the octave language.
Starting state is an array a as shown:
a = [5 1 8 0; 2 1 9 0; 2 3 3 0; 5 3 9 0]
a =
5 1 8 0
2 1 9 0
2 3 3 0
5 3 9 0
The process I need to do is essentially just this: Group by column 1, find the min statistic in column 3, return the value stored in column 2 of the same row, and write the value to column 4. I want no optional packages to be used. The built-in accumarray and min functions together get me pretty close but I’ve not found the needed syntax. Matlab seems to have many versions of parameter passing syntaxes developed over different releases and please note my code needs to run in Octave 4.0.0.
Final state desired is same array a, but column 4 is updated as shown:
a =
5 1 8 1
2 1 9 3
2 3 3 3
5 3 9 1
My best few code snippets of near-misses and most interesting things among all my failed attempts (not shown, as there are many pages of attempts that do not work) are:
[x,y] = min(a(a(:,1)==5,3),[],1)
x = 8
y = 1
Notice that y is index of row within the group, but not row within the a array, which is fine and good as long as I later do a computation to translate indexes from group-relative to global-relative, and inside there read the value of a(y,2) which is the correct answer value for each row.
>> [x,y] = min(a(a(:,1)==2,3),[],1)
x = 3
y = 2
>> [~,y] = min(a(a(:,1)==2,3),[],1);
>> y
y = 2
Notice that y is all I need from min() since it’s the index of the row of interest.
>> accumarray(a(:,1), a(:,3), [], #([~,y]=min([],[],1)))
parse error:
syntax error
Notice that with some kind of syntax I need to pass to min() in its first parameter the group of values determined by parameters 1 and 2 of accumarray.
I ultimately need to have something like this happen within the group computations after min() returns row index y:
a(y,4) = a(y,2); % y is the desired row index found by min() within each group
So, I tried to write a function that’s named for possibly simpler syntax:
>> function idx = ccen(d)
[~,y]=min(d,[],1);
idx=a(y,2);
end
>> accumarray(a(:,1), a(:,3), [], #ccen)
error: 'a' undefined near line 3 column 5
error: called from
ccen at line 3 column 4
accumarray at line 345 column 14
Seems to me, that to my surprise, a is not accessible to function ccen. Now what can I do? Thank you for reading.
When declaring functions in MATLAB / Octave, any variables declared outside the scope (by default) are not accessible. This means that even though you have a declaration for a, when you create that function, a is not accessible within the scope of the function.
What you can do is modify ccen so that a is supplied to the function so it can access the variable when the function is being called. After, wrap an anonymous function around your call to ccen when calling accumarray. Anonymous functions however do have the luxury of capturing the scope of variables that aren't explicitly declared as input variables into the function:
So first:
function idx = ccen(a, d) %// Change
[~,y]=min(d,[],1);
idx=a(y,2);
end
And now...
out = accumarray(a(:,1), a(:,3), [], #(x) ccen(a,x)); %// Change last parameter
This call is acceptable because the anonymous function is capturing a at the time of creation. Notice how x in the anonymous function is what is piped in from the accumarray calls. You're simply forwarding that as the second parameter to ccen and keeping a constant. This doesn't change the way the function is being run.... it's just resolving a scope issue.
I get the following in Octave:
octave:10> a = [5 1 8 0; 2 1 9 0; 2 3 3 0; 5 3 9 0]
a =
5 1 8 0
2 1 9 0
2 3 3 0
5 3 9 0
octave:11> function idx = ccen(a,d)
> [~,y]=min(d,[],1);
> idx=a(y,2);
> end
octave:12> out = accumarray(a(:,1), a(:,3), [], #(x) ccen(a,x))
out =
0
1
0
0
1

J and L-systems

I'm going to create a program that can generate strings from L-system grammars.
Astrid Lindenmayer's original L-System for modelling the growth of algae is:
variables : A B
constants : none
axiom : A
rules : (A → AB), (B → A)
which produces:
iteration | resulting model
0 | A
1 | AB
2 | ABA
3 | ABAAB
4 | ABAABABA
5 | ABAABABAABAAB
that is naively implemented by myself in J like this:
algae =: 1&algae : (([: ; (('AB'"0)`('A'"0) #. ('AB' i. ]))&.>"0)^:[) "1 0 1
(i.6) ([;algae)"1 0 1 'A'
┌─┬─────────────┐
│0│A │
├─┼─────────────┤
│1│AB │
├─┼─────────────┤
│2│ABA │
├─┼─────────────┤
│3│ABAAB │
├─┼─────────────┤
│4│ABAABABA │
├─┼─────────────┤
│5│ABAABABAABAAB│
└─┴─────────────┘
Step-by-step illustration:
('AB' i. ]) 'ABAAB' NB. determine indices of productions for each variable
0 1 0 0 1
'AB'"0`('A'"0)#.('AB' i. ])"0 'ABAAB' NB. apply corresponding productions
AB
A
AB
AB
A
'AB'"0`('A'"0)#.('AB' i. ])&.>"0 'ABAAB' NB. the same &.> to avoid filling
┌──┬─┬──┬──┬─┐
│AB│A│AB│AB│A│
└──┴─┴──┴──┴─┘
NB. finally ; and use ^: to iterate
By analogy, here is a result of the 4th iteration of L-system that generates Thue–Morse sequence
4 (([: ; (0 1"0)`(1 0"0)#.(0 1 i. ])&.>"0)^:[) 0
0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0
That is the best that I can do so far. I believe that boxing-unboxing method is insufficient here. This is the first time I've missed linked-lists in J - it's much harder to code grammars without them.
What I'm really thinking about is:
a) constructing a list of gerunds of those functions that build final string (in my examples those functions are constants like 'AB'"0 but in case of tree modeling functions are turtle graphics commands) and evoking (`:6) it,
or something that I am able to code:
b) constructing a string of legal J sentence that build final string and doing (".) it.
But I'm not sure if these programs are efficient.
Can you show me a better approach please?
Any hints as well as comments about a) and b) are highly appreciated!
The following will pad the rectangular array with spaces:
L=: rplc&('A';'AB';'B';'A')
L^:(<6) 'A'
A
AB
ABA
ABAAB
ABAABABA
ABAABABAABAAB
Or if you don't want padding:
L&.>^:(<6) <'A'
┌─┬──┬───┬─────┬────────┬─────────────┐
│A│AB│ABA│ABAAB│ABAABABA│ABAABABAABAAB│
└─┴──┴───┴─────┴────────┴─────────────┘
Obviously you'll want to inspect rplc / stringreplace to see what is happening under the covers.
You can use complex values in the left argument of # to expand an array without boxing.
For this particular L-system, I'd probably skip the gerunds and use a temporary substitution:
to =: 2 : 'n (I.m=y) } y' NB. replace n with m in y
ins =: 2 : '(1 j. m=y) #!.n y' NB. insert n after each m in y
L =: [: 'c'to'A' [: 'A'ins'B' [: 'B'to'c' ]
Then:
L^:(<6) 'A'
A
AB
ABA
ABAAB
ABAABABA
ABAABABAABAAB
Here's a more general approach that simplifies the code by using numbers and a gerund composed of constant functions:
'x'-.~"1 'xAB'{~([:,(0:`(1:,2:)`1:)#.]"0)^:(<6) 1
A
AB
ABA
ABAAB
ABAABABA
ABAABABAABAAB
The AB are filled in at the end for display. There's no boxing here because I use 0 as a null value. These get scattered around quite a bit but the -.~"1 removes them. It does pad all the resulting strings with nulls on the right. If you don't want that, you can use <#-.~"1 to box the results instead:
'x'<#-.~"1 'xAB'{~([:,(0:`(1:,2:)`1:)#.]"0)^:(<6) 1
┌─┬──┬───┬─────┬────────┬─────────────┐
│A│AB│ABA│ABAAB│ABAABABA│ABAABABAABAAB│
└─┴──┴───┴─────┴────────┴─────────────┘

Using bsxfun with an anonymous function

after trying to understand the bsxfun function I have tried to implement it in a script to avoid looping. I am trying to check if each individual element in an array is contained in one matrix, returning a matrix the same size as the initial array containing 1 and 0's respectively. The anonymous function I have created is:
myfunction = #(x,y) (sum(any(x == y)));
x is the matrix which will contain the 'accepted values' per say. y is the input array. So far I have tried using the bsxfun function in this way:
dummyvar = bsxfun(myfunction,dxcp,X)
I understand that myfunction is equal to the handle of the anonymous function and that bsxfun can be used to accomplish this I just do not understand the reason for the following error:
Non-singleton dimensions of the two input arrays must match each other.
I am using the following test data:
dxcp = [1 2 3 6 10 20];
X = [2 5 9 18];
and hope for the output to be:
dummyvar = [1,0,0,0]
Cheers, NZBRU.
EDIT: Reached 15 rep so I have updated the answer
Thanks again guys, I thought I would update this as I now understand how the solution provided from Divakar works. This might deter confusion from others who have read my initial question and are confused to how bsxfun() works, I think writing it out helps me understand it better too.
Note: The following may be incorrect, I have just tried to understand how the function operates by looking at this one case.
The input into the bsxfun function was dxcp and X transposed. The function handle used was #eq so each element was compared.
%%// Given data
dxcp = [1 2 3 6 10 20];
X = [2 5 9 18];
The following code:
bsxfun(#eq,dxcp,X')
compared every value of dxcp, the first input variable, to every row of X'. The following matrix is the output of this:
dummyvar =
0 1 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
The first element was found by comparing 1 and 2 dxcp = [1 2 3 6 10 20]; X' = [2;5;9;18];
The next along the first row was found by comparing 2 and 2 dxcp = [1 2 3 6 10 20]; X' = [2;5;9;18];
This was repeated until all of the values of dxcp where compared to the first row of X'. Following this logic, the first element in the second row was calculating using the comparison between: dxcp = [1 2 3 6 10 20]; X' = [2;5;9;18];
The final solution provided was any(bsxfun(#eq,dxcp,X'),2) which is equivalent to: any(dummyvar,2). http://nf.nci.org.au/facilities/software/Matlab/techdoc/ref/any.html seems to explain the any function in detail well. Basically, say:
A = [1,2;0,0;0,1]
If the following code is run:
result = any(A,2)
Then the function any will check if each row contains one or several non-zero elements and return 1 if so. The result of this example would be:
result = [1;0;1];
Because the second input parameter is equal to 2. If the above line was changed to result = any(A,1) then it would check for each column.
Using this logic,
result = any(A,2)
was used to obtain the final result.
1
0
0
0
which if needed could be transposed to equal
[1,0,0,0]
Performance- After running the following code:
tic
dummyvar = ~any(bsxfun(#eq,dxcp,X'),2)'
toc
It was found that the duration was:
Elapsed time is 0.000085 seconds.
The alternative below:
tic
arrayfun(#(el) any(el == dxcp),X)
toc
using the arrayfun() function (which applies a function to each element of an array) resulted in a runtime of:
Elapsed time is 0.000260 seconds.
^The above run times are averages over 5 runs of each meaning that in this case bsxfun() is faster (on average).
You don't want every combination of elements thrown into your any(x == y) test, you want each element from dxcp tested to see if it exists in X. So here is the short version, which also needs no transposes. Vectorization should also be a bit faster than bsxfun.
arrayfun(#(el) any(el == X), dxcp)
The result is
ans =
0 1 0 0 0 0

Finding ones in an array with J

I will explain my problem in plain English and then show my attempts in J.
Sum the indices of the 1's of a list of 1's and 0's and see if they equal another number.
e.g. given 1 0 1 1 0
the indices are 0,2, and 3, and their sum is 5. So I can then test to see if it quals another number (obviously only true for 5 in this case).
Here's my J:
indexsumtest =: =+/I.
v =: 1 0 1 1 0
5 indexsumtest v
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
What the? Here I assumed indexsumtest was a dyadic verb, maybe I need to explicitly put in x and y?
indexsumtest =: x =+/I. y
5 indexsumtest v
|value error: x
| 5 indexsumtest v
Nope. That made things worse.
So I start from the beginning:
I. v
0 2 3
Correct!
+/I. v
5
Correct again.
5 =+/I. v
1
1 means true. SO I did something right.
Why can't I compact these three operations into a single verb?
It is one that bites everyone now and then and it results because
5 =+/I. v
actually has I. acting on v, then the result is acted on by +/, then that result is tested against 5 using the = comparison. So when we define
indexsumtest =: =+/I.
we get
5 indexsumtest v
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
because indexsumtest has been defined as a tacit verb which processes its arguments as a fork as MPelletier suggested. In other words you actually don't get =+/I. in place of indexsumtest you get (=+/I.) which is a 3 verb fork where the first and third verbs take both arguments and the result of each is sent to the +/ in the centre.
MPelletier also suggests that a tacit form that does what you wanted is
[ = [: +/ [: I. ]
which will work and is actually created by J if you change your definition to 13
indexsumtest =: 13 : 'x =+/I. y'
indexsumtest
[ = [: +/ [: I. ]
Yep, that is right J will actually do most tacit conversions for you if you use the 13 : conjunction to define. Pretty cool, eh? Only problem is that it does not use hooks in this automatic generation, which can simplify the code. A hook is a two verb combination that has the right verb work on the right argument and the result is used as the right argument to the left verb which uses the left argument in the dyadic case (or the original right argument in the monadic case).
When x and y are left and right arguments and u and v are the first and second verbs then
x ( u v) y becomes x u (v y)
or in monadic case
( u v) y becomes y u (v y)
If you are still with me (good for you!) this means that we can use a hook to simplify the tacit if we set u to = and v to +/#I. (the # is a conjunction that joins +/ and I. and makes them work as one verb). So finally
indexsumtacit =: = +/#I.
5 indexsumtacit v
1
As mindbending as J is when you start, it is really neat when you understand the rules that it plays by and then start to get them to do your bidding. Hope this helps.
Consider the classic mean function:
mean =: +/%#
mean i.6
3 part declarations like that operate this way:
# is performed against y
+/ is performed against y
% is performed dyadically against the results of +/ and # in their respective places
The principle is the same with your dyadic function:
I. is performed against x and y
= is performed against x and y
+/ is performed against the results of = and I. in their respective places
So, doing
indexsumtest =: =+/I.
5 indexsumtest 1 0 1 1 0
Is equivalent to
(5 = 1 0 1 1 0) +/ (5 I. 1 0 1 1 0)
Far from what you want.
The simple trick is to define a dyadic function explicitly:
indexsumtest =: 4 : 'x =+/I. y'
J's tacit definition also suggests this:
[ = [: +/ [: I. ]
Which is a bit heavy for my taste.
It is all about how J parses an expression. When J sees a verb, it implicitly adds a parentheses around it. So 5 indexsumtest v is 5 (=+/I.) v; while 5 =+/I. v is actually 5 =+/ (I. v). These two are different as answers above.
I found that it is extremely helpful to understand how J evaluates expressions by reading Appendix 1 of Learning J. This deserves a whole chapter rather than an appendix for any J tutorials.

Resources