Find the J twin

For a 2 dimensional array we will define the elements in either the first row or the last column to be the largest "J-Bracket" of the array. For example in the following array elements in the J-bracket are highlighted:

$$\ \begin{bmatrix} \color{red}{\underline 1} & \color{red}{\underline 2} & \color{red}{\underline 4} & \color{red}{\underline 8} \\ 9 & 3 & 6 & \color{red}{\underline 7} \\ 3 & 3 & 2 & \color{red}{\underline 9} \end{bmatrix} \$$

The J-bracket is given in order starting from the first element of the first row and going clockwise. The element that is in both the row and the column is not repeated. So for the above that is:

$$\ \left[1, 2, 4, 8, 7, 9\right] \$$

To get the next largest J-bracket is just remove the largest J-bracket from the array and take the largest J-bracket of the remainder:

$$\ \begin{bmatrix} \color{lightgrey}{1} & \color{lightgrey}{2} & \color{lightgrey}{4} & \color{lightgrey}{8} \\ \color{red}{\underline 9} & \color{red}{\underline 3} & \color{red}{\underline 6} & \color{lightgrey}{7} \\ 3 & 3 & \color{red}{\underline 2} & \color{lightgrey}{9} \end{bmatrix} \$$

and so on until every element is in exactly 1 J-bracket.

The set of J-brackets from an array is not necessarily unique. In fact if the matrix is non-square every matrix has a twin with the same J-bracket set.

$$\ \begin{bmatrix} \color{red}{\underline 1} & \color{red}{\underline 2} & \color{red}{\underline 4} & \color{red}{\underline 8} \\ \color{green}9 & \color{green}3 & \color{green}6 & \color{red}{\underline 7} \\ \color{blue}{\overline 3} & \color{blue}{\overline 3} & \color{green}2 & \color{red}{\underline 9} \end{bmatrix} \cong \begin{bmatrix} \color{red}{\underline 1} & \color{red}{\underline 2} & \color{red}{\underline 4} \\ \color{green}{9} & \color{green}3 & \color{red}{\underline 8} \\ \color{blue}{\overline 3} & \color{green}6 & \color{red}{\underline 7} \\ \color{blue}{\overline 3} & \color{green}2 & \color{red}{\underline 9} \end{bmatrix} \$$

This twin has the opposite dimensions and in the case of a square matrix it is its own twin.

Your task is to take a 2D array of positive integers and output its J-twin. You may take input and output in any standard format but the input format should be the same as the output.

This is so answers will be scored in bytes with fewer bytes being the goal.

Test cases

[[2]] -> [[2]]
[[1,2,3]] -> [[1],[2],[3]]
[[1,2,4,8],[9,3,6,7],[3,3,2,9]] -> [[1,2,4],[9,3,8],[3,6,7],[3,2,9]]
[[1,2,4],[9,3,8],[3,6,7],[3,2,9]] -> [[1,2,4,8],[9,3,6,7],[3,3,2,9]]
• Related Commented Mar 30, 2022 at 13:06
• Waiting for a J answer…
Commented Mar 30, 2022 at 15:31

Jelly, 10 bytes

ZL_Lṙ@ŒdŒḍ

A monadic Link that accepts a rectangular list of lists and yields its J-bracket-twin as a list of lists.

Try it online! Or see the test-suite.

How?

ZL_Lṙ@ŒdŒḍ - Link: list of lists, A
Z          - transpose A
L         - length of that -> columnCount(A)
L       - length of A -> rowCount(A)
_        - columnCount(A) subtract rowCount(A) = N
Œd   - anti-diagonals of A
ṙ@     - rotate this list of anti-diagonals left by N
Œḍ - create a matrix with these anti-diagonals

