【问题标题】:How to construct a spiral matrix in R?如何在R中构造一个螺旋矩阵?
【发布时间】:2020-04-14 10:34:03
【问题描述】:

我试图创建一个如下图所示的螺旋矩阵(给定维度N,其中N=4 在下图中)

有没有实现它的 R 包?我没有找到它。否则,任何人都可以帮助我在基本 R 操作中构建它吗?提前致谢!

【问题讨论】:

  • 市面上有很多 R 包,但如果它们中的任何一个实现了这一点,我会感到惊讶(除非有一个 R 包专门用于解决编程难题和面试问题的 R 解决方案)。这很有趣,但似乎没有那种实用程序可以保证将其包含在一个包中。出于好奇,你为什么要这样做?我想不出任何此类事情的统计应用程序。
  • @JohnColeman 感谢您的回复!我正在为一般编程任务练习 R,而不是用于统计用途
  • 似乎没有任何方法可以对这类事情进行矢量化。 whilefor 循环可能是最好的方法。创建一个填充了 0 的 N × N 矩阵是一个好的开始(例如 matrix(0,nrow = N,ncol = N),因此在循环过程中,您可以知道您何时处于需要值的单元格。也许 this question 可能会给您一些想法。
  • @JohnColeman 再次感谢您!我去看看
  • 这里有几个解决方案:rosettacode.org/wiki/Spiral_matrix#R

标签: r matrix


【解决方案1】:

我不确定是否有特别包含螺旋矩阵构造的包,所以我只提供一个基础 R 解决方案

SpiralMatrix <- function(n) {
  M <- matrix(nrow = n,ncol = n);
  #  start from element M(1,1)
  i <- j <- 1;
  s <- 1; # first element assigned to M(1,1)
  M[i,j] = s;
  repeat {
    #  fill row from left to right
    idx <- tail(which(is.na(M[i,])),1);
    M[i,j:idx] <- s + (0:(idx-j));
    s <- s + idx - j;
    j <- idx;
    if (all(!is.na(M))) break

    #  fill column from top to bottom
    idx <- tail(which(is.na(M[,j])),1);
    M[i:idx,j] <- s + (0:(idx-i));
    s <- s + idx - i;
    i <- idx;
    if (all(!is.na(M))) break

    #  fill row from right to left
    idx <- head(which(is.na(M[i,])),1);
    M[i,j:idx] <- s + (0:(j-idx));
    s <- s + j - idx;
    j <- idx;
    if (all(!is.na(M))) break

    # fill column from bottom to top
    idx <- head(which(is.na(M[,j])),1);
    M[i:idx,j] <- s + (0:(i-idx));
    s <- s + i-idx;
    i <- idx;
    if (all(!is.na(M))) break
  }
  M
}

这样

> SpiralMatrix(5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]   16   17   18   19    6
[3,]   15   24   25   20    7
[4,]   14   23   22   21    8
[5,]   13   12   11   10    9
> SpiralMatrix(4)
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]   12   13   14    5
[3,]   11   16   15    6
[4,]   10    9    8    7

【讨论】:

    【解决方案2】:

    所以我需要从中间开始的螺旋矩阵。解决方案如下。

    # Spiral matrix Generation
    
    # Func Generating starting matrix, integer cellRange must be UNEVEN
    StartMatrix = function(cellRange){
      if((cellRange %% 2) == 0){
        print("cellRange must be UNEVEN integer.")
      }
      else{
        return(matrix(1,cellRange,cellRange))      
      }
    
    }
    
    Matrix = StartMatrix(11)
    # Starts in middle
    Column_Position = round(ncol(Matrix)/2)
    Row_Position = round(nrow(Matrix)/2)
    # Starting parameters
    Number = 1
    Direction = factor('Right', levels = c('Right', 'Up','Left','Down'))
    step = 0
    Side_counter = 0
    stepLeft = 1
    # Sequence
    for (i in c(1:(nrow(Matrix)*ncol(Matrix)))){
      Matrix[Row_Position,Column_Position] = Number
      # Position changer
      if(Direction == 'Right'){
        Column_Position<<-Column_Position+1
        Row_Position<<-Row_Position
      }
      if(Direction == 'Up'){
        Column_Position<<-Column_Position
        Row_Position<<-Row_Position-1
      }
      if(Direction == 'Left'){
        Column_Position<<-Column_Position-1
        Row_Position<<-Row_Position
      }
      if(Direction == 'Down'){
        Column_Position <<- Column_Position
        Row_Position <<- Row_Position+1
      }
      # If number of steps reaches side end. Direction is changed. Steps resets to 0 
      step = step + 1
      if (step == stepLeft){
        Side_counter <<- Side_counter + 1
        step = 0
        if(Direction == 'Right'){
          Direction = "Up"
        }else if(Direction == 'Up'){
          Direction = "Left"
        }else if(Direction == 'Left'){
          Direction = "Down"
        }else if(Direction == 'Down'){
          Direction = "Right"
        }
      }
      # Each second time direction is changed Steps that can be done rises by 1.
      if (Side_counter == 2){
        Side_counter<<-0 
        stepLeft<<-stepLeft +1
      }
      Number <<- Number + 1
    }
      
    Matrix
    

    结果:

        > Matrix
          [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
     [1,]  101  100   99   98   97   96   95   94   93    92    91
     [2,]  102   65   64   63   62   61   60   59   58    57    90
     [3,]  103   66   37   36   35   34   33   32   31    56    89
     [4,]  104   67   38   17   16   15   14   13   30    55    88
     [5,]  105   68   39   18    5    4    3   12   29    54    87
     [6,]  106   69   40   19    6    1    2   11   28    53    86
     [7,]  107   70   41   20    7    8    9   10   27    52    85
     [8,]  108   71   42   21   22   23   24   25   26    51    84
     [9,]  109   72   43   44   45   46   47   48   49    50    83
    [10,]  110   73   74   75   76   77   78   79   80    81    82
    [11,]  111  112  113  114  115  116  117  118  119   120   121
    

    对 Thomas 提供的解决方案进行一些简单的转换也可以获得类似的结果。

    【讨论】:

      猜你喜欢
      • 2022-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多