矩阵以“斜杠”顺序


23

给定两个正数,N >= 2N <= 100创建一个遵循以下规则的矩阵:

  • 第一个数字从位置开始 [0,0]
  • 第二个数字从位置开始 [0,1]
  • 第三个数字低于第一个数字(位置[1,0]
  • 以下数字朝“斜线”方向移动
  • 使用的数字范围是[1, N1 * N2]。因此,数字从开始1到两个输入相乘的结果。

输入项

  • 两个数字N >= 2N <= 100。第一个数字是行数,第二个数字是列数。

输出量

  • 矩阵。(可以输出为多维数组或带换行符的字符串)

例:

给定数字3 and 5输出:

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

给定数字 2 and 2

1   2
3   4

给定数字 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

以字节为单位的最短代码获胜。


2
我们可以对任何数字使用0索引吗?
Jo King

2
@JoKing号必须从1开始
路易斯·费利佩·穆尼奥斯耶稣


1
@LuisfelipeDejesusMunoz也许对命令更好的术语是“对角线”?就我个人而言,我将其称为“之字形”,因为它使我想起了Cantor的之字形证明,但这可能会造成混淆。
mbomb007 '18

2
@LuisfelipeDejesusMunoz反对角线是另一个对角线的术语。
qwr

Answers:


21

果冻6 5字节

pSÞỤs

在线尝试!

怎么运行的

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.

该死的。我的是200+字节。您可以添加一些说明吗?
路易斯·费利佩·德·耶稣·穆诺兹

3
真该死,丹尼斯。另外,做得好。
Nit

6
哇,它太“紧密相关”了。这与Miles答案中的第一个链接相同。考虑同时投票。:)
user202729 '18

1
我认为这样做可能是可行的,<atom><atom>¥þ但我找不到正确的组合。oþ++þ距离很近但还没到那儿
dylnan

1
@akozi到目前为止,太好了。排序数组的索引为[1, 2, 3, 4, 5, 6]使用映射1[1, 1]2[1, 2]3[2, 1]等的键对数组进行排序。本质上,这是从sorted-lexicographically数组中的sum-by-sums数组中找到每一对的索引
Dennis,


7

R101 60 54字节

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

在线尝试!

感谢@nwellnhof的建议 rank

Ports Dennis的果冻答案

旧答案,101个字节:

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

在线尝试!

split在这里完成大部分工作;可能有一个高尔夫球手算法,但这绝对有效。

说明:

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
}

在线尝试!-您可以print在任务的任意右侧使用自动换行,<-以查看中间结果,而无需更改最终结果,因为print它会返回其输入。


1
您可以添加一些说明吗?
路易斯·费利佩·德·耶稣·穆诺兹

1
@LuisfelipeDejesusMunoz添加了。如果有任何不清楚的地方,请告诉我,我会尽力澄清。
朱塞佩

1
rank(x,1,"f")比短2个字节order(order(x))
nwellnhof

@nwellnhof哦,非常好,但是使用rank(x,,"l")也会摆脱它t
朱塞佩

6

爪哇10,121个 120 109 105字节

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个字节,感谢@OlivierGrégoire
-4个字节,感谢@ceilingcat

在线尝试。

说明:

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

我意识到这首先需要列,然后是行。
路易斯·费利佩·德·耶稣·穆诺兹

@Luis我认为这是惯例采取坐标x,y/width,height
乔金


5

J,15个字节

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

此解决方案的其他字节数增加了-4英里。谢谢!

在线尝试!

J22 19字节

-3个字节,感谢FrownyFrog!

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

在线尝试!

用J实现Dennis出色的Jelly解决方案。

说明:

二进位动词,带有左右参数(MFN)

+/&i. 创建列表0..m-1和0..n-1并为其创建加法表:

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

[:>:@/:@/:@, 展平表并为列表评分两次,并对其加1:

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

,$ 将列表重塑为mxn表:

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

1
-@],\,$-3个字节。
FrownyFrog

@FrownyFrog-当然,我觉得自己很愚蠢,现在是如此愚蠢。谢谢!
Galen Ivanov

1
15个字节$1(+/:@;)</.@i.作为数组输入[r, c]
英里

@miles:非常酷,谢谢!我尝试过,/.但无法实现您的结果:)
Galen Ivanov

4

APL + WIN,38或22个字节

提示输入整数列然后行:

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

要么:

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

