hamster 0.4.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (757) hide show
  1. checksums.yaml +7 -0
  2. data/lib/hamster.rb +11 -9
  3. data/lib/hamster/core_ext.rb +2 -3
  4. data/lib/hamster/core_ext/enumerable.rb +18 -27
  5. data/lib/hamster/core_ext/io.rb +16 -25
  6. data/lib/hamster/deque.rb +252 -0
  7. data/lib/hamster/enumerable.rb +123 -112
  8. data/lib/hamster/experimental/mutable_queue.rb +5 -14
  9. data/lib/hamster/experimental/mutable_set.rb +7 -14
  10. data/lib/hamster/hash.rb +732 -102
  11. data/lib/hamster/immutable.rb +4 -10
  12. data/lib/hamster/list.rb +1155 -215
  13. data/lib/hamster/{experimental/mutable_hash.rb → mutable_hash.rb} +11 -14
  14. data/lib/hamster/nested.rb +36 -0
  15. data/lib/hamster/{experimental/read_copy_update.rb → read_copy_update.rb} +10 -8
  16. data/lib/hamster/set.rb +488 -90
  17. data/lib/hamster/sorted_set.rb +1397 -0
  18. data/lib/hamster/trie.rb +210 -65
  19. data/lib/hamster/undefined.rb +1 -7
  20. data/lib/hamster/vector.rb +1329 -83
  21. data/lib/hamster/version.rb +1 -3
  22. data/spec/{hamster/core_ext → fixtures}/io_spec.txt +0 -0
  23. data/spec/lib/hamster/core_ext/array_spec.rb +14 -0
  24. data/spec/lib/hamster/core_ext/enumerable_spec.rb +30 -0
  25. data/spec/lib/hamster/core_ext/io_spec.rb +29 -0
  26. data/spec/lib/hamster/deque/clear_spec.rb +34 -0
  27. data/spec/lib/hamster/deque/construction_spec.rb +30 -0
  28. data/spec/lib/hamster/deque/copying_spec.rb +20 -0
  29. data/spec/lib/hamster/deque/dequeue_spec.rb +35 -0
  30. data/spec/lib/hamster/deque/empty_spec.rb +40 -0
  31. data/spec/lib/hamster/deque/enqueue_spec.rb +28 -0
  32. data/spec/lib/hamster/deque/first_spec.rb +18 -0
  33. data/spec/lib/hamster/deque/inspect_spec.rb +24 -0
  34. data/spec/lib/hamster/deque/last_spec.rb +18 -0
  35. data/spec/lib/hamster/deque/marshal_spec.rb +34 -0
  36. data/spec/lib/hamster/deque/new_spec.rb +44 -0
  37. data/spec/lib/hamster/deque/pop_spec.rb +33 -0
  38. data/spec/lib/hamster/deque/pretty_print_spec.rb +24 -0
  39. data/spec/lib/hamster/deque/random_modification_spec.rb +34 -0
  40. data/spec/lib/hamster/deque/size_spec.rb +20 -0
  41. data/spec/lib/hamster/deque/to_a_spec.rb +27 -0
  42. data/spec/lib/hamster/deque/to_ary_spec.rb +36 -0
  43. data/spec/lib/hamster/deque/to_list_spec.rb +26 -0
  44. data/spec/lib/hamster/deque/unshift_spec.rb +26 -0
  45. data/spec/lib/hamster/experimental/mutable_set/add_qm_spec.rb +39 -0
  46. data/spec/lib/hamster/experimental/mutable_set/add_spec.rb +37 -0
  47. data/spec/lib/hamster/experimental/mutable_set/delete_qm_spec.rb +38 -0
  48. data/spec/lib/hamster/experimental/mutable_set/delete_spec.rb +37 -0
  49. data/spec/lib/hamster/hash/all_spec.rb +54 -0
  50. data/spec/lib/hamster/hash/any_spec.rb +54 -0
  51. data/spec/lib/hamster/hash/assoc_spec.rb +52 -0
  52. data/spec/lib/hamster/hash/clear_spec.rb +43 -0
  53. data/spec/lib/hamster/hash/construction_spec.rb +39 -0
  54. data/spec/lib/hamster/hash/copying_spec.rb +14 -0
  55. data/spec/lib/hamster/hash/default_proc_spec.rb +73 -0
  56. data/spec/lib/hamster/hash/delete_spec.rb +40 -0
  57. data/spec/lib/hamster/hash/each_spec.rb +78 -0
  58. data/spec/lib/hamster/hash/each_with_index_spec.rb +30 -0
  59. data/spec/lib/hamster/hash/empty_spec.rb +44 -0
  60. data/spec/lib/hamster/hash/eql_spec.rb +70 -0
  61. data/spec/lib/hamster/hash/except_spec.rb +43 -0
  62. data/spec/lib/hamster/hash/fetch_spec.rb +58 -0
  63. data/spec/lib/hamster/hash/find_spec.rb +44 -0
  64. data/spec/lib/hamster/hash/flat_map_spec.rb +36 -0
  65. data/spec/lib/hamster/hash/flatten_spec.rb +99 -0
  66. data/spec/lib/hamster/hash/get_spec.rb +80 -0
  67. data/spec/lib/hamster/hash/has_key_spec.rb +32 -0
  68. data/spec/lib/hamster/hash/has_value_spec.rb +28 -0
  69. data/spec/lib/hamster/hash/hash_spec.rb +30 -0
  70. data/spec/{hamster → lib/hamster}/hash/immutable_spec.rb +3 -6
  71. data/spec/lib/hamster/hash/inspect_spec.rb +31 -0
  72. data/spec/lib/hamster/hash/invert_spec.rb +31 -0
  73. data/spec/lib/hamster/hash/key_spec.rb +28 -0
  74. data/spec/lib/hamster/hash/keys_spec.rb +17 -0
  75. data/spec/lib/hamster/hash/map_spec.rb +46 -0
  76. data/spec/lib/hamster/hash/marshal_spec.rb +29 -0
  77. data/spec/lib/hamster/hash/merge_spec.rb +83 -0
  78. data/spec/lib/hamster/hash/min_max_spec.rb +46 -0
  79. data/spec/lib/hamster/hash/new_spec.rb +71 -0
  80. data/spec/lib/hamster/hash/none_spec.rb +49 -0
  81. data/spec/lib/hamster/hash/partition_spec.rb +36 -0
  82. data/spec/lib/hamster/hash/pretty_print_spec.rb +35 -0
  83. data/spec/lib/hamster/hash/put_spec.rb +103 -0
  84. data/spec/lib/hamster/hash/reduce_spec.rb +36 -0
  85. data/spec/lib/hamster/hash/reject_spec.rb +62 -0
  86. data/spec/lib/hamster/hash/reverse_each_spec.rb +28 -0
  87. data/spec/lib/hamster/hash/sample_spec.rb +14 -0
  88. data/spec/lib/hamster/hash/select_spec.rb +58 -0
  89. data/spec/{hamster → lib/hamster}/hash/size_spec.rb +9 -18
  90. data/spec/lib/hamster/hash/slice_spec.rb +45 -0
  91. data/spec/lib/hamster/hash/sort_spec.rb +27 -0
  92. data/spec/lib/hamster/hash/store_spec.rb +76 -0
  93. data/spec/lib/hamster/hash/take_spec.rb +36 -0
  94. data/spec/lib/hamster/hash/to_a_spec.rb +14 -0
  95. data/spec/lib/hamster/hash/to_hash_spec.rb +22 -0
  96. data/spec/lib/hamster/hash/update_in_spec.rb +80 -0
  97. data/spec/lib/hamster/hash/values_at_spec.rb +14 -0
  98. data/spec/lib/hamster/hash/values_spec.rb +25 -0
  99. data/spec/{hamster → lib/hamster}/immutable/copying_spec.rb +3 -10
  100. data/spec/{hamster → lib/hamster}/immutable/immutable_spec.rb +3 -16
  101. data/spec/lib/hamster/immutable/memoize_spec.rb +56 -0
  102. data/spec/lib/hamster/immutable/new_spec.rb +14 -0
  103. data/spec/lib/hamster/immutable/transform_spec.rb +26 -0
  104. data/spec/lib/hamster/immutable/transform_unless_spec.rb +44 -0
  105. data/spec/lib/hamster/list/add_spec.rb +26 -0
  106. data/spec/lib/hamster/list/all_spec.rb +58 -0
  107. data/spec/lib/hamster/list/any_spec.rb +50 -0
  108. data/spec/lib/hamster/list/append_spec.rb +39 -0
  109. data/spec/lib/hamster/list/at_spec.rb +30 -0
  110. data/spec/lib/hamster/list/break_spec.rb +70 -0
  111. data/spec/lib/hamster/list/cadr_spec.rb +39 -0
  112. data/spec/lib/hamster/list/chunk_spec.rb +29 -0
  113. data/spec/lib/hamster/list/clear_spec.rb +25 -0
  114. data/spec/lib/hamster/list/combination_spec.rb +34 -0
  115. data/spec/lib/hamster/list/compact_spec.rb +35 -0
  116. data/spec/lib/hamster/list/compare_spec.rb +31 -0
  117. data/spec/lib/hamster/list/cons_spec.rb +26 -0
  118. data/spec/lib/hamster/list/construction_spec.rb +111 -0
  119. data/spec/lib/hamster/list/copying_spec.rb +20 -0
  120. data/spec/lib/hamster/list/count_spec.rb +37 -0
  121. data/spec/lib/hamster/list/cycle_spec.rb +29 -0
  122. data/spec/lib/hamster/list/delete_at_spec.rb +19 -0
  123. data/spec/lib/hamster/list/delete_spec.rb +17 -0
  124. data/spec/lib/hamster/list/drop_spec.rb +31 -0
  125. data/spec/lib/hamster/list/drop_while_spec.rb +39 -0
  126. data/spec/lib/hamster/list/each_slice_spec.rb +52 -0
  127. data/spec/lib/hamster/list/each_spec.rb +41 -0
  128. data/spec/lib/hamster/list/each_with_index_spec.rb +29 -0
  129. data/spec/lib/hamster/list/empty_spec.rb +24 -0
  130. data/spec/lib/hamster/list/eql_spec.rb +62 -0
  131. data/spec/lib/hamster/list/fill_spec.rb +50 -0
  132. data/spec/lib/hamster/list/find_all_spec.rb +71 -0
  133. data/spec/{hamster → lib/hamster}/list/find_index_spec.rb +7 -29
  134. data/spec/{hamster → lib/hamster}/list/find_spec.rb +13 -35
  135. data/spec/lib/hamster/list/flat_map_spec.rb +52 -0
  136. data/spec/lib/hamster/list/flatten_spec.rb +31 -0
  137. data/spec/lib/hamster/list/grep_spec.rb +47 -0
  138. data/spec/lib/hamster/list/group_by_spec.rb +42 -0
  139. data/spec/lib/hamster/list/hash_spec.rb +22 -0
  140. data/spec/{hamster → lib/hamster}/list/head_spec.rb +6 -21
  141. data/spec/{hamster → lib/hamster}/list/include_spec.rb +8 -29
  142. data/spec/lib/hamster/list/index_spec.rb +34 -0
  143. data/spec/lib/hamster/list/indices_spec.rb +62 -0
  144. data/spec/lib/hamster/list/init_spec.rb +29 -0
  145. data/spec/lib/hamster/list/inits_spec.rb +29 -0
  146. data/spec/lib/hamster/list/insert_spec.rb +47 -0
  147. data/spec/lib/hamster/list/inspect_spec.rb +30 -0
  148. data/spec/lib/hamster/list/intersperse_spec.rb +29 -0
  149. data/spec/lib/hamster/list/join_spec.rb +64 -0
  150. data/spec/lib/hamster/list/last_spec.rb +24 -0
  151. data/spec/lib/hamster/list/ltlt_spec.rb +20 -0
  152. data/spec/lib/hamster/list/map_spec.rb +46 -0
  153. data/spec/lib/hamster/list/maximum_spec.rb +40 -0
  154. data/spec/{hamster → lib/hamster}/list/merge_by_spec.rb +9 -36
  155. data/spec/{hamster → lib/hamster}/list/merge_spec.rb +5 -24
  156. data/spec/lib/hamster/list/minimum_spec.rb +40 -0
  157. data/spec/lib/hamster/list/multithreading_spec.rb +48 -0
  158. data/spec/{hamster → lib/hamster}/list/none_spec.rb +14 -41
  159. data/spec/{hamster → lib/hamster}/list/one_spec.rb +15 -40
  160. data/spec/lib/hamster/list/partition_spec.rb +116 -0
  161. data/spec/lib/hamster/list/permutation_spec.rb +56 -0
  162. data/spec/lib/hamster/list/pop_spec.rb +26 -0
  163. data/spec/lib/hamster/list/product_spec.rb +24 -0
  164. data/spec/lib/hamster/list/reduce_spec.rb +54 -0
  165. data/spec/lib/hamster/list/reject_spec.rb +46 -0
  166. data/spec/lib/hamster/list/reverse_spec.rb +35 -0
  167. data/spec/lib/hamster/list/rotate_spec.rb +37 -0
  168. data/spec/lib/hamster/list/sample_spec.rb +14 -0
  169. data/spec/lib/hamster/list/select_spec.rb +71 -0
  170. data/spec/lib/hamster/list/size_spec.rb +26 -0
  171. data/spec/lib/hamster/list/slice_spec.rb +230 -0
  172. data/spec/lib/hamster/list/sorting_spec.rb +47 -0
  173. data/spec/lib/hamster/list/span_spec.rb +77 -0
  174. data/spec/lib/hamster/list/split_at_spec.rb +44 -0
  175. data/spec/lib/hamster/list/subsequences_spec.rb +24 -0
  176. data/spec/lib/hamster/list/sum_spec.rb +24 -0
  177. data/spec/lib/hamster/list/tail_spec.rb +31 -0
  178. data/spec/lib/hamster/list/tails_spec.rb +29 -0
  179. data/spec/lib/hamster/list/take_spec.rb +31 -0
  180. data/spec/lib/hamster/list/take_while_spec.rb +47 -0
  181. data/spec/lib/hamster/list/to_a_spec.rb +40 -0
  182. data/spec/lib/hamster/list/to_ary_spec.rb +42 -0
  183. data/spec/lib/hamster/list/to_list_spec.rb +20 -0
  184. data/spec/lib/hamster/list/to_set_spec.rb +19 -0
  185. data/spec/lib/hamster/list/transpose_spec.rb +20 -0
  186. data/spec/lib/hamster/list/union_spec.rb +32 -0
  187. data/spec/lib/hamster/list/uniq_spec.rb +30 -0
  188. data/spec/lib/hamster/list/zip_spec.rb +24 -0
  189. data/spec/lib/hamster/nested/construction_spec.rb +44 -0
  190. data/spec/lib/hamster/set/add_spec.rb +76 -0
  191. data/spec/lib/hamster/set/all_spec.rb +52 -0
  192. data/spec/lib/hamster/set/any_spec.rb +52 -0
  193. data/spec/lib/hamster/set/clear_spec.rb +34 -0
  194. data/spec/{hamster → lib/hamster}/set/compact_spec.rb +9 -20
  195. data/spec/lib/hamster/set/construction_spec.rb +19 -0
  196. data/spec/lib/hamster/set/copying_spec.rb +14 -0
  197. data/spec/lib/hamster/set/count_spec.rb +37 -0
  198. data/spec/lib/hamster/set/delete_spec.rb +72 -0
  199. data/spec/lib/hamster/set/difference_spec.rb +50 -0
  200. data/spec/lib/hamster/set/disjoint_spec.rb +26 -0
  201. data/spec/lib/hamster/set/each_spec.rb +46 -0
  202. data/spec/lib/hamster/set/empty_spec.rb +45 -0
  203. data/spec/lib/hamster/set/eqeq_spec.rb +104 -0
  204. data/spec/lib/hamster/set/eql_spec.rb +110 -0
  205. data/spec/lib/hamster/set/exclusion_spec.rb +48 -0
  206. data/spec/{hamster → lib/hamster}/set/find_spec.rb +10 -27
  207. data/spec/lib/hamster/set/first_spec.rb +29 -0
  208. data/spec/lib/hamster/set/flatten_spec.rb +47 -0
  209. data/spec/lib/hamster/set/grep_spec.rb +58 -0
  210. data/spec/lib/hamster/set/group_by_spec.rb +60 -0
  211. data/spec/lib/hamster/set/hash_spec.rb +23 -0
  212. data/spec/{hamster → lib/hamster}/set/immutable_spec.rb +4 -7
  213. data/spec/lib/hamster/set/include_spec.rb +61 -0
  214. data/spec/lib/hamster/set/inspect_spec.rb +48 -0
  215. data/spec/lib/hamster/set/intersect_spec.rb +26 -0
  216. data/spec/lib/hamster/set/intersection_spec.rb +53 -0
  217. data/spec/lib/hamster/set/join_spec.rb +65 -0
  218. data/spec/lib/hamster/set/map_spec.rb +60 -0
  219. data/spec/lib/hamster/set/marshal_spec.rb +29 -0
  220. data/spec/lib/hamster/set/maximum_spec.rb +37 -0
  221. data/spec/lib/hamster/set/minimum_spec.rb +37 -0
  222. data/spec/lib/hamster/set/new_spec.rb +54 -0
  223. data/spec/{hamster → lib/hamster}/set/none_spec.rb +17 -32
  224. data/spec/{hamster → lib/hamster}/set/one_spec.rb +16 -31
  225. data/spec/lib/hamster/set/partition_spec.rb +53 -0
  226. data/spec/lib/hamster/set/product_spec.rb +24 -0
  227. data/spec/lib/hamster/set/reduce_spec.rb +56 -0
  228. data/spec/lib/hamster/set/reject_spec.rb +51 -0
  229. data/spec/lib/hamster/set/reverse_each_spec.rb +39 -0
  230. data/spec/lib/hamster/set/sample_spec.rb +14 -0
  231. data/spec/lib/hamster/set/select_spec.rb +74 -0
  232. data/spec/{hamster → lib/hamster}/set/size_spec.rb +4 -13
  233. data/spec/lib/hamster/set/sorting_spec.rb +49 -0
  234. data/spec/lib/hamster/set/subset_spec.rb +52 -0
  235. data/spec/lib/hamster/set/sum_spec.rb +24 -0
  236. data/spec/lib/hamster/set/superset_spec.rb +52 -0
  237. data/spec/lib/hamster/set/to_a_spec.rb +31 -0
  238. data/spec/lib/hamster/set/to_list_spec.rb +37 -0
  239. data/spec/lib/hamster/set/to_set_spec.rb +20 -0
  240. data/spec/lib/hamster/set/union_spec.rb +64 -0
  241. data/spec/lib/hamster/sorted_set/above_spec.rb +52 -0
  242. data/spec/lib/hamster/sorted_set/add_spec.rb +63 -0
  243. data/spec/lib/hamster/sorted_set/at_spec.rb +25 -0
  244. data/spec/lib/hamster/sorted_set/below_spec.rb +52 -0
  245. data/spec/lib/hamster/sorted_set/between_spec.rb +52 -0
  246. data/spec/lib/hamster/sorted_set/clear_spec.rb +44 -0
  247. data/spec/lib/hamster/sorted_set/construction_spec.rb +29 -0
  248. data/spec/lib/hamster/sorted_set/delete_at_spec.rb +19 -0
  249. data/spec/lib/hamster/sorted_set/delete_spec.rb +90 -0
  250. data/spec/lib/hamster/sorted_set/difference_spec.rb +23 -0
  251. data/spec/lib/hamster/sorted_set/disjoint_spec.rb +26 -0
  252. data/spec/lib/hamster/sorted_set/drop_spec.rb +56 -0
  253. data/spec/lib/hamster/sorted_set/drop_while_spec.rb +35 -0
  254. data/spec/lib/hamster/sorted_set/each_spec.rb +29 -0
  255. data/spec/lib/hamster/sorted_set/empty_spec.rb +35 -0
  256. data/spec/lib/hamster/sorted_set/eql_spec.rb +121 -0
  257. data/spec/lib/hamster/sorted_set/exclusion_spec.rb +23 -0
  258. data/spec/lib/hamster/sorted_set/fetch_spec.rb +65 -0
  259. data/spec/lib/hamster/sorted_set/find_index_spec.rb +41 -0
  260. data/spec/lib/hamster/sorted_set/first_spec.rb +19 -0
  261. data/spec/lib/hamster/sorted_set/from_spec.rb +52 -0
  262. data/spec/lib/hamster/sorted_set/group_by_spec.rb +58 -0
  263. data/spec/lib/hamster/sorted_set/include_spec.rb +24 -0
  264. data/spec/lib/hamster/sorted_set/inspect_spec.rb +38 -0
  265. data/spec/lib/hamster/sorted_set/intersect_spec.rb +26 -0
  266. data/spec/lib/hamster/sorted_set/intersection_spec.rb +29 -0
  267. data/spec/lib/hamster/sorted_set/last_spec.rb +37 -0
  268. data/spec/lib/hamster/sorted_set/map_spec.rb +36 -0
  269. data/spec/lib/hamster/sorted_set/marshal_spec.rb +37 -0
  270. data/spec/lib/hamster/sorted_set/maximum_spec.rb +37 -0
  271. data/spec/lib/hamster/sorted_set/minimum_spec.rb +20 -0
  272. data/spec/lib/hamster/sorted_set/new_spec.rb +52 -0
  273. data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +29 -0
  274. data/spec/lib/hamster/sorted_set/sample_spec.rb +14 -0
  275. data/spec/lib/hamster/sorted_set/select_spec.rb +62 -0
  276. data/spec/{hamster/vector → lib/hamster/sorted_set}/size_spec.rb +6 -15
  277. data/spec/lib/hamster/sorted_set/slice_spec.rb +257 -0
  278. data/spec/lib/hamster/sorted_set/sorting_spec.rb +45 -0
  279. data/spec/lib/hamster/sorted_set/subset_spec.rb +48 -0
  280. data/spec/lib/hamster/sorted_set/superset_spec.rb +48 -0
  281. data/spec/lib/hamster/sorted_set/take_spec.rb +55 -0
  282. data/spec/lib/hamster/sorted_set/take_while_spec.rb +34 -0
  283. data/spec/lib/hamster/sorted_set/to_set_spec.rb +19 -0
  284. data/spec/lib/hamster/sorted_set/union_spec.rb +28 -0
  285. data/spec/lib/hamster/sorted_set/up_to_spec.rb +52 -0
  286. data/spec/lib/hamster/sorted_set/values_at_spec.rb +34 -0
  287. data/spec/lib/hamster/vector/add_spec.rb +68 -0
  288. data/spec/lib/hamster/vector/any_spec.rb +70 -0
  289. data/spec/lib/hamster/vector/assoc_spec.rb +36 -0
  290. data/spec/lib/hamster/vector/bsearch_spec.rb +58 -0
  291. data/spec/lib/hamster/vector/clear_spec.rb +34 -0
  292. data/spec/lib/hamster/vector/combination_spec.rb +82 -0
  293. data/spec/lib/hamster/vector/compact_spec.rb +30 -0
  294. data/spec/lib/hamster/vector/compare_spec.rb +32 -0
  295. data/spec/lib/hamster/vector/concat_spec.rb +35 -0
  296. data/spec/lib/hamster/vector/copying_spec.rb +21 -0
  297. data/spec/lib/hamster/vector/count_spec.rb +18 -0
  298. data/spec/lib/hamster/vector/delete_at_spec.rb +54 -0
  299. data/spec/lib/hamster/vector/delete_spec.rb +31 -0
  300. data/spec/lib/hamster/vector/drop_spec.rb +42 -0
  301. data/spec/lib/hamster/vector/drop_while_spec.rb +55 -0
  302. data/spec/lib/hamster/vector/each_index_spec.rb +41 -0
  303. data/spec/lib/hamster/vector/each_spec.rb +45 -0
  304. data/spec/lib/hamster/vector/each_with_index_spec.rb +40 -0
  305. data/spec/lib/hamster/vector/empty_spec.rb +42 -0
  306. data/spec/lib/hamster/vector/eql_spec.rb +77 -0
  307. data/spec/lib/hamster/vector/fetch_spec.rb +65 -0
  308. data/spec/lib/hamster/vector/fill_spec.rb +89 -0
  309. data/spec/lib/hamster/vector/first_spec.rb +19 -0
  310. data/spec/lib/hamster/vector/flat_map_spec.rb +51 -0
  311. data/spec/lib/hamster/vector/flatten_spec.rb +44 -0
  312. data/spec/lib/hamster/vector/get_spec.rb +75 -0
  313. data/spec/lib/hamster/vector/group_by_spec.rb +58 -0
  314. data/spec/{hamster → lib/hamster}/vector/include_spec.rb +6 -20
  315. data/spec/lib/hamster/vector/insert_spec.rb +69 -0
  316. data/spec/lib/hamster/vector/inspect_spec.rb +50 -0
  317. data/spec/{hamster/set → lib/hamster/vector}/join_spec.rb +24 -34
  318. data/spec/lib/hamster/vector/last_spec.rb +46 -0
  319. data/spec/lib/hamster/vector/length_spec.rb +46 -0
  320. data/spec/lib/hamster/vector/ltlt_spec.rb +66 -0
  321. data/spec/lib/hamster/vector/map_spec.rb +52 -0
  322. data/spec/lib/hamster/vector/marshal_spec.rb +32 -0
  323. data/spec/lib/hamster/vector/maximum_spec.rb +34 -0
  324. data/spec/lib/hamster/vector/minimum_spec.rb +34 -0
  325. data/spec/lib/hamster/vector/multiply_spec.rb +48 -0
  326. data/spec/lib/hamster/vector/new_spec.rb +51 -0
  327. data/spec/lib/hamster/vector/partition_spec.rb +53 -0
  328. data/spec/lib/hamster/vector/permutation_spec.rb +92 -0
  329. data/spec/lib/hamster/vector/pop_spec.rb +27 -0
  330. data/spec/lib/hamster/vector/product_spec.rb +71 -0
  331. data/spec/{hamster → lib/hamster}/vector/reduce_spec.rb +18 -49
  332. data/spec/lib/hamster/vector/reject_spec.rb +44 -0
  333. data/spec/lib/hamster/vector/repeated_combination_spec.rb +78 -0
  334. data/spec/lib/hamster/vector/repeated_permutation_spec.rb +94 -0
  335. data/spec/lib/hamster/vector/reverse_each_spec.rb +32 -0
  336. data/spec/lib/hamster/vector/reverse_spec.rb +22 -0
  337. data/spec/lib/hamster/vector/rindex_spec.rb +37 -0
  338. data/spec/lib/hamster/vector/rotate_spec.rb +74 -0
  339. data/spec/lib/hamster/vector/sample_spec.rb +14 -0
  340. data/spec/lib/hamster/vector/select_spec.rb +64 -0
  341. data/spec/lib/hamster/vector/set_spec.rb +175 -0
  342. data/spec/lib/hamster/vector/shift_spec.rb +28 -0
  343. data/spec/lib/hamster/vector/shuffle_spec.rb +44 -0
  344. data/spec/lib/hamster/vector/slice_spec.rb +241 -0
  345. data/spec/lib/hamster/vector/sorting_spec.rb +57 -0
  346. data/spec/{hamster/set → lib/hamster/vector}/sum_spec.rb +5 -19
  347. data/spec/lib/hamster/vector/take_spec.rb +43 -0
  348. data/spec/lib/hamster/vector/take_while_spec.rb +35 -0
  349. data/spec/lib/hamster/vector/to_a_spec.rb +42 -0
  350. data/spec/lib/hamster/vector/to_ary_spec.rb +35 -0
  351. data/spec/lib/hamster/vector/to_list_spec.rb +32 -0
  352. data/spec/lib/hamster/vector/to_set_spec.rb +23 -0
  353. data/spec/lib/hamster/vector/transpose_spec.rb +49 -0
  354. data/spec/lib/hamster/vector/uniq_spec.rb +56 -0
  355. data/spec/lib/hamster/vector/unshift_spec.rb +29 -0
  356. data/spec/lib/hamster/vector/update_in_spec.rb +83 -0
  357. data/spec/lib/hamster/vector/values_at_spec.rb +34 -0
  358. data/spec/lib/hamster/vector/zip_spec.rb +58 -0
  359. data/spec/spec_helper.rb +45 -13
  360. metadata +807 -458
  361. data/History.rdoc +0 -419
  362. data/LICENSE +0 -20
  363. data/README.rdoc +0 -236
  364. data/Rakefile +0 -5
  365. data/lib/hamster/core_ext/enumerator.rb +0 -30
  366. data/lib/hamster/experimental/mutable_stack.rb +0 -35
  367. data/lib/hamster/queue.rb +0 -93
  368. data/lib/hamster/sorter.rb +0 -32
  369. data/lib/hamster/stack.rb +0 -82
  370. data/lib/hamster/tuple.rb +0 -45
  371. data/spec/hamster/core_ext/array_spec.rb +0 -20
  372. data/spec/hamster/core_ext/coverage/assets/0.4.4/app.js +0 -66
  373. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/blank.gif +0 -0
  374. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_close.png +0 -0
  375. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_loading.png +0 -0
  376. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_nav_left.png +0 -0
  377. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_nav_right.png +0 -0
  378. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_e.png +0 -0
  379. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_n.png +0 -0
  380. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_ne.png +0 -0
  381. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_nw.png +0 -0
  382. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_s.png +0 -0
  383. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_se.png +0 -0
  384. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_sw.png +0 -0
  385. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_w.png +0 -0
  386. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_title_left.png +0 -0
  387. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_title_main.png +0 -0
  388. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_title_over.png +0 -0
  389. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_title_right.png +0 -0
  390. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancybox-x.png +0 -0
  391. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancybox-y.png +0 -0
  392. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancybox.png +0 -0
  393. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.css +0 -363
  394. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  395. data/spec/hamster/core_ext/coverage/assets/0.4.4/favicon.png +0 -0
  396. data/spec/hamster/core_ext/coverage/assets/0.4.4/jquery-1.4.2.min.js +0 -155
  397. data/spec/hamster/core_ext/coverage/assets/0.4.4/jquery.dataTables.min.js +0 -152
  398. data/spec/hamster/core_ext/coverage/assets/0.4.4/jquery.timeago.js +0 -141
  399. data/spec/hamster/core_ext/coverage/assets/0.4.4/jquery.url.js +0 -174
  400. data/spec/hamster/core_ext/coverage/assets/0.4.4/loading.gif +0 -0
  401. data/spec/hamster/core_ext/coverage/assets/0.4.4/magnify.png +0 -0
  402. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  403. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  404. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  405. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  406. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  407. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  408. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  409. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  410. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_222222_256x240.png +0 -0
  411. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  412. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_454545_256x240.png +0 -0
  413. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_888888_256x240.png +0 -0
  414. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  415. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  416. data/spec/hamster/core_ext/coverage/assets/0.4.4/stylesheet.css +0 -341
  417. data/spec/hamster/core_ext/coverage/covered_percent +0 -1
  418. data/spec/hamster/core_ext/coverage/index.html +0 -71
  419. data/spec/hamster/core_ext/coverage/resultset.yml +0 -10
  420. data/spec/hamster/core_ext/enumerable_spec.rb +0 -34
  421. data/spec/hamster/core_ext/enumerator_spec.rb +0 -25
  422. data/spec/hamster/core_ext/io_spec.rb +0 -29
  423. data/spec/hamster/experimental/mutable_set/add?_spec.rb +0 -47
  424. data/spec/hamster/experimental/mutable_set/add_spec.rb +0 -51
  425. data/spec/hamster/experimental/mutable_set/delete?_spec.rb +0 -47
  426. data/spec/hamster/experimental/mutable_set/delete_spec.rb +0 -47
  427. data/spec/hamster/experimental/mutable_stack/pop_spec.rb +0 -41
  428. data/spec/hamster/experimental/mutable_stack/push_spec.rb +0 -41
  429. data/spec/hamster/hash/all_spec.rb +0 -59
  430. data/spec/hamster/hash/any_spec.rb +0 -68
  431. data/spec/hamster/hash/clear_spec.rb +0 -36
  432. data/spec/hamster/hash/construction_spec.rb +0 -35
  433. data/spec/hamster/hash/copying_spec.rb +0 -23
  434. data/spec/hamster/hash/delete_spec.rb +0 -47
  435. data/spec/hamster/hash/each_spec.rb +0 -41
  436. data/spec/hamster/hash/empty_spec.rb +0 -27
  437. data/spec/hamster/hash/eql_spec.rb +0 -62
  438. data/spec/hamster/hash/except_spec.rb +0 -31
  439. data/spec/hamster/hash/fetch_spec.rb +0 -95
  440. data/spec/hamster/hash/filter_spec.rb +0 -63
  441. data/spec/hamster/hash/find_spec.rb +0 -58
  442. data/spec/hamster/hash/get_spec.rb +0 -68
  443. data/spec/hamster/hash/has_key_spec.rb +0 -35
  444. data/spec/hamster/hash/hash_spec.rb +0 -54
  445. data/spec/hamster/hash/inspect_spec.rb +0 -32
  446. data/spec/hamster/hash/keys_spec.rb +0 -21
  447. data/spec/hamster/hash/map_spec.rb +0 -64
  448. data/spec/hamster/hash/merge_spec.rb +0 -36
  449. data/spec/hamster/hash/none_spec.rb +0 -64
  450. data/spec/hamster/hash/put_spec.rb +0 -65
  451. data/spec/hamster/hash/reduce_spec.rb +0 -60
  452. data/spec/hamster/hash/remove_spec.rb +0 -63
  453. data/spec/hamster/hash/slice_spec.rb +0 -31
  454. data/spec/hamster/hash/uniq_spec.rb +0 -23
  455. data/spec/hamster/hash/values_spec.rb +0 -34
  456. data/spec/hamster/immutable/memoize_spec.rb +0 -64
  457. data/spec/hamster/immutable/new_spec.rb +0 -28
  458. data/spec/hamster/immutable/transform_spec.rb +0 -31
  459. data/spec/hamster/immutable/transform_unless_spec.rb +0 -55
  460. data/spec/hamster/list/all_spec.rb +0 -111
  461. data/spec/hamster/list/any_spec.rb +0 -79
  462. data/spec/hamster/list/append_spec.rb +0 -50
  463. data/spec/hamster/list/at_spec.rb +0 -49
  464. data/spec/hamster/list/break_spec.rb +0 -85
  465. data/spec/hamster/list/cadr_spec.rb +0 -50
  466. data/spec/hamster/list/chunk_spec.rb +0 -40
  467. data/spec/hamster/list/clear_spec.rb +0 -36
  468. data/spec/hamster/list/combinations_spec.rb +0 -51
  469. data/spec/hamster/list/compact_spec.rb +0 -46
  470. data/spec/hamster/list/cons_spec.rb +0 -41
  471. data/spec/hamster/list/construction_spec.rb +0 -140
  472. data/spec/hamster/list/copying_spec.rb +0 -32
  473. data/spec/hamster/list/count_spec.rb +0 -66
  474. data/spec/hamster/list/coverage/assets/0.4.4/app.js +0 -66
  475. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/blank.gif +0 -0
  476. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_close.png +0 -0
  477. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_loading.png +0 -0
  478. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_nav_left.png +0 -0
  479. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_nav_right.png +0 -0
  480. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_e.png +0 -0
  481. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_n.png +0 -0
  482. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_ne.png +0 -0
  483. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_nw.png +0 -0
  484. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_s.png +0 -0
  485. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_se.png +0 -0
  486. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_sw.png +0 -0
  487. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_w.png +0 -0
  488. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_title_left.png +0 -0
  489. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_title_main.png +0 -0
  490. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_title_over.png +0 -0
  491. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_title_right.png +0 -0
  492. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancybox-x.png +0 -0
  493. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancybox-y.png +0 -0
  494. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancybox.png +0 -0
  495. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.css +0 -363
  496. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  497. data/spec/hamster/list/coverage/assets/0.4.4/favicon.png +0 -0
  498. data/spec/hamster/list/coverage/assets/0.4.4/jquery-1.4.2.min.js +0 -155
  499. data/spec/hamster/list/coverage/assets/0.4.4/jquery.dataTables.min.js +0 -152
  500. data/spec/hamster/list/coverage/assets/0.4.4/jquery.timeago.js +0 -141
  501. data/spec/hamster/list/coverage/assets/0.4.4/jquery.url.js +0 -174
  502. data/spec/hamster/list/coverage/assets/0.4.4/loading.gif +0 -0
  503. data/spec/hamster/list/coverage/assets/0.4.4/magnify.png +0 -0
  504. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  505. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  506. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  507. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  508. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  509. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  510. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  511. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  512. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_222222_256x240.png +0 -0
  513. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  514. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_454545_256x240.png +0 -0
  515. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_888888_256x240.png +0 -0
  516. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  517. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  518. data/spec/hamster/list/coverage/assets/0.4.4/stylesheet.css +0 -341
  519. data/spec/hamster/list/coverage/covered_percent +0 -1
  520. data/spec/hamster/list/coverage/index.html +0 -71
  521. data/spec/hamster/list/coverage/resultset.yml +0 -225
  522. data/spec/hamster/list/cycle_spec.rb +0 -45
  523. data/spec/hamster/list/drop_spec.rb +0 -42
  524. data/spec/hamster/list/drop_while_spec.rb +0 -59
  525. data/spec/hamster/list/each_slice_spec.rb +0 -80
  526. data/spec/hamster/list/each_spec.rb +0 -72
  527. data/spec/hamster/list/each_with_index_spec.rb +0 -42
  528. data/spec/hamster/list/elem_index_spec.rb +0 -58
  529. data/spec/hamster/list/elem_indices_spec.rb +0 -45
  530. data/spec/hamster/list/empty_spec.rb +0 -47
  531. data/spec/hamster/list/eql_spec.rb +0 -78
  532. data/spec/hamster/list/filter_spec.rb +0 -61
  533. data/spec/hamster/list/find_indices_spec.rb +0 -45
  534. data/spec/hamster/list/flatten_spec.rb +0 -42
  535. data/spec/hamster/list/grep_spec.rb +0 -70
  536. data/spec/hamster/list/group_by_spec.rb +0 -77
  537. data/spec/hamster/list/hash_spec.rb +0 -43
  538. data/spec/hamster/list/init_spec.rb +0 -40
  539. data/spec/hamster/list/inits_spec.rb +0 -42
  540. data/spec/hamster/list/inspect_spec.rb +0 -43
  541. data/spec/hamster/list/intersperse_spec.rb +0 -40
  542. data/spec/hamster/list/join_spec.rb +0 -81
  543. data/spec/hamster/list/last_spec.rb +0 -44
  544. data/spec/hamster/list/map_spec.rb +0 -69
  545. data/spec/hamster/list/maximum_spec.rb +0 -77
  546. data/spec/hamster/list/minimum_spec.rb +0 -77
  547. data/spec/hamster/list/partition_spec.rb +0 -75
  548. data/spec/hamster/list/product_spec.rb +0 -44
  549. data/spec/hamster/list/reduce_spec.rb +0 -99
  550. data/spec/hamster/list/remove_spec.rb +0 -67
  551. data/spec/hamster/list/reverse_spec.rb +0 -52
  552. data/spec/hamster/list/size_spec.rb +0 -47
  553. data/spec/hamster/list/slice_spec.rb +0 -50
  554. data/spec/hamster/list/sorting_spec.rb +0 -70
  555. data/spec/hamster/list/span_spec.rb +0 -86
  556. data/spec/hamster/list/split_at_spec.rb +0 -53
  557. data/spec/hamster/list/sum_spec.rb +0 -44
  558. data/spec/hamster/list/tail_spec.rb +0 -48
  559. data/spec/hamster/list/tails_spec.rb +0 -42
  560. data/spec/hamster/list/take_spec.rb +0 -42
  561. data/spec/hamster/list/take_while_spec.rb +0 -62
  562. data/spec/hamster/list/to_a_spec.rb +0 -54
  563. data/spec/hamster/list/to_ary_spec.rb +0 -56
  564. data/spec/hamster/list/to_list_spec.rb +0 -32
  565. data/spec/hamster/list/to_set_spec.rb +0 -33
  566. data/spec/hamster/list/union_spec.rb +0 -49
  567. data/spec/hamster/list/uniq_spec.rb +0 -45
  568. data/spec/hamster/list/zip_spec.rb +0 -39
  569. data/spec/hamster/queue/clear_spec.rb +0 -36
  570. data/spec/hamster/queue/construction_spec.rb +0 -43
  571. data/spec/hamster/queue/dequeue_spec.rb +0 -40
  572. data/spec/hamster/queue/empty_spec.rb +0 -47
  573. data/spec/hamster/queue/enqueue_spec.rb +0 -41
  574. data/spec/hamster/queue/head_spec.rb +0 -35
  575. data/spec/hamster/queue/inspect_spec.rb +0 -31
  576. data/spec/hamster/queue/size_spec.rb +0 -35
  577. data/spec/hamster/queue/to_a_spec.rb +0 -42
  578. data/spec/hamster/queue/to_ary_spec.rb +0 -44
  579. data/spec/hamster/queue/to_list_spec.rb +0 -44
  580. data/spec/hamster/set/add_spec.rb +0 -51
  581. data/spec/hamster/set/all_spec.rb +0 -67
  582. data/spec/hamster/set/any_spec.rb +0 -67
  583. data/spec/hamster/set/clear_spec.rb +0 -36
  584. data/spec/hamster/set/construction_spec.rb +0 -31
  585. data/spec/hamster/set/copying_spec.rb +0 -23
  586. data/spec/hamster/set/count_spec.rb +0 -54
  587. data/spec/hamster/set/coverage/assets/0.4.4/app.js +0 -66
  588. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/blank.gif +0 -0
  589. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_close.png +0 -0
  590. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_loading.png +0 -0
  591. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_nav_left.png +0 -0
  592. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_nav_right.png +0 -0
  593. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_e.png +0 -0
  594. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_n.png +0 -0
  595. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_ne.png +0 -0
  596. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_nw.png +0 -0
  597. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_s.png +0 -0
  598. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_se.png +0 -0
  599. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_sw.png +0 -0
  600. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_w.png +0 -0
  601. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_title_left.png +0 -0
  602. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_title_main.png +0 -0
  603. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_title_over.png +0 -0
  604. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_title_right.png +0 -0
  605. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancybox-x.png +0 -0
  606. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancybox-y.png +0 -0
  607. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancybox.png +0 -0
  608. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.css +0 -363
  609. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  610. data/spec/hamster/set/coverage/assets/0.4.4/favicon.png +0 -0
  611. data/spec/hamster/set/coverage/assets/0.4.4/jquery-1.4.2.min.js +0 -155
  612. data/spec/hamster/set/coverage/assets/0.4.4/jquery.dataTables.min.js +0 -152
  613. data/spec/hamster/set/coverage/assets/0.4.4/jquery.timeago.js +0 -141
  614. data/spec/hamster/set/coverage/assets/0.4.4/jquery.url.js +0 -174
  615. data/spec/hamster/set/coverage/assets/0.4.4/loading.gif +0 -0
  616. data/spec/hamster/set/coverage/assets/0.4.4/magnify.png +0 -0
  617. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  618. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  619. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  620. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  621. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  622. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  623. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  624. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  625. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_222222_256x240.png +0 -0
  626. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  627. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_454545_256x240.png +0 -0
  628. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_888888_256x240.png +0 -0
  629. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  630. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  631. data/spec/hamster/set/coverage/assets/0.4.4/stylesheet.css +0 -341
  632. data/spec/hamster/set/coverage/covered_percent +0 -1
  633. data/spec/hamster/set/coverage/index.html +0 -71
  634. data/spec/hamster/set/coverage/resultset.yml +0 -13
  635. data/spec/hamster/set/delete_spec.rb +0 -47
  636. data/spec/hamster/set/difference_spec.rb +0 -37
  637. data/spec/hamster/set/each_spec.rb +0 -42
  638. data/spec/hamster/set/empty_spec.rb +0 -35
  639. data/spec/hamster/set/eql_spec.rb +0 -62
  640. data/spec/hamster/set/exclusion_spec.rb +0 -38
  641. data/spec/hamster/set/filter_spec.rb +0 -79
  642. data/spec/hamster/set/flatten_spec.rb +0 -49
  643. data/spec/hamster/set/grep_spec.rb +0 -62
  644. data/spec/hamster/set/group_by_spec.rb +0 -65
  645. data/spec/hamster/set/hash_spec.rb +0 -31
  646. data/spec/hamster/set/head_spec.rb +0 -39
  647. data/spec/hamster/set/include_spec.rb +0 -35
  648. data/spec/hamster/set/inspect_spec.rb +0 -32
  649. data/spec/hamster/set/intersection_spec.rb +0 -46
  650. data/spec/hamster/set/map_spec.rb +0 -64
  651. data/spec/hamster/set/maximum_spec.rb +0 -65
  652. data/spec/hamster/set/minimum_spec.rb +0 -65
  653. data/spec/hamster/set/partition_spec.rb +0 -71
  654. data/spec/hamster/set/product_spec.rb +0 -32
  655. data/spec/hamster/set/reduce_spec.rb +0 -87
  656. data/spec/hamster/set/remove_spec.rb +0 -63
  657. data/spec/hamster/set/sorting_spec.rb +0 -58
  658. data/spec/hamster/set/subset_spec.rb +0 -39
  659. data/spec/hamster/set/superset_spec.rb +0 -39
  660. data/spec/hamster/set/to_a_spec.rb +0 -42
  661. data/spec/hamster/set/to_list_spec.rb +0 -47
  662. data/spec/hamster/set/to_set_spec.rb +0 -32
  663. data/spec/hamster/set/union_spec.rb +0 -45
  664. data/spec/hamster/set/uniq_spec.rb +0 -23
  665. data/spec/hamster/sorter/coverage/assets/0.4.4/app.js +0 -66
  666. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/blank.gif +0 -0
  667. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_close.png +0 -0
  668. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_loading.png +0 -0
  669. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_nav_left.png +0 -0
  670. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_nav_right.png +0 -0
  671. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_e.png +0 -0
  672. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_n.png +0 -0
  673. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_ne.png +0 -0
  674. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_nw.png +0 -0
  675. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_s.png +0 -0
  676. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_se.png +0 -0
  677. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_sw.png +0 -0
  678. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_w.png +0 -0
  679. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_title_left.png +0 -0
  680. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_title_main.png +0 -0
  681. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_title_over.png +0 -0
  682. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_title_right.png +0 -0
  683. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancybox-x.png +0 -0
  684. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancybox-y.png +0 -0
  685. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancybox.png +0 -0
  686. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.css +0 -363
  687. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  688. data/spec/hamster/sorter/coverage/assets/0.4.4/favicon.png +0 -0
  689. data/spec/hamster/sorter/coverage/assets/0.4.4/jquery-1.4.2.min.js +0 -155
  690. data/spec/hamster/sorter/coverage/assets/0.4.4/jquery.dataTables.min.js +0 -152
  691. data/spec/hamster/sorter/coverage/assets/0.4.4/jquery.timeago.js +0 -141
  692. data/spec/hamster/sorter/coverage/assets/0.4.4/jquery.url.js +0 -174
  693. data/spec/hamster/sorter/coverage/assets/0.4.4/loading.gif +0 -0
  694. data/spec/hamster/sorter/coverage/assets/0.4.4/magnify.png +0 -0
  695. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  696. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  697. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  698. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  699. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  700. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  701. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  702. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  703. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_222222_256x240.png +0 -0
  704. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  705. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_454545_256x240.png +0 -0
  706. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_888888_256x240.png +0 -0
  707. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  708. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  709. data/spec/hamster/sorter/coverage/assets/0.4.4/stylesheet.css +0 -341
  710. data/spec/hamster/sorter/coverage/covered_percent +0 -1
  711. data/spec/hamster/sorter/coverage/index.html +0 -71
  712. data/spec/hamster/sorter/coverage/resultset.yml +0 -22
  713. data/spec/hamster/sorter/immutable_spec.rb +0 -12
  714. data/spec/hamster/stack/clear_spec.rb +0 -36
  715. data/spec/hamster/stack/construction_spec.rb +0 -43
  716. data/spec/hamster/stack/copying_spec.rb +0 -31
  717. data/spec/hamster/stack/empty_spec.rb +0 -31
  718. data/spec/hamster/stack/eql_spec.rb +0 -60
  719. data/spec/hamster/stack/immutable_spec.rb +0 -12
  720. data/spec/hamster/stack/inspect_spec.rb +0 -31
  721. data/spec/hamster/stack/peek_spec.rb +0 -40
  722. data/spec/hamster/stack/pop_spec.rb +0 -41
  723. data/spec/hamster/stack/push_spec.rb +0 -41
  724. data/spec/hamster/stack/size_spec.rb +0 -35
  725. data/spec/hamster/stack/to_a_spec.rb +0 -42
  726. data/spec/hamster/stack/to_ary.rb +0 -44
  727. data/spec/hamster/stack/to_list_spec.rb +0 -33
  728. data/spec/hamster/trie/remove_spec.rb +0 -117
  729. data/spec/hamster/tuple/copying_spec.rb +0 -24
  730. data/spec/hamster/tuple/eql_spec.rb +0 -61
  731. data/spec/hamster/tuple/first_spec.rb +0 -19
  732. data/spec/hamster/tuple/immutable_spec.rb +0 -12
  733. data/spec/hamster/tuple/inspect_spec.rb +0 -19
  734. data/spec/hamster/tuple/last_spec.rb +0 -19
  735. data/spec/hamster/tuple/to_a_spec.rb +0 -38
  736. data/spec/hamster/tuple/to_ary_spec.rb +0 -44
  737. data/spec/hamster/undefined/erase_spec.rb +0 -47
  738. data/spec/hamster/vector/add_spec.rb +0 -41
  739. data/spec/hamster/vector/any_spec.rb +0 -67
  740. data/spec/hamster/vector/clear_spec.rb +0 -36
  741. data/spec/hamster/vector/copying_spec.rb +0 -32
  742. data/spec/hamster/vector/each_spec.rb +0 -46
  743. data/spec/hamster/vector/each_with_index_spec.rb +0 -42
  744. data/spec/hamster/vector/empty_spec.rb +0 -35
  745. data/spec/hamster/vector/eql_spec.rb +0 -65
  746. data/spec/hamster/vector/filter_spec.rb +0 -63
  747. data/spec/hamster/vector/first_spec.rb +0 -35
  748. data/spec/hamster/vector/get_spec.rb +0 -81
  749. data/spec/hamster/vector/inspect_spec.rb +0 -31
  750. data/spec/hamster/vector/last_spec.rb +0 -32
  751. data/spec/hamster/vector/map_spec.rb +0 -64
  752. data/spec/hamster/vector/set_spec.rb +0 -153
  753. data/spec/hamster/vector/to_a_spec.rb +0 -42
  754. data/spec/hamster/vector/to_ary_spec.rb +0 -44
  755. data/tasks/bundler.rb +0 -2
  756. data/tasks/publish.rb +0 -12
  757. data/tasks/spec.rb +0 -13
