Finding the minimum integer satisfying a predicate - search

Is there a good way of finding the smallest integer (starting zero) that satisfies a given predicate in J ?

This is what infinite power with a right verb is for (^:v^:_). For example, find the first integer divisible by 7.
check =: 0 ~: 7 | ] NB. check if y is not a multiple of 7
(>:^:check)^:_ ] 1 NB. increment y (1) while check is true
7
A second point is that if you are searching in an array, you can use the special code f i. 1: (first place where x f y). See: http://www.jsoftware.com/help/release/edot504.htm

Eelvex's answer may be what you are looking for, but one way to read your question is what is the minimum integer greater than 0 in a list. These functions return index of first conditional minimum.
(i. <./) _"_^:(<&0)("0) _3 _1 3 4 2
4
minatleast =: (i. <./)#]#:(_"_^:>("0))
0 minatleast _3 _1 3 4 2
4
3 minatleast _3 _1 3 4 2
2

Related

different result once square root is added inside tacit

Very new to J. I love it but still far from fluent in it.
I have managed to hit an issue and I don't know why it is happening. If somebody could please explain why this is occuring I could learn more about this straight-to-the-point language.
Basically I'm doing difference (-) then squared (*:) then sum (+/) then want to take the square root (%:).
Now the sum square error part ( (+/#:*:#:-) ) works fine:
1 2 3 4 5 (+/#:*:#:-) 2 2 2 2 2
15
Then I can get the square root this way (just add %: to left):
%: 1 2 3 4 5 (+/#:*:#:-) 2 2 2 2 2
3.87298
But when I add square root to left of the atco (tacit?) part in the middle it doesn't give me the right result:
1 2 3 4 5 (%:#:+/#:*:#:-) 2 2 2 2 2
1.57001
It instead returns 1.57001 instead of 3.87298.
My understanding is all I have done is add a 'then do square root' but obviously I am wrong. But I don't understand why.
When I dissect:
require 'debug/dissect'
dissect '1 2 3 4 5 (%:#:+/#:*:#:-) 2 2 2 2 2'
I see diff (-) and square (*:) are in their own dissect boxes. But then the last box combines sum (+/) and square root (%:) together, showing %:#:+/ . Not a separate box for +/ and then %: .
As I said I am new to J and am struggling to understand why this is occuring here.
I've tried changing to &, &: and # instead but as expected that didn't fix this issue.
It doesn't appear to be due to some composition limit either since this works fine (has many more atco's combined):
(>:#:>:#:>:#:>:#:>:#:>:#:>:#:>:#:>:) 2 2 2
11 11 11
Thank you
The issue that you are encountering is that
(%:#:+/#:*:#:-)
is being evaluated as
1 2 3 4 5 ((%:#:+)/#:*:#:-) 2 2 2 2 2
1.57001
and not
1 2 3 4 5 %:#:(+/#:*:#:-) 2 2 2 2 2
3.87298
because of the way that conjunctions take as much of the left operand as possible. This means that your partial result from *:#:- is being processed by %:#:+/ when you want %: to apply to the result of +/#:*:#:-
Since you are just starting your journey with J, this may be a bit advanced, but at some point you may want to read the tacit programming section of J for C programmers by Henry Rich. It has a very good explanation about how J sentences are parsed. Parenthesis are your friend when you want to change the order of execution. https://www.jsoftware.com/help/jforc/contents.htm#_Toc191734581
Edit: As #Eelvex points out in the comment below the break actually occurs at (+/), but the result is the same because of the way that conjunctions are evaluated left to right.
You are trying to form a dyadic verb for the expression:
%: +/ *: x - y NB. which we can write as
f g h x - y NB. if we define:
f =: %:
g =: +/
h =: *:
f g h x - y
3.87298
One way of making this a dyadic verb is to apply #: everywhere:
x (f#:g#:h#:-) y
3.87298
x (%: #: (+/) #: *: #: -) y
3.87298
A more idiomatic way of doing it uses under (&.) which inverses a verb after applying another:
f &.: g y NB. expands to
(g-inverse) f g y
g &.: h (x - y)
3.87298
x ( g &.: h #: -) y
3.87298
NB. or if you prefer monadic verbs:
(g &.: h #: -/) x,: y

Sum of arrays with repeated indices

How can I add an array of numbers to another array by indices? Especially with repeated indices. Like that
x
1 2 3 4
idx
0 1 0
y
5 6 7
] x add idx;y NB. (1 + 5 + 7) , (2 + 6) , 3 , 4
13 8 3 4
All nouns (x, idx, y) can be millions of items and I need to fast 'add' verb.
UPDATE
Solution (thanks to Dan Bron):
cumIdx =: 1 : 0
:
'i z' =. y
n =. ~. i
x n}~ (n{x) + i u//. z
)
(1 2 3 4) + cumIdx (0 1 0);(5 6 7)
13 8 3 4
For now, a short answer in the "get it done" mode:
data =. 1 2 3 4
idx =. 0 1 0
updat =. 5 6 7
cumIdx =: adverb define
:
n =. ~. m
y n}~ (n{y) + m +//. x
)
updat idx cumIdx data NB. 13 8 3 4
In brief:
Start by grouping the update array (in your post, y¹) where your index array has the same value, and taking the sum of each group
Accomplish this using the adverb key (/.) with sum (+/) as its verbal argument, deriving a dyadic verb whose arguments are idx on the left and the update array (your y, my updat) on the right.
Get the nub (~.) of your index array
Select these (unique) indices from your value array (your x, my data)
This will, by definition, have the same length as the cumulative sums we calculated in (1.)
Add these to the cumulative sum
Now you have your final updates to the data; updat and idx have the same length, so you just merge them into your value array using }, as you did in your code
Since we kept the update array small (never greater than its original length), this should have decent performance on larger inputs, though I haven't run any tests. The only performance drawback is the double computation of the nub of idx (once explicitly with ~. and once implicitly with /.), though since your values are integers, this should be relatively cheap; it's one of J's stronger areas, performance-wise.
¹ I realize renaming your arrays makes this answer more verbose than it needs to be. However, since you named your primary data x rather than y (which is the convention), if I had just kept your naming convention, then when I invoked cumIdx, the names of the nouns inside the definition would have the opposite meanings to the ones outside the definition, which I thought would cause greater confusion. For this reason, it's best to keep "primary data" on the right (y), and "control data" on the left (x).You might also consider constraining your use of the special names x,y,u,v,m and n to where they're already implicitly defined by invoking an explicit definition; definitely never change their nameclasses.
This approach also uses key (/.) but is a bit more simplistic in its approach.
It is likely to use more space especially for big updates than Dan Bron's.
addByIdx=: {{ (m , i.## y) +//. x,y }}
updat idx addByIdx data
13 8 3 4

Modifying one row of an array

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?
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
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'.
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.
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
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

How to filter a list in J?

I'm currently learning the fascinating J programming language, but one thing I have not been able to figure out is how to filter a list.
Suppose I have the arbitrary list 3 2 2 7 7 2 9 and I want to remove the 2s but leave everything else unchanged, i.e., my result would be 3 7 7 9. How on earth do I do this?
The short answer
2 (~: # ]) 3 2 2 7 7 2 9
3 7 7 9
The long answer
I have the answer for you, but before you should get familiar with some details. Here we go.
Monads, dyads
There are two types of verbs in J: monads and dyads. The former accept only one parameter, the latter accept two parameters.
For example passing a sole argument to a monadic verb #, called tally, counts the number of elements in the list:
# 3 2 2 7 7 2 9
7
A verb #, which accepts two arguments (left and right), is called copy, it is dyadic and is used to copy elements from the right list as many times as specified by the respective elements in the left list (there may be a sole element in the list also):
0 0 0 3 0 0 0 # 3 2 2 7 7 2 9
7 7 7
Fork
There's a notion of fork in J, which is a series of 3 verbs applied to their arguments, dyadically or monadically.
Here's the diagram of a kind of fork I used in the first snippet:
x (F G H) y
G
/ \
F H
/ \ / \
x y x y
It describes the order in which verbs are applied to their arguments. Thus these applications occur:
2 ~: 3 2 2 7 7 2 9
1 0 0 1 1 0 1
The ~: (not equal) is dyadic in this example and results in a list of boolean values which are true when an argument doesn't equal 2. This was the F application according to diagram.
The next application is H:
2 ] 3 2 2 7 7 2 9
3 2 2 7 7 2 9
] (identity) can be a monad or a dyad, but it always returns the right argument passed to a verb (there's an opposite verb, [ which returns.. Yes, the left argument! :)
So far, so good. F and H after application returned these values accordingly:
1 0 0 1 1 0 1
3 2 2 7 7 2 9
The only step to perform is the G verb application.
As I noted earlier, the verb #, which is dyadic (accepts two arguments), allows us to duplicate the items from the right argument as many times as specified in the respective positions in the left argument. Hence:
1 0 0 1 1 0 1 # 3 2 2 7 7 2 9
3 7 7 9
We've just got the list filtered out of 2s.
Reference
Slightly different kind of fork, hook and other primitves (including abovementioned ones) are described in these two documents:
A Brief J Reference (175 KiB)
Easy-J. An Introduction to the World's most Remarkable Programming Language (302 KiB)
Other useful sources of information are the Jsoftware site with their wiki and a few mail list archives in internets.
Just to be sure it's clear, the direct way - to answer the original question - is this:
3 2 2 7 7 2 9 -. 2
This returns
3 7 7 9
The more elaborate method - generating the boolean and using it to compress the vector - is more APLish.
To answer the other question in the very long post, to return the first element and the number of times it occurs, is simply this:
({. , {. +/ .= ]) 1 4 1 4 2 1 3 5
1 3
This is a fork using "{." to get the first item, "{. +/ . = ]" to add up the number of times the first item equals each element, and "," as the middle verb to concatenate these two parts.
Also:
2 ( -. ~ ]) 3 2 2 7 7 2 9
3 7 7 9
There are a million ways to do this - it bothers me, vaguely, that these these things don't evaluate strictly right to left, I'm an old APL programmer and I think of things as right to left even when they ain't.
If it were a thing that I was going to put into a program where I wanted to pull out some number and the number was a constant, I would do the following:
(#~ 2&~:) 1 3 2 4 2 5
1 3 4 5
This is a hook sort of thing, I think. The right half of the expression generates the truth vector regarding which are not 2, and then the octothorpe on the left has its arguments swapped so that the truth vector is the left argument to copy and the vector is the right argument. I am not sure that a hook is faster or slower than a fork with an argument copy.
+/3<+/"1(=2&{"1)/:~S:_1{;/5 6$1+i.6
156
This above program answers the question, "For all possible combinations of Yatzee dice, how many have 4 or 5 matching numbers in one roll?" It generates all the permutations, in boxes, sorts each box individually, unboxing them as a side effect, and extracts column 2, comparing the box against their own column 2, in the only successful fork or hook I've ever managed to write. The theory is that if there is a number that appears in a list of 5, three or more times, if you sort the list the middle number will be the number that appears with the greatest frequency. I have attempted a number of other hooks and/or forks and every one has failed because there is something I just do not get. Anyway that truth table is reduced to a vector, and now we know exactly how many times each group of 5 dice matched the median number. Finally, that number is compared to 3, and the number of successful compares (greater than 3, that is, 4 or 5) are counted.
This program answers the question, "For all possible 8 digit numbers made from the symbols 1 through 5, with repetition, how many are divisible by 4?"
I know that you need only determine how many within the first 25 are divisible by 4 and multiply, but the program runs more or less instantly. At one point I had a much more complex version of this program that generated the numbers in base 5 so that individual digits were between 0 and 4, added 1 to the numbers thus generated, and then put them into base 10. That was something like 1+(8$5)#:i.5^8
+/0=4|,(8$10)#. >{ ;/ 8 5$1+i.5
78125
As long as I have solely verb trains and selection, I don't have a problem. When I start having to repeat my argument within the verb so that I'm forced to use forks and hooks I start to get lost.
For example, here is something I can't get to work.
((1&{~+/)*./\(=1&{))1 1 1 3 2 4 1
I always get Index Error.
The point is to output two numbers, one that is the same as the first number in the list, the second which is the same as the number of times that number is repeated.
So this much works:
*./\(=1&{)1 1 1 3 2 4 1
1 1 1 0 0 0 0
I compare the first number against the rest of the list. Then I do an insertion of an and compression - and this gives me a 1 so long as I have an unbroken string of 1's, once it breaks the and fails and the zeros come forth.
I thought that I could then add another set of parens, get the lead element from the list again, and somehow record those numbers, the eventual idea would be to have another stage where I apply the inverse of the vector to the original list, and then use $: to get back for a recursive application of the same verb. Sort of like the quicksort example, which I thought I sort of understood, but I guess I don't.
But I can't even get close. I will ask this as a separate question so that people get proper credit for answering.

J # not working as expected

I'm just starting to try to pick up the J language, and am confused by the following:
1 2 +/#{ i.4
1 2
+/ 1 2 { i.4
3
when in the documentation for # it says: "x u#v y ↔ u x v y"
I assume I'm just mistaking one part of speech for another, but can't figure it out
also, how do I tell what type of speech a name is?
NB. u b. 0 returns the rank of u
NB. the rank of a verb determines the arguments it applies to at a time
NB. monadic + y applies to atoms; dyadic x + y applies to pairs of atoms
+ b. 0
0 0 0
NB. monadic +/ y and dyadic x +/ y apply to anything (unbounded rank)
+/ b. 0
_ _ _
NB. monadic { y applies to arrays of atoms;
NB. dyadic x { y applies to pairs of atoms and anything
{ b. 0
1 0 _
NB. u # v has the rank of v
+/#{ b. 0
1 0 _
NB. since 1 2 { i.4 returns atoms at a time, +/ works on atoms
+/"0 [ 1 2 { i.4
1 2
NB. u #: v has unbounded rank
+/#:{ b. 0
_ _ _
NB. +/ applies to all of 1 2 { i.4 at once
+/"_ [ 1 2 { i.4
3
NB. mechanical translation to tacit form
13 : '+/ x { y'
[: +/ {
Wikipedia has, in my biased opinion, a decent writeup on rank, and what it means in the context of the different parts of "speech" in J.
But to answer the original question, J's trace facility can be useful for understanding how its grammar works:
require'trace'
trace '1 2 +/#{ i.4'
This will take you step by step through the parsing process, showing the words being consumed by each production rule and the result each generates.
Ah, I think I may have figured it out, I need to use #: instead of #
1 2 +/#:{ i.4
3
which is what I wanted. Guess I'm going to have to read up some more on rank, which is the only difference between # and #:

Resources