# 一题多解 -- 循环填充二维数组

### 问题描述

1   2   3   4
10  11  12  5

9   8   7   6

### 解题思路1

从右到左 (x,y) -> ( x, y - 1 )

从下到上  (x,y) -> (x-1,y)

int directionMap[][2] = {
{ 0 , 1 },   // left -> right
{ 1 , 0 },   // top  -> bottom
{ 0 , -1 },  // right -> left
{ -1 , 0 },  // bottom -> top
};

#include <iostream>
#include <iomanip>
#include <memory>
using namespace std;

namespace CyclePrint
{
// map the two dimensional array index to flat index
class IndexMap
{
public:
IndexMap( int Column )
:m_nColumn(Column) {}

inline int operator()( int X, int Y ) const
{
return X * m_nColumn + Y;
}
private:
int m_nColumn;
};

void DeleteArray( int* array )
{
if( array )
{
delete [] array;
}
}

void DoPrint( int Row , int Column )
{
if ( Row <= 0 || Column <= 0 )
return ;

// create a flat array to store the data
shared_ptr<int> matrixAutoRelease( new int[Row * Column] , DeleteArray );

int * matrix = matrixAutoRelease.get();
memset( matrix , 0 , sizeof(int) * Row * Column );

int directionMap[][2] = {
{ 0 , 1 },   // left -> right
{ 1 , 0 },   // top  -> bottom
{ 0 , -1 },  // right -> left
{ -1 , 0 },  // bottom -> top
};

int currentNumber = 1;
int currentDirection = 0;
IndexMap im(Column);
int x(0) , y(0);
while( currentNumber <= Row * Column )
{
if( x >= Row || x < 0 || y >= Column || y < 0 || matrix[im(x,y)] != 0 )
{
// revert the wrong move
x -= directionMap[currentDirection][0];
y -= directionMap[currentDirection][1];
// modify direction
currentDirection = ( currentDirection + 1) % 4;
// step to the correct index
x += directionMap[currentDirection][0];
y += directionMap[currentDirection][1];
}
else
{
matrix[im(x,y)] = currentNumber++ ;
x += directionMap[currentDirection][0];
y += directionMap[currentDirection][1];
}
}

for ( int i = 0 ; i < Row ; ++i )
{
for ( int j = 0 ; j < Column ; ++j )
{
cout << setw(4) << matrix[im(i,j)];
}
cout << endl;
}

}

};

int main(int argc, char* argv[])
{
CyclePrint::DoPrint( 3 , 4 );
return 0;
}



### 解题思路2

MapToCoordinate为主要的映射函数。

// Learn more about F# at http://fsharp.net
module CyclePrint

type Direction =
| Left2Right
| Top2Bottom
| Right2Left
| Bottom2Top

let rec MapToCoordinate x y row column =
let MakeCoordinateFromDirection direction=
match direction with
| Left2Right when column > 0 && row > 0 ->
[ 0 .. column - 1 ] |> List.map ( fun offset -> ( x , y + offset) )
| Top2Bottom when column > 0 && row > 2 ->
[ 0 .. row - 2 - 1 ] |> List.map ( fun offset -> ( x + 1 + offset, y + column - 1 ) )
| Right2Left when column > 0 && row > 1  ->
[ 0 .. -1 .. -( column - 1 ) ] |> List.map ( fun offset -> ( x + row - 1  , y + column - 1 + offset) )
| Bottom2Top when column > 0 && row > 2 ->
[ 0 .. -1 .. - ( row - 2 - 1) ] |> List.map ( fun offset -> ( x + row - 1 - 1 + offset, y  ) )
| _ ->
[]
let head = [ Left2Right ; Top2Bottom ; Right2Left ; Bottom2Top ]
|> List.map MakeCoordinateFromDirection
|> List.fold (fun acc elem -> (List.append acc elem) ) []

| [] -> []
| _ -> List.append head (MapToCoordinate (x+1) (y+1) (row-2) (column-2))

let DoPrint row column =
let matrix = Array2D.create row column 0
MapToCoordinate 0 0 row column
|> List.zip [ 1 .. (row*column) ]
|> List.iter (fun ( num , (x,y) ) -> matrix.[x,y] <- num )
for x in 0..(row-1) do
for y in 0..(column-1) do
printf "%4d" matrix.[x,y]
printfn ""

[<EntryPoint>]
let main ( args : string[] ) =
DoPrint  4 8
0