@@ -1,10 +1,14 @@
1
- require 'forwardable'
2
-
3
1
  module Hamster
4
-
2
+ # @private
5
3
  class Trie
4
+ def self.[](pairs)
5
+ result = self.new(0)
6
+ pairs.each { |key, val| result.put!(key, val) }
7
+ result
8
+ end
6
9
 
7
- extend Forwardable
10
+ # Returns the number of key-value pairs in the trie.
11
+ attr_reader :size
8
12
 
9
13
  def initialize(significant_bits, size = 0, entries = [], children = [])
10
14
  @significant_bits = significant_bits
@@ -13,27 +17,30 @@ module Hamster
13
17
  @size = size
14
18
  end
15
19
 
16
- # Returns the number of key-value pairs in the trie.
17
- def size
18
- @size
19
- end
20
-
21
20
  # Returns <tt>true</tt> if the trie contains no key-value pairs.
22
21
  def empty?
23
22
  size == 0
24
23
  end
25
24
 
26
25
  # Returns <tt>true</tt> if the given key is present in the trie.
27
- def has_key?(key)
28
- !! get(key)
26
+ def key?(key)
27
+ !!get(key)
29
28
  end
30
29
 
31
30
  # Calls <tt>block</tt> once for each entry in the trie, passing the key-value pair as parameters.
