20
\$\begingroup\$

You are given a square \$n \times n\$ matrix \$A\$, and a list (or vector) \$u\$ of length \$n\$ containing the numbers \$1\$ through \$n\$ (or \$0\$ through \$n-1\$). Your task is to reorder the columns and rows of the matrix \$A\$ according to the order specified in \$u\$.

That is, you will construct a matrix \$B\$ where the \$(i,j)\$-th element is the \$(u(i),u(j))\$-th element of \$A\$. You should also output the inverse of this action; that is, the (i,j)-th element of \$A\$ will end up at position \$(u(i),u(j))\$ in a new matrix \$C\$.

For example, given $$A = \begin{bmatrix} 11 &12& 13 \\ 21& 22& 23 \\ 31& 32& 33 \end{bmatrix},\quad u=\begin{bmatrix}3 & 1 & 2\end{bmatrix}$$

the output should be $$B = \begin{bmatrix}33 & 31 & 32 \\ 13 & 11 & 12 \\ 23 & 21 & 22 \end{bmatrix},\quad C= \begin{bmatrix}22 & 23 & 21 \\32 & 33 & 31 \\ 12 & 13 & 11 \end{bmatrix}$$

You may take input and output through any of the default I/O methods. You do not have to specify which matrix is \$B\$ or \$C\$, as long as you output both. You may assume \$A\$ only contains positive integers, and you may use 1- or 0-based indexing for \$u\$. You must support matrices up to at least size \$64 \times 64\$.

Example

===== Input =====
A =
 35     1     6    26    19    24
  3    32     7    21    23    25
 31     9     2    22    27    20
  8    28    33    17    10    15
 30     5    34    12    14    16
  4    36    29    13    18    11
u=
  3 5 6 1 4 2

==== Output =====
B = 
  2    27    20    31    22     9
 34    14    16    30    12     5
 29    18    11     4    13    36
  6    19    24    35    26     1
 33    10    15     8    17    28
  7    23    25     3    21    32
C = 
 17    15     8    10    28    33
 13    11     4    18    36    29
 26    24    35    19     1     6
 12    16    30    14     5    34
 21    25     3    23    32     7
 22    20    31    27     9     2
\$\endgroup\$
  • \$\begingroup\$ Sandbox \$\endgroup\$ – Sanchises Sep 20 at 20:01
  • \$\begingroup\$ Can we output without the empty line here, that is, like this? (there is no ambiguity) Or, failing that, use 0 as separator? \$\endgroup\$ – Luis Mendo Sep 20 at 20:10
  • \$\begingroup\$ @LuisMendo Sure no problem. \$\endgroup\$ – Sanchises Sep 20 at 20:32
  • \$\begingroup\$ Is 1-indexing required for this? Can we use 0-indexing and input u = [2, 0, 1]? \$\endgroup\$ – Value Ink Sep 20 at 23:50
  • \$\begingroup\$ @ValueInk See the first sentence, [...] containing the numbers 1 through n (or 0 through n−1) \$\endgroup\$ – Sanchises Sep 21 at 7:13

20 Answers 20

6
\$\begingroup\$

R, 42 bytes

function(A,o)list(A[o,o],A[I<-order(o),I])

Try it online!

Takes A as a matrix and 1-based indexes o.

\$\endgroup\$
6
\$\begingroup\$

MATL, 15 13 bytes

t3$)&Gw&St3$)

Inputs u, then A.

Outputs B, then C without a separator, as there is no ambiguity.

Try it online!

Explanation

t     % Take input u implicitly. Duplicate u
3$)   % Take input A implicitly. Index A with u as row and column indices
&G    % Push the two inputs again: u, A
w     % Swap
&S    % Push indices that would make u sorted. Call that v
t     % Duplicate v
3$)   % Index A with v as row as column indices. Display implcitly
\$\endgroup\$
5
\$\begingroup\$

Octave, 33 bytes

@(A,u){A(u,u) A([~,v]=sort(u),v)}

Try it online!

Thanks to Luis for correcting an error and saving several bytes!

Basic indexing works here for both tasks, by defining a vector \$ v \$ equal to the permutation that undoes \$ u \$. That is, if \$ u = ( 3, 1, 2 ) \$ then the first element of \$ v \$ is 2, since 1 is in the second position of \$ u \$. This is accomplished with Octave's sort function.

