23
\$\begingroup\$

Given two positive numbers N >= 2 and N <= 100 create a matrix which follows the following rules:

  • First Number starts at position [0,0]
  • Second Number starts at position [0,1]
  • Third number goes below First Number (position [1,0])
  • Following numbers goes in "slash" direction
  • Range of numbers used is [1, N1 * N2]. So, numbers goes from starting 1 to the result of the multiplication of both inputs.

Input

  • Two numbers N >= 2 and N <= 100. First number is the amount of rows, Second number the amount of columns.

Output

  • Matrix. (Can be outputted as a multidimensional array or a string with line breaks)

Example:

Given numbers 3 and 5 output:

1   2   4   7   10
3   5   8   11  13
6   9   12  14  15

Given numbers 2 and 2

1   2
3   4

Given Numbers 5 and 5

1   2   4   7   11
3   5   8   12  16
6   9   13  17  20
10  14  18  21  23
15  19  22  24  25

The shortest code in bytes wins.

\$\endgroup\$
6
  • 2
    \$\begingroup\$ Can we use 0 indexing for any of the numbers? \$\endgroup\$
    – Jo King
    Apr 24, 2018 at 12:41
  • 2
    \$\begingroup\$ @JoKing No. Must start at 1. \$\endgroup\$ Apr 24, 2018 at 12:42
  • 5
    \$\begingroup\$ Very closely related. \$\endgroup\$ Apr 24, 2018 at 12:49
  • 1
    \$\begingroup\$ @LuisfelipeDejesusMunoz Perhaps a better term for the order is "diagonals"? Personally, I'd call it a "zig-zag", because it reminds me of Cantor's Zig-Zag proof, but that might confusing. \$\endgroup\$
    – mbomb007
    Apr 24, 2018 at 14:12
  • 2
    \$\begingroup\$ @LuisfelipeDejesusMunoz anti-diagonal is the term for the other diagonal. \$\endgroup\$
    – qwr
    Apr 25, 2018 at 2:45

23 Answers 23

21
\$\begingroup\$

Jelly, 6 5 bytes

pSÞỤs

Try it online!

How it works

pSÞỤs  Main link. Left argument: n. Right argument: k

p      Take the Cartesian product of [1, ..., n] and [1, ..., k], yielding
       [[1, 1], [1, 2], ..., [n, k-1], [n, k]].
 SÞ    Sort the pairs by their sums.
       Note that index sums are constant on antidiagonals.
   Ụ   Grade up, sorting the indices of the sorted array of pairs by their values.
    s  Split the result into chunks of length k.
\$\endgroup\$
11
  • \$\begingroup\$ Damn. Mine is 200+ bytes. Can you add some explanation pls? \$\endgroup\$ Apr 24, 2018 at 13:21
  • 3
    \$\begingroup\$ God damn it, Dennis. Also, good job. \$\endgroup\$
    – Etheryte
    Apr 24, 2018 at 13:35
  • 6
    \$\begingroup\$ Wow, it is too "closely related". That's identical to the first link in miles' answer. Consider upvoting both. :) \$\endgroup\$
    – DELETE_ME
    Apr 24, 2018 at 13:56
  • 1
    \$\begingroup\$ I think it might be possible to do this with <atom><atom>¥þ but I can't find the right combination. oþ++þ is close but doesn't quite get there \$\endgroup\$
    – dylnan
    Apr 24, 2018 at 17:38
  • 1
    \$\begingroup\$ @akozi So far, so good. The indices of the sorted array are [1, 2, 3, 4, 5, 6]. sorts this array, using the key that maps 1 to [1, 1], 2 to [1, 2], 3 to [2, 1], etc. Essentially, this finds the index of each pair from the sorted-by-sums array in the sorted-lexicographically array \$\endgroup\$
    – Dennis
    Apr 26, 2018 at 14:51
8
\$\begingroup\$

Python 3, 91 bytes