32
- def each
31
+ def each(&block)
33
32
  @entries.each { |entry| yield(entry) if entry }
34
33
  @children.each do |child|
35
- child.each { |entry| yield(entry) } if child
34
+ child.each(&block) if child
35
+ end
36
+ nil
37
+ end
38
+
39
+ def reverse_each(&block)
40
+ @children.reverse_each do |child|
41
+ child.reverse_each(&block) if child
36
42
  end
43
+ @entries.reverse_each { |entry| yield(entry) if entry }
37
44
  nil
38
45
  end
39
46
 
@@ -42,60 +49,215 @@ module Hamster
42
49
  memo
43
50
  end
44
51
 
45
- def filter
46
- reduce(self) { |trie, entry| yield(entry) ? trie : trie.delete(entry.key) }
52
+ def select
53
+ keys_to_delete = []
54
+ each { |entry| keys_to_delete << entry[0] unless yield(entry) }
55
+ bulk_delete(keys_to_delete)
47
56
  end
48
57
 
49
- # Returns a copy of <tt>self</tt> with the given value associated with the key.
58
+ # @return [Trie] A copy of `self` with the given value associated with the
59
+ # key (or `self` if no modification was needed because an identical
60
+ # key-value pair wes already stored
50
61
  def put(key, value)
51
62
  index = index_for(key)