\$\endgroup\$
5
\$\begingroup\$

Python 3 with numpy, 51 45 bytes

lambda m,p:[m[x][:,x]for x in(p,p.argsort())]

Try it online!

-6 bytes thanks to @xnor

The function takes two arguments: a numpy matrix and a permutation vector having values from \$0\$ to \$n-1\$.

\$\endgroup\$
  • \$\begingroup\$ 45 bytes as lambda \$\endgroup\$ – xnor Sep 21 at 4:50
  • \$\begingroup\$ @xnor Thanks ! I felt that it could be shortened in some way but the idea of using a for-loop did not come to my mind. \$\endgroup\$ – Joel Sep 21 at 4:55
4
\$\begingroup\$

Wolfram Language (Mathematica), 30 bytes

ii[[#,#]]&/@{#,Ordering@#}&

Try it online!

Input as f[A][u].

\$\endgroup\$
4
\$\begingroup\$

PowerShell, 78 73 71 bytes

($A,$u=$args)|%{$A[$u]|%{''+$_[$u]}
$u=1..$u.count|%{$u.indexof($_-1)}}

Try it online.

\$\endgroup\$
3
\$\begingroup\$

Jelly, 13 bytes

ŒJṁ⁸ịⱮ⁹,Ụ¤œị⁸

Try it online!

\$\endgroup\$
3
\$\begingroup\$

J, 19 bytes

(]/:~"1/:)"_ 1],:/:

Try it online!

  • Main verb ]/:~"1/:
    • The right most /: sorts the left arg (matrix) according to the order that would sort the right arg (specified order). This sorts rows.
    • Now that result get sorted /:~"1 again according to the order specified ]. But this time we're sorting with rank 1, ie, we're sorting each row, which has the effect of sorting columns.
  • ],:/: We apply the above using both the order specified ] and the grade up of the order specified /:. This gives us the 2 results we want.
