Python/PHP数字螺旋矩阵
什么是螺旋矩阵?
螺旋矩阵是指一个呈螺旋状的矩阵,它的数字由第一行开始到右边不断变大,向下变大,向左变大,向上变大,如此循环。下图就是一个螺旋矩阵的示例:
郑晓在这里分别使用了Python和PHP来实现了数字的螺旋矩阵。其中的PHP版本写成了函数,更加灵活的对矩阵进行控制。写Python时由于是第一次写,有些生疏,分别用了两种方法来实现。。。下面上代码吧:
Python螺旋矩阵的第一版(比较难以理解–!):
#coding:gbk
L = 6 #矩阵大小
result = [ [ 0 ]*L for n in range (L ) ]
row = 0 #初始行 从左上角开始
col = 0 #初始列 从左上角开始
value = 1 #初始值
direction = 'r' #初始方向 向右
circle = 1 #初始圈数 第一圈
while True:
#向右走
if direction == 'r':
result [row ] [col ] = value
if col >=L-circle:
direction = 'd'
continue
col + = 1
#向下走
if direction == 'd':
result [row ] [col ] = value
if row >= L-circle:
direction = 'l'
continue
row + = 1
#向左走
if direction == 'l':
result [row ] [col ] = value
if col <= circle - 1:
direction = 'u'
continue
col - = 1
#向上走
if direction == 'u':
result [row ] [col ] = value
if row- 1 <= circle:
direction = 'r'
circle + = 1
#continue
row - = 1
value + = 1
if value > L * L :
break
for R in result:
for c in R:
print "%3d" % (c ) ,
print
raw_input ( )
L = 6 #矩阵大小
result = [ [ 0 ]*L for n in range (L ) ]
row = 0 #初始行 从左上角开始
col = 0 #初始列 从左上角开始
value = 1 #初始值
direction = 'r' #初始方向 向右
circle = 1 #初始圈数 第一圈
while True:
#向右走
if direction == 'r':
result [row ] [col ] = value
if col >=L-circle:
direction = 'd'
continue
col + = 1
#向下走
if direction == 'd':
result [row ] [col ] = value
if row >= L-circle:
direction = 'l'
continue
row + = 1
#向左走
if direction == 'l':
result [row ] [col ] = value
if col <= circle - 1:
direction = 'u'
continue
col - = 1
#向上走
if direction == 'u':
result [row ] [col ] = value
if row- 1 <= circle:
direction = 'r'
circle + = 1
#continue
row - = 1
value + = 1
if value > L * L :
break
for R in result:
for c in R:
print "%3d" % (c ) ,
raw_input ( )
接下来是Python螺旋矩阵的第二版,其中使用了迭代器控制方向,代码量明显减少,而且更容易理解了。多次使用不同的起点生成的矩阵时,你会发现有个地方写的有点儿“问题”,找到问题了没有?
#coding:gbk
import itertools
#参数:矩阵宽(w)、高(h)、起始横坐标、起始纵坐标
def print_matrix (w , h , x = 0 , y = 0 ):
#方向移动时的操作
op = [ ( 1 , 0 ) , (- 1 , 0 ) , ( 0 ,- 1 ) , ( 0 , 1 ) ]
#迭代器可无限迭代列表 每次要换方向时就next()
direction = itertools. cycle (op )
#根据行列生成所有坐标
result = { (xx ,yy ): None for xx in range (w ) for yy in range (h ) }
result [ (x ,y ) ] = 1
_x , _y = direction. next ( )
i = 1
flag = 0
while True:
new_x = x + _x
new_y = y + _y
if (new_x , new_y ) in result and result [ (new_x , new_y ) ] is None:
i = i + 1
result [ (new_x , new_y ) ] = i
x = new_x
y = new_y
flag = 0
else:
_x , _y = direction. next ( )
flag = flag + 1
if flag > 4: break
#打印结果
for y in range (h ):
for x in range (w ):
print "%3d" % (result [ (x ,y ) ] ) ,
print
#调用示例
print_matrix ( 6 , 6 , 5 , 0 )
raw_input ( )
import itertools
#参数:矩阵宽(w)、高(h)、起始横坐标、起始纵坐标
def print_matrix (w , h , x = 0 , y = 0 ):
#方向移动时的操作
op = [ ( 1 , 0 ) , (- 1 , 0 ) , ( 0 ,- 1 ) , ( 0 , 1 ) ]
#迭代器可无限迭代列表 每次要换方向时就next()
direction = itertools. cycle (op )
#根据行列生成所有坐标
result = { (xx ,yy ): None for xx in range (w ) for yy in range (h ) }
result [ (x ,y ) ] = 1
_x , _y = direction. next ( )
i = 1
flag = 0
while True:
new_x = x + _x
new_y = y + _y
if (new_x , new_y ) in result and result [ (new_x , new_y ) ] is None:
i = i + 1
result [ (new_x , new_y ) ] = i
x = new_x
y = new_y
flag = 0
else:
_x , _y = direction. next ( )
flag = flag + 1
if flag > 4: break
#打印结果
for y in range (h ):
for x in range (w ):
print "%3d" % (result [ (x ,y ) ] ) ,
#调用示例
print_matrix ( 6 , 6 , 5 , 0 )
raw_input ( )
下面是PHP版的螺旋矩阵,思路和上面的Python是一样的(其实我是照着写的…)。
/* *
* @param $w : 宽
* @param $h : 高
* @param $s : 起始数字
* @param $x, $y : 起始位置坐标 只能从四顶点开始
* @param $r :方向 默认顺时间 false为逆时针
* @author : 郑晓
* php5.6.11
* 这是一个螺旋矩阵的PHP版本,由于之前在python下写过,有了一些经验,所以在php中也使用了SPL的一个迭代器,用于换向。算法编写时是使用的过程式,后来又改为了函数,加入了一些自定义参数,方便调用(然并卵)。输出中使用的是制表和换行符,请在浏览器源代码中查看运行结果。
*/
function print_matrix ( $w , $h , $s = 1 , $l = 1 , $x = 0 , $y = 0 , $r = true ) {
$R = array ( array ( 1 , 0 ) , array ( 0 , 1 ) , array ( - 1 , 0 ) , array ( 0 ,- 1 ) ) ;
! $r && $R = array_reverse ( $R ) ;
$iterator = new InfiniteIterator ( new ArrayIterator ( $R ) ) ; //创建一个无限迭代器
$iterator -> rewind ( ) ; //指针指向第一元素
list ( $_x , $_y ) = $iterator -> current ( ) ;
$result = [ ] ;
$result [ $x ] [ $y ] = $s ;
for ( $i = $s + 1 ; $i < $s + $w * $h ; $i ++ ) {
$new_x = $x + $_x ;
$new_y = $y + $_y ;
if ( 0 <= $new_x && 0 <= $new_y && $new_x < $w && $new_y < $h && ! isset ( $result [ $new_x ] [ $new_y ] ) ) {
$result [ $new_x ] [ $new_y ] = $i ;
$x = $new_x ;
$y = $new_y ;
} else {
$iterator -> next ( ) ;
list ( $_x , $_y ) = $iterator -> current ( ) ;
$i --;
}
}
//以下是打印矩阵结构
for ( $i = 0 ; $i < $h ; $i ++ ) {
for ( $j = 0 ; $j < $w ; $j ++ ) {
echo $result [ $j ] [ $i ] , "\t" ;
}
echo "\n" ;
}
}
//调用示例测试
print_matrix ( 5 , 5 ) ; echo "\n" ;
print_matrix ( 7 , 4 ) ; echo "\n" ;
print_matrix ( 5 , 5 , 1 , 4 , 0 ) ; echo "\n" ;
print_matrix ( 5 , 5 , 10 , 0 , 4 , false ) ; echo "\n" ;
* @param $w : 宽
* @param $h : 高
* @param $s : 起始数字
* @param $x, $y : 起始位置坐标 只能从四顶点开始
* @param $r :方向 默认顺时间 false为逆时针
* @author : 郑晓
* php5.6.11
* 这是一个螺旋矩阵的PHP版本,由于之前在python下写过,有了一些经验,所以在php中也使用了SPL的一个迭代器,用于换向。算法编写时是使用的过程式,后来又改为了函数,加入了一些自定义参数,方便调用(然并卵)。输出中使用的是制表和换行符,请在浏览器源代码中查看运行结果。
*/
function print_matrix ( $w , $h , $s = 1 , $l = 1 , $x = 0 , $y = 0 , $r = true ) {
$R = array ( array ( 1 , 0 ) , array ( 0 , 1 ) , array ( - 1 , 0 ) , array ( 0 ,- 1 ) ) ;
! $r && $R = array_reverse ( $R ) ;
$iterator = new InfiniteIterator ( new ArrayIterator ( $R ) ) ; //创建一个无限迭代器
$iterator -> rewind ( ) ; //指针指向第一元素
list ( $_x , $_y ) = $iterator -> current ( ) ;
$result = [ ] ;
$result [ $x ] [ $y ] = $s ;
for ( $i = $s + 1 ; $i < $s + $w * $h ; $i ++ ) {
$new_x = $x + $_x ;
$new_y = $y + $_y ;
if ( 0 <= $new_x && 0 <= $new_y && $new_x < $w && $new_y < $h && ! isset ( $result [ $new_x ] [ $new_y ] ) ) {
$result [ $new_x ] [ $new_y ] = $i ;
$x = $new_x ;
$y = $new_y ;
} else {
$iterator -> next ( ) ;
list ( $_x , $_y ) = $iterator -> current ( ) ;
$i --;
}
}
//以下是打印矩阵结构
for ( $i = 0 ; $i < $h ; $i ++ ) {
for ( $j = 0 ; $j < $w ; $j ++ ) {
echo $result [ $j ] [ $i ] , "\t" ;
}
echo "\n" ;
}
}
//调用示例测试
print_matrix ( 5 , 5 ) ; echo "\n" ;
print_matrix ( 7 , 4 ) ; echo "\n" ;
print_matrix ( 5 , 5 , 1 , 4 , 0 ) ; echo "\n" ;
print_matrix ( 5 , 5 , 10 , 0 , 4 , false ) ; echo "\n" ;
下面是依次的运行结果: