当心矩阵龙卷风!


27

矩阵龙卷风就像其他任何龙卷风一样:它由围绕中心旋转的事物组成。在这种情况下,矩阵元素代替空气。

这是矩阵龙卷风的示例:

Matrix tornado in action

首先,我们将矩阵切成正方形环,每个部分由距离边界相同距离的元素组成。这些部分将围绕中心顺时针旋转。在真正的龙卷风中,严重程度朝中心方向增加,矩阵龙卷风中的旋转步骤也是如此:最外面的部分(红色的部分)旋转1步,下一个部分(黄色的部分)旋转2步,依此类推上。旋转步骤是围绕中心旋转90°。

任务:

您应该接受的任务是编写一个函数或程序,该函数或程序将一个方矩阵作为输入,对其施加龙卷风效果,然后输出结果矩阵。

输入:

输入应为n其中的阶方矩阵n >= 1。无需对矩阵元素进行任何假设,它们可以是任何东西。

输出:

相同阶数的方阵,这是对输入矩阵施加龙卷风效应的结果。

例子:

订单矩阵n = 1

[['Hello']]               ===>    [['Hello']]

订单矩阵n = 2

[[1 , 2],                 ===>    [[5 , 1],
 [5 , 0]]                          [0 , 2]]

订单矩阵n = 5

[[A , B , C , D , E],             [[+ , 6 , 1 , F , A],
 [F , G , H , I , J],              [- , 9 , 8 , 7 , B],
 [1 , 2 , 3 , 4 , 5],     ===>     [/ , 4 , 3 , 2 , C],
 [6 , 7 , 8 , 9 , 0],              [* , I , H , G , D],
 [+ , - , / , * , %]]              [% , 0 , 5 , J , E]]

我想您想澄清一下旋转是90°旋转。
暴民埃里克(Erik the Outgolfer)'18年

另外,您是否从其他地方接受了这一挑战?如果是这样,您必须提供出处。
暴民埃里克(Erik the Outgolfer)'18年

1
@EriktheOutgolfer 1)我已经澄清了。2)这个挑战是我的。
易卜拉欣·马尔里尔

4
@Giuseppe取决于您所在的半球;)
Jo King

12
首先,我想说我认为这是一个很好的挑战:出色的工作!但我也想补充一下这一点,因为我认为您的选择可能是任何类型的数据都使您的挑战变得尴尬。与关于输入为列表列表的陈述类似,您限制了可以解决此问题的语言,而无需进行任何额外的工作。我认为,如果放宽这些要求,挑战会更好。希望您继续提出类似的挑战!:)
FryAmTheEggman '18年

Answers:


5

Python 3字节

import numpy
def f(a):
 if len(a): a=numpy.rot90(a,axes=(1,0));a[1:-1,1:-1]=f(a[1:-1,1:-1]);return a

在线尝试!


8
经典的Python,就像掉下来a[1:-1,1:-1]=f(a[1:-1,1:-1])一样,这是世界上最普通的事情,它可以直接获取并设置二维数组的整个内部
ETHproductions'Aug

1
@ETHproductions公平地说,其中一部分是从numpy
Jo King

1
numpy.rot90(a,1,(1,0))短了3个字节,应该也可以。
Graipher '18年

1
没有任何测试用例的TIO链接的意义是什么?。:S 这里是with(在if len(a):a=...-1字节处删除了空格)。
凯文·克鲁伊森

5

木炭,44字节

≔EθSθWθ«≔Eθ⮌⭆觧θνλθθM¹⁻¹Lθ≔E✂θ¹±¹¦¹✂κ¹±¹¦¹θ

在线尝试!链接是详细版本的代码。仅适用于角色方块,因为Charcoal的默认I / O不能正常排列数组。说明:

≔EθSθ

阅读字符方块。

Wθ«

循环直到它为空。

≔Eθ⮌⭆觧θνλθ

旋转它。

θM¹⁻¹Lθ

打印它,然后将光标从原始角向对角线移动一个正方形。

≔E✂θ¹±¹¦¹✂κ¹±¹¦¹θ

从数组修剪外部。


5

果冻,27个字节

J«þ`UṚ«Ɗ‘ịZU$LСŒĖḢŒHEƊƇṁµG

在线尝试!

我认为这可能要短得多。

           Input: n×n matrix A.
J          Get [1..n].
 «þ`       Table of min(x, y).
    UṚ«Ɗ   min with its 180° rotation.

Now we have a matrix like: 1 1 1 1 1
                           1 2 2 2 1
                           1 2 3 2 1
                           1 2 2 2 1
                           1 1 1 1 1

‘ị          Increment all, and use as indices into...
     LС    List of [A, f(A), f(f(A)), …, f^n(A)]
  ZU$       where f = rotate 90°

