根据逆时针螺旋路径对方阵数组的行进行排序

问题描述 投票:0回答:4

我已经问过类似的问题,但我需要不同的效果。原来的问题是这里


我有一个简单的数组。数组长度始终是平方数。所以 16、25、36 等等

$array = array('1', '2', '3', '4' ... '25');

我所做的就是用 HTML 排列数组,使其看起来像一个具有偶数边的块。

我想做的是对元素进行排序,这样当我将 JSON 编码的数组传递给 jQuery 时,它将迭代该数组,淡入当前块,这样我就会得到一个圆形动画。所以我想像这样对数组进行排序

所以我的排序数组看起来像

$sorted = array('1', '6', '11'', '16', '21', '22', '23' .. '13');

有办法吗?...谢谢


编辑:

我试图通过创建类似矩阵的列/行数组来做到这一点:

$side = 5;

$elems = $side*$side;
$array = range(1,$elems);

for($i=1; $i <= $side; $i++) {
   for($x=$i; $x <= $elems; $x=$x+$side) {
      $columns[$i][] = $x; 
   }
}

for($i=1, $y=1; $i <= $elems; $i=$i+$side, $y++) {
   for($x=$i; $x < $side+$i; $x++) {
      $rows[$y][] = $x;
   }
}

我的下一步是从第一列开始,如果它直接在最后一个元素列上,则在最后,在最后一个元素上结束,等等。如果有人有更好的想法,那就太好了:)

php arrays algorithm sorting animation
4个回答
1
投票

只要网格始终是正方形,这就可以工作:

<?php

    // The size of the grid - 5x5 in the example above
    $gridSize = 5;

    // Create a 2D array representing the grid
    $elements = array_chunk(range(1, pow($gridSize, 2)), $gridSize);

    // Find the half way point - this will be the end of the loop since we
    // want to stop in the middle
    $end = ceil($gridSize / 2);

    // An array to hold the result    
    $result = array();

    // The stopping point of the current interation
    $stop = $gridSize;

    // Loop from start to the middle
    for ($i = 0; $i < $end; $i++) {

        // start in the top left corner
        $x = $y = $i;

        // Traverse Y top to bottom
        while ($y < $stop) {
            $result[] = $elements[$y++][$x];
        }
        $y--;
        $x++;

        // Traverse X left to right
        while ($x < $stop) {
            $result[] = $elements[$y][$x++];
        }
        $x--;
        $y--;

        // Traverse Y bottom to top
        while ($y >= $gridSize - $stop) {
            $result[] = $elements[$y--][$x];
        }
        $y++;
        $x--;

        // Make sure we come in a level
        $stop--;

        // Traverse X right to left
        while ($x >= $gridSize - $stop) {
            $result[] = $elements[$y][$x--];
        }
    }

    print_r($result);

看到它工作了


0
投票

这应该有效。您可以将任何数组传递给circularSort函数,它将返回您的排序数组。

/*
Get the circular sorted array
*/
function circularSort($array)
{
    //Get the length of array
    $arrayLength = count($array);
    //Find the square root of length of array
    $arrayRows = sqrt($arrayLength);

    //Divide the arrays in $arrayRows
    $arrayChunks = array_chunk($array,$arrayRows);
    $circularArray = array();

    //Call Circular Array function .. Result will be stored in $circularArray
    circularArray($arrayChunks,$circularArray);
    return $circularArray;
}