{$[1=&/#'1*:\x;:+x;[r:,/(*x),1_-1#'x;(,(#x)#r),+(+o(1_-1_'x)),,(#x)_r]]} Try it online! • This is basically two functions. One to make the J bracket and one to make a matrix from a J bracket. Looking at the other solutions, I clearly didn't need to make the J bracket first. I'm sure mimicking one of the other answers will be much shorter. – doug Commented Apr 3, 2022 at 10:29 • Reworked to use recursion. – doug Commented Apr 3, 2022 at 12:00 Python 3, 111 bytes def f(x): r,*a=x;k=len(a) if k*r[1:]:r+=map(list.pop,a);x=*zip(r[:k],*f(a)),r[k:] return[*map(list,zip(*x))] Try it online! R, 76 bytes \(m)array(unsplit(split(m,i),rev(t(i<-pmin(row(m),rev(col(m)))))),dim(t(i))) Attempt This Online! As in the other challenge, splits the array to find the J-brackets. Then unsplits and adds array structure to get to the J-twin as a matrix. Longer explanation to follow. J, 62 60 bytes Quite messy. The logic is very similar to my Python answer. Porting the Jelly answer might be shorter. [:|:*@#@,(({.,{:"1@}.)((}.~#),~({.~#),.])|:@$:@:(}:"1)@}.^:)

Try it online!

• I wrote this a few days ago and forgot to post it. 51: Try it online! IIRC it didn't feel fully golfed yet. Commented Apr 7, 2022 at 5:17

PARI/GP, 59 bytes

m->matrix(#m,#m~,i,j,m[i-d=min(l=i+j-1,#m)-min(l,#m~),j+d])

Attempt This Online!

Shift the $$\n\$$-th anti-diagonal to lower left by $$\\min(n,w)-\min(n,h)\$$, where $$\w\$$ and $$\h\$$ are the number of columns and rows of the matrix respectively.

Python + NumPy, 80 bytes

def f(a):b=0*a.T;b[1:,:-1]=a.any()and f(a[1:,:-1]);b[b<1]=a[a>0];a[:]=0;return b

Attempt This Online!

Accepts and destroys (overwrites with zeros) a NumPy array. Relies on elements being positive as promised in OP.

• Shouldn't the import statement be included in the byte count? Or is there a precedence? Commented Apr 2, 2022 at 23:12
• @jezza_99 right now I'm too lazy to find relevant meta post. But the consensus rule is import is only required if names from the module are actually referenced. Here I access the module's functionality exclusively through arguments and their attributes. Another way of looking at it would be that the function works without ever explicitly importing the module. Commented Apr 3, 2022 at 0:26
• Ah yeah makes sense, just don't think I've seen an answer with that before. Cheers for the explanation Commented Apr 3, 2022 at 1:05

-11 thanks to Wheat Wizard

t[h]=pure<$>h t s@([x]:r)=[s>>=id] t(h:r)|n<-t$init<$>r,(a,b)<-splitAt(length r)$h++(last<$>r)=zipWith(\i->(++[i]))b(a:n) Try it online! If the input list has only one row, or only one column, transpose it. Otherwise, recurse on the "nub" that results from removing the J-bracket; then split the J-bracket into two parts, put one part atop the nub, and append the other part itemwise to the right side of the nub. It's still pretty long, so I'm guessing there's a better way to do this... • 11 bytes shorter Commented Apr 2, 2022 at 23:14 • @WheatWizard Ah, thanks. I vaguely remembered that something like @ existed, but I'd forgotten the syntax. Commented Apr 3, 2022 at 2:51 Charcoal, 524339 38 bytes Ｆ⁺θ§θ⁰⊞υ⟦⟧ＵＭθＥι⊞Ｏ§υ⁺κμλ≦⮌υＩＥ⌊θＥθ⊟§υ⁺κμ Try it online! Link is to verbose version of code. Outputs in Charcoal's default one-element-per-line format. Explanation: Ｆ⁺θ§θ⁰⊞υ⟦⟧ Create a list of empty lists that will eventually hold the antidiagonals. ＵＭθＥι⊞Ｏ§υ⁺κμλ Extract the antidiagonals from the input. (This replaces each element in the array with the antidiagonal to which it belongs, but unfortunately I can't make use of this fact.) ≦⮌υ Reverse the antidiagonals so that we can extract the elements in the original order using Pop(). ＩＥ⌊θＥθ⊟§υ⁺κμ` Transpose the array, but read the elements back from the antidiagonals. (If Charcoal had an equivalent of JavaScript's unshift() then I would be able to unshift directly from the transposed array's antidiagonals to recover the elements.) Haskell, 100 bytes -3 bytes thanks to Wheat Wizard. t m=[[m!!(i-1-x+y)!!(j+x-y)|j<-[0..l m-1],let[x,y]=min(i+j)<$>[l$m!!0,l m]]|i<-[1..l$m!!0]]
l=length

Try it online!

An ugly port of my PARI/GP answer.

Curry (PAKCS), 101 bytes

-4 bytes thanks to Wheat Wizard.

t m=[[m!!(i-1-x+y)!!(j+x-y)|j<-[0..l m-1],let[x,y]=map(min$i+j)[l$m!!0,l m]]|i<-[1..l\$m!!0]]
l=length

Try it online!

• 108 bytes Commented Apr 8, 2022 at 7:50
• 101 bytes Commented Apr 8, 2022 at 11:07

Python3, 234 bytes:

E=enumerate
s=lambda m,d:(k for i,j in E(m)for x,k in E(j)if(i==d and x<(len(m[0])-d))or(i>d and x==(len(m[0])-1-d)))
r=lambda d,m:[[next(d[min(x,len(m)-1-y)])for y,_ in E(m)]for x,_ in E(m[0])]
lambda m:r({i:s(m,i)for i,_ in E(m)},m)

Try it online!