Looping in a spiral

前端 未结 30 2417
独厮守ぢ
独厮守ぢ 2020-11-22 15:07

A friend was in need of an algorithm that would let him loop through the elements of an NxM matrix (N and M are odd). I came up with a solution, but I wanted to see if my fe

相关标签:
30条回答
  • 2020-11-22 15:26

    Haskell, take your pick:

    spiral x y = (0, 0) : concatMap ring [1 .. max x' y'] where
        ring n | n > x' = left x' n  ++ right x' (-n)
        ring n | n > y' = up   n  y' ++ down (-n) y'
        ring n          = up n n ++ left n n ++ down n n ++ right n n
        up    x y = [(x, n) | n <- [1-y .. y]]; down = (.) reverse . up
        right x y = [(n, y) | n <- [1-x .. x]]; left = (.) reverse . right
        (x', y') = (x `div` 2, y `div` 2)
    
    spiral x y = filter (\(x',y') -> 2*abs x' <= x && 2*abs y' <= y) .
                 scanl (\(a,b) (c,d) -> (a+c,b+d)) (0,0) $
                 concat [ (:) (1,0) . tail 
                        $ concatMap (replicate n) [(0,1),(-1,0),(0,-1),(1,0)]
                        | n <- [2,4..max x y] ]
    
    0 讨论(0)
  • 2020-11-22 15:26

    //PHP implementation

    function spiral($n) {
    
        $r = intval((sqrt($n + 1) - 1) / 2) + 1;
    
        // compute radius : inverse arithmetic sum of 8+16+24+...=
        $p = (8 * $r * ($r - 1)) / 2;
        // compute total point on radius -1 : arithmetic sum of 8+16+24+...
    
        $en = $r * 2;
        // points by face
    
        $a = (1 + $n - $p) % ($r * 8);
        // compute de position and shift it so the first is (-r,-r) but (-r+1,-r)
        // so square can connect
    
        $pos = array(0, 0, $r);
        switch (intval($a / ($r * 2))) {
            // find the face : 0 top, 1 right, 2, bottom, 3 left
            case 0:
                $pos[0] = $a - $r;
                $pos[1] = -$r;
                break;
            case 1:
                $pos[0] = $r;
                $pos[1] = ($a % $en) - $r;
                break;
            case 2:
                $pos[0] = $r - ($a % $en);
                $pos[1] = $r;
                break;
            case 3:
                $pos[0] = -$r;
                $pos[1] = $r - ($a % $en);
                break;
        }
        return $pos;
    }
    
    for ($i = 0; $i < 168; $i++) {
    
        echo '<pre>';
        print_r(spiral($i));
        echo '</pre>';
    }
    
    0 讨论(0)
  • 2020-11-22 15:27

    Java spiral "Code golf" attempt, based on the C++ variant.

    public static void Spiral(int X, int Y) {
        int x=0, y=0, dx = 0, dy = -1;
        int t = Math.max(X,Y);
        int maxI = t*t;
    
        for (int i=0; i < maxI; i++){
            if ((-X/2 <= x) && (x <= X/2) && (-Y/2 <= y) && (y <= Y/2)) {
                System.out.println(x+","+y);
                //DO STUFF
            }
    
            if( (x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1-y))) {
                t=dx; dx=-dy; dy=t;
            }   
            x+=dx; y+=dy;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:27

    Solution for AutoIt

    #include <Math.au3>
    #include <Array.au3>
    
    Func SpiralSearch($xMax,$yMax)
        $x = 0
        $y = 0
        $dx = 0
        $dy = -1
        for $i=0 To _max($xMax, $yMax)^2-1 Step 1
            if -$xMax/2 < $x and $x <= $xMax/2 And -$yMax/2 < $y And $y <= $yMax/2 Then
                MsgBox(0, "We are here ", $x & " " & $y)
            EndIf
            if $x == $y or ($x < 0 and $x == -$y) or ($x > 0 and $x == 1-$y) Then
                _ArraySwap ($dx, $dy)
                $dx=-$dx
            EndIf
            $x += $dx
            $y += $dy
        Next
    EndFunc
    
    0 讨论(0)
  • 2020-11-22 15:28

    Davidont's excellent solution in VB.Net

        Public Function Spiral(n As Integer) As RowCol
        ' given n an index in the squared spiral
        ' p the sum of point in inner square
        ' a the position on the current square
        ' n = p + a
        ' starts with row 0 col -1
        Dim r As Integer = CInt(Math.Floor((Math.Sqrt(n + 1) - 1) / 2) + 1)
    
        ' compute radius : inverse arithmetic sum of 8+16+24+...=
        Dim p As Integer = (8 * r * (r - 1)) \ 2
        ' compute total point on radius -1 : arithmetic sum of 8+16+24+...
    
        Dim en As Integer = r * 2
        ' points by face
    
        Dim a As Integer = (1 + n - p) Mod (r * 8)
        ' compute the position and shift it so the first is (-r,-r) but (-r+1,-r)
        ' so square can connect
    
        Dim row As Integer
        Dim col As Integer
    
        Select Case Math.Floor(a \ (r * 2))
            ' find the face : 0 top, 1 right, 2, bottom, 3 left
            Case 0
                row = a - r
                col = -r
            Case 1
                row = r
                col = (a Mod en) - r
            Case 2
                row = r - (a Mod en)
                col = r
            Case 3
                row = -r
                col = r - (a Mod en)
        End Select
    
        Return New RowCol(row, col)
    End Function
    
    0 讨论(0)
  • 2020-11-22 15:29

    Here's my solution (in Python):

    def spiral(X, Y):
        x = y = 0
        dx = 0
        dy = -1
        for i in range(max(X, Y)**2):
            if (-X/2 < x <= X/2) and (-Y/2 < y <= Y/2):
                print (x, y)
                # DO STUFF...
            if x == y or (x < 0 and x == -y) or (x > 0 and x == 1-y):
                dx, dy = -dy, dx
            x, y = x+dx, y+dy
    
    0 讨论(0)
提交回复
热议问题