hamster 1.0.0 → 1.0.1.pre.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (509) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hamster.rb +2 -3
  3. data/lib/hamster/core_ext.rb +1 -0
  4. data/lib/hamster/core_ext/enumerable.rb +17 -17
  5. data/lib/hamster/core_ext/enumerator.rb +16 -0
  6. data/lib/hamster/core_ext/io.rb +17 -15
  7. data/lib/hamster/enumerable.rb +107 -123
  8. data/lib/hamster/experimental/mutable_queue.rb +6 -2
  9. data/lib/hamster/experimental/mutable_set.rb +3 -1
  10. data/lib/hamster/experimental/mutable_stack.rb +30 -0
  11. data/lib/hamster/hash.rb +95 -713
  12. data/lib/hamster/immutable.rb +0 -4
  13. data/lib/hamster/list.rb +242 -1062
  14. data/lib/hamster/mutable_hash.rb +3 -1
  15. data/lib/hamster/queue.rb +87 -0
  16. data/lib/hamster/read_copy_update.rb +1 -2
  17. data/lib/hamster/set.rb +73 -478
  18. data/lib/hamster/sorter.rb +25 -0
  19. data/lib/hamster/stack.rb +75 -0
  20. data/lib/hamster/trie.rb +48 -199
  21. data/lib/hamster/tuple.rb +39 -0
  22. data/lib/hamster/undefined.rb +3 -1
  23. data/lib/hamster/vector.rb +72 -1326
  24. data/lib/hamster/version.rb +1 -1
  25. data/spec/hamster/core_ext/array_spec.rb +20 -0
  26. data/spec/{lib/hamster → hamster}/core_ext/enumerable_spec.rb +0 -5
  27. data/spec/hamster/core_ext/enumerator_spec.rb +19 -0
  28. data/spec/{lib/hamster → hamster}/core_ext/io_spec.rb +0 -0
  29. data/spec/hamster/experimental/mutable_set/add_qm_spec.rb +47 -0
  30. data/spec/hamster/experimental/mutable_set/add_spec.rb +51 -0
  31. data/spec/hamster/experimental/mutable_set/delete_qm_spec.rb +47 -0
  32. data/spec/hamster/experimental/mutable_set/delete_spec.rb +47 -0
  33. data/spec/hamster/experimental/mutable_stack/pop_spec.rb +41 -0
  34. data/spec/hamster/experimental/mutable_stack/push_spec.rb +41 -0
  35. data/spec/hamster/hash/all_spec.rb +59 -0
  36. data/spec/hamster/hash/any_spec.rb +67 -0
  37. data/spec/hamster/hash/clear_spec.rb +36 -0
  38. data/spec/hamster/hash/construction_spec.rb +35 -0
  39. data/spec/{lib/hamster → hamster}/hash/copying_spec.rb +12 -3
  40. data/spec/hamster/hash/delete_spec.rb +47 -0
  41. data/spec/hamster/hash/each_spec.rb +41 -0
  42. data/spec/hamster/hash/empty_spec.rb +27 -0
  43. data/spec/hamster/hash/eql_spec.rb +62 -0
  44. data/spec/hamster/hash/except_spec.rb +31 -0
  45. data/spec/hamster/hash/fetch_spec.rb +95 -0
  46. data/spec/hamster/hash/filter_spec.rb +63 -0
  47. data/spec/hamster/hash/find_spec.rb +58 -0
  48. data/spec/hamster/hash/get_spec.rb +55 -0
  49. data/spec/hamster/hash/has_key_spec.rb +35 -0
  50. data/spec/hamster/hash/hash_spec.rb +52 -0
  51. data/spec/{lib/hamster → hamster}/hash/immutable_spec.rb +3 -0
  52. data/spec/hamster/hash/inspect_spec.rb +32 -0
  53. data/spec/hamster/hash/keys_spec.rb +21 -0
  54. data/spec/hamster/hash/map_spec.rb +64 -0
  55. data/spec/{lib/hamster → hamster}/hash/marshal_spec.rb +3 -3
  56. data/spec/hamster/hash/merge_spec.rb +36 -0
  57. data/spec/{lib/hamster → hamster}/hash/none_spec.rb +14 -12
  58. data/spec/hamster/hash/put_spec.rb +65 -0
  59. data/spec/hamster/hash/reduce_spec.rb +60 -0
  60. data/spec/hamster/hash/remove_spec.rb +63 -0
  61. data/spec/{lib/hamster → hamster}/hash/size_spec.rb +2 -2
  62. data/spec/hamster/hash/slice_spec.rb +26 -0
  63. data/spec/hamster/hash/uniq_spec.rb +23 -0
  64. data/spec/hamster/hash/values_spec.rb +34 -0
  65. data/spec/{lib/hamster → hamster}/immutable/copying_spec.rb +8 -1
  66. data/spec/{lib/hamster → hamster}/immutable/immutable_spec.rb +14 -1
  67. data/spec/{lib/hamster → hamster}/immutable/memoize_spec.rb +3 -2
  68. data/spec/{lib/hamster → hamster}/immutable/new_spec.rb +0 -0
  69. data/spec/{lib/hamster → hamster}/immutable/transform_spec.rb +0 -0
  70. data/spec/{lib/hamster → hamster}/immutable/transform_unless_spec.rb +0 -0
  71. data/spec/hamster/list/add_spec.rb +16 -0
  72. data/spec/hamster/list/all_spec.rb +111 -0
  73. data/spec/hamster/list/any_spec.rb +79 -0
  74. data/spec/{lib/hamster → hamster}/list/append_spec.rb +22 -11
  75. data/spec/hamster/list/at_spec.rb +49 -0
  76. data/spec/hamster/list/break_spec.rb +85 -0
  77. data/spec/{lib/hamster → hamster}/list/cadr_spec.rb +17 -6
  78. data/spec/{lib/hamster → hamster}/list/chunk_spec.rb +17 -6
  79. data/spec/{lib/hamster → hamster}/list/clear_spec.rb +16 -5
  80. data/spec/hamster/list/combinations_spec.rb +51 -0
  81. data/spec/{lib/hamster → hamster}/list/compact_spec.rb +17 -6
  82. data/spec/hamster/list/cons_spec.rb +41 -0
  83. data/spec/hamster/list/construction_spec.rb +166 -0
  84. data/spec/{lib/hamster → hamster}/list/copying_spec.rb +16 -4
  85. data/spec/hamster/list/count_spec.rb +66 -0
  86. data/spec/hamster/list/cycle_spec.rb +45 -0
  87. data/spec/{lib/hamster → hamster}/list/drop_spec.rb +17 -6
  88. data/spec/hamster/list/drop_while_spec.rb +59 -0
  89. data/spec/hamster/list/each_slice_spec.rb +80 -0
  90. data/spec/hamster/list/each_spec.rb +72 -0
  91. data/spec/hamster/list/each_with_index_spec.rb +42 -0
  92. data/spec/hamster/list/elem_index_spec.rb +58 -0
  93. data/spec/hamster/list/elem_indices_spec.rb +45 -0
  94. data/spec/hamster/list/empty_spec.rb +47 -0
  95. data/spec/hamster/list/eql_spec.rb +78 -0
  96. data/spec/hamster/list/filter_spec.rb +70 -0
  97. data/spec/{lib/hamster → hamster}/list/find_all_spec.rb +2 -3
  98. data/spec/{lib/hamster → hamster}/list/find_index_spec.rb +27 -5
  99. data/spec/hamster/list/find_indices_spec.rb +45 -0
  100. data/spec/{lib/hamster → hamster}/list/find_spec.rb +33 -11
  101. data/spec/{lib/hamster → hamster}/list/flat_map_spec.rb +0 -0
  102. data/spec/{lib/hamster → hamster}/list/flatten_spec.rb +17 -6
  103. data/spec/{lib/hamster → hamster}/list/grep_spec.rb +33 -10
  104. data/spec/{lib/hamster → hamster}/list/group_by_spec.rb +44 -9
  105. data/spec/{lib/hamster → hamster}/list/hash_spec.rb +12 -4
  106. data/spec/{lib/hamster → hamster}/list/head_spec.rb +18 -3
  107. data/spec/{lib/hamster → hamster}/list/include_spec.rb +27 -6
  108. data/spec/{lib/hamster → hamster}/list/init_spec.rb +17 -6
  109. data/spec/hamster/list/inits_spec.rb +42 -0
  110. data/spec/hamster/list/inspect_spec.rb +43 -0
  111. data/spec/{lib/hamster → hamster}/list/intersperse_spec.rb +17 -6
  112. data/spec/hamster/list/join_spec.rb +81 -0
  113. data/spec/hamster/list/last_spec.rb +44 -0
  114. data/spec/{lib/hamster → hamster}/list/map_spec.rb +35 -12
  115. data/spec/hamster/list/maximum_spec.rb +77 -0
  116. data/spec/{lib/hamster → hamster}/list/merge_by_spec.rb +32 -5
  117. data/spec/{lib/hamster → hamster}/list/merge_spec.rb +20 -1
  118. data/spec/hamster/list/minimum_spec.rb +77 -0
  119. data/spec/{lib/hamster → hamster}/list/none_spec.rb +39 -12
  120. data/spec/{lib/hamster → hamster}/list/one_spec.rb +38 -13
  121. data/spec/hamster/list/partition_spec.rb +75 -0
  122. data/spec/{lib/hamster → hamster}/list/pop_spec.rb +1 -1
  123. data/spec/hamster/list/product_spec.rb +44 -0
  124. data/spec/hamster/list/reduce_spec.rb +73 -0
  125. data/spec/{lib/hamster/list/reject_spec.rb → hamster/list/remove_spec.rb} +35 -11
  126. data/spec/{lib/hamster → hamster}/list/reverse_spec.rb +25 -8
  127. data/spec/{lib/hamster → hamster}/list/select_spec.rb +2 -3
  128. data/spec/{lib/hamster → hamster}/list/size_spec.rb +26 -5
  129. data/spec/hamster/list/slice_spec.rb +50 -0
  130. data/spec/{lib/hamster → hamster}/list/sorting_spec.rb +34 -11
  131. data/spec/hamster/list/span_spec.rb +86 -0
  132. data/spec/{lib/hamster → hamster}/list/split_at_spec.rb +23 -14
  133. data/spec/hamster/list/sum_spec.rb +44 -0
  134. data/spec/hamster/list/tail_spec.rb +48 -0
  135. data/spec/hamster/list/tails_spec.rb +42 -0
  136. data/spec/{lib/hamster → hamster}/list/take_spec.rb +17 -6
  137. data/spec/{lib/hamster → hamster}/list/take_while_spec.rb +18 -11
  138. data/spec/hamster/list/to_a_spec.rb +54 -0
  139. data/spec/{lib/hamster → hamster}/list/to_ary_spec.rb +4 -1
  140. data/spec/{lib/hamster → hamster}/list/to_list_spec.rb +16 -4
  141. data/spec/hamster/list/to_set_spec.rb +33 -0
  142. data/spec/{lib/hamster → hamster}/list/union_spec.rb +23 -6
  143. data/spec/hamster/list/uniq_spec.rb +45 -0
  144. data/spec/{lib/hamster → hamster}/list/zip_spec.rb +9 -2
  145. data/spec/hamster/queue/clear_spec.rb +36 -0
  146. data/spec/hamster/queue/construction_spec.rb +43 -0
  147. data/spec/hamster/queue/dequeue_spec.rb +40 -0
  148. data/spec/hamster/queue/empty_spec.rb +47 -0
  149. data/spec/{lib/hamster/deque → hamster/queue}/enqueue_spec.rb +21 -8
  150. data/spec/hamster/queue/head_spec.rb +35 -0
  151. data/spec/hamster/queue/inspect_spec.rb +31 -0
  152. data/spec/{lib/hamster/deque → hamster/queue}/size_spec.rb +20 -5
  153. data/spec/hamster/queue/to_a_spec.rb +42 -0
  154. data/spec/{lib/hamster/deque → hamster/queue}/to_ary_spec.rb +6 -6
  155. data/spec/hamster/queue/to_list_spec.rb +44 -0
  156. data/spec/hamster/set/add_spec.rb +51 -0
  157. data/spec/hamster/set/all_spec.rb +67 -0
  158. data/spec/hamster/set/any_spec.rb +67 -0
  159. data/spec/hamster/set/clear_spec.rb +36 -0
  160. data/spec/{lib/hamster → hamster}/set/compact_spec.rb +16 -5
  161. data/spec/{lib/hamster → hamster}/set/construction_spec.rb +17 -5
  162. data/spec/{lib/hamster → hamster}/set/copying_spec.rb +12 -3
  163. data/spec/{lib/hamster → hamster}/set/count_spec.rb +28 -11
  164. data/spec/hamster/set/delete_spec.rb +47 -0
  165. data/spec/{lib/hamster/sorted_set → hamster/set}/difference_spec.rb +21 -7
  166. data/spec/{lib/hamster/set/reverse_each_spec.rb → hamster/set/each_spec.rb} +7 -8
  167. data/spec/hamster/set/empty_spec.rb +35 -0
  168. data/spec/{lib/hamster → hamster}/set/eqeq_spec.rb +0 -0
  169. data/spec/{lib/hamster → hamster}/set/eql_spec.rb +1 -7
  170. data/spec/{lib/hamster/sorted_set → hamster/set}/exclusion_spec.rb +20 -5
  171. data/spec/hamster/set/filter_spec.rb +79 -0
  172. data/spec/{lib/hamster → hamster}/set/find_spec.rb +25 -8
  173. data/spec/hamster/set/flatten_spec.rb +49 -0
  174. data/spec/hamster/set/foreach_spec.rb +39 -0
  175. data/spec/{lib/hamster → hamster}/set/grep_spec.rb +1 -1
  176. data/spec/hamster/set/group_by_spec.rb +65 -0
  177. data/spec/hamster/set/hash_spec.rb +20 -0
  178. data/spec/hamster/set/head_spec.rb +39 -0
  179. data/spec/{lib/hamster → hamster}/set/immutable_spec.rb +4 -1
  180. data/spec/hamster/set/include_spec.rb +35 -0
  181. data/spec/hamster/set/inspect_spec.rb +32 -0
  182. data/spec/hamster/set/intersection_spec.rb +46 -0
  183. data/spec/{lib/hamster/vector → hamster/set}/join_spec.rb +33 -23
  184. data/spec/hamster/set/map_spec.rb +64 -0
  185. data/spec/{lib/hamster → hamster}/set/marshal_spec.rb +9 -4
  186. data/spec/hamster/set/maximum_spec.rb +65 -0
  187. data/spec/hamster/set/minimum_spec.rb +65 -0
  188. data/spec/{lib/hamster → hamster}/set/none_spec.rb +30 -15
  189. data/spec/{lib/hamster → hamster}/set/one_spec.rb +29 -14
  190. data/spec/hamster/set/partition_spec.rb +71 -0
  191. data/spec/{lib/hamster → hamster}/set/product_spec.rb +15 -7
  192. data/spec/hamster/set/reduce_spec.rb +87 -0
  193. data/spec/hamster/set/remove_spec.rb +63 -0
  194. data/spec/{lib/hamster → hamster}/set/size_spec.rb +10 -1
  195. data/spec/{lib/hamster → hamster}/set/sorting_spec.rb +16 -18
  196. data/spec/hamster/set/subset_spec.rb +39 -0
  197. data/spec/{lib/hamster/vector → hamster/set}/sum_spec.rb +18 -4
  198. data/spec/hamster/set/superset_spec.rb +39 -0
  199. data/spec/hamster/set/to_a_spec.rb +42 -0
  200. data/spec/{lib/hamster/vector → hamster/set}/to_list_spec.rb +23 -8
  201. data/spec/{lib/hamster → hamster}/set/to_set_spec.rb +15 -3
  202. data/spec/hamster/set/union_spec.rb +45 -0
  203. data/spec/hamster/set/uniq_spec.rb +23 -0
  204. data/spec/hamster/sorter/immutable_spec.rb +12 -0
  205. data/spec/hamster/stack/clear_spec.rb +36 -0
  206. data/spec/hamster/stack/construction_spec.rb +43 -0
  207. data/spec/hamster/stack/copying_spec.rb +31 -0
  208. data/spec/hamster/stack/empty_spec.rb +31 -0
  209. data/spec/hamster/stack/eql_spec.rb +60 -0
  210. data/spec/hamster/stack/immutable_spec.rb +12 -0
  211. data/spec/hamster/stack/inspect_spec.rb +31 -0
  212. data/spec/hamster/stack/peek_spec.rb +40 -0
  213. data/spec/hamster/stack/pop_spec.rb +41 -0
  214. data/spec/hamster/stack/push_spec.rb +41 -0
  215. data/spec/hamster/stack/size_spec.rb +35 -0
  216. data/spec/hamster/stack/to_a_spec.rb +42 -0
  217. data/spec/hamster/stack/to_ary.rb +37 -0
  218. data/spec/hamster/stack/to_list_spec.rb +33 -0
  219. data/spec/hamster/trie/remove_spec.rb +117 -0
  220. data/spec/hamster/tuple/copying_spec.rb +24 -0
  221. data/spec/hamster/tuple/eql_spec.rb +61 -0
  222. data/spec/hamster/tuple/first_spec.rb +19 -0
  223. data/spec/hamster/tuple/immutable_spec.rb +12 -0
  224. data/spec/hamster/tuple/inspect_spec.rb +19 -0
  225. data/spec/hamster/tuple/last_spec.rb +19 -0
  226. data/spec/hamster/tuple/to_a_spec.rb +38 -0
  227. data/spec/hamster/tuple/to_ary_spec.rb +38 -0
  228. data/spec/hamster/undefined/erase_spec.rb +47 -0
  229. data/spec/hamster/vector/add_spec.rb +48 -0
  230. data/spec/{lib/hamster → hamster}/vector/any_spec.rb +0 -0
  231. data/spec/hamster/vector/clear_spec.rb +35 -0
  232. data/spec/{lib/hamster → hamster}/vector/copying_spec.rb +14 -4
  233. data/spec/hamster/vector/each_spec.rb +45 -0
  234. data/spec/hamster/vector/each_with_index_spec.rb +41 -0
  235. data/spec/hamster/vector/empty_spec.rb +34 -0
  236. data/spec/hamster/vector/eql_spec.rb +64 -0
  237. data/spec/hamster/vector/filter_spec.rb +62 -0
  238. data/spec/hamster/vector/first_spec.rb +35 -0
  239. data/spec/hamster/vector/get_spec.rb +80 -0
  240. data/spec/{lib/hamster → hamster}/vector/include_spec.rb +17 -4
  241. data/spec/hamster/vector/inspect_spec.rb +33 -0
  242. data/spec/{lib/hamster → hamster}/vector/last_spec.rb +3 -12
  243. data/spec/{lib/hamster → hamster}/vector/length_spec.rb +3 -12
  244. data/spec/hamster/vector/map_spec.rb +63 -0
  245. data/spec/{lib/hamster → hamster}/vector/reduce_spec.rb +47 -16
  246. data/spec/hamster/vector/set_spec.rb +113 -0
  247. data/spec/{lib/hamster → hamster}/vector/to_a_spec.rb +12 -11
  248. data/spec/{lib/hamster → hamster}/vector/to_ary_spec.rb +0 -0
  249. data/spec/lib/hamster/vector/cons_spec.rb +48 -0
  250. data/spec/lib/hamster/vector/exist_spec.rb +70 -0
  251. data/spec/lib/hamster/vector/exists_spec.rb +70 -0
  252. data/spec/lib/hamster/vector/ltlt_spec.rb +2 -20
  253. data/spec/spec_helper.rb +5 -36
  254. metadata +510 -723
  255. data/lib/hamster/deque.rb +0 -252
  256. data/lib/hamster/nested.rb +0 -36
  257. data/lib/hamster/sorted_set.rb +0 -1397
  258. data/spec/lib/hamster/core_ext/array_spec.rb +0 -14
  259. data/spec/lib/hamster/deque/clear_spec.rb +0 -34
  260. data/spec/lib/hamster/deque/construction_spec.rb +0 -30
  261. data/spec/lib/hamster/deque/copying_spec.rb +0 -20
  262. data/spec/lib/hamster/deque/dequeue_spec.rb +0 -35
  263. data/spec/lib/hamster/deque/empty_spec.rb +0 -40
  264. data/spec/lib/hamster/deque/first_spec.rb +0 -18
  265. data/spec/lib/hamster/deque/inspect_spec.rb +0 -24
  266. data/spec/lib/hamster/deque/last_spec.rb +0 -18
  267. data/spec/lib/hamster/deque/marshal_spec.rb +0 -34
  268. data/spec/lib/hamster/deque/new_spec.rb +0 -44
  269. data/spec/lib/hamster/deque/pop_spec.rb +0 -33
  270. data/spec/lib/hamster/deque/pretty_print_spec.rb +0 -24
  271. data/spec/lib/hamster/deque/random_modification_spec.rb +0 -34
  272. data/spec/lib/hamster/deque/to_a_spec.rb +0 -27
  273. data/spec/lib/hamster/deque/to_list_spec.rb +0 -26
  274. data/spec/lib/hamster/deque/unshift_spec.rb +0 -26
  275. data/spec/lib/hamster/experimental/mutable_set/add_qm_spec.rb +0 -39
  276. data/spec/lib/hamster/experimental/mutable_set/add_spec.rb +0 -37
  277. data/spec/lib/hamster/experimental/mutable_set/delete_qm_spec.rb +0 -38
  278. data/spec/lib/hamster/experimental/mutable_set/delete_spec.rb +0 -37
  279. data/spec/lib/hamster/hash/all_spec.rb +0 -54
  280. data/spec/lib/hamster/hash/any_spec.rb +0 -54
  281. data/spec/lib/hamster/hash/assoc_spec.rb +0 -52
  282. data/spec/lib/hamster/hash/clear_spec.rb +0 -43
  283. data/spec/lib/hamster/hash/construction_spec.rb +0 -39
  284. data/spec/lib/hamster/hash/default_proc_spec.rb +0 -73
  285. data/spec/lib/hamster/hash/delete_spec.rb +0 -40
  286. data/spec/lib/hamster/hash/each_spec.rb +0 -78
  287. data/spec/lib/hamster/hash/each_with_index_spec.rb +0 -30
  288. data/spec/lib/hamster/hash/empty_spec.rb +0 -44
  289. data/spec/lib/hamster/hash/eql_spec.rb +0 -70
  290. data/spec/lib/hamster/hash/except_spec.rb +0 -43
  291. data/spec/lib/hamster/hash/fetch_spec.rb +0 -58
  292. data/spec/lib/hamster/hash/find_spec.rb +0 -44
  293. data/spec/lib/hamster/hash/flat_map_spec.rb +0 -36
  294. data/spec/lib/hamster/hash/flatten_spec.rb +0 -99
  295. data/spec/lib/hamster/hash/get_spec.rb +0 -80
  296. data/spec/lib/hamster/hash/has_key_spec.rb +0 -32
  297. data/spec/lib/hamster/hash/has_value_spec.rb +0 -28
  298. data/spec/lib/hamster/hash/hash_spec.rb +0 -30
  299. data/spec/lib/hamster/hash/inspect_spec.rb +0 -31
  300. data/spec/lib/hamster/hash/invert_spec.rb +0 -31
  301. data/spec/lib/hamster/hash/key_spec.rb +0 -28
  302. data/spec/lib/hamster/hash/keys_spec.rb +0 -17
  303. data/spec/lib/hamster/hash/map_spec.rb +0 -46
  304. data/spec/lib/hamster/hash/merge_spec.rb +0 -83
  305. data/spec/lib/hamster/hash/min_max_spec.rb +0 -46
  306. data/spec/lib/hamster/hash/new_spec.rb +0 -71
  307. data/spec/lib/hamster/hash/partition_spec.rb +0 -36
  308. data/spec/lib/hamster/hash/pretty_print_spec.rb +0 -35
  309. data/spec/lib/hamster/hash/put_spec.rb +0 -103
  310. data/spec/lib/hamster/hash/reduce_spec.rb +0 -36
  311. data/spec/lib/hamster/hash/reject_spec.rb +0 -62
  312. data/spec/lib/hamster/hash/reverse_each_spec.rb +0 -28
  313. data/spec/lib/hamster/hash/sample_spec.rb +0 -14
  314. data/spec/lib/hamster/hash/select_spec.rb +0 -58
  315. data/spec/lib/hamster/hash/slice_spec.rb +0 -45
  316. data/spec/lib/hamster/hash/sort_spec.rb +0 -27
  317. data/spec/lib/hamster/hash/store_spec.rb +0 -76
  318. data/spec/lib/hamster/hash/take_spec.rb +0 -36
  319. data/spec/lib/hamster/hash/to_a_spec.rb +0 -14
  320. data/spec/lib/hamster/hash/to_hash_spec.rb +0 -22
  321. data/spec/lib/hamster/hash/update_in_spec.rb +0 -80
  322. data/spec/lib/hamster/hash/values_at_spec.rb +0 -14
  323. data/spec/lib/hamster/hash/values_spec.rb +0 -25
  324. data/spec/lib/hamster/list/add_spec.rb +0 -26
  325. data/spec/lib/hamster/list/all_spec.rb +0 -58
  326. data/spec/lib/hamster/list/any_spec.rb +0 -50
  327. data/spec/lib/hamster/list/at_spec.rb +0 -30
  328. data/spec/lib/hamster/list/break_spec.rb +0 -70
  329. data/spec/lib/hamster/list/combination_spec.rb +0 -34
  330. data/spec/lib/hamster/list/compare_spec.rb +0 -31
  331. data/spec/lib/hamster/list/cons_spec.rb +0 -26
  332. data/spec/lib/hamster/list/construction_spec.rb +0 -111
  333. data/spec/lib/hamster/list/count_spec.rb +0 -37
  334. data/spec/lib/hamster/list/cycle_spec.rb +0 -29
  335. data/spec/lib/hamster/list/delete_at_spec.rb +0 -19
  336. data/spec/lib/hamster/list/delete_spec.rb +0 -17
  337. data/spec/lib/hamster/list/drop_while_spec.rb +0 -39
  338. data/spec/lib/hamster/list/each_slice_spec.rb +0 -52
  339. data/spec/lib/hamster/list/each_spec.rb +0 -41
  340. data/spec/lib/hamster/list/each_with_index_spec.rb +0 -29
  341. data/spec/lib/hamster/list/empty_spec.rb +0 -24
  342. data/spec/lib/hamster/list/eql_spec.rb +0 -62
  343. data/spec/lib/hamster/list/fill_spec.rb +0 -50
  344. data/spec/lib/hamster/list/index_spec.rb +0 -34
  345. data/spec/lib/hamster/list/indices_spec.rb +0 -62
  346. data/spec/lib/hamster/list/inits_spec.rb +0 -29
  347. data/spec/lib/hamster/list/insert_spec.rb +0 -47
  348. data/spec/lib/hamster/list/inspect_spec.rb +0 -30
  349. data/spec/lib/hamster/list/join_spec.rb +0 -64
  350. data/spec/lib/hamster/list/last_spec.rb +0 -24
  351. data/spec/lib/hamster/list/ltlt_spec.rb +0 -20
  352. data/spec/lib/hamster/list/maximum_spec.rb +0 -40
  353. data/spec/lib/hamster/list/minimum_spec.rb +0 -40
  354. data/spec/lib/hamster/list/multithreading_spec.rb +0 -48
  355. data/spec/lib/hamster/list/partition_spec.rb +0 -116
  356. data/spec/lib/hamster/list/permutation_spec.rb +0 -56
  357. data/spec/lib/hamster/list/product_spec.rb +0 -24
  358. data/spec/lib/hamster/list/reduce_spec.rb +0 -54
  359. data/spec/lib/hamster/list/rotate_spec.rb +0 -37
  360. data/spec/lib/hamster/list/sample_spec.rb +0 -14
  361. data/spec/lib/hamster/list/slice_spec.rb +0 -230
  362. data/spec/lib/hamster/list/span_spec.rb +0 -77
  363. data/spec/lib/hamster/list/subsequences_spec.rb +0 -24
  364. data/spec/lib/hamster/list/sum_spec.rb +0 -24
  365. data/spec/lib/hamster/list/tail_spec.rb +0 -31
  366. data/spec/lib/hamster/list/tails_spec.rb +0 -29
  367. data/spec/lib/hamster/list/to_a_spec.rb +0 -40
  368. data/spec/lib/hamster/list/to_set_spec.rb +0 -19
  369. data/spec/lib/hamster/list/transpose_spec.rb +0 -20
  370. data/spec/lib/hamster/list/uniq_spec.rb +0 -30
  371. data/spec/lib/hamster/nested/construction_spec.rb +0 -44
  372. data/spec/lib/hamster/set/add_spec.rb +0 -76
  373. data/spec/lib/hamster/set/all_spec.rb +0 -52
  374. data/spec/lib/hamster/set/any_spec.rb +0 -52
  375. data/spec/lib/hamster/set/clear_spec.rb +0 -34
  376. data/spec/lib/hamster/set/delete_spec.rb +0 -72
  377. data/spec/lib/hamster/set/difference_spec.rb +0 -50
  378. data/spec/lib/hamster/set/disjoint_spec.rb +0 -26
  379. data/spec/lib/hamster/set/each_spec.rb +0 -46
  380. data/spec/lib/hamster/set/empty_spec.rb +0 -45
  381. data/spec/lib/hamster/set/exclusion_spec.rb +0 -48
  382. data/spec/lib/hamster/set/first_spec.rb +0 -29
  383. data/spec/lib/hamster/set/flatten_spec.rb +0 -47
  384. data/spec/lib/hamster/set/group_by_spec.rb +0 -60
  385. data/spec/lib/hamster/set/hash_spec.rb +0 -23
  386. data/spec/lib/hamster/set/include_spec.rb +0 -61
  387. data/spec/lib/hamster/set/inspect_spec.rb +0 -48
  388. data/spec/lib/hamster/set/intersect_spec.rb +0 -26
  389. data/spec/lib/hamster/set/intersection_spec.rb +0 -53
  390. data/spec/lib/hamster/set/join_spec.rb +0 -65
  391. data/spec/lib/hamster/set/map_spec.rb +0 -60
  392. data/spec/lib/hamster/set/maximum_spec.rb +0 -37
  393. data/spec/lib/hamster/set/minimum_spec.rb +0 -37
  394. data/spec/lib/hamster/set/new_spec.rb +0 -54
  395. data/spec/lib/hamster/set/partition_spec.rb +0 -53
  396. data/spec/lib/hamster/set/reduce_spec.rb +0 -56
  397. data/spec/lib/hamster/set/reject_spec.rb +0 -51
  398. data/spec/lib/hamster/set/sample_spec.rb +0 -14
  399. data/spec/lib/hamster/set/select_spec.rb +0 -74
  400. data/spec/lib/hamster/set/subset_spec.rb +0 -52
  401. data/spec/lib/hamster/set/sum_spec.rb +0 -24
  402. data/spec/lib/hamster/set/superset_spec.rb +0 -52
  403. data/spec/lib/hamster/set/to_a_spec.rb +0 -31
  404. data/spec/lib/hamster/set/to_list_spec.rb +0 -37
  405. data/spec/lib/hamster/set/union_spec.rb +0 -64
  406. data/spec/lib/hamster/sorted_set/above_spec.rb +0 -52
  407. data/spec/lib/hamster/sorted_set/add_spec.rb +0 -63
  408. data/spec/lib/hamster/sorted_set/at_spec.rb +0 -25
  409. data/spec/lib/hamster/sorted_set/below_spec.rb +0 -52
  410. data/spec/lib/hamster/sorted_set/between_spec.rb +0 -52
  411. data/spec/lib/hamster/sorted_set/clear_spec.rb +0 -44
  412. data/spec/lib/hamster/sorted_set/construction_spec.rb +0 -29
  413. data/spec/lib/hamster/sorted_set/delete_at_spec.rb +0 -19
  414. data/spec/lib/hamster/sorted_set/delete_spec.rb +0 -90
  415. data/spec/lib/hamster/sorted_set/disjoint_spec.rb +0 -26
  416. data/spec/lib/hamster/sorted_set/drop_spec.rb +0 -56
  417. data/spec/lib/hamster/sorted_set/drop_while_spec.rb +0 -35
  418. data/spec/lib/hamster/sorted_set/each_spec.rb +0 -29
  419. data/spec/lib/hamster/sorted_set/empty_spec.rb +0 -35
  420. data/spec/lib/hamster/sorted_set/eql_spec.rb +0 -121
  421. data/spec/lib/hamster/sorted_set/fetch_spec.rb +0 -65
  422. data/spec/lib/hamster/sorted_set/find_index_spec.rb +0 -41
  423. data/spec/lib/hamster/sorted_set/first_spec.rb +0 -19
  424. data/spec/lib/hamster/sorted_set/from_spec.rb +0 -52
  425. data/spec/lib/hamster/sorted_set/group_by_spec.rb +0 -58
  426. data/spec/lib/hamster/sorted_set/include_spec.rb +0 -24
  427. data/spec/lib/hamster/sorted_set/inspect_spec.rb +0 -38
  428. data/spec/lib/hamster/sorted_set/intersect_spec.rb +0 -26
  429. data/spec/lib/hamster/sorted_set/intersection_spec.rb +0 -29
  430. data/spec/lib/hamster/sorted_set/last_spec.rb +0 -37
  431. data/spec/lib/hamster/sorted_set/map_spec.rb +0 -36
  432. data/spec/lib/hamster/sorted_set/marshal_spec.rb +0 -37
  433. data/spec/lib/hamster/sorted_set/maximum_spec.rb +0 -37
  434. data/spec/lib/hamster/sorted_set/minimum_spec.rb +0 -20
  435. data/spec/lib/hamster/sorted_set/new_spec.rb +0 -52
  436. data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +0 -29
  437. data/spec/lib/hamster/sorted_set/sample_spec.rb +0 -14
  438. data/spec/lib/hamster/sorted_set/select_spec.rb +0 -62
  439. data/spec/lib/hamster/sorted_set/size_spec.rb +0 -18
  440. data/spec/lib/hamster/sorted_set/slice_spec.rb +0 -257
  441. data/spec/lib/hamster/sorted_set/sorting_spec.rb +0 -45
  442. data/spec/lib/hamster/sorted_set/subset_spec.rb +0 -48
  443. data/spec/lib/hamster/sorted_set/superset_spec.rb +0 -48
  444. data/spec/lib/hamster/sorted_set/take_spec.rb +0 -55
  445. data/spec/lib/hamster/sorted_set/take_while_spec.rb +0 -34
  446. data/spec/lib/hamster/sorted_set/to_set_spec.rb +0 -19
  447. data/spec/lib/hamster/sorted_set/union_spec.rb +0 -28
  448. data/spec/lib/hamster/sorted_set/up_to_spec.rb +0 -52
  449. data/spec/lib/hamster/sorted_set/values_at_spec.rb +0 -34
  450. data/spec/lib/hamster/vector/add_spec.rb +0 -68
  451. data/spec/lib/hamster/vector/assoc_spec.rb +0 -36
  452. data/spec/lib/hamster/vector/bsearch_spec.rb +0 -58
  453. data/spec/lib/hamster/vector/clear_spec.rb +0 -34
  454. data/spec/lib/hamster/vector/combination_spec.rb +0 -82
  455. data/spec/lib/hamster/vector/compact_spec.rb +0 -30
  456. data/spec/lib/hamster/vector/compare_spec.rb +0 -32
  457. data/spec/lib/hamster/vector/concat_spec.rb +0 -35
  458. data/spec/lib/hamster/vector/count_spec.rb +0 -18
  459. data/spec/lib/hamster/vector/delete_at_spec.rb +0 -54
  460. data/spec/lib/hamster/vector/delete_spec.rb +0 -31
  461. data/spec/lib/hamster/vector/drop_spec.rb +0 -42
  462. data/spec/lib/hamster/vector/drop_while_spec.rb +0 -55
  463. data/spec/lib/hamster/vector/each_index_spec.rb +0 -41
  464. data/spec/lib/hamster/vector/each_spec.rb +0 -45
  465. data/spec/lib/hamster/vector/each_with_index_spec.rb +0 -40
  466. data/spec/lib/hamster/vector/empty_spec.rb +0 -42
  467. data/spec/lib/hamster/vector/eql_spec.rb +0 -77
  468. data/spec/lib/hamster/vector/fetch_spec.rb +0 -65
  469. data/spec/lib/hamster/vector/fill_spec.rb +0 -89
  470. data/spec/lib/hamster/vector/first_spec.rb +0 -19
  471. data/spec/lib/hamster/vector/flat_map_spec.rb +0 -51
  472. data/spec/lib/hamster/vector/flatten_spec.rb +0 -44
  473. data/spec/lib/hamster/vector/get_spec.rb +0 -75
  474. data/spec/lib/hamster/vector/group_by_spec.rb +0 -58
  475. data/spec/lib/hamster/vector/insert_spec.rb +0 -69
  476. data/spec/lib/hamster/vector/inspect_spec.rb +0 -50
  477. data/spec/lib/hamster/vector/map_spec.rb +0 -52
  478. data/spec/lib/hamster/vector/marshal_spec.rb +0 -32
  479. data/spec/lib/hamster/vector/maximum_spec.rb +0 -34
  480. data/spec/lib/hamster/vector/minimum_spec.rb +0 -34
  481. data/spec/lib/hamster/vector/multiply_spec.rb +0 -48
  482. data/spec/lib/hamster/vector/new_spec.rb +0 -51
  483. data/spec/lib/hamster/vector/partition_spec.rb +0 -53
  484. data/spec/lib/hamster/vector/permutation_spec.rb +0 -92
  485. data/spec/lib/hamster/vector/pop_spec.rb +0 -27
  486. data/spec/lib/hamster/vector/product_spec.rb +0 -71
  487. data/spec/lib/hamster/vector/reject_spec.rb +0 -44
  488. data/spec/lib/hamster/vector/repeated_combination_spec.rb +0 -78
  489. data/spec/lib/hamster/vector/repeated_permutation_spec.rb +0 -94
  490. data/spec/lib/hamster/vector/reverse_each_spec.rb +0 -32
  491. data/spec/lib/hamster/vector/reverse_spec.rb +0 -22
  492. data/spec/lib/hamster/vector/rindex_spec.rb +0 -37
  493. data/spec/lib/hamster/vector/rotate_spec.rb +0 -74
  494. data/spec/lib/hamster/vector/sample_spec.rb +0 -14
  495. data/spec/lib/hamster/vector/select_spec.rb +0 -64
  496. data/spec/lib/hamster/vector/set_spec.rb +0 -175
  497. data/spec/lib/hamster/vector/shift_spec.rb +0 -28
  498. data/spec/lib/hamster/vector/shuffle_spec.rb +0 -44
  499. data/spec/lib/hamster/vector/slice_spec.rb +0 -241
  500. data/spec/lib/hamster/vector/sorting_spec.rb +0 -57
  501. data/spec/lib/hamster/vector/take_spec.rb +0 -43
  502. data/spec/lib/hamster/vector/take_while_spec.rb +0 -35
  503. data/spec/lib/hamster/vector/to_set_spec.rb +0 -23
  504. data/spec/lib/hamster/vector/transpose_spec.rb +0 -49
  505. data/spec/lib/hamster/vector/uniq_spec.rb +0 -56
  506. data/spec/lib/hamster/vector/unshift_spec.rb +0 -29
  507. data/spec/lib/hamster/vector/update_in_spec.rb +0 -83
  508. data/spec/lib/hamster/vector/values_at_spec.rb +0 -34
  509. data/spec/lib/hamster/vector/zip_spec.rb +0 -58
