90_array2d.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. from array2d import array2d
  2. from linalg import vec2i
  3. # test error args for __init__
  4. try:
  5. a = array2d(0, 0)
  6. exit(0)
  7. except ValueError:
  8. pass
  9. # test callable constructor
  10. a = array2d[int](2, 4, lambda pos: (pos.x, pos.y))
  11. assert a.width == a.n_cols == 2
  12. assert a.height == a.n_rows == 4
  13. assert a.numel == 8
  14. assert a.tolist() == [
  15. [(0, 0), (1, 0)],
  16. [(0, 1), (1, 1)],
  17. [(0, 2), (1, 2)],
  18. [(0, 3), (1, 3)]]
  19. # test is_valid
  20. assert a.is_valid(0, 0) and a.is_valid(vec2i(0, 0))
  21. assert a.is_valid(1, 3) and a.is_valid(vec2i(1, 3))
  22. assert not a.is_valid(2, 0) and not a.is_valid(vec2i(2, 0))
  23. assert not a.is_valid(0, 4) and not a.is_valid(vec2i(0, 4))
  24. assert not a.is_valid(-1, 0) and not a.is_valid(vec2i(-1, 0))
  25. assert not a.is_valid(0, -1) and not a.is_valid(vec2i(0, -1))
  26. # test get
  27. assert a.get(0, 0, -1) == (0, 0)
  28. assert a.get(vec2i(1, 3), -1) == (1, 3)
  29. assert a.get(2, 0, None) is None
  30. assert a.get(vec2i(0, 4), 'S') == 'S'
  31. # test __getitem__
  32. assert a[0, 0] == (0, 0)
  33. assert a[1, 3] == (1, 3)
  34. try:
  35. a[2, 0]
  36. exit(1)
  37. except IndexError:
  38. pass
  39. # test __setitem__
  40. a = array2d[int](2, 4, default=0)
  41. a[0, 0] = 5
  42. assert a[0, 0] == 5
  43. a[1, 3] = 6
  44. assert a[1, 3] == 6
  45. try:
  46. a[0, -1] = 7
  47. exit(1)
  48. except IndexError:
  49. pass
  50. # test tolist
  51. a_list = [[5, 0], [0, 0], [0, 0], [0, 6]]
  52. assert a_list == a.tolist()
  53. # test __eq__
  54. x = array2d(2, 4, default=0)
  55. b = array2d(2, 4, default=0)
  56. assert (x == b).all()
  57. b[0, 0] = 1
  58. assert (x != b).any()
  59. # test __repr__
  60. assert repr(a) == f'array2d(2, 4)'
  61. # test map
  62. c = a.map(lambda x: x + 1)
  63. assert c.tolist() == [[6, 1], [1, 1], [1, 1], [1, 7]]
  64. assert a.tolist() == [[5, 0], [0, 0], [0, 0], [0, 6]]
  65. assert c.width == c.n_cols == 2
  66. assert c.height == c.n_rows == 4
  67. assert c.numel == 8
  68. # test copy
  69. d = c.copy()
  70. assert (d == c).all() and d is not c
  71. # test fill_
  72. d.fill_(-3)
  73. assert (d == array2d(2, 4, default=-3)).all()
  74. # test apply_
  75. d.apply_(lambda x: x + 3)
  76. assert (d == array2d(2, 4, default=0)).all()
  77. # test copy_
  78. a.copy_(d)
  79. assert (a == d).all() and a is not d
  80. x = array2d(2, 4, default=0)
  81. x.copy_(d)
  82. assert (x == d).all() and x is not d
  83. x.copy_([1, 2, 3, 4, 5, 6, 7, 8])
  84. assert x.tolist() == [[1, 2], [3, 4], [5, 6], [7, 8]]
  85. # test alive_neighbors
  86. a = array2d[int](3, 3, default=0)
  87. a[1, 1] = 1
  88. """ Moore von Neumann
  89. 0 0 0 1 1 1 0 1 0
  90. 0 1 0 1 0 1 1 0 1
  91. 0 0 0 1 1 1 0 1 0
  92. """
  93. moore_result = array2d(3, 3, default=1)
  94. moore_result[1, 1] = 0
  95. von_neumann_result = array2d(3, 3, default=0)
  96. von_neumann_result[0, 1] = von_neumann_result[1, 0] = von_neumann_result[1, 2] = von_neumann_result[2, 1] = 1
  97. _0 = a.count_neighbors(1, 'Moore')
  98. assert _0 == moore_result
  99. _1 = a.count_neighbors(1, 'von Neumann')
  100. assert _1 == von_neumann_result
  101. MOORE_KERNEL = array2d[int].fromlist([[1, 1, 1], [1, 0, 1], [1, 1, 1]])
  102. VON_NEUMANN_KERNEL = array2d.fromlist([[0, 1, 0], [1, 0, 1], [0, 1, 0]])
  103. moore_conv_result = a.convolve(MOORE_KERNEL, 0)
  104. assert (moore_conv_result == moore_result).all()
  105. von_neumann_conv_result = a.convolve(VON_NEUMANN_KERNEL, 0)
  106. assert (von_neumann_conv_result == von_neumann_result).all()
  107. # test slice get
  108. a = array2d(5, 5, default=0)
  109. b = array2d(3, 2, default=1)
  110. assert a[1:4, 1:4] == array2d(3, 3, default=0)
  111. assert a[1:4, 1:3] == array2d(3, 2, default=0)
  112. assert (a[1:4, 1:3] != b).any()
  113. a[1:4, 1:3] = b
  114. assert (a[1:4, 1:3] == b).all()
  115. """
  116. 0 0 0 0 0
  117. 0 1 1 1 0
  118. 0 1 1 1 0
  119. 0 0 0 0 0
  120. 0 0 0 0 0
  121. """
  122. assert a.count(1) == 3*2
  123. assert a.get_bounding_rect(1) == (1, 1, 3, 2)
  124. assert a.get_bounding_rect(0) == (0, 0, 5, 5)
  125. try:
  126. a.get_bounding_rect(2)
  127. exit(1)
  128. except ValueError:
  129. pass
  130. a = array2d(3, 2, default='?')
  131. # int/float/str/bool/None
  132. for value in [0, 0.0, '0', False, None]:
  133. a[0:2, 0:1] = value
  134. assert a[2, 1] == '?'
  135. assert a[0, 0] == value
  136. a[:, :] = 3
  137. assert a == array2d(3, 2, default=3)
  138. try:
  139. a[:, :] = array2d(1, 1)
  140. exit(1)
  141. except ValueError:
  142. pass
  143. try:
  144. a[:, :] = ...
  145. exit(1)
  146. except TypeError:
  147. pass
  148. # test __iter__
  149. a = array2d(3, 4, default=1)
  150. for xy, val in a:
  151. assert a[xy] == x
  152. # test convolve
  153. a = array2d[int].fromlist([[1, 0, 2, 4, 0], [3, 1, 0, 5, 1]])
  154. """
  155. 1 0 2 4 0
  156. 3 1 0 5 1
  157. """
  158. assert a.tolist() == [[1, 0, 2, 4, 0], [3, 1, 0, 5, 1]]
  159. kernel = array2d[int](3, 3, default=1)
  160. res = a.convolve(kernel, -1)
  161. """
  162. 0 4 9 9 5
  163. 0 4 9 9 5
  164. """
  165. assert res.tolist() == [[0, 4, 9, 9, 5], [0, 4, 9, 9, 5]]
  166. mask = res == 9
  167. assert mask.tolist() == [
  168. [False, False, True, True, False],
  169. [False, False, True, True, False]
  170. ]
  171. assert res[mask] == [9, 9, 9, 9]
  172. mask = res != 9
  173. assert mask.tolist() == [
  174. [True, True, False, False, True],
  175. [True, True, False, False, True]
  176. ]
  177. assert res[mask] == [0, 4, 5, 0, 4, 5]
  178. res[mask] = -1
  179. assert res.tolist() == [[-1, -1, 9, 9, -1], [-1, -1, 9, 9, -1]]
  180. # test get_connected_components
  181. a = array2d[int].fromlist([
  182. [1, 1, 0, 1],
  183. [0, 2, 2, 1],
  184. [0, 1, 1, 1],
  185. [1, 0, 0, 0],
  186. ])
  187. vis, cnt = a.get_connected_components(1, 'von Neumann')
  188. assert vis == [
  189. [1, 1, 0, 2],
  190. [0, 0, 0, 2],
  191. [0, 2, 2, 2],
  192. [3, 0, 0, 0]
  193. ]
  194. assert cnt == 3
  195. vis, cnt = a.get_connected_components(1, 'Moore')
  196. assert vis == [
  197. [1, 1, 0, 2],
  198. [0, 0, 0, 2],
  199. [0, 2, 2, 2],
  200. [2, 0, 0, 0]
  201. ]
  202. assert cnt == 2
  203. vis, cnt = a.get_connected_components(2, 'von Neumann')
  204. assert cnt == 1
  205. vis, cnt = a.get_connected_components(0, 'Moore')
  206. assert cnt == 2
  207. # stackoverflow bug due to recursive mark-and-sweep
  208. # class Cell:
  209. # neighbors: list['Cell']
  210. # cells: array2d[Cell] = array2d(192, 108, default=Cell)
  211. # OutOfBounds = Cell()
  212. # for x, y, cell in cells:
  213. # cell.neighbors = [
  214. # cells.get(x-1, y-1, OutOfBounds),
  215. # cells.get(x , y-1, OutOfBounds),
  216. # cells.get(x+1, y-1, OutOfBounds),
  217. # cells.get(x-1, y , OutOfBounds),
  218. # cells.get(x+1, y , OutOfBounds),
  219. # cells.get(x , y+1, OutOfBounds),
  220. # cells.get(x+1, y+1, OutOfBounds),
  221. # ]
  222. # import gc
  223. # gc.collect()