Square spiral

Square spiral

Nikola picks up a strange circuit board. All of its elements are connected in a spiral and it is possible to connect the neighboring elements vertically and horizontally.

The map of the circuit consists of a series of square cells. The first element in the center is marked as 1, and continuing in a clockwise spiral, each other elements is marked in ascending order. On the map, you can move (connect cells) vertically and horizontally. You can help Nikola find the manhattan distance between any two elements on the map. For example, the distance between cells 1 and 9 is two moves and the distance between 24 and 9 is one move.

Input: Two marks of cells as an integers.

Output: The manhattan distance between the two cells as an integer.

原题链接:http://www.checkio.org/mission/strange-curcuit/

题目大义:找出两点在图上的曼哈顿距离

思路:首先观察得到,图中的数字由边数为2,4,6,8...的子正方形组成,而每个子正方形的数字个数有通项公式,为8*n + 4,如[1, 2, 3, 4],[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],然后每个子正方形的最大数字的值可以通过累加子正方形的数字个数得到,为[4, 16, 36, ...]。有了子正方形最大数字序列后,可判断给定的点在几号子正方形上,并以该最大值作为坐标圆点,向左为x轴正向,向上为y轴正向,求出该点在该子正方形上的坐标。分别得到两点在相应子正方形中的坐标后,内侧子坐标加上两个子正方形的序号差即可统一坐标系,最后距离为abs(x1 - x2) + abs(y1 - y2)

 1 def search_for_subsquare(number, sub_square_max_numbers):

 2     mlen = len(sub_square_max_numbers)

 3     for i in range(mlen):

 4         if number <= sub_square_max_numbers[i]:

 5             return i

 6 

 7 def cal_relative_position(sub_square_line_number, max_number_in_sub_square, number):

 8     pos = [0, 0]

 9 

10     itr_number = max_number_in_sub_square

11 

12     if itr_number == number:

13         return pos

14 

15     direction = [1, 0, 1, 0] #up left down right

16     move = [1, 1, -1, -1] #+ + - -

17 

18     for pos_mv, each_dir in enumerate(direction):

19         for i in range(sub_square_line_number - 1): #range(4) means range(0, 4)

20             itr_number -= 1

21             pos[each_dir] += move[pos_mv]

22             if itr_number == number:

23                 return pos

24 

25 

26 def find_distance(first, second):

27     sub_square_number_counts = [(8 * n + 4) for n in range(64)]

28 

29     sub_square_max_numbers = [4]

30 

31     len_count = len(sub_square_number_counts)

32 

33     for i in range(1, len_count):

34         sub_square_max_numbers.append(sub_square_max_numbers[i - 1] + sub_square_number_counts[i])

35 

36     #search first and second in which sub_square

37     first_square = search_for_subsquare(first, sub_square_max_numbers)

38     second_square = search_for_subsquare(second, sub_square_max_numbers)

39 

40     #cal relative position in its sub_square

41     pos_first = cal_relative_position((first_square + 1) * 2, sub_square_max_numbers[first_square], first)

42     pos_second = cal_relative_position((second_square + 1) * 2, sub_square_max_numbers[second_square], second)

43 

44     #unify relative postition and cal manhatan dist

45     if first_square > second_square:

46         scale = first_square - second_square

47         pos_second[0] += scale

48         pos_second[1] += scale

49     else:

50         scale = second_square - first_square

51         pos_first[0] += scale

52         pos_first[1] += scale

53 

54     return abs(pos_first[0] - pos_second[0]) + abs(pos_first[1] - pos_second[1])

review Sim0000's codes

 1 from math import sqrt

 2  

 3 # calculate the coordinate of n

 4 def coord(n):

 5     if n == 1: return (0, 0)

 6     r = int(sqrt(n - 1) - 1) // 2 + 1

 7     g, d = divmod(n - (2*r-1)**2 - 1, 2*r)

 8     return [(-r+d+1, r), (r, r-d-1), (r-d-1, -r), (-r, -r+d+1)][g]

 9  

10 def find_distance(first, second):

11     x1, y1 = coord(first)

12     x2, y2 = coord(second)

13     return abs(x2 - x1) + abs(y2 - y1)

14  

15     # At first, we determine ring which include n

16     #   ring 0 : 1

17     #   ring 1 : 2,3,...,9

18     #   ring 2 : 10,11,...,25

19     #   ring r : (2*r-1)**2+1,...,(2*r+1)**2

20     # Using following formula, we can calculate r from n.

21     #   r = int((sqrt(n - 1) - 1) / 2) + 1

22     # Ring r have 8*r elements and start position is (-r+1, r).

23     # And another interesting position is follows.

24     #   (-r,  r) : left upper corner,  n = (2*r-1)**2 + 8*r = (2*r+1)**2

25     #   ( r,  r) : right upper corner, n = (2*r-1)**2 + 2*r

26     #   ( r, -r) : right lower corner, n = (2*r-1)**2 + 4*r

27     #   (-r, -r) : left lower corner,  n = (2*r-1)**2 + 6*r

28     #

29     # Second, I divide ring into 4 groups corresponding to the direction.

30     # Each group size is 2*r. The group 0 is the first 2*r elements of the ring

31     # and its direction is right, and so on.

32     #   group 0 (dir = R) : n is from (2*r-1)**2    +1 to (2*r-1)**2+2*r

33     #   group 1 (dir = D) : n is from (2*r-1)**2+2*r+1 to (2*r-1)**2+4*r

34     #   group 2 (dir = L) : n is from (2*r-1)**2+4*r+1 to (2*r-1)**2+6*r

35     #   group 3 (dir = U) : n is from (2*r-1)**2+6*r+1 to (2*r-1)**2+8*r

36     # Using following formula, we can calculate group number g from n, r.

37     #   g = int((n - (2*r-1)**2 - 1) / (2*r)

38     #

39     # Finally, using above information, we will calulate the coordinate of n.

40     # When n belongs to group 0 of ring r, then the coordinate of n is

41     # (-r+1 + d, r), where d means n is the d-th elements of the group.

42     # As well, we can calculate for another groups.

43     #   group 0 : (-r+1+d, r)

44     #   group 1 : (r, r-1+d)

45     #   group 2 : (r-1-d, r)

46     #   group 3 : (-r, -r+d+1)

用的是数学方法,有时间再仔细看了

你可能感兴趣的:(SPI)