@@ -1,5 +1,7 @@
1
1
  module Hamster
2
- # @private
3
2
  module Undefined
3
+ def self.erase(value)
4
+ value unless value.equal?(self)
5
+ end
4
6
  end
5
7
  end
@@ -1,1409 +1,155 @@
1
+ require "forwardable"
2
+ require "hamster/undefined"
1
3
  require "hamster/immutable"
2
4
  require "hamster/enumerable"
3
- require "hamster/hash"
4
5
 
5
6
  module Hamster
6
- # Create a new `Vector` populated with the given items.
7
- # [Vector]
8
7
  def self.vector(*items)
9
- items.empty? ? EmptyVector : Vector.new(items.freeze)
8
+ items.reduce(EmptyVector) { |vector, item| vector.add(item) }
10
9
  end
11
10
 
12
- # A `Vector` is an ordered, integer-indexed collection of objects. Like `Array`,
13
- # `Vector` indexing starts at 0. Also like `Array`, negative indexes count back
14
- # from the end of the `Vector`.
15
- #
16
- # `Vector`'s interface is modeled after that of `Array`, minus all the methods
17
- # which do destructive updates. Some methods which modify `Array`s destructively
18
- # (like {#insert} or {#delete_at}) are included, but they return new `Vectors`
19
- # and leave the existing one unchanged.
20
- #
21
- # ### Creating New Vectors
22
- #
23
- # Hamster.vector('a', 'b', 'c')
24
- # Hamster::Vector.new([:first, :second, :third])
25
- # Hamster::Vector[1, 2, 3, 4, 5]
26
- #
27
- # ### Retrieving Items from Vectors
28
- #
29
- # require 'hamster/vector'
30
- # vector = Hamster.vector(1, 2, 3, 4, 5)
31
- # vector[0] # => 1
32
- # vector[-1] # => 5
33
- # vector[0,3] # => Hamster::Vector[1, 2, 3]
34
- # vector[1..-1] # => Hamster::Vector[2, 3, 4, 5]
35
- # vector.first # => 1
36
- # vector.last # => 5
37
- #
38
- # ### Creating Modified Vectors
39
- #
40
- # vector.add(6) # => Hamster::Vector[1, 2, 3, 4, 5, 6]
41
- # vector.insert(1, :a, :b) # => Hamster::Vector[1, :a, :b, 2, 3, 4, 5]
42
- # vector.delete_at(2) # => Hamster::Vector[1, 2, 4, 5]
43
- # vector + [6, 7] # => Hamster::Vector[1, 2, 3, 4, 5, 6, 7]
44
- #
45
- # Other `Array`-like methods like {#select}, {#map}, {#shuffle}, {#uniq}, {#reverse},
46
- # {#rotate}, {#flatten}, {#sort}, {#sort_by}, {#take}, {#drop}, {#take_while},
47
- # {#drop_while}, {#fill}, {#product}, and {#transpose} are also supported.
48
- #
49
11
  class Vector