def f(n,k):M=[(t//k+t%k,t)for t in range(n*k)];return zip(*k*[map([M,*sorted(M)].index,M)])

Try it online!

\$\endgroup\$
7
\$\begingroup\$

R, 101 60 54 bytes

function(M,N)matrix(rank(outer(1:M,1:N,"+"),,"l"),M,N)

Try it online!

Thanks to @nwellnhof for the suggestion of rank

Ports Dennis' Jelly answer.

Old answer, 101 bytes:

function(M,N)matrix(unsplit(lapply(split(1:(M*N),unlist(split(x,x))),rev),x<-outer(1:M,1:N,"+")),M,N)

Try it online!

split is doing most of the work here; possibly there's a golfier algorithm but this definitely works.

Explanation:

function(M,N){
x <- outer(1:M,1:N,"+")			# create matrix with distinct indices for the antidiagonals
idx <- split(x,x)			# split into factor groups
items <- split(1:(M*N),unlist(idx))	# now split 1:(M*N) into factor groups using the groupings from idx
items <- lapply(items,rev)		# except that the factor groups are
					# $`2`:1, $`3`:2,3, (etc.) but we need
                                        # $`2`:1, $`3`:3,2, so we reverse each sublist
matrix(unsplit(items,x),M,N)		# now unsplit to rearrange the vector to the right order
					# and construct a matrix, returning the value
}

Try it online! -- you can use wrap a print around any of the right-hand sides of the assignments <- to see the intermediate results without changing the final outcome, as print returns its input.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Can you add some explanation pls? \$\endgroup\$ Apr 24, 2018 at 13:36
  • 1
    \$\begingroup\$ @LuisfelipeDejesusMunoz added. If there's anything unclear, let me know and I'll try and clarify. \$\endgroup\$
    – Giuseppe
    Apr 24, 2018 at 13:56
  • 1
    \$\begingroup\$ rank(x,1,"f") is 2 bytes shorter than order(order(x)). \$\endgroup\$
    – nwellnhof
    Apr 25, 2018 at 11:19
  • \$\begingroup\$ @nwellnhof oh, very nice, but using rank(x,,"l") will get rid of the t as well. \$\endgroup\$
    – Giuseppe
    Apr 25, 2018 at 11:26
6
\$\begingroup\$

Java 10, 121 120 109 105 bytes

m->n->{var R=new int[m][n];for(int i=0,j,v=0;i<m+n;)for(j=++i<n?0:i-n;j<i&j<m;)R[j][i-++j]=++v;return R;}

-11 bytes thanks to @OlivierGrégoire.
-4 bytes thanks to @ceilingcat.

Try it online.

Explanation:

m->n->{                // Method with two integer parameters and integer-matrix return-type
  var R=new int[m][n]; //  Result-matrix of size `m` by `n`
  for(int i=0,j,       //  Index integers, starting at 0
          v=0;         //  Count integer, starting at 0
      i<m+n;)          //  Loop as long as `i` is smaller than `m+n`
    for(j=++i<n?0      //   Set `j` to 0 if `i+1` is smaller than `n`
               :i-n;   //   or to the difference between `i` and `n` otherwise
        j<i&j<m;)      //   Inner loop `j` until it's equal to either `i` or `m`,
                       //   so basically check if it's still within bounds:
      R[j][i-++j]=++v; //    Add the current number to cell `j, i-(j+1)`
  return R;}           //  Return the result-matrix
\$\endgroup\$
3
  • \$\begingroup\$ I realized this takes columns first and then rows. \$\endgroup\$ Apr 24, 2018 at 13:33
  • \$\begingroup\$ @Luis I think it's convention to take coordinates as x,y/width,height \$\endgroup\$
    – Jo King
    Apr 24, 2018 at 13:46
  • 2
    \$\begingroup\$ 109 bytes \$\endgroup\$ Apr 25, 2018 at 15:23
5
\$\begingroup\$

J, 15 bytes

$1(+/:@;)</.@i.

-4 more bytes for this solution by miles. Thanks!

Try it online!

J, 22 19 bytes

-3 bytes thanks to FrownyFrog!

,$[:>:@/:@/:@,+/&i.

Try it online!

An implementation of Dennis' fantastic Jelly solution in J.

Explanation:

Dyadic verb, takes left and right argument (m f n)

+/&i. creates lists 0..m-1 and 0..n-1 and makes an addition table for them:

   3 +/&i. 5
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6

[:>:@/:@/:@, flattens the table and grades the list twice and adds 1 to it:

   3 ([:>:@/:@/:@,+/&i.) 5
1 2 4 7 10 3 5 8 11 13 6 9 12 14 15

,$ reshapes the list back into mxn table:

   3 (-@],\[:>:@/:@/:@,+/&i.) 5
1 2  4  7 10
3 5  8 11 13
6 9 12 14 15
\$\endgroup\$
4
  • 1
    \$\begingroup\$ -@],\,$ for −3 bytes. \$\endgroup\$
    – FrownyFrog
    Apr 24, 2018 at 14:18
  • \$\begingroup\$ @FrownyFrog - Of course, I feel stupid, it's so obvous now. Thank you! \$\endgroup\$ Apr 24, 2018 at 14:28
  • 1
    \$\begingroup\$ 15 bytes $1(+/:@;)</.@i. with input as an array [r, c] \$\endgroup\$
    – miles
    Apr 24, 2018 at 14:38
  • \$\begingroup\$ @miles: Very cool, thanks! I tried /. but could't achieve your result :) \$\endgroup\$ Apr 24, 2018 at 18:22
4
\$\begingroup\$

APL+WIN, 38 or 22 bytes

Prompts for integer input column then row:

m[⍋+⌿1+(r,c)⊤m-1]←m←⍳(c←⎕)×r←⎕⋄(r,c)⍴m

or:

(r,c)⍴⍋⍋,(⍳r←⎕)∘.+⍳c←⎕

based on Dennis's double application of grade up. Missed that :(

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Sorry for the question but is there somewhere I can test it? \$\endgroup\$ Apr 24, 2018 at 14:08
  • \$\begingroup\$ @Luis felipe De jesus Munoz No problem. APL+WIN is not available on line but you can test it on the Dyalog website at tryapl.org if you replace the ⎕ characters with the integers of your choice. \$\endgroup\$
    – Graham
    Apr 24, 2018 at 14:35
4
\$\begingroup\$

Wolfram Language (Mathematica), 73 67 bytes

Count elements in rows above: Min[j+k,#2]~Sum~{k,i-1}

Count elements on the current row and below: Max[j-k+i-1,0]~Sum~{k,i,#}

Put into a table and add 1. Voila:

1+Table[Min[j+k,#2]~Sum~{k,i-1}+Max[j-k+i-1,0]~Sum~{k,i,#},{i,#},{j,#2}]&

Update: I realized there is a shorter way to count all the positions ahead of a normally specified position in the matrix with just one sum over two dimensions:

Table[1+Sum[Boole[s-i<j-t||s-i==j-t<0],{s,#},{t,#2}],{i,#},{j,#2}]&

Try it online!

Try it online!

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

APL (Dyalog Unicode), 14 12 bytes

{⍵⍴⍋⍋∊+/↑⍳⍵}

Try it online!

-2 thanks to ngn, due to his clever usage of ↑⍳.

Based off of Dennis's 5-byte Jelly solution.

\$\endgroup\$
2
  • \$\begingroup\$ ∘.+⌿⍳¨⍵ -> +/↑⍳⍵ \$\endgroup\$
    – ngn
    May 4, 2018 at 9:20
  • \$\begingroup\$ @ngn Wow, that's a clever usage of combined with . \$\endgroup\$ May 4, 2018 at 12:53
3
\$\begingroup\$

05AB1E, 23 bytes

*L<DΣ¹LILâOsè}UΣXsè}Á>ô

Try it online!

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

Python 3, 164 bytes

from numpy import*
r=range
def h(x,y):
 a,i,k,j=-array([i//y+i%y for i in r(x*y)]),1,2,0
 while j<x+y:a[a==-j],i,k,j=r(i,k),k,k+sum(a==~j),j+1
 a.shape=x,y;return a

Try it online!

This is definitely not the shortest solution, but I thought it was a fun one.

\$\endgroup\$
2
  • \$\begingroup\$ from numpy import* and dropping both n. is slightly shorter. Also, you can drop the space at ) for. And changing to Python 2 allows you to change return a to print a (in Python 3 it would be the same byte-count print(a)). \$\endgroup\$ Apr 24, 2018 at 14:25
  • \$\begingroup\$ Thanks! I should have thought of import*. I'll never beat Dennis' answer, so I'll stick to Python 3. \$\endgroup\$
    – maxb
    Apr 24, 2018 at 14:36
2
\$\begingroup\$

Python 2, 93 bytes

def f(b,a):i=1;o=[];exec"if b:o+=[],;b-=1\nfor l in o:k=len(l)<a;l+=[i]*k;i+=k\n"*a*b;print o

Try it online!

Semi-Ungolfed version:

def f(b,a):
    i=1
    o=[]
    for _ in range(a*b)
        if b:
            o+=[[]]
            b-=1

        for l in o:
            if len(l)<a:
                l+=[i]
                i+=1
    print o
\$\endgroup\$
2
\$\begingroup\$

Japt, 25 24 bytes

Hardly elegant, but gets the job done. Working with 2D data in Japt is tricky.

;N×Ç<U©Ap[] A®Ê<V©Zp°T
A

;                      // Set alternative default vars where A is an empty array.
 N×Ç                   // Multiply the inputs and map the range [0..U*V).
    <U                 // If the current item is less than the second input,
      ©Ap[]            // add a new empty subarray into A.
            A®         // Then, for each item in A,
              Ê<V      // if its length is less than the first input,
                 ©Zp°T // Add the next number in the sequence to it.
A                      // Output the results, stored in A.

I added the -Q flag in TIO for easier visualization of the results, it doesn't affect the solution.
Bit off one byte thanks to Oliver.

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Speaking of ×, you can replace *V with . \$\endgroup\$
    – Oliver
    Apr 25, 2018 at 0:30
  • 1
    \$\begingroup\$ @Oliver And here I was, thinking that shortcut is handy, but not a common use case. Thanks a lot! \$\endgroup\$
    – Etheryte
    Apr 25, 2018 at 1:03
2
\$\begingroup\$

JavaScript (Node.js), 103 bytes

(a,b,e=[...Array(b)].map(_=>[]))=>f=(x=0,y=i=0)=>(x<a&y<b&&(e[y][x]=++i),x?f(--x,++y):y>a+b?e:f(++y,0))

Try it online!

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

TI-Basic, 76 bytes

Prompt A,B
{A,B🡒dim([A]
1🡒X
For(E,1,B+A
For(D,1,E
If D≤A and E-D<B
Then
X🡒[A](D,E-D+1
X+1🡒X
End
End
End
[A]

Prompts for user input and returns the matrix in Ans and prints it.

TI-Basic is a tokenized language; all tokens used here are one byte, other than [A] which is 2 bytes.

Note: TI-Basic (at least on the TI-84 Plus CE) only supports matrices up to 99x99, and so does this program.

Explanation:

Prompt A,B        # 5 bytes, prompt for user input
{A,B🡒dim([A]      # 9 bytes, make the matrix the right size
1🡒X               # 4 bytes, counter variable starts at 1
For(E,1,B+A       # 9 bytes, Diagonal counter, 1 to A+B-1, but we can over-estimate since we have to check later anyway.
For(D,1,E         # 7 bytes, Row counter, 1 to diagonal count
If D≤A and E-D<B  # 10 bytes, Check if we are currently on a valid point in the matrix
Then              # 2 bytes, If so,
X🡒[A](D,E-D+1     # 13 bytes, Store the current number in the current point in the matrix
X+1🡒X             # 6 bytes, Increment counter
End               # 2 bytes, End dimension check if statement
End               # 2 bytes, End row for loop
End               # 2 bytes, End dimension for loop
[A]               # 2 bytes, Implicitly return the matrix in Ans and print it
\$\endgroup\$
2
\$\begingroup\$

Perl 6, 61 59 bytes

{($!={sort($_ Z=>1..*)>>.{*}})($!([X+] ^<<$_)).rotor(.[1])}

Try it online!

Another port of Dennis' Jelly solution.

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

Java (JDK 10), 142 131 bytes

X->Y->{var A=new int[X][Y];int E=1;for(int y=0;y<Y+X-1;y++)for(int x=0;x<X;x++){if(y-x<0|y-x>Y-1)continue;A[x][y-x]=E++;}return A;}

Try it online!

Explanation:

X->Y->{                            // Method with two integer parameters and integer-matrix return-type
    var A=new int[X][Y];           // The Matrix with the size of X and Y
    int E=1;                       // It's a counter
        for(int y=0;y<Y+X-1;y++)   // For each column plus the number of rows minus one so it will run as long as the bottom right corner will be reached
            for(int x=0;x<X;x++){  // For each row
                if(y-x<0|y-x>Y-1)  // If the cell does not exist becouse it's out of range
                    continue;      // Skip this loop cycle
                A[x][y-x]=E++;     // Set the cell to the counter plus 1
            }
    return A;                      // Return the filled Array
}

Big thank to Kevin Cruijssen because I didn't know how to run my code on tio.
Some code like the header and footer are stolen from him. -> His answer

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

Husk, 9 bytes

ṠCoηÖ¤×,ḣ

Try it online! Most of the heavy lifting is done by ×, which creates pairs in the desired order so that it can support infinite lists.

Explanation

CηÖ×,ḣ²ḣ⁰⁰  (Expanded; let N and K denote the arguments.)
 ηÖ          Take the list of indices of the sorted values of
   ×,         the list of all pairs taken from
     ḣ²        the range from 1 to N and
       ḣ⁰      the range from 1 to K, and
C        ⁰  cut it into lengths of K.
\$\endgroup\$
1
\$\begingroup\$

PHP, 115 bytes

a pretty lazy approach; probably not the shortest possible.

function($w,$h){for(;$i++<$h*$w;$r[+$y][+$x]=$i,$x--&&++$y<$h||$x=++$d+$y=0)while($x>=$w|$y<0)$y+=!!$x--;return$r;}

anonymous function, takes width and height as parameters, returns 2d matrix

try it online

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

JavaScript (Node.js), 108 105 101 100 bytes

n=>(l=>{for(r=[];i<n*n;n*~-n/2+2>i?l++:l--*y++)for(T=y,t=l;t--;)r[T]=[...r[T++]||[],++i]})(y=i=0)||r

Try it online!

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

Attache, 45 bytes

{Chop[Grade//2<|Flat!Table[`+,1:_2,1:_],_]+1}

Try it online!

Anonymous lambda, where paramaters are switched. This can be fixed for +1 byte, by prepending ~ to the program. The test suite does this already.

Explanation

This approach is similar to the J answer and the Jelly answer.

The first idea is to generate a table of values:

Table[`+,1:_2,1:_]

This generates an addition table using ranges of both input parameters. For input [5, 3], this gives:

A> Table[`+,1:3,1:5]
 2 3 4 5 6
 3 4 5 6 7
 4 5 6 7 8

Then, we flatten this with Flat!:

A> Flat!Table[`+,1:3,1:5]
[2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8]

Using the approach in the J answer, we can grade the array (that is, return indices of sorted values) twice, with Grade//2:

A> Grade//2<|Flat!Table[`+,1:3,1:5]
[0, 1, 3, 6, 9, 2, 4, 7, 10, 12, 5, 8, 11, 13, 14]

Then, we need to chop the values up correctly, as in the Jelly answer. We can cut every _ elements to do this:

A> Chop[Grade//2<|Flat!Table[`+,1:3,1:5],5]
 0 1  3  6  9
 2 4  7 10 12
 5 8 11 13 14

Then, we just need to compensate for the 0-indexing of Attache with +1:

A> Chop[Grade//2<|Flat!Table[`+,1:3,1:5],5]+1
 1 2  4  7 10
 3 5  8 11 13
 6 9 12 14 15

And thus we have the result.

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

Python 3, 259 bytes

So I did this a weird way. I noticed that there were two patterns in the way the array forms.

The first is how the top rows pattern has the difference between each term increasing from 1 -> h where h is the height and l is the length. So I construct the top row based on that pattern

For a matrix of dim(3,4) giving a max RoC = 3 We will see the top row of the form

1, (1+1), (2+2), (4+3) = 1, 2, 4, 7

Suppose instead that the dim(3,9) giving a max RoC = 3 we will instead see a top row of

`1, (1+1), (2+2), (4+3), (7+3), (10+3), (13+3), (16+3), (19+3) = 1, 2, 4, 7, 10, 13, 16, 19, 22

The second pattern is how the rows change from one another. If we consider the matrix:

1   2   4   7   11
3   5   8   12  16
6   9   13  17  20
10  14  18  21  23
15  19  22  24  25

and subtract each row from the row below (ignoring the extra row) we get

2 3 4 5 5
3 4 5 5 4
4 5 5 4 3
5 5 4 3 2

Upon seeing this matrix we can notice this matrix is the sequence 2 3 4 5 5 4 3 2 where by each row is 5 terms of this pattern shifted by 1 for each row. See below for visual.

         |2 3 4 5 5| 4 3 2
       2 |3 4 5 5 4| 3 2
     2 3 |4 5 5 4 3| 2
   2 3 4 |5 5 4 3 2|

So to get the final matrix we take our first row we created and output that row added with the 5 needed terms of this pattern.

This pattern will always have the characteristics of beginning 2-> max value and ending max value -> 2 where the max value = min(h+1, l) and the number of times that the max value will appear is appearances of max = h + l -2*c -2 where c = min(h+1, l) - 2

So in whole my method of creating new rows looks like

1  2  3  7  11 +      |2 3 4 5 5|4 3 2  = 3  5  8  12 16

3  5  8  12 16 +     2|3 4 5 5 4|3 4 2  = 6  9  13 17 20

6  9  13 17 20 +   2 3|4 5 5 4 3|4 2    = 10 14 18 21 23

10 14 18 21 23 + 2 3 4|5 5 4 3 2|       = 15 19 22 24 25

Relevant code below. It didn't end up being short but I still like the method.

o,r=len,range
def m(l,h):
 a,t=[1+sum(([0]+[x for x in r(1,h)]+[h]*(l-h))[:x+1]) for x in r(l)],min(l,h+1);s,c=[x for x in r(2,t)],[a[:]]
 for i in r(h-1):
  for j in r(o(a)):
   a[j]+=(s+[t]*(l+h-2*(t-2)-2)+s[::-1])[0+i:l+i][j]
  c+=[a[:]]
 for l in c:print(l)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Japt, 20 bytes

õ ïVõ)ñx
£bYgUñ¹ÄÃòV

Try it

\$\endgroup\$
0
\$\begingroup\$

Haskell, 92 bytes

r=[1..]
(#)=take
n!k=[[sum$lookup(i,j)$zip[(i,j)|s<-r,i<-n#r,j<-k#r,i+j==s]r|j<-k#r]|i<-n#r]

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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