Now we have a 4D array (a 2D array of 2D arrays).
We wish to extract the [i,j]th element from the [i,j]th array.

ŒĖ     Multidimensional enumerate

This gives us: [[[1,1,1,1],X],
                [[1,1,1,2],Y],
                ...,
                [[n,n,n,n],Z]]

ḢŒHEƊƇ     Keep elements whose Ḣead (the index) split into equal halves (ŒH)
           has the halves Equal to one another. i.e. indices of form [i,j,i,j]
           (Also, the head is POPPED from each pair, so now only [X] [Y] etc remain.)

ṁµG        Shape this like the input and format it in a grid.

1
你可能只是把µG在页脚和要求您所提交的是25
Xcoder先生

5

Perl 6的78个73 72字节

感谢nwellnhof提供-5个字节!

$!={my@a;{(@a=[RZ] rotor @_: sqrt @_)[1..*-2;1..@a-2].=$!}if @_;@a[*;*]}

在线尝试!

递归代码块,它采用扁平化的2D数组并返回类似的扁平化数组。

说明:

$!={      # Assign code block to pre-declared variable $!
    my@a; # Create local array variable a
   {
     (@a=[RZ]  # Transpose:
             rotor @_: sqrt @_;  # The input array converted to a square matrix
     )[1..*-2;1..@a-2].=$!  # And recursively call the function on the inside of the array
   }if @_;    # But only do all this if the input matrix is not empty
   @a[*;*]  # Return the flattened array
}

您可以使用@a[*;*]而不是map |*,@a将数组展平。(如果有一种方法可以处理未展平的数组和多维下标,那很好,但我想不到一个。)
nwellnhof

但是@a[1..*-2;1..@a-2].=$!有效。
nwellnhof '18

5

八度86 81字节

f(f=@(g)@(M,v=length(M))rot90({@(){M(z,z)=g(g)(M(z=2:v-1,z)),M}{2},M}{1+~v}(),3))

在线尝试!

我知道递归匿名函数并不是在Octave中做事的最短方法,但是到目前为止,它们是最有趣的方法。这是我可以想到的最短的匿名函数,但是我很想被超越。

说明

递归功能是根据定义 由ceilingcat答案。q=f(f=@(g)@(M) ... g(g)(M) ...是带有g(g)(M)递归调用的此类匿名函数的基本结构。因为这会无穷递归下去,我们总结在有条件单元阵列递归调用:{@()g(g)(M),M}{condition}()。参数列表为空的匿名函数会将条件评估延迟到选择条件之后(尽管稍后,我们看到可以使用该参数列表来定义z)。到目前为止,这只是基本的簿记。

现在开始实际工作。我们希望函数以rot90(P,-1)P 返回在g(g)M的中心部分递归调用的矩阵。我们首先设置z=2:end-1可以隐藏在M索引M(z,z)中的矩阵。这样,选择需要被递归调用进一步折腾。该,3零件可确保顺时针旋转。如果您生活在南半球,则可以将此位删除-2个字节。

然后我们做M(z,z)=g(g)M(z,z)。但是,此操作的结果值仅是修改的中心部分,而不是整个P矩阵。因此,我们做{M(z,z)=g(g)M(z,z),M}{2}这基本上是从窃取这个 通过Stewie新的答案。

最后,condition只是当输入为空时递归停止。


南半球+1
吊顶猫

我还没有尝试过在匿名函数中绕过递归,所以我不会尝试,但是我很好奇,看看递归是否比循环中的循环短。
Stewie Griffin

@StewieGriffin我将看看我能做什么:)
Sanchises

@StewieGriffin顺便说一下,请挑战在Octave中发布基于循环的版本来应对这一挑战。我真的很想知道您是否可以击败递归方法。
桑契斯

4

R,87字节

function(m,n=nrow(m)){for(i in seq(l=n%/%2))m[j,j]=t(apply(m[j<-i:(n-i+1),j],2,rev));m}

在线尝试!



可以吗 该图像显示了一个顺时针箭头,下面的说明指出了顺时针旋转...
digEmAll

我一定已经读了十遍这个问题,却从未注意到它是顺时针方向的(因此我发表了评论)。唉。
朱塞佩

恩,告诉我这件事...我是误读帖子的国王:D
digEmAll

1
不幸的是1x1矩阵不起作用(因为seq(0.5)返回1而不是空向量)
digEmAll

4

马耳他25 24 23 22

t"tX@Jyq-ht3$)3X!7Mt&(

在线尝试!

在MATL中建立索引从来都不是一件容易的事,但是通过打高尔夫球,它实际上已经超过了目前最好的果冻答案...