12
+ extend Forwardable
50
13
  include Immutable
51
14
  include Enumerable
52
15
 
53
- # @private
54
16
  BLOCK_SIZE = 32
55
- # @private
56
17
  INDEX_MASK = BLOCK_SIZE - 1
57
- # @private
58
18
  BITS_PER_LEVEL = 5
59
19
 
60
- # Return the number of items in this `Vector`
61
- # @return [Integer]
62
20
  attr_reader :size
63
- alias :length :size
21
+ def_delegator :self, :size, :length
64
22
 
65
- class << self
66
- # Create a new `Vector` populated with the given items.
67
- # @return [Vector]
68
- def [](*items)
69
- new(items.freeze)
70
- end
71
-
72
- # Return an empty `Vector`. If used on a subclass, returns an empty instance
73
- # of that class.
74
- #
75
- # @return [Vector]
76
- def empty
77
- @empty ||= self.new
78
- end
79
-
80
- # "Raw" allocation of a new `Vector`. Used internally to create a new
81
- # instance quickly after building a modified trie.
82
- #
83
- # @return [Vector]
84
- # @private
85
- def alloc(root, size, levels)
86
- obj = allocate
87
- obj.instance_variable_set(:@root, root)
88
- obj.instance_variable_set(:@size, size)
89
- obj.instance_variable_set(:@levels, levels)
90
- obj
91
- end
23
+ def initialize
24
+ @levels = 0
25
+ @root = []
26
+ @size = 0
92
27
  end
