Reorder a matrix, twice

21

2

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

Sanchises

Posted 2019-09-20T20:01:50.513

Reputation: 8 530

Sandbox – Sanchises – 2019-09-20T20:01:59.550

Can we output without the empty line here, that is, like this? (there is no ambiguity) Or, failing that, use 0 as separator?

– Luis Mendo – 2019-09-20T20:10:03.037

@LuisMendo Sure no problem. – Sanchises – 2019-09-20T20:32:09.047

Is 1-indexing required for this? Can we use 0-indexing and input u = [2, 0, 1]? – Value Ink – 2019-09-20T23:50:57.007

@ValueInk See the first sentence, [...] containing the numbers 1 through n (or 0 through n−1) – Sanchises – 2019-09-21T07:13:16.370

Answers

6

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

Luis Mendo

Posted 2019-09-20T20:01:50.513

Reputation: 87 464

6

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.

Giuseppe

Posted 2019-09-20T20:01:50.513

Reputation: 21 077

5

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.

FryAmTheEggman

Posted 2019-09-20T20:01:50.513

Reputation: 16 206

5

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\$.

Joel

Posted 2019-09-20T20:01:50.513

Reputation: 1 691

45 bytes as lambda – xnor – 2019-09-21T04:50:49.607

@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. – Joel – 2019-09-21T04:55:40.213

4

Wolfram Language (Mathematica), 30 bytes

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

Try it online!

Input as f[A][u].

attinat

Posted 2019-09-20T20:01:50.513

Reputation: 3 495

4

PowerShell, 78 73 71 bytes

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

Try it online.

Andrei Odegov

Posted 2019-09-20T20:01:50.513

Reputation: 939

3

Jelly, 13 bytes

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

Try it online!

Erik the Outgolfer

Posted 2019-09-20T20:01:50.513

Reputation: 38 134

3

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.

Jonah

Posted 2019-09-20T20:01:50.513

Reputation: 8 729

Nice! I was thinking about applying sort+transpose twice, but will end up longer. – Galen Ivanov – 2019-09-22T07:32:31.113

u is allowed to be 0-based, so sort (/:) could be indexing ({) with swapped args – ngn – 2019-09-22T10:01:35.230

3

J, 17 16 15 14 bytes

-1 thanks to @Jonah

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

Try it online!

ngn

Posted 2019-09-20T20:01:50.513

Reputation: 11 449

1

Nice! You can get down to 14 with ([{"1{)~(,:/:): Try it online!

– Jonah – 2019-09-22T18:08:11.930

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? – Jonah – 2019-09-22T18:23:42.057

@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

– ngn – 2019-09-22T18:54:34.983

3

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!

James

Posted 2019-09-20T20:01:50.513

Reputation: 491

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. – Patrick Roberts – 2019-09-23T15:34:25.467

3

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

Adám

Posted 2019-09-20T20:01:50.513

Reputation: 37 779

2

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

Neil

Posted 2019-09-20T20:01:50.513

Reputation: 95 035

2

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!

JohnWells

Posted 2019-09-20T20:01:50.513

Reputation: 611

2

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

Graham

Posted 2019-09-20T20:01:50.513

Reputation: 3 184

1

Perl 5, 79 bytes

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

Try it online!

Nahuel Fouilleul

Posted 2019-09-20T20:01:50.513

Reputation: 5 582

1

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

Jonathan Allan

Posted 2019-09-20T20:01:50.513

Reputation: 67 804

1

C++ (gcc), 148 142 bytes

#import<queue>
#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=R=V(i);i--;r[i]=m q)R q=m[i];}

Try it online!

Thanks to @ceilingcat suggestion to use #import <queue> instead of <vector> which mysteriously brings std::vector

AZTECCO

Posted 2019-09-20T20:01:50.513

Reputation: 2 441

@ceilingcat now I see that import queue gives me access to vector.. Is it compiler dependant? I'm trying to search information about this but found nothing – AZTECCO – 2019-12-10T05:57:50.490

1Tips for golfing in C++ – ceilingcat – 2019-12-10T09:59:48.943

1

q, 26 bytes

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

iasc returns indexes to sort it's argument.

skeevey

Posted 2019-09-20T20:01:50.513

Reputation: 4 139

1

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.

Οurous

Posted 2019-09-20T20:01:50.513

Reputation: 7 916

1

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.

Matthew Jensen

Posted 2019-09-20T20:01:50.513

Reputation: 713