t                       % Take input implicitly, duplicate.  
 "                      % Loop over the columns of the input*
   X@                   % Push iteration index, starting with 0. Indicates the start of the indexing range.
     Jyq-               % Push 1i-k+1 with k the iteration index. Indicates the end of the indexing range
         t              % Duplicate for 2-dimensional indexing.
  t       3$)           % Index into a copy of the matrix. In each loop, the indexing range gets smaller
             3X!        % Rotate by 270 degrees anti-clockwise
                7Mt&(   % Paste the result back into the original matrix. 

*对于n x n矩阵,此程序进行n迭代,而您实际上只需要n/2旋转。但是,MATL(AB)中的索引具有足够的灵活性,因此无法索引不可能的范围只是禁止操作。这样,就不需要浪费字节来使迭代次数恰到好处。



3

K(ngn / k)41 39 38字节

{s#(+,/'4(+|:)\x)@'4!1+i&|i:&/!s:2##x}

在线尝试!

{ } 带参数的功能 x

#x长度x-矩阵的高度

2##x 两份-高度和宽度(假定相同)

s:分配给s“形状”

!s形状为的矩阵的所有索引s,例如!5 5

(0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4
 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4)

这是一个2行矩阵(列表列表),其列对应于5x5矩阵中的索引。

&/ 两行中的最小值:

0 0 0 0 0 0 1 1 1 1 0 1 2 2 2 0 1 2 3 3 0 1 2 3 4

i&|i:分配给i,取反(|),并取最小值(&i

0 0 0 0 0 0 1 1 1 0 0 1 2 1 0 0 1 1 1 0 0 0 0 0 0

这些是5x5矩阵的扁平环号:

4!1+ 加1并取余数模4

(+|:)是通过反转(|-我们需要:使其强制为单声道)然后移置(+-由于它不是“火车”中最右边的动词,所以不需要:)来旋转的函数

4(+|:)\x涂抹4次x,保留中间结果

,/' 压平每个

+ 转置

( )@' 索引左侧的每个值,右侧的每个值

s# 重塑 s


2
我很高兴看到您的代码说明
Galen Ivanov '18

1
@GalenIvanov当然。我认为我不能再打高尔夫了,所以我不妨尝试解释一下。
ngn

谢谢!您的解决方案使我想开始学习k(甚至ngn / k :))
Galen Ivanov '18

@GalenIvanov熟悉J(和APL?),您已经中途了。K更小,更简单,因此我强烈建议您学习它,当然,我很乐意随时在果园里聊天。ngn / k只是真实事物的一个子集,但我的目标是使其变得快速实用。
ngn

是的,我想我要尝试一下。
加伦·伊万诺夫

3

JavaScript(ES6),99个字节

f=(a,k=m=~-a.length/2)=>~k?f(a.map((r,y)=>r.map(v=>y-m>k|m-y>k|--x*x>k*k?v:a[m+x][y],x=m+1)),k-1):a

在线尝试!

怎么样?

给定宽度的方阵 w ^,我们定义:

=w ^-1个2ŤXÿ=最高|ÿ-||X-|

示例输出 ŤXÿ 对于5x5矩阵(w ^=5=2):

2222221个1个1个221个01个221个1个1个222222

我们从 ķ= 然后将所有电池顺时针旋转90° Xÿ 满足:

ŤXÿķ

而其他的则保持不变。

这等效于说如果有以下情况,则单元格不会旋转:

ÿ->ķ 要么 -ÿ>ķ 要么 X2>ķ2 与 X=-X

这是代码中使用的测试:

a.map((r, y) =>
  r.map(v =>
    y - m > k | m - y > k | --x * x > k * k ?
      v
    :
      a[m + x][y],
    x = m + 1
  )
)

然后我们递减 ķ 然后重新开始,直到 ķ=-1个 要么 ķ=-3/2 (取决于 w ^)。无论哪种方式,它都会触发我们的暂停条件:

~k === 0

3

果冻,24字节

ṙ⁹ṙ€
ḊṖ$⁺€ßḷ""ç1$ç-ZUµḊ¡

在线尝试!

我认为这可能要短得多。

林恩


我想知道这样的解决方案!这ḷ""对我来说似乎很神奇^^想要添加一个解释吗?
林恩

@Lynn我期望的最后一件事是听到那ḷ""是神奇的。只是ḷ"有一个额外的"...哦,还有一种可能ḷ"是我已经“发明”了一些东西,因为它经常可以被单个原子代替(因此在这种情况下,不是输入也可以包含0)。
暴民埃里克(Erik the Outgolfer)'18年

2

Haskell,108个字节

e=[]:e
r=foldl(flip$zipWith(:))e
g!(h:t)=h:g(init t)++[last t]
f[x,y]=r[x,y]
f[x]=[x]
f x=r$(r.r.r.(f!).r)!x

在线尝试!

我使用Laikoni的转置并对其进行了一些修改,以将阵列旋转90°:

  e=[]:e;foldr(zipWith(:))e.reverse
 e=[]:e;foldl(flip$zipWith(:))e

说明

r 将阵列旋转90°。

(!)是更高级别的功能:“应用于中心”。g![1,2,3,4,5][1] ++ g[2,3,4] ++ [5]

f 是龙卷风功能:基本大小为1和2(以某种方式0无效)。

最后一行是魔术发生的地方:我们r.r.r.(f!).r在的中间行上应用x,然后旋转结果。让我们把那些中间行中号。我们要递归在中间中号,并让那些,我们可以旋转中号,然后使用(f!)。然后,我们r.r.rM旋转回其原始方向。


2

Java的10,198个 192字节

m->{int d=m.length,b=0,i,j;var r=new Object[d][d];for(;b<=d/2;b++){for(i=b;i<d-b;i++)for(j=b;j<d-b;)r[j][d+~i]=m[i][j++];for(m=new Object[d][d],i=d*d;i-->0;)m[i/d][i%d]=r[i/d][i%d];}return r;}

-6个字节,感谢@ceilingcat

在线尝试。

说明:

m->{                         // Method with Object-matrix as both parameter and return-type
  int d=m.length,            //  Dimensions of the matrix
      b=0,                   //  Boundaries-integer, starting at 0
      i,j;                   //  Index-integers
  var r=new Object[d][d];    //  Result-matrix of size `d` by `d`
  for(;b<=d/2;b++){          //  Loop `b` in the range [0, `d/2`]
    for(i=b;i<d-b;i++)       //   Inner loop `i` in the range [`b`, `d-b`)
      for(j=b;j<d-b;)        //    Inner loop `j` in the range [`b`, `d-b`)
        r[j][d+~i]=          //     Set the result-cell at {`j`, `d-i-1`} to:
          m[i][j++];         //      The cell at {`i`, `j`} of the input-matrix
    for(m=new Object[d][d],  //   Empty the input-matrix
        i=d*d;i-->0;)        //   Inner loop `i` in the range (`d*d`, 0]
      m[i/d][i%d]            //     Copy the cell at {`i/d`, `i%d`} from the result-matrix
        =r[i/d][i%d];}       //      to the replaced input-matrix
  return r;}                 //  Return the result-matrix as result

b基本上用来表示我们在哪一环。然后,它将在每次迭代期间顺时针旋转一次该环,包括其中的所有内容。

因为Java是按引用传递的,所以完成了输入矩阵的替换,因此简单地设置r=m将意味着从单元格复制时两个矩阵都被修改,从而导致错误的结果。因此,我们必须创建一个新的Object-matrix(新引用),然后逐个复制每个单元格中的值。


1

MATLAB,93字节

function m=t(m),for i=0:nnz(m),m(1+i:end-i,1+i:end-i)=(rot90(m(1+i:end-i,1+i:end-i),3));end;end

我相信这可以通过某种方式打更多。

说明

function m=t(m),                                                                          end % Function definition
                for i=0:nnz(m),                                                       end;    % Loop from 0 to n^2 (too large a number but matlab indexing doesn't care)
                                                            m(1+i:end-i,1+i:end-i)            % Take the whole matrix to start, and then smaller matrices on each iteration
                                                      rot90(                      ,3)         % Rotate 90deg clockwise (anti-clockwise 3 times)
                               m(1+i:end-i,1+i:end-i)=                                        % Replace the old section of the matrix with the rotated one

1

C(GCC) 128 118 115字节

@ceilingcat的-15个字节

j,i;f(a,b,w,s)int*a,*b;{for(j=s;j<w-s;j++)for(i=s;i<w-s;)b[~i++-~j*w]=a[i*w+j];wmemcpy(a,b,w*w);++s<w&&f(a,b,w,s);}

在线尝试!


1

Haskell,274个字节

w是主要功能,具有[[a]] -> [[a]]您所期望的类型。

我相信更有经验的Haskell高尔夫球手可以在此方面有所改进。

w m|t m==1=m|0<1=let m'=p m in(\a b->[h a]++x(\(o,i)->[h o]++i++[f o])(zip(tail a)b)++[f a])m'(w(g m'))
p m|t m==1=m|0<1=z(:)(f m)(z(\l->(l++).(:[]))(r(x h(i m)):(p(g m))++[r(x f(i m))])(h m))
t[]=1
t[[_]]=1
t _=0
h=head
f=last
x=map
i=tail.init
g=x i.i
z=zipWith
r=reverse

您可能想查看我们在Haskell打高尔夫球的技巧,例如,使用护卫代替条件护腕可以节省一些字节。
Laikoni '18
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.