93
28
 
94
- def initialize(items=[].freeze)
95
- items = items.to_a
96
- if items.size <= 32
97
- items = items.dup.freeze if !items.frozen?
98
- @root, @size, @levels = items, items.size, 0
99
- else
100
- root, size, levels = items, items.size, 0
101
- while root.size > 32
102
- root = root.each_slice(32).to_a
103
- levels += 1
104
- end
105
- @root, @size, @levels = root.freeze, size, levels
106
- end
107
- end
108
-
109
- # Return `true` if this `Vector` contains no items.
110
- #
111
- # @return [Boolean]
112
29
  def empty?
113
30
  @size == 0
114
31
  end
32
+ def_delegator :self, :empty?, :null?
115
33
 
116
- # Return the first item in the `Vector`. If the vector is empty, return `nil`.
117
- #
118
- # @example
119
- # Hamster::Vector["A", "B", "C"].first # => "A"
120
- #
121
- # @return [Object]
122
34
  def first
123
35
  get(0)
124
36
  end
37
+ def_delegator :self, :first, :head
125
38
 
126
- # Return the last item in the `Vector`. If the vector is empty, return `nil`.
127
- #
128
- # @example
129
- # Hamster::Vector["A", "B", "C"].last # => "C"
130
- #
131
- # @return [Object]
132
39
  def last
133
40
  get(-1)
134
41
  end
135
42
 
136
- # Return a new `Vector` with `item` added after the last occupied position.
137
- #
138
- # @example
139
- # Hamster::Vector[1, 2].add(99) # => Hamster::Vector[1, 2, 99]
140
- #
141
- # @param item [Object] The object to insert at the end of the vector
142
- # @return [Vector]
143
43
  def add(item)
