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