\$\endgroup\$
  • \$\begingroup\$ Nice! I was thinking about applying sort+transpose twice, but will end up longer. \$\endgroup\$ – Galen Ivanov Sep 22 at 7:32
  • \$\begingroup\$ u is allowed to be 0-based, so sort (/:) could be indexing ({) with swapped args \$\endgroup\$ – ngn Sep 22 at 10:01
3
\$\begingroup\$

JavaScript (Node.js), 77 70 68 bytes

a=>g=(u,v=[])=>[u.map((i,x)=>u.map(j=>a[i][j],v[i]=x)),v&&g(v,0)[0]]

Try it online!

\$\endgroup\$
  • \$\begingroup\$ It took me a minute to figure out what v was. It's neat how you found a use for non-strict mode silent failure of property assignment to a primitive value, and used that for your recursion base-case. \$\endgroup\$ – Patrick Roberts Sep 23 at 15:34
3
\$\begingroup\$

J, 17 16 15 14 bytes

-1 thanks to @Jonah

([{"1{)~(,:/:)

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Nice! You can get down to 14 with ([{"1{)~(,:/:): Try it online! \$\endgroup\$ – Jonah Sep 22 at 18:08
  • \$\begingroup\$ Btw, random question: I noticed you golf (very well) in J, APL and K. Curious which you prefer overall? Also I seem to recall you saying you used K professionally, am I remembering that right? \$\endgroup\$ – Jonah Sep 22 at 18:23
  • \$\begingroup\$ @Jonah if i must choose one, that would definitely be k (pls ping me in the k chat if you wanna know the reasons), but i do enjoy golfing in all array languages. sadly, i'm not one of the lucky few who can have a k-language job \$\endgroup\$ – ngn Sep 22 at 18:54
2
\$\begingroup\$

Charcoal, 24 bytes

E⟦ηEη⌕ηκ⟧Eθ⪫E觧θ§ιμ§ιξ 

Try it online! Link is to verbose version of code. 0-indexed. Note: Trailing space. Explanation:

    η                       Input `u`
   E                        Map over elements
     ⌕                      Index of
       κ                    Current index in
      η                     Input `u`
  η                         Input `u`
E⟦      ⟧                   Map over `u` and its inverse
          θ                 Input `A`
         E                  Map over elements
             θ              Input `A`
            E               Map over elements
                θ           Input `A`
               §            Indexed by
                  ι         Current vector
                 §          Indexed by
                   μ        Row index
              §             Indexed by
                     ι      Current vector
                    §       Indexed by
                      ξ     Column index
           ⪫                Join with spaces for readability
                            Implicitly print
\$\endgroup\$
2
\$\begingroup\$

Kotlin, 213 bytes

{a:List<List<Int>>,u:List<Int>->val s=u.size
for(l in List(s){r->List(s){c->a[u[r]][u[c]]}})println(l.joinToString(" "))
for(l in List(s){r->List(s){c->a[u.indexOf(r)][u.indexOf(c)]}})println(l.joinToString(" "))}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

APL+WIN, 21 bytes

Prompts for input of u followed by a. Outputs b immediately over the top of c with no separator:

(a←⎕)[u;u←⎕]⋄a[⍋u;⍋u]

Try it online! Courtesy of Dyalog Classic

\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog Extended), 12 bytesSBCS

Full program. Prompts for \$u\$ and then \$A\$. Prints \$C\$ next to \$B\$, separated by two spaces

⌷∘⎕¨⍋¨⍛⍮⍨⍮⍨⎕

Try it online!

 prompt for \$u\$; [3,1,2]

⍮⍨ juxtaposition-selfie; [[3,1,2],[3,1,2]]

⍋¨ permutation-inversion of each; [[2,3,1],[2,3,1]]
 then
⍮⍨ juxtapose with itself [[[2,3,1],[2,3,1]],[[3,1,2],[3,1,2]]]

 reorder
 the value of
\$A\$ as inputted
¨ using each pair as a set of orders, one order per axis

\$\endgroup\$
1
\$\begingroup\$

Perl 5, 79 bytes

sub{$[=1;($A,$u)=@_;@$v[@$u]=(1..@$u);map{$x=$_;[map[@$_[@$x]],@$A[@$x]]}$u,$v}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Jelly,  12 11  13 bytes

+2 :( to fix cases when B = C

ṭþ`œị¥@Ƭị@2,0

A dyadic Link accepting a list of lists, A (n by n), on the left and a list of the first n integers on the right, u, which yields a list of lists of lists, [B, C].

Try it online!

How?

ṭþ`œị¥@Ƭị@2,0 - Link: A, u
       Ƭ      - collect up while the results are no longer unique, applying:
     ¥@       -   last two links as a dyad with swapped arguments:
  `           -     use left (u) as both arguments of:
 þ            -       outer product with:
ṭ             -         tack
   œị         -     multi-dimensional index into last result (starting with A)
                ...at the end of the Ƭ-loop we have [A,B,...,C]
                                                 or [A] if A=B=C
                                                 or [A,B] if B=C but A!=B
          2,0 - literal pair [2,0]
         @    - with swapped arguments:
        ị     -   index into (1-based & modular) -> [B,C]
                                                 or [A,A]=[B,C] if A=B=C
                                                 or [B,B]=[B,C] if B=C
\$\endgroup\$
1
\$\begingroup\$

q, 26 bytes

{Y:iasc y;(x[y;y];x[Y;Y])}

iasc returns indexes to sort it's argument.

\$\endgroup\$
1
\$\begingroup\$

C++ (gcc), 148 bytes

#import<vector>
#define q[o[i/z]*z+o[i%z]]
using V=std::vector<int>;int f(V m,V o,V&r,V&R,int z){int i=z*z;for(r=V(i),R=V(i);i--;r[i]=m q)R q=m[i];}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Clean, 91 bytes

import StdEnv
$a u=map(\l={{a.[i,j]\\j<-l}\\i<-l})[u,[k\\i<-[0..]&_<-u,j<-u&k<-[0..]|j==i]]

Try it online!

Defines $ :: {{a}} [Int] -> [{{a}}] (used with a = Int) taking an array of arrays and a list of zero-based indices, returning a list of arrays of arrays containing B and C.

\$\endgroup\$
1
\$\begingroup\$

Python 3, 91 bytes

lambda a,u:[[[a[y][x]for x in t]for y in t]for t in[u,[u.index(i)for i in range(len(u))]]]

Try it online!

Takes parameters as a 2D and 1D list and returns a list containing two 2D lists B and C. I'm not sure if there's a cleaner way to do all the for-loops.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.