144
- update_root(@size, item)
145
- end
146
- alias :<< :add
147
- alias :push :add
148
-
149
- # Return a new `Vector` with the item at `index` replaced by `item`. If the
150
- # `item` argument is missing, but an optional code block is provided, it will
151
- # be passed the existing item and what the block returns will replace it.
152
- #
153
- # @example
154
- # Hamster::Vector[1, 2, 3, 4].set(2, 99)
155
- # # => Hamster::Vector[1, 2, 99, 4]
156
- # Hamster::Vector[1, 2, 3, 4].set(2) { |v| v * 10 }
157
- # # => Hamster::Vector[1, 2, 30, 4]
158
- #
159
- # @param index [Integer] The index to update
160
- # @param item [Object] The object to insert into that position
161
- # @return [Vector]
162
- def set(index, item = yield(get(index)))
163
- raise IndexError, "index #{index} outside of vector bounds" if index < -@size
164
- index += @size if index < 0
165
- if index > @size
166
- suffix = Array.new(index - @size, nil)
167
- suffix << item
168
- replace_suffix(@size, suffix)
169
- else
170
- update_root(index, item)
171
- end
172
- end
173
-
174
- # Return a new `Vector` with a deeply nested value modified to the result
175
- # of the given code block. When traversing the nested `Vector`s and
176
- # `Hash`es, non-existing keys are created with empty `Hash` values.
177
- #
178
- # The code block receives the existing value of the deeply nested key (or
179
- # `nil` if it doesn't exist). This is useful for "transforming" the value
180
- # associated with a certain key.
181
- #
182
- # Note that the original `Vector` and sub-`Vector`s and sub-`Hash`es are
183
- # left unmodified; new data structure copies are created along the path
184
- # wherever needed.
185
- #
186
- # @example
187
- # v = Hamster::Vector[123, 456, 789, Hamster::Hash["a" => Hamster::Vector[5, 6, 7]]]
188
- # v.update_in(3, "a", 1) { |value| value + 9 }
189
- # # => Hamster::Vector[123, 456, 789, Hamster::Hash["a" => Hamster::Vector[5, 15, 7]]]
190
- #
191
- # @param key_path [Object(s)] List of keys which form the path to the key to be modified
192
- # @yield [value] The previously stored value
193
- # @yieldreturn [Object] The new value to store
194
- # @return [Hash]
195
- def update_in(*key_path, &block)
196
- if key_path.empty?
197
- raise ArgumentError, "must have at least one key in path"
198
- end
199
- key = key_path[0]
200
- if key_path.size == 1
201
- new_value = block.call(get(key))
202
- else
203
- value = fetch(key, EmptyHash)
204
- new_value = value.update_in(*key_path[1..-1], &block)
205
- end
206
- set(key, new_value)
207
- end
208
-
209
- # Retrieve the item at `index`. If there is none (either the provided index
210
- # is too high or too low), return `nil`.
211
- #
212
- # @example
213
- # v = Hamster::Vector["A", "B", "C", "D"]
214
- # v.get(2) # => "C"
215
- # v.get(-1) # => "D"
216
- # v.get(4) # => nil
217
- #
218
- # @param index [Integer] The index to retrieve
219
- # @return [Object]
220
- def get(index)
221
- return nil if @size == 0
222
- index += @size if index < 0
223
- return nil if index >= @size || index < 0
224
- leaf_node_for(@root, @levels * BITS_PER_LEVEL, index)[index & INDEX_MASK]
225
- end
226
- alias :at :get
227
-
228
- # Retrieve the value at `index`, or use the provided default value or block,
229
- # or otherwise raise an `IndexError`.
230
- #
231
- # @overload fetch(index)
232
- # Retrieve the value at the given index, or raise an `IndexError` if it is
233
- # not found.
234
- # @param index [Integer] The index to look up
235
- # @overload fetch(index) { |index| ... }
236
- # Retrieve the value at the given index, or call the optional
237
- # code block (with the non-existent index) and get its return value.
238
- # @yield [index] The index which does not exist
239
- # @yieldreturn [Object] Object to return instead
240
- # @param index [Integer] The index to look up
241
- # @overload fetch(index, default)
242
- # Retrieve the value at the given index, or else return the provided
243
- # `default` value.
244
- # @param index [Integer] The index to look up
245
- # @param default [Object] Object to return if the key is not found
246
- #
247
- # @example
248
- # v = Hamster::Vector["A", "B", "C", "D"]
249
- # v.fetch(2) # => "C"
250
- # v.fetch(-1) # => "D"
251
- # v.fetch(4) # => IndexError: index 4 outside of vector bounds
252
- # # With default value:
253
- # v.fetch(2, "Z") # => "C"
254
- # v.fetch(4, "Z") # => "Z"
255
- # # With block:
256
- # v.fetch(2) { |i| i * i } # => "C"
257
- # v.fetch(4) { |i| i * i } # => 16
258
- #
259
- # @return [Object]
260
- def fetch(index, default = (missing_default = true))
261
- if index >= -@size && index < @size
262
- get(index)
263
- elsif block_given?
264
- yield(index)
265
- elsif !missing_default
266
- default
267
- else
268
- raise IndexError, "index #{index} outside of vector bounds"
269
- end
270
- end
271
-
272
- # Element reference. Return the item at a specific index, or a specified,
273
- # contiguous range of items (as a new `Vector`).
274
- #
275
- # @overload vector[index]
276
- # Return the item at `index`.
277
- # @param index [Integer] The index to retrieve.
278
- # @overload vector[start, length]
279
- # Return a subvector starting at index `start` and continuing for `length` elements.
280
- # @param start [Integer] The index to start retrieving items from.
281
- # @param length [Integer] The number of items to retrieve.
282
- # @overload vector[range]
283
- # Return a subvector specified by the given `range` of indices.
284
- # @param range [Range] The range of indices to retrieve.
285
- #
286
- # @example
287
- # v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
288
- # v[2] # => "C"
289
- # v[-1] # => "D"
290
- # v[6] # => nil
291
- # v[2, 2] # => Hamster::Vector["C", "D"]
292
- # v[2..3] # => Hamster::Vector["C", "D"]
293
- #
294
- # @return [Object]
295
- def [](arg, length = (missing_length = true))
296
- if missing_length
297
- if arg.is_a?(Range)
298
- from, to = arg.begin, arg.end
299
- from += @size if from < 0
300
- to += @size if to < 0
301
- to += 1 if !arg.exclude_end?
302
- length = to - from
303
- length = 0 if length < 0
304
- subsequence(from, length)
305
- else
306
- get(arg)
307
- end
308
- else
309
- arg += @size if arg < 0
310
- subsequence(arg, length)
44
+ transform do
45
+ update_leaf_node(@size, item)
46
+ @size += 1
311
47
  end
312
48
  end
313
- alias :slice :[]
49
+ def_delegator :self, :add, :<<
50
+ def_delegator :self, :add, :cons
314
51
 
315
- # Return a new `Vector` with the given values inserted before the element at `index`.
316
- #
317
- # @example
318
- # Hamster::Vector["A", "B", "C", "D"].insert(2, "X", "Y", "Z")
319
- # # => Hamster::Vector["A", "B", "X", "Y", "Z", "C", "D"]
320
- #
321
- # @param index [Integer] The index where the new items should go
322
- # @param items [Array] The items to add
323
- # @return [Vector]
324
- def insert(index, *items)
325
- raise IndexError if index < -@size
326
- index += @size if index < 0
52
+ # def delete(index)
53
+ # end
327
54
 
328
- if index < @size
329
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
330
- suffix.unshift(*items)
331
- elsif index == @size
332
- suffix = items
333
- else
334
- suffix = Array.new(index - @size, nil).concat(items)
335
- index = @size
55
+ def set(index, item = Undefined)
56
+ return set(index, yield(get(index))) if item.equal?(Undefined)
57
+ raise IndexError if empty? || index == @size
58
+ raise IndexError if index.abs > @size
59
+ return set(@size + index, item) if index < 0
60
+ transform do
61
+ update_leaf_node(index, item)
336
62
  end
337
-
338
- replace_suffix(index, suffix)
339
- end
340
-
341
- # Return a new `Vector` with the element at `index` removed. If the given `index`
342
- # does not exist, return `self`.
343
- #
344
- # @example
345
- # Hamster::Vector["A", "B", "C", "D"].delete_at(2)
346
- # # => Hamster::Vector["A", "B", "D"]
347
- #
348
- # @param index [Integer] The index to remove
349
- # @return [Vector]
350
- def delete_at(index)
351
- return self if index >= @size || index < -@size
352
- index += @size if index < 0
353
-
354
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
355
- replace_suffix(index, suffix.tap { |a| a.shift })
356
63
  end
357
64
 
358
- # Return a new `Vector` with the last element removed. If empty, just return `self`.
359
- #
360
- # @example
361
- # Hamster::Vector["A", "B", "C"].pop # => Hamster::Vector["A", "B"]
362
- #
363
- # @return [Vector]
364
- def pop
365
- return self if @size == 0
366
- replace_suffix(@size-1, [])
367
- end
368
-
369
- # Return a new `Vector` with `obj` inserted before the first element, moving
370
- # the other elements upwards.
371
- #
372
- # @example
373
- # Hamster::Vector["A", "B"].unshift("Z") # => Hamster::Vector["Z", "A", "B"]
374
- #
375
- # @param obj [Object] The value to prepend
376
- # @return [Vector]
377
- def unshift(obj)
378
- insert(0, obj)
379
- end
380
-
381
- # Return a new `Vector` with the first element removed. If empty, just return `self`.
382
- #
383
- # @example
384
- # Hamster::Vector["A", "B", "C"].shift # => Hamster::Vector["B", "C"]
385
- #
386
- # @return [Vector]
387
- def shift
388
- delete_at(0)
65
+ def get(index)
66
+ return nil if empty? || index == @size
67
+ return nil if index.abs > @size
68
+ return get(@size + index) if index < 0
69
+ leaf_node_for(@root, root_index_bits, index)[index & INDEX_MASK]
389
70
  end
71
+ def_delegator :self, :get, :[]
72
+ def_delegator :self, :get, :at
390
73
 
391
- # Call the given block once for each item in the vector, passing each
392
- # item from first to last successively to the block.
393
- #
394
- # @example
395
- # Hamster::Vector["A", "B", "C"].each { |e| puts "Element: #{e}" }
396
- #
397
- # Element: A
398
- # Element: B
399
- # Element: C
400
- # # => Hamster::Vector["A", "B", "C"]
401
- #
402
- # @return [self]
403
74
  def each(&block)