基于丹尼斯对成绩的双重应用。错过了:(


1
很抱歉这个问题,但是我可以在某个地方进行测试吗?
路易斯·费利佩·德·耶稣·穆诺兹

@路易斯·费利佩·德·耶稣·穆诺兹没问题。APL + WIN无法在线使用,但是如果将⎕字符替换为您选择的整数,则可以在Dyalog网站tryapl.org上对其进行测试。
格雷厄姆

4

Wolfram语言(Mathematica)73 67字节

计算上方各行中的元素: Min[j+k,#2]~Sum~{k,i-1}

计算当前行及以下的元素: Max[j-k+i-1,0]~Sum~{k,i,#}

放入表中并添加1. Voila:

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

更新:我意识到有一种较短的方法可以对矩阵中通常指定的位置之前的所有位置进行计数,而在两个维度上只有一个总和:

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

在线尝试!

在线尝试!




2

Python 3,164字节

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

在线尝试!

这绝对不是最短的解决方案,但我认为这是一个有趣的解决方案。


from numpy import*和同时删除两者的n.时间略短。另外,您可以将空格放在) for。并且更改为Python 2允许您更改return aprint a(在Python 3中将是相同的byte-count print(a))。
凯文·克鲁伊森

谢谢!我应该想到的import*。我永远不会击败丹尼斯的答案,所以我会坚持使用
Python3。– maxb

2

Python 2,93个字节

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

在线尝试!

半平底版本:

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

2

Japt25 24字节

几乎不优雅,但可以完成工作。在Japt中处理2D数据非常棘手。

;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.

-Q在TIO中添加了该标志,以便更直观地显示结果,它不会影响解决方案。
多亏了奥利弗(Oliver),少了一个字节。

在线尝试!


说到×,您可以替换*V
奥利弗

1
@Oliver在这里,我认为快捷方式很方便,但不是常见的用例。非常感谢!
Nit


2

TI-Basic,76个字节

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]

提示用户输入并返回矩阵Ans并进行打印。

TI-Basic是 标记化语言;这里使用的所有令牌都是一个字节,除了[A]2个字节。

注意:TI-Basic(至少在TI-84 Plus CE上)仅支持高达99x99的矩阵,因此该程序也支持。

说明:

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


2

Java(JDK 10)142131字节

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;}

在线尝试!

说明:

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
}

非常感谢Kevin Cruijssen,因为我不知道如何在tio上运行我的代码。
诸如页眉和页脚之类的代码已从他那里窃取。->他的答案


1
119字节:tio.run/...
实施例无知


1

PHP,115字节

一种很懒惰的方法;可能不是最短的时间。

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;}

匿名函数,将width和height作为参数,返回二维矩阵

在线尝试



1

附件,45字节

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

在线尝试!

匿名lambda,其中参数已切换。通过添加前缀,可以将其固定为+1个字节~在程序。测试套件已经做到了。

说明

这种方法类似于J答案Jelly答案

第一个想法是生成一个值表:

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

这将使用两个输入参数的范围生成一个加法表。对于input [5, 3],这给出:

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

然后,我们使用以下方法将其展平Flat!

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

使用J答案中的方法,我们可以对数组(即,排序后的值的返回索引)进行两次评分,方法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]

然后,我们需要像Jelly答案中那样正确地将值切碎。我们可以削减所有_元素来做到这一点:

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

然后,我们只需要使用以下方法补偿Attache的0索引+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

这样我们得到了结果。


1

Python 3,259字节

所以我这样做很奇怪。我注意到数组形成的方式有两种模式。

第一个是顶部行模式如何使每个项之间的差从1-> h增加,其中h是高度,l是长度。所以我根据该模式构造了第一行

对于dim(3,4)给出的矩阵,max RoC = 3我们将看到表格的第一行

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

假设给定a的dim(3,9)max RoC = 3相反会看到

`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

第二种模式是行如何彼此改变。如果考虑矩阵:

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

并从下面的行中减去每一行(忽略多余的行),我们得到

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

看到此矩阵后,我们可以注意到该矩阵是一个序列2 3 4 5 5 4 3 2,其中每一行是该模式的5个项,每行偏移1。视觉内容请见下文。

         |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|

因此,要获得最终矩阵,我们将创建第一行并输出该行,并添加此模式的5个必要条件。

这种模式将始终有开始的特性2-> max value和结束max value -> 2max value = min(h+1, l)和最大值将出现的次数是appearances of max = h + l -2*c -2哪里c = min(h+1, l) - 2

所以总的来说,我创建新行的方法看起来像

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

下面的相关代码。最终并没有变得很短,但是我仍然喜欢这种方法。

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)

在线尝试!


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.