Fix my notation for lists of matrices, part 1

21

Sometimes, I have lists of constant matrices in my code:

[ [[1, 0],
   [0, 1]],

  [[1, 0],
   [0,-1]],

  [[0, 1],
   [1, 0]],

  [[0,-1],
   [1, 0]] ]

That's a terrible use of screen real estate. I'd much rather write them next to each other:

[   [[1, 0],    [[1, 0],    [[0, 1],    [[0,-1],
     [0, 1]],    [0,-1]],    [1, 0]],    [1, 0]]   ]

You'll find that this is still a syntactically valid nested list, it's just no longer rectangular and it has a very different structure (in particular, it gets deeper every time I add a matrix larger than 1x1). However, it's still possible to reconstruct the initial list of matrices from this new list.

So that I can use this syntax in the future, I need you to write some code which converts arrays that were written in a horizontal arrangement to the list of matrices they represent.

To make sure that answers don't perform 2D pattern matching on the layout in the source code, the input will be given either as just the array object, or if you take a string representation, then it will not contain any whitespace indicating how the literal was written in the code. So you'd get some input like this:

[[[1, 0], [[1, 0], [[0, 1], [[0,-1], [0, 1]], [0,-1]], [1, 0]], [1, 0]]]

And the output should be the following array or its string representation (again, no further layout is needed):

[[[1, 0], [0, 1]], [[1, 0], [0,-1]], [[0, 1], [1, 0]], [[0,-1], [1, 0]]]

This is the first and easier part of a two-part challenge. In this one, you may assume that all matrices are square and have the same dimensions and that they are properly aligned next to each other. In the second part we'll relax these assumptions.

Rules

The input will be a nested list or its canonical string representation (in your language of choice), and you should output the result in the same format. The result will always contain at least one matrix, and the matrices can be as small as 1x1. The matrices will only contain (signed) integers with absolute value less than 128.

You may write a program or a function and use any of the standard methods of receiving input and providing output.

You may use any programming language, but note that these loopholes are forbidden by default.

This is , so the shortest valid answer – measured in bytes – wins.

Test Cases

Each test case has a) the list matrices laid out nicely next to each other as they would be in the code (this is not your input), b) the unformatted list without the extraneous whitespace (this is your input), c) the expected output.

Pretty: [ [[0]] ]
Input:  [[[0]]]
Output: [[[0]]]

Pretty: [  [[-1]],  [[0]],  [[1]]  ]
Input:  [[[-1]],[[0]],[[1]]]
Output: [[[-1]],[[0]],[[1]]]

Pretty: [  [[1, 0],   [[1, 0],   [[0, 1],   [[0,-1],
            [0, 1]],   [0,-1]],   [1, 0]],   [1, 0]]  ]
Input:  [[[1,0],[[1,0],[[0,1],[[0,-1],[0,1]],[0,-1]],[1,0]],[1,0]]]
Output: [[[1,0],[0,1]],[[1,0],[0,-1]],[[0,1],[1,0]],[[0,-1],[1,0]]]

Pretty: [  [[1, 0, 0],   [[ 127,  63,   31],   [[1, 0, 0],   [[0, 0, 0],
            [0, 1, 0],    [  15,   0,  -15],    [0, 0, 1],    [0, 0, 0],
            [0, 0, 1]],   [ -31, -63, -127]],   [0, 1, 0]],   [0, 0, 0]]  ]
Input:  [[[1,0,0],[[127,63,31],[[1,0,0],[[0,0,0],[0,1,0],[15,0,-15],[0,0,1],[0,0,0],[0,0,1]],[-31,-63,-127]],[0,1,0]],[0,0,0]]]
Output: [[[1,0,0],[0,1,0],[0,0,1]],[[127,63,31],[15,0,-15],[-31,-63,-127]],[[1,0,0],[0,0,1],[0,1,0]],[[0,0,0],[0,0,0],[0,0,0]]]

Martin Ender

Posted 2017-05-21T10:26:35.860

Reputation: 184 808

1I think I might know what inspired this challenge... – Neil – 2017-05-21T12:39:35.127

Is [([1, 0], [0, 1]), ([1, 0], [0, -1]), ([0, 1], [1, 0]), ([0, -1], [1, 0])] valid output for the third testcase? It is mixed list and tuple. – ovs – 2017-05-21T12:40:50.047

@ovs No, sorry. Since input and output format should match, the corresponding input would be [([1,0], ([1, 0}, ... and that would give you additional information. – Martin Ender – 2017-05-21T12:51:28.760

@Neil what inspired this challenge? – caird coinheringaahing – 2017-05-21T15:22:12.697

@RandomUser The desire to golf all the things. Least amount of screen real estate wins! – Dennis – 2017-05-21T15:23:39.173

@RandomUser this did.

– Martin Ender – 2017-05-21T15:32:51.433

Answers

14

Jelly, 20 15 13 11 bytes

Fðs⁹œsZµḢḢL

Try it online!

Background

Like most things, this challenge is rather simple once you've figured out what you have to do. And I eventually did, after three deletions and one rollback...

First, we must figure out the dimensions of the matrices. That's easier done than said: the first element of the first element is the first row of the first output matrix, so its length is equal to the number of columns of the square output matrices.

For example, if the input is

[  [[1, 0, 0],   [[ 127,  63,   31],   [[1, 0, 0],   [[0, 0, 0],
    [0, 1, 0],    [  15,   0,  -15],    [0, 0, 1],    [0, 0, 0],
    [0, 0, 1]],   [ -31, -63, -127]],   [0, 1, 0]],   [0, 0, 0]]  ]

the first element of the first element is [1, 0, 0], whose length is ℓ = 3.

If we flatten the input and split it into chunks of that length, we get all rows of the output matrices, albeit in the wrong order. For our example input, this gives

[  [1, 0, 0], [127,  63,   31], [1, 0, 0], [0, 0, 0],
   [0, 1, 0], [ 15,  0,   -15], [0, 0, 1], [0, 0, 0],
   [0, 0, 1], [-31, -63, -127], [0, 1, 0], [0, 0, 0]  ]

To obtain the final output, we must first split the row array into chunks of equal length. For our example input, this gives

[ [[1, 0, 0], [127,  63,   31], [1, 0, 0], [0, 0, 0]],
  [[0, 1, 0], [ 15,  0,   -15], [0, 0, 1], [0, 0, 0]],
  [[0, 0, 1], [-31, -63, -127], [0, 1, 0], [0, 0, 0]] ]

Each column is now one of the output matrices, so transposing the resulting matrix of arrays is all that's left to do. For our example input, that gives

[
 [[1, 0, 0],
  [0, 1, 0],
  [0, 0, 1]],

 [[127,  63,   31],
  [ 15,   0,  -15],
  [-31, -63, -127]],

 [[1, 0, 0],
  [0, 0, 1],
  [0, 1, 0]],

 [[0, 0, 0],
  [0, 0, 0],
  [0, 0, 0]]
]

as desired.

How it works

Fðs⁹œsZµḢḢL  Monadic link. Argument: A (ragged array)


F            Monadic chain. Argument: A

F            Flatten A. This yields the vector V.


       µḢḢL  Monadic chain. Argument: A

        Ḣ    Head; retrieve the first element of A.
         Ḣ   Head; retrieve the first element of the first element of A.
          L  Compute ℓ, the length of the resulting array.


 ðs⁹œsZ      Dyadic chain. Left argument: V. Right argument: ℓ

  s⁹         Split V into chunks of length ℓ.
    œs       Split the result into ℓ chunks of equal length.
      Z      Zip/transpose the result.

Dennis

Posted 2017-05-21T10:26:35.860

Reputation: 196 637

6

Pyth, 12 bytes

CcJlhhQc.nQJ

This is a port of my Jelly answer.

Try it online!

How it works

Pyth parses the program as follows (pseudo-code).

C(c(J = l(h(h(Q))), c(.n(Q), J)))

Q is a variable that holds the input. J is an undefined variable.

First J = l(h(h(Q))) stores the length of the head (first element) of the head of Q in J.

Then, .n(Q) flattens Q, and c(..., J) splits the result into pieces of length J.

Afterwards, c(J, ...) splits the result in J pieces.

Finally, C(...) transposes the result.

Dennis

Posted 2017-05-21T10:26:35.860

Reputation: 196 637

1sancta mater dei – Leaky Nun – 2017-05-21T17:13:01.570

3

Pyth, 29 bytes

.xj\,sCcJh-UJ:z"\B,"3x\[@R1Jz

Test suite.

How it works

.xj\,sCcJh-UJ:z"\B,"3x\[@R1Jz

              z        input
             :      3  split at matches of the following regex
               "\B,"   /\B,/
            J          store at J
           U           [1,2,...,len(J)]

                           J  J
                        @R1   take the second character of each
                              substring in J
                     x\[      indices of all occurrences of "["

          -   filter away the elements in ^ from the
              elements in ^^ to find the first substring
              which does not start with "[["
         h    the first element
              note: this will generate an error if
              all substrings start with "[[", e.g. in the
              first example. We will deal with the error later.
       cJ     split J in groups of the specified length
      C       transpose                             ^
     s        flatten                               |
  j\,         join with ","                         |
.x            if the above code generated an error (|), return
              the following instead:
                            z      the input

Algorithm

Let's work on the input [[[1,0],[[1,0],[[0,1],[[0,-1],[0,1]],[0,-1]],[1,0]],[1,0]]].

We will be using pure string operations here.

Firstly, we split the input at the commas which are not part of the deepest list (this is done by splitting at the regex \B,):

[[[1,0]
[[1,0]
[[0,1]
[[0,-1]
[0,1]]
[0,-1]]
[1,0]]
[1,0]]]

Then, we find the index of the first substring which does not start with [[ (this is done by checking whether the character at index 1 is [). In this case, it is 4, because the substring at index 4 is [0,1]] which does not start with [[.

Then, we group the substrings in groups of 4, and then transpose:

[[[1,0]
[0,1]]
[[1,0]
[0,-1]]
[[0,1]
[1,0]]
[[0,-1]
[1,0]]]

And then we join them with commas:

[[[1,0],[0,1]],[[1,0],[0,-1]],[[0,1],[1,0]],[[0,-1],[1,0]]]

Leaky Nun

Posted 2017-05-21T10:26:35.860

Reputation: 45 011

2You were just massively outgolfed by Dennis. – Erik the Outgolfer – 2017-05-21T16:54:37.133

3

JavaScript (ES6), 132 130 bytes

f=(a,n=1)=>a[0][n]?a[0][n][0][0]?f(a,n+1,a[0].splice(n,1,...a[0][n])):n>1?[...Array(n)].map((_,i)=>a[0].filter((_,j)=>j%n==i)):a:a

There are four cases:

  • A 1×n array, which is just returned (this is the first test, but inverted)
  • An m×n array which hasn't been flattened yet, which we recursively flatten by one step, counting n at the same time.
  • An m×n array which has been flattened, where we filter out every nth element.
  • An m×1 array, which is just returned

Neil

Posted 2017-05-21T10:26:35.860

Reputation: 95 035

2

05AB1E, 11 bytes

A port of Dennis' answer. Code:

¬¬g¹˜sô¬gäø

Uses the CP-1252 encoding. Try it online!

Adnan

Posted 2017-05-21T10:26:35.860

Reputation: 41 965

1

Mathematica, 104 bytes

l=Length;(m=l@#[[1,1]];n=l@Flatten@#/m;Table[Partition[#~ArrayReshape~{n,m},n/m][[j,i]],{i,n/m},{j,m}])&

Input

{{{1, 0}, {{1, 0}, {{0, 1}, {{0, -1}, {0, 1}}, {0, -1}}, {1, 0}}, {1, 0}}}

output

{{{1, 0}, {0, 1}}, {{1, 0}, {0, -1}}, {{0, 1}, {1, 0}}, {{0, -1}, {1, 0}}}

input

{{{1, 0, 0}, {{127, 63, 31}, {{1, 0, 0}, {{0, 0, 0}, {0, 1, 0}, {15, 0, -15}, {0, 0, 1}, {0, 0, 0}, {0, 0, 1}}, {-31, -63, -127}}, {0, 1, 0}}, {0, 0, 0}}}

output

{{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, {{127, 63, 31}, {15, 0, -15}, {-31, -63, -127}}, {{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}, {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}

{{{0}}} and {{{-1}}, {{0}}, {{1}}} work,too

-11 bytes thanks to Martin Ender

J42161217

Posted 2017-05-21T10:26:35.860

Reputation: 15 931