52
63
  entry = @entries[index]
53
64
 
54
65
  if !entry
55
66
  entries = @entries.dup
56
- entries[index] = Entry.new(key, value)
57
- self.class.new(@significant_bits, @size + 1, entries, @children)
58
- elsif entry.key.eql?(key)
59
- entries = @entries.dup
60
- entries[index] = Entry.new(key, value)
61
- self.class.new(@significant_bits, @size, entries, @children)
67
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
68
+ entries[index] = [key, value].freeze
69
+ Trie.new(@significant_bits, @size + 1, entries, @children)
70
+ elsif entry[0].eql?(key)
71
+ if entry[1].equal?(value)
72
+ self
73
+ else
74
+ entries = @entries.dup
75
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
76
+ entries[index] = [key, value].freeze
77
+ Trie.new(@significant_bits, @size, entries, @children)
78
+ end
79
+ else
80
+ child = @children[index]
81
+ if child
82
+ new_child = child.put(key, value)
83
+ if new_child.equal?(child)
84
+ self
85
+ else
86
+ children = @children.dup
87
+ children[index] = new_child
88
+ new_self_size = @size + (new_child.size - child.size)
89
+ Trie.new(@significant_bits, new_self_size, @entries, children)
90
+ end
91
+ else
92
+ children = @children.dup
93
+ children[index] = Trie.new(@significant_bits + 5).put!(key, value)
94
+ Trie.new(@significant_bits, @size + 1, @entries, children)
95
+ end
96
+ end
97
+ end
98
+
99
+ # Put multiple elements into a Trie. This is more efficient than several
100
+ # calls to `#put`.
101
+ #
102
+ # @param key_value_pairs Enumerable of pairs (`[key, value]`)
103
+ # @return [Trie] A copy of `self` after associated the given keys and
104
+ # values (or `self` if no modifications where needed).
105
+ def bulk_put(key_value_pairs)
106
+ new_entries = nil
107
+ new_children = nil
108
+ new_size = @size
109
+
110
+ key_value_pairs.each do |key, value|
111
+ index = index_for(key)
112
+ entry = (new_entries || @entries)[index]
113
+
114
+ if !entry
115
+ new_entries ||= @entries.dup
116
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
117
+ new_entries[index] = [key, value].freeze
118
+ new_size += 1
119
+ elsif entry[0].eql?(key)
120
+ if !entry[1].equal?(value)
121
+ new_entries ||= @entries.dup
122
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
123
+ new_entries[index] = [key, value].freeze
124
+ end
125
+ else
126
+ child = (new_children || @children)[index]
127
+ if child
128
+ new_child = child.put(key, value)
129
+ if !new_child.equal?(child)
130
+ new_children ||= @children.dup
131
+ new_children[index] = new_child
132
+ new_size += new_child.size - child.size
133
+ end
134
+ else
135
+ new_children ||= @children.dup
136
+ new_children[index] = Trie.new(@significant_bits + 5).put!(key, value)
137
+ new_size += 1
138
+ end
139
+ end
140
+ end
141
+
142
+ if new_entries || new_children
143
+ Trie.new(@significant_bits, new_size, new_entries || @entries, new_children || @children)
144
+ else
145
+ self
146
+ end
147
+ end
148
+
149
+ # Returns <tt>self</tt> after overwriting the element associated with the specified key.
150
+ def put!(key, value)
151
+ index = index_for(key)
152
+ entry = @entries[index]
153
+ if !entry
154
+ @size += 1
155
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
156
+ @entries[index] = [key, value].freeze
157
+ elsif entry[0].eql?(key)
158
+ key = key.dup.freeze if key.is_a?(String) && !key.frozen?
159
+ @entries[index] = [key, value].freeze
62
160
  else
