PHP - 创建一个螺旋

时间:2011-04-30 17:04:12

标签: php arrays

假设我有$rows = 4$cols = 4;,如何以螺旋顺序创建包含16个元素的数组,例如:

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

3 个答案:

答案 0 :(得分:5)

我的解决方案非常详细,因为您的目的是检查它并了解它是如何工作的。

<?php
/**
 * Creates a 2D array with the given dimensions,
 * whose elements are numbers in increasing order
 * rendered in a 'spiral' pattern.
 */
function createSpiral($w, $h) {
   if ($w <= 0 || $h <= 0) return FALSE;

   $ar   = Array();
   $used = Array();

   // Establish grid
   for ($j = 0; $j < $h; $j++) {
      $ar[$j] = Array();
      for ($i = 0; $i < $w; $i++)
          $ar[$j][$i]   = '-';
   }

   // Establish 'used' grid that's one bigger in each dimension
   for ($j = -1; $j <= $h; $j++) {
      $used[$j] = Array();
      for ($i = -1; $i <= $w; $i++) {
          if ($i == -1 || $i == $w || $j == -1 || $j == $h)
             $used[$j][$i] = true;
          else
             $used[$j][$i] = false;
      }
   }

   // Fill grid with spiral
   $n = 0;
   $i = 0;
   $j = 0;
   $direction = 0; // 0 - left, 1 - down, 2 - right, 3 - up
   while (true) {
      $ar[$j][$i]   = $n++;
      $used[$j][$i] = true;

      // Advance
      switch ($direction) {
         case 0:
            $i++; // go right
            if ($used[$j][$i]) { // got to RHS
               $i--; $j++; // go back left, then down
               $direction = 1;
            }
            break;
        case 1:
           $j++; // go down
           if ($used[$j][$i]) { // got to bottom
               $j--; $i--; // go back up, then left
               $direction = 2;
            }
            break;
         case 2:
            $i--; // go left
            if ($used[$j][$i]) { // got to LHS
               $i++; $j--; // go back left, then up
               $direction = 3;
            }
            break;
         case 3:
            $j--; // go up
            if ($used[$j][$i]) { // got to top
               $j++; $i++; // go back down, then right
               $direction = 0;
            }
            break;
       }

       // if the new position is in use, we're done!
       if ($used[$j][$i])
           return $ar;
   }
}

/**
 * Assumes the input is a 2D array.
 */
function print2DGrid($array) {
   foreach ($array as $row) {
       foreach ($row as $col) {
          print sprintf("% 2d ", $col);
       }
       print "\n";
   }
}


$width  = 12;
$height = 8;

print2DGrid(createSpiral($width, $height));
?>

Here it is正在执行,提供以下输出:

 0  1  2  3  4  5  6  7  8  9 10 11 
35 36 37 38 39 40 41 42 43 44 45 12 
34 63 64 65 66 67 68 69 70 71 46 13 
33 62 83 84 85 86 87 88 89 72 47 14 
32 61 82 95 94 93 92 91 90 73 48 15 
31 60 81 80 79 78 77 76 75 74 49 16 
30 59 58 57 56 55 54 53 52 51 50 17 
29 28 27 26 25 24 23 22 21 20 19 18 

希望这有帮助。

答案 1 :(得分:3)

使用向量和布尔值。在X轴上迭代开始,直到到达行尾。在遍历每个位置时将值设置为true。无论何时到达边框或布尔值为true,请向右转。

因此,在第一行,你的“向量”会将X增量更改为零,Y增量为1.然后,您将检查每个回合的增量值,并适应4种情况。

这是我想到的第一种方式。

第二种方式不会使用布尔值,而只是简单地跟踪光标在其路径上留下多少列或行,减少每一圈剩余的X或Y.其余的逻辑将保持不变。

当你到达中心时,你会遇到一个不再有迭代的循环。你可以通过验证方块周围的可能性数量,或者从你开始的地方的N个总方格数倒数来计算,并在数字达到零时停止。

您可以将上述方法用于任何大小的正方形。

答案 2 :(得分:1)

算法并不是很困难。您必须从1迭代到$rows*$cols。在迭代期间,您必须计算矩阵($x,$y)中当前数字的位置。第一个将在(1,1)当然。以下是($x+1,$y),因为你正朝东。因此,每个数字的位置取决于前一个数字的位置和当前方向。

算法的棘手部分是计算方向。但是如果你看一下它,你会发现每次撞到一个用过的单元格时方向都会顺时针改变,或者你越界了。

总而言之,这将是~30行PHP代码。

我希望这会有所帮助。

PHP高尔夫中也存在类似的挑战:http://www.phpgolf.org/challenge/Spiral。有人用130个字符解决了它!