hamster 0.4.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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