63
- children = @children.dup
64
- child = children[index]
65
- child_size = child ? child.size : 0
66
- children[index] = if child
67
- child.put(key, value)
161
+ child = @children[index]
162
+ if child
163
+ old_child_size = child.size
164
+ @children[index] = child.put!(key, value)
165
+ @size += child.size - old_child_size
68
166
  else
69
- self.class.new(@significant_bits + 5).put!(key, value)
167
+ @children[index] = Trie.new(@significant_bits + 5).put!(key, value)
168
+ @size += 1
70
169
  end
71
- new_child_size = children[index].size
72
- new_self_size = @size + (new_child_size - child_size)
73
- self.class.new(@significant_bits, new_self_size, @entries, children)
74
170
  end
171
+ self
75
172
  end
76
173
 
77
174
  # Retrieves the entry corresponding to the given key. If not found, returns <tt>nil</tt>.
78
175
  def get(key)
79
176
  index = index_for(key)
80
177
  entry = @entries[index]
81
- if entry && entry.key.eql?(key)
178
+ if entry && entry[0].eql?(key)
82
179
  entry
83
180
  else
84
181
  child = @children[index]
85
- if child
86
- child.get(key)
87
- end
182
+ child.get(key) if child
88
183
  end
89
184
  end
90
185
 
