A couple of J tests for Claude and Gemini

30 views
Skip to first unread message

Devon McCormick

unread,
Jun 24, 2026, 11:51:32 PM (13 days ago) Jun 24
to fo...@jsoftware.com
I tested both Claude and Gemini with the same questions.  One was simple: "What is the J code for calculating the average of a list of numbers?"  This was followed by "How would I apply this code to a matrix of numbers to get the average of each column?".

Both got the first one with the expected standard J expression, which is not surprising because this may be the most common J expression floating around the web.  On the second, Claude was better than Gemini which seemed confused by applying the expression on rank 1 for columns.  However, Claude started this way, then corrected itself.

The second question was more involved but it was something I solved years ago in APL: "In J, if I have two 2-column tables of integers where the first column is the start of an interval and the second column is the end of an interval, how would I produce a matrix showing how much each interval in the first table overlaps with each interval in the second table?  Bonus points if, for intervals with no overlap, we get a negative number showing the shortest gap between the two intervals."

Gemini basically failed and Claude did OK but was tripped up by the assumption that the start of an interval is always less than the end of an interval.  This tripped me up too when I first wrote this but I subsequently accounted for it by cleaning my input data.

The Claude code basically worked, sans the tricky case, but was not terribly idiomatic and exhibited the same sort of false start as in the follow up to the first question.  Here is what it ended up with after it cleaned up its original try:
Final Working Version
j
A =: 3 2 $ 1 5  3 8  10 15
B =: 3 2 $ 2 6  4 7  12 20

NB. Overlap of two intervals (2-element vectors): min(ends) - max(starts)
NB. Positive = overlap amount, negative = gap
ov =: 4 : '(<./ (1{x),(1{y)) - (>./ (0{x),(0{y))'

NB. Outer table: every row of A against every row of B
result =: A ov"1 1/ B

I will leave my version as an exercise for the reader.  Here was my test input with a couple of tricky intervals that end before they start:
   A=. 1 2,2 3,1 5,0 _1,4 6,:9 3
   B=. 0 10,5 6,3 1,2 3,:_3 _1

 
Regards,

Devon

Devon McCormick


David C. Salthouse

unread,
Jun 25, 2026, 3:52:49 AM (13 days ago) Jun 25
to fo...@jsoftware.com
Here is what my Gem gave me. Running with my Gemini pro account.

What is the J code for calculating the average of a list of numbers?"  This was followed by "How would I apply this code to a matrix of numbers to get the average of each column?".
Modified to "Write  J code for calculating the average of a list of numbers and  apply this code to a matrix of numbers to get the average of each column?".

calcAverage =: 3 : 0
  NB. Calculate the arithmetic mean of a list or column averages of a matrix
  NB. DCS dev 20260625
  NB.
  NB. HELP: calcAverage y
  NB. y : A numeric list (vector) or a numeric matrix.
  NB.     If y is a matrix, returns the average of each column.
 
  t_start =. 6 !: 1 ''                NB. Start Timing
  smoutput '>>> PROCESS START: calcAverage'
  smoutput '>>> LOG: Executing array-oriented mean fork (+/ % #)'

  NB. 1. Localize and Extract
  data =. y
  mean_verb =. +/ % #
 
  NB. 2. Core Processing Logic
  NB. J automatically applies +/ across the items of the array.
  NB. For a matrix, the items are rows, meaning they are summed downwards,
  NB. resulting in a vector of column sums before dividing by the tally of rows.
  res =. mean_verb data
 
  NB. 3. Output / Return Results
  smoutput 'Results:'
  smoutput res
 
  t_end =. 6 !: 1 ''                  NB. End Timing
  smoutput '>>> LOG: Execution Time: ', (": t_end - t_start), 's'
  smoutput '>>> PROCESS END: calcAverage'
 
  res
)
NB. end of function calcAverage