404
- return to_enum unless block_given?
405
- traverse_depth_first(@root, @levels, &block)
406
- self
407
- end
408
-
409
- # Call the given block once for each item in the vector, passing each
410
- # item starting from the last, and counting back to the first, successively to
411
- # the block.
412
- #
413
- # @example
414
- # Hamster::Vector["A", "B", "C"].reverse_each { |e| puts "Element: #{e}" }
415
- #
416
- # Element: C
417
- # Element: B
418
- # Element: A
419
- #
420
- # @return [self]
421
- def reverse_each(&block)
422
- return enum_for(:reverse_each) unless block_given?
423
- reverse_traverse_depth_first(@root, @levels, &block)
424
- self
425
- end
426
-
427
- # Return a new `Vector` containing all elements for which the given block returns
428
- # true.
429
- #
430
- # @example
431
- # Hamster::Vector["Bird", "Cow", "Elephant"].select { |e| e.size >= 4 }
432
- # # => Hamster::Vector["Bird", "Elephant"]
433
- #
434
- # @return [Vector]
435
- def select
436
- return enum_for(:select) unless block_given?
437
- reduce(self.class.empty) { |vector, item| yield(item) ? vector.add(item) : vector }
438
- end
439
- alias :find_all :select
440
- alias :keep_if :select
441
-
442
- # Return a new `Vector` with all items which are equal to `obj` removed.
443
- # `#==` is used for checking equality.
444
- #
445
- # @example
446
- # Hamster::Vector["C", "B", "A", "B"].delete("B") # => Hamster::Vector["C", "A"]
447
- #
448
- # @param obj [Object] The object to remove (every occurrence)
449
- # @return [Vector]
450
- def delete(obj)
451
- select { |item| item != obj }
452
- end
453
-
454
- # Invoke the given block once for each item in the vector, and return a new
455
- # `Vector` containing the values returned by the block.
456
- #
457
- # @example
458
- # Hamster::Vector[3, 2, 1].map { |e| e * e } # => Hamster::Vector[9, 4, 1]
459
- #
460
- # @return [Vector]
461
- def map
462
- return enum_for(:map) if not block_given?
463
- return self if empty?
464
- self.class.new(super)
465
- end
466
- alias :collect :map
467
-
468
- # Return a new `Vector` with the concatenated results of running the block once
469
- # for every element in this `Vector`.
470
- #
471
- # @example
472
- # Hamster.vector(1, 2, 3).flat_map { |x| [x, -x] }
473
- # # => Hamster::Vector[1, -1, 2, -2, 3, -3]
474
- #
475
- # @return [Vector]
476
- def flat_map
477
- return enum_for(:flat_map) if not block_given?
478
- return self if empty?
479
- self.class.new(super)
480
- end
481
-
482
- # Return a new `Vector` with the same elements as this one, but randomly permuted.
483
- #
484
- # @example
485
- # Hamster::Vector[1, 2, 3, 4].shuffle # => Hamster::Vector[4, 1, 3, 2]
486
- #
487
- # @return [Vector]
488
- def shuffle
489
- self.class.new(((array = to_a).frozen? ? array.shuffle : array.shuffle!).freeze)
490
- end
491
-
492
- # Return a new `Vector` with no duplicate elements, as determined by `#hash` and
493
- # `#eql?`. For each group of equivalent elements, only the first will be retained.
494
- #
495
- # @example
496
- # Hamster::Vector["A", "B", "C", "B"].uniq # => Hamster::Vector["A", "B", "C"]
497
- #
498
- # @return [Vector]
499
- def uniq
500
- self.class.new(((array = to_a).frozen? ? array.uniq : array.uniq!).freeze)
501
- end
502
-
503
- # Return a new `Vector` with the same elements as this one, but in reverse order.
504
- #
505
- # @example
506
- # Hamster::Vector["A", "B", "C"].reverse # => Hamster::Vector["C", "B", "A"]
507
- #
508
- # @return [Vector]
509
- def reverse
510
- self.class.new(((array = to_a).frozen? ? array.reverse : array.reverse!).freeze)
511
- end
512
-
513
- # Return a new `Vector` with the same elements, but rotated so that the one at
514
- # index `count` is the first element of the new vector. If `count` is positive,
515
- # the elements will be shifted left, and those shifted past the lowest position
516
- # will be moved to the end. If `count` is negative, the elements will be shifted
517
- # right, and those shifted past the last position will be moved to the beginning.
518
- #
519
- # @example
520
- # v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
521
- # v.rotate(2) # => Hamster::Vector["C", "D", "E", "F", "A", "B"]
522
- # v.rotate(-1) # => Hamster::Vector["F", "A", "B", "C", "D", "E"]
523
- #
524
- # @param count [Integer] The number of positions to shift items by
525
- # @return [Vector]
526
- def rotate(count = 1)
527
- return self if (count % @size) == 0
528
- self.class.new(((array = to_a).frozen? ? array.rotate(count) : array.rotate!(count)).freeze)
529
- end
530
-
531
- # Return a new `Vector` with all nested vectors and arrays recursively "flattened
532
- # out", that is, their elements inserted into the new `Vector` in the place where
533
- # the nested array/vector originally was. If an optional `level` argument is
534
- # provided, the flattening will only be done recursively that number of times.
535
- # A `level` of 0 means not to flatten at all, 1 means to only flatten nested
536
- # arrays/vectors which are directly contained within this `Vector`.
537
- #
538
- # @example
539
- # v = Hamster::Vector["A", Hamster::Vector["B", "C", Hamster::Vector["D"]]]
540
- # v.flatten(1)
541
- # # => Hamster::Vector["A", "B", "C", Hamster::Vector["D"]]
542
- # v.flatten
543
- # # => Hamster::Vector["A", "B", "C", "D"]
544
- #
545
- # @param level [Integer] The depth to which flattening should be applied
546
- # @return [Vector]
547
- def flatten(level = -1)
548
- return self if level == 0
549
- self.class.new(((array = to_a).frozen? ? array.flatten(level) : array.flatten!(level)).freeze)
550
- end
551
-
552
- # Return a new `Vector` built by concatenating this one with `other`. `other`
553
- # can be any object which is convertible to an `Array` using `#to_a`.
554
- #
555
- # @example
556
- # Hamster::Vector["A", "B", "C"] + ["D", "E"]
557
- # # => Hamster::Vector["A", "B", "C", "D", "E"]
558
- #
559
- # @param other [Enumerable] The collection to concatenate onto this vector
560
- # @return [Vector]
561
- def +(other)
562
- other = other.to_a
563
- other = other.dup if other.frozen?
564
- replace_suffix(@size, other)
565
- end
566
- alias :concat :+
567
-
568
- # `others` should be arrays and/or vectors. The corresponding elements from this
569
- # `Vector` and each of `others` (that is, the elements with the same indices)
570
- # will be gathered into arrays.
571
- #
572
- # If an optional block is provided, each such array will be passed successively
573
- # to the block. Otherwise, a new `Vector` of all those arrays will be returned.
574
- #
575
- # @example
576
- # v1 = Hamster::Vector["A", "B", "C"]
577
- # v2 = Hamster::Vector[1, 2, 3]
578
- # v1.zip(v2)
579
- # # => Hamster::Vector[["A", 1], ["B", 2], ["C", 3]]
580
- #
581
- # @param others [Array] The arrays/vectors to zip together with this one
582
- # @return [Vector, nil]
583
- def zip(*others)
584
- if block_given?
585
- super
586
- else
587
- self.class.new(super)
588
- end
589
- end
590
-
591
- # Return a new `Vector` with the same items, but sorted. The sort order will
592
- # be determined by comparing items using `#<=>`, or if an optional code block
593
- # is provided, by using it as a comparator. The block should accept 2 parameters,
594
- # and should return 0, 1, or -1 if the first parameter is equal to, greater than,
595
- # or less than the second parameter (respectively).
596
- #
597
- # @example
598
- # Hamster::Vector["Elephant", "Dog", "Lion"].sort
599
- # # => Hamster::Vector["Dog", "Elephant", "Lion"]
600
- # Hamster::Vector["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
601
- # # => Hamster::Vector["Dog", "Lion", "Elephant"]
602
- #
603
- # @return [Vector]
604
- def sort
605
- self.class.new(super)
606
- end
607
-
608
- # Return a new `Vector` with the same items, but sorted. The sort order will be
609
- # determined by mapping the items through the given block to obtain sort keys,
610
- # and then sorting the keys according to their natural sort order.
611
- #
612
- # @example
613
- # Hamster::Vector["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
614
- # # => Hamster::Vector["Dog", "Lion", "Elephant"]
615
- #
616
- # @return [Vector]
617
- def sort_by
618
- self.class.new(super)
619
- end
620
-
621
- # Drop the first `n` elements and return the rest in a new `Vector`.
622
- #
623
- # @example
624
- # Hamster::Vector["A", "B", "C", "D", "E", "F"].drop(2)
625
- # # => Hamster::Vector["C", "D", "E", "F"]
626
- #
627
- # @param n [Integer] The number of elements to remove
628
- # @return [Vector]
629
- def drop(n)
630
- return self if n == 0
631
- return self.class.empty if n >= @size
632
- raise ArgumentError, "attempt to drop negative size" if n < 0
633
- self.class.new(flatten_suffix(@root, @levels * BITS_PER_LEVEL, n, []))
634
- end
635
-
636
- # Return only the first `n` elements in a new `Vector`.
637
- #
638
- # @example
639
- # Hamster::Vector["A", "B", "C", "D", "E", "F"].take(4)
640
- # # => Hamster::Vector["A", "B", "C", "D"]
641
- #
642
- # @param n [Integer] The number of elements to retain
643
- # @return [Vector]
644
- def take(n)
645
- return self if n >= @size
646
- self.class.new(super)
647
- end
648
-
649
- # Drop elements up to, but not including, the first element for which the
650
- # block returns `nil` or `false`. Gather the remaining elements into a new
651
- # `Vector`. If no block is given, an `Enumerator` is returned instead.
652
- #
653
- # @example
654
- # Hamster::Vector[1, 3, 5, 7, 6, 4, 2].drop_while { |e| e < 5 }
655
- # # => Hamster::Vector[5, 7, 6, 4, 2]
656
- #
657
- # @return [Vector, Enumerator]
658
- def drop_while
659
- return enum_for(:drop_while) if not block_given?
660
- self.class.new(super)
661
- end
662
-
663
- # Gather elements up to, but not including, the first element for which the
664
- # block returns `nil` or `false`, and return them in a new `Vector`. If no block
665
- # is given, an `Enumerator` is returned instead.
666
- #
667
- # @example
668
- # Hamster::Vector[1, 3, 5, 7, 6, 4, 2].take_while { |e| e < 5 }
669
- # # => Hamster::Vector[1, 3]
670
- #
671
- # @return [Vector, Enumerator]
672
- def take_while
673
- return enum_for(:take_while) if not block_given?
674
- self.class.new(super)
675
- end
676
-
677
- # Repetition. Return a new `Vector` built by concatenating `times` copies
678
- # of this one together.
679
- #
680
- # @example
681
- # Hamster::Vector["A", "B"] * 3
682
- # # => Hamster::Vector["A", "B", "A", "B", "A", "B"]
683
- #
684
- # @param times [Integer] The number of times to repeat the elements in this vector
685
- # @return [Vector]
686
- def *(times)
687
- return self.class.empty if times == 0
688
- return self if times == 1
689
- result = (to_a * times)
690
- result.is_a?(Array) ? self.class.new(result) : result
691
- end
692
-
693
- # Replace a range of indexes with the given object.
694
- #
695
- # @overload fill(obj)
696
- # Return a new `Vector` of the same size, with every index set to `obj`.
697
- # @overload fill(obj, start)
698
- # Return a new `Vector` with all indexes from `start` to the end of the
699
- # vector set to `obj`.
700
- # @overload fill(obj, start, length)
701
- # Return a new `Vector` with `length` indexes, beginning from `start`,
702
- # set to `obj`.
703
- #
704
- # @example
705
- # v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
706
- # v.fill("Z")
707
- # # => Hamster::Vector["Z", "Z", "Z", "Z", "Z", "Z"]
708
- # v.fill("Z", 3)
709
- # # => Hamster::Vector["A", "B", "C", "Z", "Z", "Z"]
710
- # v.fill("Z", 3, 2)
711
- # # => Hamster::Vector["A", "B", "C", "Z", "Z", "F"]
712
- #
713
- # @return [Vector]
714
- def fill(obj, index = 0, length = nil)
715
- raise IndexError if index < -@size
716
- index += @size if index < 0
717
- length ||= @size - index # to the end of the array, if no length given
718
-
719
- if index < @size
720
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
721
- suffix.fill(obj, 0, length)
722
- elsif index == @size
723
- suffix = Array.new(length, obj)
724
- else
725
- suffix = Array.new(index - @size, nil).concat(Array.new(length, obj))
726
- index = @size
727
- end
728
-
729
- replace_suffix(index, suffix)
730
- end
731
-
732
- # When invoked with a block, yields all combinations of length `n` of items
733
- # from the `Vector`, and then returns `self`. There is no guarantee about
734
- # which order the combinations will be yielded in.
735
- #
736
- # If no block is given, an `Enumerator` is returned instead.
737
- #
738
- # @example
739
- # v = Hamster::Vector[5, 6, 7, 8]
740
- # v.combination(3) { |c| puts "Combination: #{c}" }
741
- #
742
- # Combination: [5, 6, 7]
743
- # Combination: [5, 6, 8]
744
- # Combination: [5, 7, 8]
745
- # Combination: [6, 7, 8]
746
- # #=> Hamster::Vector[5, 6, 7, 8]
747
- #
748
- # @return [self, Enumerator]
749
- def combination(n)
750
- return enum_for(:combination, n) if not block_given?
751
- return self if n < 0 || @size < n
752
- if n == 0
753
- yield []
754
- elsif n == 1
755
- each { |item| yield [item] }
756
- elsif n == @size
757
- yield self.to_a
758
- else
759
- combos = lambda do |result,index,remaining|
760
- while @size - index > remaining
761
- if remaining == 1
762
- yield result.dup << get(index)
763
- else
764
- combos[result.dup << get(index), index+1, remaining-1]
765
- end
766
- index += 1
767
- end
768
- index.upto(@size-1) { |i| result << get(i) }
769
- yield result
770
- end
771
- combos[[], 0, n]
772
- end
773
- self
774
- end
775
-
776
- # When invoked with a block, yields all repeated combinations of length `n` of
777
- # items from the `Vector`, and then returns `self`. A "repeated combination" is
778
- # one in which any item from the `Vector` can appear consecutively any number of
779
- # times.
780
- #
781
- # There is no guarantee about which order the combinations will be yielded in.
782
- #
783
- # If no block is given, an `Enumerator` is returned instead.
784
- #
785
- # @example
786
- # v = Hamster::Vector[5, 6, 7, 8]
787
- # v.repeated_combination(2) { |c| puts "Combination: #{c}" }
788
- #
789
- # Combination: [5, 5]
790
- # Combination: [5, 6]
791
- # Combination: [5, 7]
792
- # Combination: [5, 8]
793
- # Combination: [6, 6]
794
- # Combination: [6, 7]
795
- # Combination: [6, 8]
796
- # Combination: [7, 7]
797
- # Combination: [7, 8]
798
- # Combination: [8, 8]
799
- # # => Hamster::Vector[5, 6, 7, 8]
800
- #
801
- # @return [self, Enumerator]
802
- def repeated_combination(n)
803
- return enum_for(:repeated_combination, n) if not block_given?
804
- if n < 0
805
- # yield nothing
806
- elsif n == 0
807
- yield []
808
- elsif n == 1
809
- each { |item| yield [item] }
810
- elsif @size == 0
811
- # yield nothing
812
- else
813
- combos = lambda do |result,index,remaining|
814
- while index < @size-1
815
- if remaining == 1
816
- yield result.dup << get(index)
817
- else
818
- combos[result.dup << get(index), index, remaining-1]
819
- end
820
- index += 1
821
- end
822
- item = get(index)
823
- remaining.times { result << item }
824
- yield result
825
- end
826
- combos[[], 0, n]
827
- end
828
- self
829
- end
830
-
831
- # Yields all permutations of length `n` of items from the `Vector`, and then
832
- # returns `self`. If no length `n` is specified, permutations of all elements
833
- # will be yielded.
834
- #
835
- # There is no guarantee about which order the permutations will be yielded in.
836
- #
837
- # If no block is given, an `Enumerator` is returned instead.
838
- #
839
- # @example
840
- # v = Hamster::Vector[5, 6, 7]
841
- # v.permutation(2) { |p| puts "Permutation: #{p}" }
842
- #
843
- # Permutation: [5, 6]
844
- # Permutation: [5, 7]
845
- # Permutation: [6, 5]
846
- # Permutation: [6, 7]
847
- # Permutation: [7, 5]
848
- # Permutation: [7, 6]
849
- # # => Hamster::Vector[5, 6, 7]
850
- #
851
- # @return [self, Enumerator]
852
- def permutation(n = @size)
853
- return enum_for(:permutation, n) if not block_given?
854
- if n < 0 || @size < n
855
- # yield nothing
856
- elsif n == 0
857
- yield []
858
- elsif n == 1
859
- each { |item| yield [item] }
860
- else
861
- used, result = [], []
862
- perms = lambda do |index|
863
- 0.upto(@size-1) do |i|
864
- if !used[i]
865
- result[index] = get(i)
866
- if index < n-1
867
- used[i] = true
868
- perms[index+1]
869
- used[i] = false
870
- else
871
- yield result.dup
872
- end
873
- end
874
- end
875
- end
876
- perms[0]
877
- end
878
- self
879
- end
880
-
881
- # When invoked with a block, yields all repeated permutations of length `n` of
882
- # items from the `Vector`, and then returns `self`. A "repeated permutation" is
883
- # one where any item from the `Vector` can appear any number of times, and in
884
- # any position (not just consecutively)
885
- #
886
- # If no length `n` is specified, permutations of all elements will be yielded.
887
- # There is no guarantee about which order the permutations will be yielded in.
888
- #
889
- # If no block is given, an `Enumerator` is returned instead.
890
- #
891
- # @example
892
- # v = Hamster::Vector[5, 6, 7]
893
- # v.repeated_permutation(2) { |p| puts "Permutation: #{p}" }
894
- #
895
- # Permutation: [5, 5]
896
- # Permutation: [5, 6]
897
- # Permutation: [5, 7]
898
- # Permutation: [6, 5]
899
- # Permutation: [6, 6]
900
- # Permutation: [6, 7]
901
- # Permutation: [7, 5]
902
- # Permutation: [7, 6]
903
- # Permutation: [7, 7]
904
- # # => Hamster::Vector[5, 6, 7]
905
- #
906
- # @return [self, Enumerator]
907
- def repeated_permutation(n = @size)
908
- return enum_for(:repeated_permutation, n) if not block_given?
909
- if n < 0
910
- # yield nothing
911
- elsif n == 0
912
- yield []
913
- elsif n == 1
914
- each { |item| yield [item] }
915
- else
916
- result = []
917
- perms = lambda do |index|
918
- 0.upto(@size-1) do |i|
919
- result[index] = get(i)
920
- if index < n-1
921
- perms[index+1]
922
- else
923
- yield result.dup
924
- end
925
- end
926
- end
927
- perms[0]
928
- end
929
- self
930
- end
931
-
932
- # With one or more vector or array arguments, return the cartesian product of
933
- # this vector's elements and those of each argument; with no arguments, return the
934
- # result of multiplying all this vector's items together.
935
- #
936
- # @overload product(*vectors)
937
- # Return a `Vector` of all combinations of elements from this `Vector` and each
938
- # of the given vectors or arrays. The length of the returned `Vector` is the product
939
- # of `self.size` and the size of each argument vector or array.
940
- # @overload product
941
- # Return the result of multiplying all the items in this `Vector` together.
942
- #
943
- # @example
944
- # # Cartesian product:
945
- # v1 = Hamster::Vector[1, 2, 3]
946
- # v2 = Hamster::Vector["A", "B"]
947
- # v1.product(v2)
948
- # # => [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"], [3, "B"]]
949
- #
950
- # # Multiply all items:
951
- # Hamster::Vector[1, 2, 3, 4, 5].product # => 120
952
- #
953
- # @return [Vector]
954
- def product(*vectors)
955
- # if no vectors passed, return "product" as in result of multiplying all items
956
- return super if vectors.empty?
957
-
958
- vectors.unshift(self)
959
-
960
- if vectors.any?(&:empty?)
961
- return block_given? ? self : []
962
- end
963
-
964
- counters = Array.new(vectors.size, 0)
965
-
966
- bump_counters = lambda do
967
- i = vectors.size-1
968
- counters[i] += 1
969
- while counters[i] == vectors[i].size
970
- counters[i] = 0
971
- i -= 1
972
- return true if i == -1 # we are done
973
- counters[i] += 1
974
- end
975
- false # not done yet
976
- end
977
- build_array = lambda do
978
- array = []
979
- counters.each_with_index { |index,i| array << vectors[i][index] }
980
- array
981
- end
982
-
983
- if block_given?
984
- while true
985
- yield build_array[]
986
- return self if bump_counters[]
987
- end
988
- else
989
- result = []
990
- while true
991
- result << build_array[]
992
- return result if bump_counters[]
993
- end
994
- end
75
+ return self unless block_given?
76
+ traverse_depth_first(&block)
77
+ nil
995
78
  end