91
186
  # Returns a copy of <tt>self</tt> with the given key (and associated value) deleted. If not found, returns <tt>self</tt>.
92
187
  def delete(key)
93
- find_and_delete(key) || self.class.new(@significant_bits)
188
+ find_and_delete(key) || Trie.new(@significant_bits)
189
+ end
190
+
191
+ # Delete multiple elements from a Trie. This is more efficient than
192
+ # several calls to `#delete`.
193
+ #
194
+ # @param keys [Enumerable] The keys to delete
195
+ # @return [Trie]
196
+ def bulk_delete(keys)
197
+ new_entries = nil
198
+ new_children = nil
199
+ new_size = @size
200
+
201
+ keys.each do |key|
202
+ index = index_for(key)
203
+ entry = (new_entries || @entries)[index]
204
+ if !entry
205
+ next
206
+ elsif entry[0].eql?(key)
207
+ new_entries ||= @entries.dup
208
+ child = (new_children || @children)[index]
209
+ if child
210
+ # Bring up the first entry from the child into entries
211
+ new_children ||= @children.dup
212
+ new_children[index] = child.delete_at do |entry|
213
+ new_entries[index] = entry
214
+ end
215
+ else
216
+ new_entries[index] = nil
217
+ end
218
+ new_size -= 1
219
+ else
220
+ child = (new_children || @children)[index]
221
+ if child
222
+ copy = child.find_and_delete(key)
223
+ unless copy.equal?(child)
224
+ new_children ||= @children.dup
225
+ new_children[index] = copy
226
+ new_size -= (child.size - copy_size(copy))
227
+ end
228
+ end
229
+ end
230
+ end
231
+
232
+ if new_entries || new_children
233
+ Trie.new(@significant_bits, new_size, new_entries || @entries, new_children || @children)
234
+ else
235
+ self
236
+ end
94
237
  end