NB. =================================================================
NB. GLOSSARY OF J PRIMITIVES AND TRAINS
NB. =================================================================
NB. +/ (Insert / Sum)
NB. Valence: Monad (derived from the Adverb / applied to the Verb +)
NB. Mechanics: Inserts the plus verb between items of the array.
NB. Example: +/ 1 2 3 4
NB. Result:  10
NB.
NB. % (Divide)
NB. Valence: Dyad
NB. Mechanics: Standard arithmetic division.
NB. Example: 10 % 2
NB. Result:  5
NB.
NB. # (Tally)
NB. Valence: Monad
NB. Mechanics: Returns the number of items in the array (length of list, or rows in matrix).
NB. Example: # 10 20 30
NB. Result:  3
NB.
NB. +/ % # (Fork - Mean)
NB. Valence: Monadic Train (Verb Verb Verb)
NB. Mechanics: Passes the argument to the outer tines (+/ and #), then applies the middle tine (%) to those results.
NB. Example: (+/ % #) 2 4 6
NB. Result:  4 (Evaluates as: (+/ 2 4 6) % (# 2 4 6) -> 12 % 3 -> 4)
NB. =================================================================

NB. =================================================================
NB. USAGE AND EDGE CASE TESTS
NB. =================================================================
NB. Test 1: Standard List
NB. calcAverage 10 20 30 40
NB. Expected Result: 25

NB. Test 2: Matrix (Column Averages)
NB. 3 4 $ 1 2 3 4 5 6 7 8 9 10 11 12 creates a 3x4 matrix.
NB. calcAverage 3 4 $ 1 2 3 4 5 6 7 8 9 10 11 12
NB. Expected Result: 5 6 7 8

NB. Test 3: Single Item Vector
NB. ,5 forces the atom 5 to be a list.
NB. calcAverage ,5
NB. Expected Result: 5

NB. Test 4: Matrix containing Negatives and Floats
NB. calcAverage 2 2 $ _1.5 2.5 _3.5 4.5
NB. Expected Result: _2.5 3.5
NB. =================================================================

David C. Salthouse  


To unsubscribe from this group and stop receiving emails from it, send an email to forum+un...@jsoftware.com.

David C. Salthouse

unread,
Jun 25, 2026, 9:42:33 AM (13 days ago) Jun 25
to fo...@jsoftware.com
After a French lunch I tried the second question  and got this    NB. overlap_matrix: Calculates a matrix of interval overlaps and gaps

   NB. DCS dev 20260625
   NB.
   overlap_matrix =: 4 : 0
  NB. HELP: x overlap_matrix y
  NB. x : N-by-2 matrix of integers representing intervals [start, end]
  NB. y : M-by-2 matrix of integers representing intervals [start, end]

 
  t_start =. 6 !: 1 ''                NB. Start Timing
  smoutput '>>> PROCESS START: overlap_matrix'
  smoutput '>>> LOG: Extracting start and end vectors across all intervals'


  NB. 1. Localize and Extract
  xs =. {."1 x      NB. Start values of table x
  xe =. {:"1 x      NB. End values of table x
  ys =. {."1 y      NB. Start values of table y
  ye =. {:"1 y      NB. End values of table y

 
  NB. 2. Core Processing Logic
  smoutput '>>> LOG: Computing Cartesian minimums of ends and maximums of starts'
 
  NB. Minimum table of ends
  min_ends =. xe <./ ye  
 
  NB. Maximum table of starts, elegantly achieved using Minimum Under (&.) Negation
  max_starts =. xs (<./&.-) ys  
 
  NB. Array subtraction gives the overlap (positive) or gap (negative)
  result =. min_ends - max_starts

 
  NB. 3. Output / Return Results
  smoutput 'Results:'
  smoutput result

 
  t_end =. 6 !: 1 ''                  NB. End Timing
  smoutput '>>> LOG: Execution Time: ', (": t_end - t_start), 's'
  smoutput '>>> PROCESS END: overlap_matrix'
 
  result
)
   NB. end of function overlap_matrix
   
   NB. =======================================================================

   NB. GLOSSARY OF J PRIMITIVES AND TRAINS
   NB.
   NB. {."1 (Head Rank 1) - Monadic
   NB.   Valence: Monadic | Fetches the first element of each row.
   NB.   Example: {."1 (3 2 $ 1 5 6 10 1 10)
   NB.   Result:  1 6 1
   NB.
   NB. {:"1 (Tail Rank 1) - Monadic
   NB.   Valence: Monadic | Fetches the last element of each row.
   NB.   Example: {:"1 (3 2 $ 1 5 6 10 1 10)
   NB.   Result:  5 10 10
   NB.
   NB. <./ (Minimum Table) - Dyadic
   NB.   Valence: Dyadic | Generates a Cartesian table by applying Minimum (<.)
   NB.   between every element of the left array and every element of the right.
   NB.   Example: 5 10 <./ 7 5 15
   NB.   Result:  5 5 5
   NB.            7 5 10
   NB.
   NB. &. (Under) - Conjunction
   NB.   Valence: u &. v | Applies v to both arguments, applies u to the results,
   NB.   and then applies the inverse of v.
   NB.
   NB. <./&.- (Maximum Table via Minimum Under Negation) - Dyadic Train
   NB.   Valence: Dyadic | To find the maximum between arrays, we negate both (-),
   NB.   find their minimum (<./), and apply the inverse of negation (which is
   NB.   negation again) to return to the positive domain.
   NB.   Example: 1 6 (<./&.-) 3 12
   NB.   Result:  3 12
   NB.            6 12
   NB.
   NB. - (Minus) - Dyadic
   NB.   Valence: Dyadic | Element-wise subtraction across entire arrays.
   NB.   Example: 5 10 - 2 3
   NB.   Result:  3 7
   NB.
   NB. =======================================================================
   
   NB. =======================================================================

   NB. USAGE AND EDGE CASE TESTS
   NB. Let's define Table A (x) and Table B (y) to cover edge cases:
   NB. A = [1,5] standard, [6,10] standard, [1,10] large superset
   NB. B = [3,7] partial overlap, [12,15] wide gap, [2,4] subset, [5,8] touching edge
   NB. =======================================================================
   smoutput '>>> RUNNING TESTS <<<'
>>> RUNNING TESTS <<<
   A_test =. 3 2 $ 1 5, 6 10, 1 10
   B_test =. 4 2 $ 3 7, 12 15, 2 4, 5 8
   
   A_test overlap_matrix B_test
>>> PROCESS START: overlap_matrix
>>> LOG: Extracting start and end vectors across all intervals
>>> LOG: Computing Cartesian minimums of ends and maximums of starts
|length error in overlap_matrix, executing dyad <./&.-
|shapes 3 and 4 do not conform
|   max_starts=.xs    (<./&.-)ys
Press ENTER to inspect
   
dbr 0 to end inspection; use y___1 to look inside top stack frame (see code.jsoftware.com/wiki/Debug/Stack#irefs)

So I asked it to fix the bug and it gave me this:-

dbr 0 to end inspection; use y___1 to look inside top stack frame (see code.jsoftware.com/wiki/Debug/Stack#irefs)
      NB. overlap_matrix: Calculates a matrix of interval overlaps and gaps

      NB. DCS dev 20260625
      NB.
      overlap_matrix =: 4 : 0
  NB. HELP: x overlap_matrix y
  NB. x : N-by-2 matrix of integers representing intervals [start, end]
  NB. y : M-by-2 matrix of integers representing intervals [start, end]

 
  t_start =. 6 !: 1 ''                NB. Start Timing
  smoutput '>>> PROCESS START: overlap_matrix'
  smoutput '>>> LOG: Extracting start and end vectors across all intervals'


  NB. 1. Localize and Extract
  xs =. {."1 x      NB. Start values of table x
  xe =. {:"1 x      NB. End values of table x
  ys =. {."1 y      NB. Start values of table y
  ye =. {:"1 y      NB. End values of table y

 
  NB. 2. Core Processing Logic
  smoutput '>>> LOG: Computing Cartesian minimums of ends and maximums of starts'
 
  NB. Minimum table of ends
  min_ends =. xe <./ ye  
 
  NB. Maximum table of starts: Minimum Under (&.) Negation at Rank Infinity ("_)
  max_starts =. xs (<./ &. (-"_)) ys  
 
  NB. Array subtraction gives the overlap (positive) or gap (negative)
  result =. min_ends - max_starts

 
  NB. 3. Output / Return Results
  smoutput 'Results:'
  smoutput result

 
  t_end =. 6 !: 1 ''                  NB. End Timing
  smoutput '>>> LOG: Execution Time: ', (": t_end - t_start), 's'
  smoutput '>>> PROCESS END: overlap_matrix'
 
  result
)
      NB. end of function overlap_matrix

      NB. =======================================================================
      NB. GLOSSARY OF J PRIMITIVES AND TRAINS (UPDATED)
      NB.
      NB. {."1 (Head Rank 1) - Monadic
      NB.   Valence: Monadic | Fetches the first element of each row.
      NB.   Example: {."1 (3 2 $ 1 5 6 10 1 10)
      NB.   Result:  1 6 1
      NB.
      NB. {:"1 (Tail Rank 1) - Monadic
      NB.   Valence: Monadic | Fetches the last element of each row.
      NB.
      NB. <./ (Minimum Table) - Dyadic
      NB.   Valence: Dyadic | Generates a Cartesian table by applying Minimum (<.)
      NB.
      NB. &. (Under) - Conjunction
      NB.   Valence: u &. v | Applies v, then u, then the inverse of v.
      NB.   *CRITICAL DETAIL*: Inherits its operational Rank from v.
      NB.
      NB. "_ (Constant / Rank Infinity) - Conjunction
      NB.   Valence: u"_ | Forces a verb to operate at Rank Infinity (on the whole array
      NB.   at once) instead of its native rank.
      NB.
      NB. <./&.(-"_) (Maximum Table via Minimum Under Negation at Rank Infinity)
      NB.   Valence: Dyadic | Negates both arrays entirely, generates the minimum
      NB.   Cartesian table, and negates the table back.
      NB.
      NB. - (Minus) - Dyadic
      NB.   Valence: Dyadic | Element-wise subtraction.
      NB. =======================================================================

      NB. =======================================================================

      NB. USAGE AND EDGE CASE TESTS
      NB. =======================================================================
      smoutput '>>> RUNNING TESTS <<<'
>>> RUNNING TESTS <<<
      A_test =. 3 2 $ 1 5, 6 10, 1 10
      B_test =. 4 2 $ 3 7, 12 15, 2 4, 5 8

      A_test overlap_matrix B_test
>>> PROCESS START: overlap_matrix
>>> LOG: Extracting start and end vectors across all intervals
>>> LOG: Computing Cartesian minimums of ends and maximums of starts
Results:
2 _7  2 0
1 _2 _2 2
4 _2  2 3
>>> LOG: Execution Time: 8.79765e_5s
>>> PROCESS END: overlap_matrix
2 _7  2 0
1 _2 _2 2
4 _2  2 3

And it wrote this essay on the details

The bug is not in your logic; it is in how the conjunction &. (Under) handles array Rank.

When you create a verb train using u &. v, the resulting verb inherits its operational rank entirely from v.

  • The rank of - (Negate) is 0 (scalar, element-by-element).

  • Therefore, the entire train (<./&.-) gets restricted to Rank 0 0.

  • Because xs has 3 items and ys has 4 items, J tries to pair them up one-to-one and immediately throws a length error because shapes 3 and 4 do not conform element-by-element.


Cheers 

David C. Salthouse  

Raul Miller

unread,
Jun 25, 2026, 10:21:46 AM (12 days ago) Jun 25
to fo...@jsoftware.com
@David C. Salthouse

It looks to me like the concept of "overlap between matrices of
differing sizes" was ill defined, which led to a logic problem which
Gemini Pro was unable to recognize.

--
Raul

On Thu, Jun 25, 2026 at 9:42 AM David C. Salthouse

LdBeth

unread,
Jun 25, 2026, 11:54:15 PM (12 days ago) Jun 25
to fo...@jsoftware.com

Raul> It looks to me like the concept of "overlap between matrices of
Raul> differing sizes" was ill defined, which led to a logic problem which
Raul> Gemini Pro was unable to recognize.

True, it took me a while to understand what could be the interpretation
if an interval ends before it starts.

Claude Opus 4.7 gives this tacit form by knowing that I'm a J user from auto memory.

overlap =: ({:"1@[ <./ {:"1@]) - ({."1@[ >./ {."1@])

not vastly different from what Devon has got, and straight up admit
this would not work on intervals that "ends before it starts."

I guess it is because even the J expression itself is not in the knowledge
base, the formula itself had became too familiar to LLM. so I did not
push for a much more "creative" answer.

I immediately noticed the opportunity to use &:

ov =: <./&:({:"1) - >./&:({."1)

and that's it.

Devon> The second question was more involved but it was something I
Devon> solved years ago in APL: "In J, if I have two 2-column tables
Devon> of integers where the first column is the start of an interval
Devon> and the second column is the end of an interval, how would I
Devon> produce a matrix showing how much each interval in the first
Devon> table overlaps with each interval in the second table? Bonus
Devon> points if, for intervals with no overlap, we get a negative
Devon> number showing the shortest gap between the two intervals."
Devon>
Devon> Gemini basically failed and Claude did OK but was tripped up by
Devon> the assumption that the start of an interval is always less
Devon> than the end of an interval. This tripped me up too when I
Devon> first wrote this but I subsequently accounted for it by
Devon> cleaning my input data.
Devon>
Devon> The Claude code basically worked, sans the tricky case, but was
Devon> not terribly idiomatic and exhibited the same sort of false
Devon> start as in the follow up to the first question. Here is what
Devon> it ended up with after it cleaned up its original try:

Devon> Final Working Version
Devon> j
Devon> A =: 3 2 $ 1 5 3 8 10 15
Devon> B =: 3 2 $ 2 6 4 7 12 20
Devon>
Devon> NB. Overlap of two intervals (2-element vectors): min(ends) - max(starts)
Devon> NB. Positive = overlap amount, negative = gap
Devon> ov =: 4 : '(<./ (1{x),(1{y)) - (>./ (0{x),(0{y))'
Devon>
Devon> NB. Outer table: every row of A against every row of B
Devon> result =: A ov"1 1/ B
Devon>
Devon> I will leave my version as an exercise for the reader. Here
Devon> was my test input with a couple of tricky intervals that end
Devon> before they start:
Devon> A=. 1 2,2 3,1 5,0 _1,4 6,:9 3
Devon> B=. 0 10,5 6,3 1,2 3,:_3 _1
Devon>

Reply all
Reply to author
Forward
0 new messages