996
79
 
997
- # Assume all elements are vectors or arrays and transpose the rows and columns.
998
- # In other words, take the first element of each nested vector/array and gather
999
- # them together into a new `Vector`. Do likewise for the second, third, and so on
1000
- # down to the end of each nested vector/array. Gather all the resulting `Vectors`
1001
- # into a new `Vector` and return it.
1002
- #
1003
- # This operation is closely related to {#zip}. The result is almost the same as
1004
- # calling {#zip} on the first nested vector/array with the others supplied as
1005
- # arguments.
1006
- #
1007
- # @example
1008
- # Hamster::Vector[["A", 10], ["B", 20], ["C", 30]].transpose
1009
- # # => Hamster::Vector[Hamster::Vector["A", "B", "C"], Hamster::Vector[10, 20, 30]]
1010
- #
1011
- # @return [Vector]
1012
- def transpose
1013
- return self.class.empty if empty?
1014
- result = Array.new(first.size) { [] }
1015
-
1016
- 0.upto(@size-1) do |i|
1017
- source = get(i)
1018
- if source.size != result.size
1019
- raise IndexError, "element size differs (#{source.size} should be #{result.size})"
1020
- end
1021
-
1022
- 0.upto(result.size-1) do |j|
1023
- result[j].push(source[j])
1024
- end
1025
- end
1026
-
1027
- result.map! { |a| self.class.new(a) }
1028
- self.class.new(result)
80
+ def map(&block)
81
+ return self unless block_given?
82
+ reduce(EmptyVector) { |vector, item| vector.add(yield(item)) }
1029
83
  end
84
+ def_delegator :self, :map, :collect
1030
85
 
1031
- # By using binary search, finds a value from this `Vector` which meets the
1032
- # condition defined by the provided block. Behavior is just like `Array#bsearch`.
1033
- # See `Array#bsearch` for details.
1034
- #
1035
- # @example
1036
- # v = Hamster::Vector[1, 3, 5, 7, 9, 11, 13]
1037
- # # Block returns true/false for exact element match:
1038
- # v.bsearch { |e| e > 4 } # => 5
1039
- # # Block returns number to match an element in 4 <= e <= 7:
1040
- # v.bsearch { |e| 1 - e / 4 } # => 7
1041
- #
1042
- # @return [Object]
1043
- def bsearch
1044
- low, high, result = 0, @size, nil
1045
- while low < high
1046
- mid = (low + ((high - low) >> 1))
1047
- val = get(mid)
1048
- v = yield val
1049
- if v.is_a? Numeric
1050
- if v == 0
1051
- return val
1052
- elsif v > 0
1053
- high = mid
1054
- else
1055
- low = mid + 1
1056
- end
1057
- elsif v == true
1058
- result = val
1059
- high = mid
1060
- elsif !v
1061
- low = mid + 1
1062
- else
1063
- raise TypeError, "wrong argument type #{v.class} (must be numeric, true, false, or nil)"
1064
- end
1065
- end
1066
- result
86
+ def filter
87
+ return self unless block_given?
88
+ reduce(EmptyVector) { |vector, item| yield(item) ? vector.add(item) : vector }
1067
89
  end
1068
90
 
1069
- # Return an empty `Vector` instance, of the same class as this one. Useful if you
1070
- # have multiple subclasses of `Vector` and want to treat them polymorphically.
1071
- #
1072
- # @return [Vector]
1073
91
  def clear
1074
- self.class.empty
1075
- end
1076
-
1077
- # Return a randomly chosen item from this `Vector`. If the vector is empty, return `nil`.
1078
- #
1079
- # @example
1080
- # Hamster::Vector[1, 2, 3, 4, 5].sample # => 2
1081
- #
1082
- # @return [Object]
1083
- def sample
1084
- get(rand(@size))
1085
- end
1086
-
1087
- # Return a new `Vector` with only the elements at the given `indices`, in the
1088
- # order specified by `indices`. If any of the `indices` do not exist, `nil`s will
1089
- # appear in their places.
1090
- #
1091
- # @example
1092
- # v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
1093
- # v.values_at(2, 4, 5) # => Hamster::Vector["C", "E", "F"]
1094
- #
1095
- # @param indices [Array] The indices to retrieve and gather into a new `Vector`
1096
- # @return [Vector]
1097
- def values_at(*indices)
1098
- self.class.new(indices.map { |i| get(i) }.freeze)
1099
- end
1100
-
1101
- # Return the index of the last element which is equal to the provided object,
1102
- # or for which the provided block returns true.
1103
- #
1104
- # @overload rindex(obj)
1105
- # Return the index of the last element in this `Vector` which is `#==` to `obj`.
1106
- # @overload rindex { |item| ... }
1107
- # Return the index of the last element in this `Vector` for which the block
1108
- # returns true. (Iteration starts from the last element, counts back, and
1109
- # stops as soon as a matching element is found.)
1110
- #
1111
- # @example
1112
- # v = Hamster::Vector[7, 8, 9, 7, 8, 9]
1113
- # v.rindex(8) # => 4
1114
- # v.rindex { |e| e.even? } # => 4
1115
- #
1116
- # @return [Index]
1117
- def rindex(obj = (missing_arg = true))
1118
- i = @size - 1
1119
- if missing_arg
1120
- if block_given?
1121
- reverse_each { |item| return i if yield item; i -= 1 }
1122
- nil
1123
- else
1124
- enum_for(:rindex)
1125
- end
1126
- else
1127
- reverse_each { |item| return i if item == obj; i -= 1 }
1128
- nil
1129
- end
1130
- end
1131
-
1132
- # Assumes all elements are nested, indexable collections, and searches through them,
1133
- # comparing `obj` with the first element of each nested collection. Return the
1134
- # first nested collection which matches, or `nil` if none is found.
1135
- #
1136
- # @example
1137
- # v = Hamster::Vector[["A", 10], ["B", 20], ["C", 30]]
1138
- # v.assoc("B") # => ["B", 20]
1139
- #
1140
- # @param obj [Object] The object to search for
1141
- # @return [Object]
1142
- def assoc(obj)
1143
- each { |array| return array if obj == array[0] }
1144
- nil
1145
- end
1146
-
1147
- # Assumes all elements are nested, indexable collections, and searches through them,
1148
- # comparing `obj` with the second element of each nested collection. Return the
1149
- # first nested collection which matches, or `nil` if none is found.
1150
- #
1151
- # @example
1152
- # v = Hamster::Vector[["A", 10], ["B", 20], ["C", 30]]
1153
- # v.rassoc(20) # => ["B", 20]
1154
- #
1155
- # @param obj [Object] The object to search for
1156
- # @return [Object]
1157
- def rassoc(obj)
1158
- each { |array| return array if obj == array[1] }
1159
- nil
92
+ EmptyVector
1160
93
  end