95
238
 
96
239
  def include?(key, value)
97
240
  entry = get(key)
98
- entry && value.eql?(entry.value)
241
+ entry && value.eql?(entry[1])
242
+ end
243
+
244
+ def at(index)
245
+ @entries.each do |entry|
246
+ if entry
247
+ return entry if index == 0
248
+ index -= 1
249
+ end
250
+ end
251
+ @children.each do |child|
252
+ if child
253
+ if child.size >= index+1
254
+ return child.at(index)
255
+ else
256
+ index -= child.size
257
+ end
258
+ end
259
+ end
260
+ nil
99
261
  end
100
262
 
101
263
  # Returns <tt>true</tt> if . <tt>eql?</tt> is synonymous with <tt>==</tt>
@@ -103,40 +265,31 @@ module Hamster
103
265
  return true if equal?(other)
104
266
  return false unless instance_of?(other.class) && size == other.size
105
267
  each do |entry|
106
- return false unless other.include?(entry.key, entry.value)
268
+ return false unless other.include?(entry[0], entry[1])
107
269
  end
108
270
  true
109
271
  end
110
- def_delegator :self, :eql?, :==
272
+ alias :== :eql?
111
273
 
112
274
  protected
113
275
 
114
- # Returns <tt>self</tt> after overwriting the element associated with the specified key.
115
- def put!(key, value)
116
- index = index_for(key)
117
- @size += 1 unless @entries[index]
118
- @entries[index] = Entry.new(key, value)
119
- self
120
- end
121
-
122
276
  # Returns a replacement instance after removing the specified key.
