각 방향별로 포인터가 이동하는 회수를 세는 방법으로 만들어봄.
가령 4x5 의 array라면,
1 | 2 | 3 | 4 |
14 | 15 | 16 | 5 |
13 | 20 | 17 | 6 |
12 | 19 | 18 | 7 |
11 | 10 | 9 | 8 |
이런 순으로 배열이 되게 되는데, (시작점과 끝점을 제외하고) 포인터의 이동방향을 나열해보면 →→→ ↓↓↓↓↓ ←←← ↑↑↑ →→ ↓↓ ← ↑ 순으로 된다. 여기에는 간단한 규칙성이 생기는데 (첫줄의 움직임을 제외) 다음과 같은 수식으로 포현될 수 있다.
현재 방향으로 진행횟수 = 반대 방향의 진행회수+1
이 식으로 간단한 수열을 만들 수 있고, 이 수열로 배열의 인덱스를 바꿔가며 값을 채워나간다.
처음에는 다른 디자인으로 접근을 했는데, 일단은 문제를 풀어보자는 취지 하에 제일 쉽게 풀릴것 같은 방법을 사용하였다.
~cpp
# -*- coding: UTF-8 -*
import unittest
def makeRotList(row, col):
rotList = []
row -= 1
col -= 1
rotList.append(row)
while True:
#cols
rotList.append(col)
if col == 1:
rotList.append(row)
break
#rows
rotList.append(row)
if row == 1:
rotList.append(col-1) # 제일 첫줄을 (루프전에 )이미 리스트에 넣었기 때문에 1을 빼야 함
break
row-=1
col-=1
return rotList
def makeSpirialArray(rows, cols):
s = Sequence()
SpirialArray = []
for i in range(rows):
SpirialArray += [[0]*cols]
index = [0,0]
value = 0
SpirialArray[index[0]][index[1]] = value + 1
value += 1
rotList = makeRotList(rows, cols)
for i in rotList:
dir = s.next()
for j in range(i):
index[0] += dir[0]
index[1] += dir[1]
SpirialArray[index[0]][index[1]] = value + 1
value += 1
print index
return SpirialArray
class Sequence:
def __init__(self):
self.sequence = [[1,0],[0,1],[-1,0],[0,-1]]
self.idx = 3
def next(self):
if self.idx == 3:
self.idx = 0
else:
self.idx += 1
return self.sequence[self.idx]
class MyTest(unittest.TestCase):
def testNextSeqence(self):
s = Sequence()
self.assertEquals([1,0], s.next())
self.assertEquals([0,1], s.next())
self.assertEquals([-1,0], s.next())
self.assertEquals([0,-1], s.next())
self.assertEquals([1,0], s.next())
def testRotList(self):
expected = [5,3,5,2,4,1,3]
self.assertEquals(expected, makeRotList(6,4))
expected = [3,5,3,4,2,3,1,2]
self.assertEquals(expected, makeRotList(4,6))
expected = [2,2,2,1,1]
self.assertEquals(expected, makeRotList(3,3))
expected = [3,3,3,2,2,1,1]
self.assertEquals(expected, makeRotList(4,4))
def testArrayCreation(self):
testArr = [[0]*3]*3
expected = [[0,0,0],[0,0,0],[0,0,0]]
self.assertEquals(expected, testArr)
if __name__=='__main__':
#unittest.main(argv=('','-v'))
print makeSpirialArray(3,3)
print makeSpirialArray(6,4)