20
\$\begingroup\$

Given a matrix, output a representation of the matrix where the top left element is on top, the anti-diagonal is the central row and the bottom right element is at the bottom.

For example, consider the following matrix:

1 2 3
4 5 6
7 8 9

The diamond version of this matrix is:

  1
 4 2
7 5 3
 8 6
  9

Inputs and outputs

An input matrix will be given as a list of lists (or anything similar in your language of choice). The output shall be a list of lists as well.

The matrices will only contain positive integers.

The input matrix will not necessarily be square.

The input matrix will be at least 1×1.

Test Cases

Input:  [[1]]
Output: [[1]]

Input:  [[1,2],[3,4]]
Output: [[1],[3,2],[4]]

Input:  [[1,2,3],[4,5,6]]
Output: [[1],[4,2],[5,3],[6]]

Input:  [[11,2,5],[3,99,3],[4,8,15],[16,23,42]]
Output: [[11],[3,2],[4,99,5],[16,8,3],[23,15],[42]]

Scoring

This is , so the shortest answer in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ Related \$\endgroup\$ – Fatalize Apr 6 '16 at 8:23
  • \$\begingroup\$ Related/Generalisation. (Wouldn't consider it a dupe though, since that one allowed ragged arrays and required rotation by any multiple of 45 degrees.) \$\endgroup\$ – Martin Ender Apr 6 '16 at 8:32
  • \$\begingroup\$ Related. \$\endgroup\$ – Martin Ender Apr 6 '16 at 8:42

15 Answers 15

19
\$\begingroup\$

J, 7 bytes

<@|./.

This is an unnamed a monadic verb which takes a matrix and returns a list of antidiagonals:

   input =. i.3 4
   input
0 1  2  3
4 5  6  7
8 9 10 11

   <@|./. input
┌─┬───┬─────┬─────┬────┬──┐
│0│4 1│8 5 2│9 6 3│10 7│11│
└─┴───┴─────┴─────┴────┴──┘

Test it here.

Explanation

  • /. is J's built-in to apply a function to each anti-diagonal. Unfortunately, these anti-diagonals are given in the opposite order of what we want here.
  • In <@|., we first apply |. which reverses the anti-diagonal and then < to box it (which is the only way to return a ragged array in J, since normal arrays are always rectangular, so the antidiagonals would be padded with zeroes).
\$\endgroup\$
  • \$\begingroup\$ That is crazy and beautiful. I will take the time to learn this language some day. \$\endgroup\$ – machine yearning Apr 7 '16 at 11:24
5
\$\begingroup\$

Python, 91 bytes

e=enumerate
lambda M:[[r[n-i]for i,r in e(M)if-1<n-i<len(r)][::-1]for n,_ in e(M[1:]+M[0])]

Test it on Ideone.


Python + NumPy, 69 bytes

import numpy
lambda M:map(M[::-1].diagonal,range(1-len(M),len(M[0])))

Expects a 2D NumPy array as input and returns a list of NumPy arrays. Test it on Ideone.

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

Jelly, 7 bytes

ṚŒDṙZL$

Try it online!

Explanation

Ṛ         Reverse the matrix vertically.
 ŒD       Get its diagonals. However these start from 
          the main diagonal, not the corners.
    ZL$   Get the width of the input matrix.
   ṙ      Rotate the list of diagonals left by that many 
          places to obtain the correct order.
\$\endgroup\$
  • \$\begingroup\$ Don't know Jelly, but that isn't 7 bytes if it requires unicode operands. \$\endgroup\$ – Guidobot Apr 6 '16 at 22:55
  • 5
    \$\begingroup\$ @Guidobot Jelly uses a custom code page that encodes each of the 256 characters it understands as a single byte. \$\endgroup\$ – Dennis Apr 6 '16 at 22:59
4
\$\begingroup\$

Mathematica, 58 56 bytes

a=Length;Reverse@#~Diagonal~b~Table~{b,1-a@#,a@#&@@#-1}&

Anonymous function, takes nested arrays.

\$\endgroup\$
  • \$\begingroup\$ You can save one with Length[#] where is \[Transpose]. And probably another from aliasing Length. \$\endgroup\$ – Sp3000 Apr 6 '16 at 14:39
  • \$\begingroup\$ Or Length@#&@@# for ASCII only at the same byte count. \$\endgroup\$ – Martin Ender Apr 6 '16 at 14:41
3
\$\begingroup\$

CJam, 17 bytes

{eeSf.*::+W%zSf-}

An unnamed block (function) which expects the matrix on the stack and replaces it with its antidiagonals.

Test it here.

This (found by Sp3000) works for the same byte count:

{_,,Sf*\.+W%zSf-}

Explanation

This is best explained with an example. Consider the input:

[[0  1  2  3]
 [4  5  6  7]
 [8  9 10 11]]

ee    e# Enumerate matrix, turning each row [x ... z] into [i [x ... z]] where
      e# i is the vertical index from the top.

[[0 [0  1  2  3]]
 [1 [4  5  6  7]]
 [2 [8  9 10 11]]]

Sf.*  e# Replace each i with a string of i spaces.

[[""   [0  1  2  3]]
 [" "  [4  5  6  7]]
 ["  " [8  9 10 11]]]

::+   e# Prepend these strings to the rows.

[[0  1  2  3]
 ['  4  5  6  7]
 ['  '  8  9 10 11]]   e# Note that each '  corresponds to a space character.

W%    e# Reverse the rows.

[['  '  8  9 10 11]
 ['  4  5  6  7]
 [0  1  2  3]]

z     e# Zip/transpose.

[[ '  '  0]
 [ '  4  1]
 [ 8  5  2]
 [ 9  6  3]
 [10  7]
 [11]]

Sf-   e# Remove spaces from each row.

[[ 0]
 [ 4  1]
 [ 8  5  2]
 [ 9  6  3]
 [10  7]
 [11]]
\$\endgroup\$
3
\$\begingroup\$

Python 2, 88 87 bytes

lambda L:[filter(None,x)[::-1]for x in map(None,[],*[i*[0]+r for i,r in enumerate(L)])]

Prepend 0s, zip, then remove falsy elements. Returns a list of tuples. This uses map(None,...) to perform zip_longest (padding missing spots with None) and filter(None,...) to remove falsy elements.

Annoyingly, we need to add an extra [] row to the map to guarantee that a list of tuples is returned, since map(None,*[[1]]) returns [1] rather than [(1,)] for a 1x1 matrix. The extra row gets stripped out by the filter though.

(Thanks to @Dennis for -1 byte)

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

Ruby, 68 66 bytes

Anonymous function.

->l{i=-1;k=[];l.map{|r|i-=j=-1;r.map{|e|k[i+j+=1]=[e,*k[i+j]]}};k}
  • Because of how the splat operator works, I was able to save 2 bytes by forgoing the array addition.
\$\endgroup\$
2
\$\begingroup\$

Mathematica, 60 bytes

#&@@@#&/@GatherBy[Join@@MapIndexed[List,#,{2}],Tr@*Last]&

where is a Unicode character which Mathematica reads as the postfix \[Transpose] operator.

This is a bit longer than the other Mathematica solution but I figured I'd post it because it doesn't use the Diagonals built-in and uses a completely different approach.

Explanation

MapIndexed[List,#,{2}]

This first transposes the matrix (such that the antidiagonals appear in the correct order if the matrix was flattened). Then we map List over the cells of the matrix together with the index, which turns each matrix element i into {i, {x, y}} where x and y are the coordinates of the element in the matrix.

Join@@...

This flattens the outermost dimension, so that we now have a flat list of the matrix elements (with their coordinates) in column-major order.

GatherBy[..., Tr@*Last]

This groups those elements by the sum of their coordinates. Note that antidiagonals are lines of constant x+y, so this does exactly the grouping we want. The order within each group is preserved. Now we just need to get rid of the coordinates again. This is done via the rather cryptic:

#&@@@#&/@...

This maps the function #&@@@#& over each group, which itself applies #& to each element in the group, and # is simply the first argument, i.e. the original matrix element.

\$\endgroup\$
  • \$\begingroup\$ Any explanation as to why is read as \[transpose] ? \$\endgroup\$ – Fatalize Apr 6 '16 at 14:51
  • 1
    \$\begingroup\$ @Fatalize It's a private-use Unicode codepoint, and the glyph Mathematica associates with this codepoint is a superscript T: reference.wolfram.com/language/ref/character/Transpose.html ... \[Transpose] is simply the ASCII transliteration of that Unicode character. Copying either the Unicode character or the transliteration into Mathematica will work. \$\endgroup\$ – Martin Ender Apr 6 '16 at 14:53
2
\$\begingroup\$

Octave, 77 bytes

With a little abuse of the accumarray function:

@(M)char(accumarray(((1:size(M,1))+(0:size(M,2)-1)')(:),M(:),[],@(x){num2str(x')}))

This defines an anonymous function. To use it, assign to a varible or use ans.

Input is the matrix with : as row separator. Output is a cell array containing an array for each row (Octave's equivalent to jagged arrays). This is displayed by Octave showing the indices of the cell array and the contents of each cell. Try it here.

To display the result separated by spaces and newlines only: 83 bytes

@(M)char(accumarray(((1:size(M,1))+(0:size(M,2)-1)')(:),M(:),[],@(x){num2str(x')}))

You can also try it here.

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

JavaScript (Firefox), 86 75 bytes

a=>a.concat(a[0]).slice(1).map((_,i)=>[for(v of a)if(n=v[i--])n].reverse())

Saved 11 bytes thanks to @Neil!

Works in Firefox 30+. Takes an array of arrays.

\$\endgroup\$
  • \$\begingroup\$ Nice algorithm, but you can use a.concat(a[0]).slice(1) to get an array of the right length. Also, [for(of)] is not ES6; I normally write it as (Firefox 30+) or some such. \$\endgroup\$ – Neil Apr 6 '16 at 19:55
  • \$\begingroup\$ @Neil Wow, I feel a bit silly not figuring out to use concat and slice. Thanks! \$\endgroup\$ – user81655 Apr 7 '16 at 1:38
2
\$\begingroup\$

Octave, 63 62 bytes

Removed one byte thanks to @DonMue... @LuisMendo!

@(a)cellfun(@(x)x(x>0)',num2cell(spdiags(flipud(a)),1),'un',0)

I went the boring route and munged the antidiagonals.

Sample run on ideone.

\$\endgroup\$
  • \$\begingroup\$ I think you can shorten 'uni' to 'un' \$\endgroup\$ – Luis Mendo Apr 7 '16 at 21:12
  • \$\begingroup\$ @LuisMendo Why, yes I can! Thanks! :) \$\endgroup\$ – beaker Apr 7 '16 at 21:43
2
\$\begingroup\$

Haskell, 83 82 bytes

r=zip[0..]
\o->fst$span(any(>0))[reverse[e|(x,t)<-r o,(v,e)<-r t,x+v==a]|a<-[0..]]

nimi saved a byte. Thanks!

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

Python, 128 bytes (numpy)

(lambda A: (lambda A,S:[[A[U][I-U] for U in range(min(S[1]-1,I),max(I-S[0]+1,0)-1,-1)] for I in range(S[1]+S[0]-1)])(A,A.shape))
\$\endgroup\$
  • \$\begingroup\$ Welcome to Programming Puzzles & Code Golf! By default, submissions to code golf challenge must be programs or functions and use one of the approved methods for I/O. A snippet that expects the input in a hardcoded variable is not allowed. \$\endgroup\$ – Dennis Apr 6 '16 at 23:19
  • \$\begingroup\$ Looks like you can rework the first solution that uses lambda into just a lambda that you can use as your submission. \$\endgroup\$ – Alex A. Apr 6 '16 at 23:22
  • \$\begingroup\$ I will lambda it \$\endgroup\$ – Luis Masuelli Apr 6 '16 at 23:29
  • \$\begingroup\$ lambda A:[[A[U][I-U]for U in range(max(I-len(A)+1,0),min(len(A[0])-1,I)+1)]for I in range(len(A+A[0])-1)] (as in your original revision) would be a bit shorter. Also, you should change A[U][I-U] to A[I-U][U] to get orientation from the question. \$\endgroup\$ – Dennis Apr 6 '16 at 23:40
  • \$\begingroup\$ I will check it when back at home. Makes sense \$\endgroup\$ – Luis Masuelli Apr 6 '16 at 23:48
1
\$\begingroup\$

Pyth, 41 17 bytes

tm_<dx+dYk.T+LaYk

Try it online!

Inspired by @Doorknob's solution to another problem.

How it works:

tm_<dx+dYk.T+LaYk
            +L      prepend to each subarray...
              aYk   (Y += ''). Y is initialized to [],
                    so this prepends [''] to the first
                    subarray, ['', ''] to the second, etc.
                    ['' 1  2  3
                     '' '' 4  5  6
                     '' '' '' 7  8  9
                     '' '' '' '' 10 11 12
                     '' '' '' '' '' 13 14 15]
          .T        transpose, giving us
                    ['' '' '' '' ''
                     1  '' '' '' ''
                     2  4  '' '' ''
                     3  5  7  '' ''
                     6  8  10 ''
                     9  11 13
                     12 14
                     15]
 m_<dx+dYk          removes all empty strings in the
                    subarrays while reversing each one
t                   remove the first subarray

Previous attempt:

JlQKlhQm_m@@Qk-dk}h.MZ,0-dtKh.mb,tJdUt+JK

Try it online!

How it works:

JlQKlhQm_m@@Qk-dk}h.MZ,0-dtKh.mb,tJdUt+JK    input array stored as Q
JlQ                                          J = len(Q)
   KlhQ                                      K = len(Q[0])
       m                            Ut+JK    list for d from 0 to J+K-1:
        _m       }AAAAAAAAAABBBBBBBB             reversed list for k from A to B, where:
                  h.MZ,0-dtK                       A = max(0, d-(K-1))
                       0-dtK                               0  d-(K-1)
                            h.mb,tJd               B = min(J-1, d)
                                 tJd                       J-1  d
          @@Qk-dk                                    Q[k][d-k]
\$\endgroup\$
1
\$\begingroup\$

Groovy, 77 73 75

{i->o=[].withDefault{[]};a=0;i.each{b=0;it.each{o[a+b++].add(0,it)};a++};o}

Takes array of arrays as input and returns array of arrays.

Try it

EDIT: I forgot to output the anwser, after adding it score goes up to 75.

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