123
277
  # If not found, returns <tt>self</tt>.
124
278
  # If empty, returns <tt>nil</tt>.
125
279
  def find_and_delete(key)
126
280
  index = index_for(key)
127
281
  entry = @entries[index]
128
- if entry && entry.key.eql?(key)
282
+ if entry && entry[0].eql?(key)
129
283
  return delete_at(index)
130
284
  else
131
285
  child = @children[index]
132
286
  if child
133
287
  copy = child.find_and_delete(key)
134
- if !copy.equal?(child)
288
+ unless copy.equal?(child)
135
289
  children = @children.dup
136
290
  children[index] = copy
137
- copy_size = copy ? copy.size : 0
138
- new_size = @size - (child.size - copy_size)
139
- return self.class.new(@significant_bits, new_size, @entries, children)
291
+ new_size = @size - (child.size - copy_size(copy))
292
+ return Trie.new(@significant_bits, new_size, @entries, children)
140
293
  end
141
294
  end
142
295
  end
@@ -157,7 +310,7 @@ module Hamster
157
310
  else
158
311
  entries[index] = nil
159
312
  end
160
- self.class.new(@significant_bits, @size - 1, entries, children || @children)
313
+ Trie.new(@significant_bits, @size - 1, entries, children || @children)
161
314
  end
162
315
  end
163
316
 
@@ -167,19 +320,11 @@ module Hamster
167
320
  (key.hash.abs >> @significant_bits) & 31
168
321
  end
169
322
 
170
- class Entry
171
-
172
- attr_reader :key, :value
173
-
174
- def initialize(key, value)
175
- @key = key
176
- @value = value
177
- end
178
-
323
+ def copy_size(copy)
324
+ copy ? copy.size : 0
179
325
  end
180
-
181
326
  end
182
327
 
183
- EmptyTrie = Trie.new(0)
184
-
328
+ # @private
329
+ EmptyTrie = Hamster::Trie.new(0)
185
330
  end
@@ -1,11 +1,5 @@
1
1
  module Hamster
2
-
2
+ # @private
3
3
  module Undefined
4
-
5
- def self.erase(value)
6
- value unless value.equal?(self)
7
- end
8
-
9
4
  end
10
-
11
5
  end
@@ -1,163 +1,1409 @@
1
- require 'forwardable'
2
-
3
- require 'hamster/undefined'
4
- require 'hamster/immutable'
5
- require 'hamster/enumerable'
1
+ require "hamster/immutable"
2
+ require "hamster/enumerable"
3
+ require "hamster/hash"
6
4
 
7
5
  module Hamster
8
-
6
+ # Create a new `Vector` populated with the given items.
7
+ # [Vector]
9
8
  def self.vector(*items)
10
- items.reduce(EmptyVector) { |vector, item| vector.add(item) }
9
+ items.empty? ? EmptyVector : Vector.new(items.freeze)
11
10
  end
12
11
 
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
+ #
13
49
  class Vector
14
-
15
- extend Forwardable
16
-
17
50
  include Immutable
18
-
19
51
  include Enumerable
20
52
 
53
+ # @private
21
54
  BLOCK_SIZE = 32
55
+ # @private
22
56
  INDEX_MASK = BLOCK_SIZE - 1
57
+ # @private
23
58
  BITS_PER_LEVEL = 5
24
59
 
25
- def initialize
26
- @levels = 0
27
- @root = []
28
- @size = 0
60
+ # Return the number of items in this `Vector`
61
+ # @return [Integer]
62
+ attr_reader :size
63
+ alias :length :size
64
+
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
29
92
  end
30
93
 
31
- def empty?
32
- @size == 0
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
33
107
  end
34
- def_delegator :self, :empty?, :null?
35
108
 
36
- def size
37
- @size
109
+ # Return `true` if this `Vector` contains no items.
110
+ #
111
+ # @return [Boolean]
112
+ def empty?
113
+ @size == 0
38
114
  end
39
- def_delegator :self, :size, :length
40
115
 
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]
41
122
  def first
42
123
  get(0)
43
124
  end
44
- def_delegator :self, :first, :head
45
125
 
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]
46
132
  def last
47
133
  get(-1)
48
134
  end
49
135
 
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]
50
143
  def add(item)
51
- transform do
52
- update_leaf_node(@size, item)
53
- @size += 1
54
- end
144
+ update_root(@size, item)
55
145
  end
56
- def_delegator :self, :add, :<<
57
- def_delegator :self, :add, :cons
146
+ alias :<< :add
147
+ alias :push :add
58
148
 
59
- # def delete(index)
60
- # end
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
61
173
 
62
- def set(index, item = Undefined)
63
- return set(index, yield(get(index))) if item.equal?(Undefined)
64
- raise IndexError if empty? or index == @size
65
- raise IndexError if index.abs > @size
66
- return set(@size + index, item) if index < 0
67
- transform do
68
- update_leaf_node(index, item)
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)
69
205
  end
206
+ set(key, new_value)
70
207
  end
71
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]
72
220
  def get(index)
73
- return nil if empty? or index == @size
74
- return nil if index.abs > @size
75
- return get(@size + index) if index < 0
76
- leaf_node_for(@root, root_index_bits, index)[index & INDEX_MASK]
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)
311
+ end
312
+ end
313
+ alias :slice :[]
314
+
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
327
+
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
336
+ 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
+ end
357
+
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)
77
389
  end
78
- def_delegator :self, :get, :[]
79
- def_delegator :self, :get, :at
80
390
 
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]
81
403
  def each(&block)
82
- return self unless block_given?
83
- traverse_depth_first(&block)
84
- nil
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)
85
465
  end
466
+ alias :collect :map
86
467
 
87
- def map(&block)
88
- return self unless block_given?
89
- reduce(EmptyVector) { |vector, item| vector.add(yield(item)) }
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)
90
480
  end
91
- def_delegator :self, :map, :collect
92
481
 
93
- def filter
94
- return self unless block_given?
95
- reduce(EmptyVector) { |vector, item| yield(item) ? vector.add(item) : vector }
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
96
589
  end
97
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
995
+ end
996
+
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)
1029
+ end
1030
+
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
1067
+ end
1068
+
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]
98
1073
  def clear
99
- EmptyVector
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
100
1160
  end
101
1161
 
102
- def inspect
103
- to_a.inspect
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
104
1172
  end
1173
+ alias :to_ary :to_a
105
1174
 
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]
106
1179
  def eql?(other)
107
1180
  return true if other.equal?(self)
108
1181
  return false unless instance_of?(other.class) && @size == other.size
109
1182
  @root.eql?(other.instance_variable_get(:@root))
110
1183
  end
111
- def_delegator :self, :eql?, :==
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
112
1201
 
113
1202
  private
114
1203
 
115
- def traverse_depth_first(node = @root, level = @levels, &block)
1204
+ def traverse_depth_first(node, level, &block)
116
1205
  return node.each(&block) if level == 0
117
1206
  node.each { |child| traverse_depth_first(child, level - 1, &block) }
118
1207
  end
119
1208
 
120
- def leaf_node_for(node, child_index_bits, index)
121
- return node if child_index_bits == 0
122
- child_index = (index >> child_index_bits) & INDEX_MASK
123
- leaf_node_for(node[child_index], child_index_bits - BITS_PER_LEVEL, index)
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) }
124
1212
  end
125
1213
 
126
- def update_leaf_node(index, item)
127
- copy_leaf_node_for(new_root, root_index_bits, index)[index & INDEX_MASK] = item
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
128
1220
  end
129
1221
 
130
- def copy_leaf_node_for(node, child_index_bits, index)
131
- return node if child_index_bits == 0
132
- child_index = (index >> child_index_bits) & INDEX_MASK
133
- if child_node = node[child_index]
134
- child_node = child_node.dup
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
135
1231
  else
136
- child_node = []
1232
+ self.class.alloc(new_root, @size > index ? @size : index + 1, levels)
137
1233
  end
138
- node[child_index] = child_node
139
- copy_leaf_node_for(child_node, child_index_bits - BITS_PER_LEVEL, index)
140
1234
  end
141
1235
 
142
- def new_root
143
- if full?
144
- @levels += 1
145
- @root = [@root]
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
146
1245
  else
147
- @root = @root.dup
1246
+ node.dup.tap { |n| n[slot_index] = item }.freeze
148
1247
  end
149
1248
  end
150
1249
 
151
- def full?
152
- (@size >> root_index_bits) > 0
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
153
1282
  end
154
1283
 
155
- def root_index_bits
156
- @levels * BITS_PER_LEVEL
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
157
1294
  end
158
1295
 
159
- end
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
160
1339
 
161
- EmptyVector = Vector.new
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
1401
+ end
1402
+ end
162
1403
 
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
163
1409
  end