/*
Loop arrayChunk in following order
1. Fetch first item from each chunks
2. Fetch all items from last chunk and remove that array from arrayChunk
3. Reverse elements in each remaining chunk
4. Reverse entire arrayChunk array
5. Repeat above 4 steps until $arrayChunks is empty
*/
function circularArray(&$arrayChunks, &$circularArray)
{
    if(empty($arrayChunks))
    {
        return true;
    }

    //1. Fetch first item from each chunks
    foreach($arrayChunks as &$arrayChunk)
    {
        $circularArray[] = array_shift($arrayChunk);
    }

    //Fetch Last Chunk from array
    $lastChunk = array_pop($arrayChunks);

    //2. Fetch all items from last chunk and remove that array from arrayChunk
    foreach($lastChunk as $chunkElement)
    {
        $circularArray[] = $chunkElement;
    }

    //3. Reverse elements in each remaining chunk
    foreach($arrayChunks as &$arrayChunk)
    {  
        if (is_array($arrayChunk))
        {    
            $arrayChunk = array_reverse($arrayChunk);
        }
    }

    $arrayChunks = array_reverse($arrayChunks);

    return circularArray(&$arrayChunks, &$circularArray);
}

例如

$array = range(1, 25);
$circularArray = circularSort($array);

0
投票

O(n) 的另一种方法:

<?php
function circ_sort ($inArray) {

    $rowSize = pow(count($inArray), 0.5);
    if((int)$rowSize != $rowSize) {
        throw new InvalidArgumentException();
    }
    $rowSize = (int)$rowSize;

    $round =-1;
    for ($x =-1, $y=0, $count =0; $count < count($inArray);) {

        if ($y > $x) {
            if ($x +1 == $y) {
                $direction = 'D';   //Down
                $round ++;
                $max_iter = $rowSize - (2 * $round);
            } else {
                $direction = 'L'; //Left
                $max_iter = $y - $x -1;
            }
        } else if ($x > $y) {
            $direction = 'R'; //Right
            $max_iter = $rowSize - (2 * $round) -1;

        } else if ($x == $y) {
            $direction = 'U'; //Up
            $max_iter = $rowSize - (2 * $round) -1;

        }

        switch ($direction) {
            case 'D':   //Down
                for ($iter =0; $iter < $max_iter; $iter++) {
                    $x++;
                    $circArray[] = $inArray[$x*$rowSize + $y];
                    $count++;
                }
                break;
            case 'R': //Right
                for ($iter =0; $iter < $max_iter; $iter++) {
                    $y++;
                    $circArray[] = $inArray[$x*$rowSize + $y];
                    $count++;
                }
                break;
            case 'U':   //Up
                for ($iter =0; $iter < $max_iter; $iter++) {
                    $x--;
                    $circArray[] = $inArray[$x*$rowSize + $y];
                    $count++;
                }
                break;
            case 'L':   //Left
                for ($iter =0; $iter < $max_iter; $iter++) {
                    $y--;
                    $circArray[] = $inArray[$x*$rowSize + $y];
                    $count++;
                }
                break;
        }
    }
    return ($circArray);
}

$array = range(1, 25);
$circ_array = circ_sort($array);

var_dump($circ_array);

?>

0
投票

我的解决方案:

技巧是:第一次运行是 5 个元素,然后两次运行 4 个元素、两个 3 个元素、两个 2 个元素和两个 1 个元素。 (5,4,4,3,3,2,2,1,1) 在每次运行中,都会增加一个状态模块 4。根据状态,运行会朝一个方向或另一个方向进行。

这是代码:

function circularSort(array $array) {
    $n2=count($array);
    $n=sqrt($n2);
    if((int)$n != $n) throw new InvalidArgumentException();

    $Result = Array();
    $run =$n; $dir=1;
    $x=0; $y=-1;
    $i=0;
    $st=0;
    while ($run) {
        while ($dir) {
            for ($j=0; $j<$run; $j++) {

                if ($st==0) $y++;
                if ($st==1) $x++;
                if ($st==2) $y--;
                if ($st==3) $x--;

                $p=$y * $n +$x;
                array_push($Result,$array[$p]);

            }
            $st = ($st +1) & 3;
            $dir--;
        }

        $dir=2;
        $run--;
    } 

    return $Result;
}

$a = range(1,25);
var_dump(circularSort($a));
© www.soinside.com 2019 - 2024. All rights reserved.