1161
94
 
1162
- # Return an `Array` with the same elements, in the same order. The returned
1163
- # `Array` may or may not be frozen.
1164
- #
1165
- # @return [Array]
1166
- def to_a
1167
- if @levels == 0
1168
- @root
1169
- else
1170
- flatten_node(@root, @levels * BITS_PER_LEVEL, [])
1171
- end
95
+ def inspect
96
+ to_a.inspect
1172
97
  end
1173
- alias :to_ary :to_a
1174
98
 
1175
- # Return true if `other` has the same type and contents as this `Vector`.
1176
- #
1177
- # @param other [Object] The collection to compare with
1178
- # @return [Boolean]
1179
99
  def eql?(other)
1180
100
  return true if other.equal?(self)
1181
101
  return false unless instance_of?(other.class) && @size == other.size
1182
102
  @root.eql?(other.instance_variable_get(:@root))
1183
103
  end
1184
-
1185
- # See `Object#hash`.
1186
- # @return [Integer]
1187
- def hash
1188
- reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
1189
- end
1190
-
1191
- # @return [::Array]
1192
- # @private
1193
- def marshal_dump
1194
- to_a
1195
- end
1196
-
1197
- # @private
1198
- def marshal_load(array)
1199
- initialize(array.freeze)
1200
- end
104
+ def_delegator :self, :eql?, :==
1201
105
 
1202
106
  private
1203
107
 
1204
- def traverse_depth_first(node, level, &block)
108
+ def traverse_depth_first(node = @root, level = @levels, &block)
1205
109
  return node.each(&block) if level == 0
1206
110
  node.each { |child| traverse_depth_first(child, level - 1, &block) }
1207
111
  end
1208
112
 
1209
- def reverse_traverse_depth_first(node, level, &block)
1210
- return node.reverse_each(&block) if level == 0
1211
- node.reverse_each { |child| reverse_traverse_depth_first(child, level - 1, &block) }
113
+ def leaf_node_for(node, child_index_bits, index)
114
+ return node if child_index_bits == 0
115
+ child_index = (index >> child_index_bits) & INDEX_MASK
116
+ leaf_node_for(node[child_index], child_index_bits - BITS_PER_LEVEL, index)
1212
117
  end
1213
118
 
1214
- def leaf_node_for(node, bitshift, index)
1215
- while bitshift > 0
1216
- node = node[(index >> bitshift) & INDEX_MASK]
1217
- bitshift -= BITS_PER_LEVEL
1218
- end
1219
- node
119
+ def update_leaf_node(index, item)
120
+ copy_leaf_node_for(new_root, root_index_bits, index)[index & INDEX_MASK] = item
1220
121
  end
1221
122
 
1222
- def update_root(index, item)
1223
- root, levels = @root, @levels
1224
- while index >= (1 << (BITS_PER_LEVEL * (levels + 1)))
1225
- root = [root].freeze
1226
- levels += 1
1227
- end
1228
- new_root = update_leaf_node(root, levels * BITS_PER_LEVEL, index, item)
1229
- if new_root.equal?(root)
1230
- self
123
+ def copy_leaf_node_for(node, child_index_bits, index)
124
+ return node if child_index_bits == 0
125
+ child_index = (index >> child_index_bits) & INDEX_MASK
126
+ child_node = node[child_index]
127
+ if child_node
128
+ child_node = child_node.dup
1231
129
  else
1232
- self.class.alloc(new_root, @size > index ? @size : index + 1, levels)
130
+ child_node = []
1233
131
  end
132
+ node[child_index] = child_node
133
+ copy_leaf_node_for(child_node, child_index_bits - BITS_PER_LEVEL, index)
1234
134
  end
1235
135
 
1236
- def update_leaf_node(node, bitshift, index, item)
1237
- slot_index = (index >> bitshift) & INDEX_MASK
1238
- if bitshift > 0
1239
- old_child = node[slot_index] || []
1240
- item = update_leaf_node(old_child, bitshift - BITS_PER_LEVEL, index, item)
1241
- end
1242
- existing_item = node[slot_index]
1243
- if existing_item.equal?(item)
1244
- node
136
+ def new_root
137
+ if full?
138
+ @levels += 1
139
+ @root = [@root]
1245
140
  else
1246
- node.dup.tap { |n| n[slot_index] = item }.freeze
141
+ @root = @root.dup
1247
142
  end
1248
143
  end
1249
144
 
1250
- def flatten_range(node, bitshift, from, to)
1251
- from_slot = (from >> bitshift) & INDEX_MASK
1252
- to_slot = (to >> bitshift) & INDEX_MASK
1253
-
1254
- if bitshift == 0 # are we at the bottom?
1255
- node.slice(from_slot, to_slot-from_slot+1)
1256
- elsif from_slot == to_slot
1257
- flatten_range(node[from_slot], bitshift - BITS_PER_LEVEL, from, to)
1258
- else
1259
- # the following bitmask can be used to pick out the part of the from/to indices
1260
- # which will be used to direct path BELOW this node
1261
- mask = ((1 << bitshift) - 1)
1262
- result = []
1263
-
1264
- if from & mask == 0
1265
- flatten_node(node[from_slot], bitshift - BITS_PER_LEVEL, result)
1266
- else
1267
- result.concat(flatten_range(node[from_slot], bitshift - BITS_PER_LEVEL, from, from | mask))
1268
- end
1269
-
1270
- (from_slot+1).upto(to_slot-1) do |slot_index|
1271
- flatten_node(node[slot_index], bitshift - BITS_PER_LEVEL, result)
1272
- end
1273
-
1274
- if to & mask == mask
1275
- flatten_node(node[to_slot], bitshift - BITS_PER_LEVEL, result)
1276
- else
1277
- result.concat(flatten_range(node[to_slot], bitshift - BITS_PER_LEVEL, to & ~mask, to))
1278
- end
1279
-
1280
- result
1281
- end
145
+ def full?
146
+ (@size >> root_index_bits) > 0
1282
147
  end
1283
148
 
1284
- def flatten_node(node, bitshift, result)
1285
- if bitshift == 0
1286
- result.concat(node)
1287
- elsif bitshift == BITS_PER_LEVEL
1288
- node.each { |a| result.concat(a) }
1289
- else
1290
- bitshift -= BITS_PER_LEVEL
1291
- node.each { |a| flatten_node(a, bitshift, result) }
1292
- end
1293
- result
1294
- end
1295
-
1296
- def subsequence(from, length)
1297
- return nil if from > @size || from < 0 || length < 0
1298
- length = @size - from if @size < from + length
1299
- return self.class.empty if length == 0
1300
- self.class.new(flatten_range(@root, @levels * BITS_PER_LEVEL, from, from + length - 1))
1301
- end
1302
-
1303
- def flatten_suffix(node, bitshift, from, result)
1304
- from_slot = (from >> bitshift) & INDEX_MASK
1305
-
1306
- if bitshift == 0
1307
- if from_slot == 0
1308
- result.concat(node)
1309
- else
1310
- result.concat(node.slice(from_slot, 32)) # entire suffix of node. excess length is ignored by #slice
1311
- end
1312
- else
1313
- mask = ((1 << bitshift) - 1)
1314
- if from & mask == 0
1315
- from_slot.upto(node.size-1) do |i|
1316
- flatten_node(node[i], bitshift - BITS_PER_LEVEL, result)
1317
- end
1318
- elsif child = node[from_slot]
1319
- flatten_suffix(child, bitshift - BITS_PER_LEVEL, from, result)
1320
- (from_slot+1).upto(node.size-1) do |i|
1321
- flatten_node(node[i], bitshift - BITS_PER_LEVEL, result)
1322
- end
1323
- end
1324
- result
1325
- end
1326
- end
1327
-
1328
- def replace_suffix(from, suffix)
1329
- # new suffix can go directly after existing elements
1330
- raise IndexError if from > @size
1331
- root, levels = @root, @levels
1332
-
1333
- if (from >> (BITS_PER_LEVEL * (@levels + 1))) != 0
1334
- # index where new suffix goes doesn't fall within current tree
1335
- # we will need to deepen tree
1336
- root = [root].freeze
1337
- levels += 1
1338
- end
1339
-
1340
- new_size = from + suffix.size
1341
- root = replace_node_suffix(root, levels * BITS_PER_LEVEL, from, suffix)
1342
-
1343
- if !suffix.empty?
1344
- levels.times { suffix = suffix.each_slice(32).to_a }
1345
- root.concat(suffix)
1346
- while root.size > 32
1347
- root = root.each_slice(32).to_a
1348
- levels += 1
1349
- end
1350
- else
1351
- while root.size == 1 && levels > 0
1352
- root = root[0]
1353
- levels -= 1
1354
- end
1355
- end
1356
-
1357
- self.class.alloc(root.freeze, new_size, levels)
1358
- end
1359
-
1360
- def replace_node_suffix(node, bitshift, from, suffix)
1361
- from_slot = (from >> bitshift) & INDEX_MASK
1362
-
1363
- if bitshift == 0
1364
- if from_slot == 0
1365
- suffix.shift(32)
1366
- else
1367
- node.take(from_slot).concat(suffix.shift(32 - from_slot))
1368
- end
1369
- else
1370
- mask = ((1 << bitshift) - 1)
1371
- if from & mask == 0
1372
- if from_slot == 0
1373
- new_node = suffix.shift(32 * (1 << bitshift))
1374
- while bitshift != 0
1375
- new_node = new_node.each_slice(32).to_a
1376
- bitshift -= BITS_PER_LEVEL
1377
- end
1378
- new_node
1379
- else
1380
- result = node.take(from_slot)
1381
- remainder = suffix.shift((32 - from_slot) * (1 << bitshift))
1382
- while bitshift != 0
1383
- remainder = remainder.each_slice(32).to_a
1384
- bitshift -= BITS_PER_LEVEL
1385
- end
1386
- result.concat(remainder)
1387
- end
1388
- elsif child = node[from_slot]
1389
- result = node.take(from_slot)
1390
- result.push(replace_node_suffix(child, bitshift - BITS_PER_LEVEL, from, suffix))
1391
- remainder = suffix.shift((31 - from_slot) * (1 << bitshift))
1392
- while bitshift != 0
1393
- remainder = remainder.each_slice(32).to_a
1394
- bitshift -= BITS_PER_LEVEL
1395
- end
1396
- result.concat(remainder)
1397
- else
1398
- raise "Shouldn't happen"
1399
- end
1400
- end
149
+ def root_index_bits
150
+ @levels * BITS_PER_LEVEL
1401
151
  end
1402
152
  end
1403
153
 
1404
- # The canonical empty `Vector`. Returned by `Hamster.vector` and `Vector[]` when
1405
- # invoked with no arguments; also returned by `Vector.empty`. Prefer using this
1406
- # one rather than creating many empty vectors using `Vector.new`.
1407
- #
1408
- EmptyVector = Hamster::Vector.empty
154
+ EmptyVector = Hamster::Vector.new
1409
155
  end