
=encoding utf8

=head1 NAME

Sidef::Types::Array::Array

=head1 DESCRIPTION

This class implements ...

=head1 SYNOPSIS

var obj = Array(...)


=head1 INHERITS

Inherits methods from:

       * Sidef::Object::Object

=head1 METHODS

=head2 &

    a & b

Returns the intersection of two arrays.

    <a a a b c> & <a x y a c>    #=> ["a", "a", "c"]

Aliases: I<and>

=cut

=head2 *

    a * n

Repeats the content of array C<a> n times, returning a new array.

    <a b> * 2   #=> ["a", "b", "a", "b"]

Aliases: I<mul>

=cut

=head2 **

    a ** n

Matrix exponentiation, excpecting array C<a> to be a 2D array.

    var A = [[1, 2, 0],
             [0, 3, 1],
             [1, 0, 0]]

    say A**5     #=> [[37, 274, 84], [42, 311, 95], [11, 84, 26]]

Aliases: I<mpow>, I<matrix_pow>

=cut

=head2 +

    a + b

Array concatenation, returning a new array.

    <a b> + <c d>    #=> ["a", "b", "c", "d"]

Aliases: I<add>, I<concat>

=cut

=head2 -

    a - b

Array difference: removes any element from array C<a> that exists inside array C<b>, returning a new array.

    <a a a b c> - <a x y a c>       #=> ["a", "b"]

Aliases: I<sub>, I<diff>

=cut

=head2 ...

    a...

Converts array C<a> into a list.

    var (a,b,c) = <1 2 3>...

Aliases: I<to_list>

=cut

=head2 /

    a / n

Divides the array C<a> into C<n> segments.

If the division is not exact, the remaining incomplete segment is added to the end of the returned array.

    <a b c d>   / 2     #=> [["a", "b"], ["c", "d"]]
    <a b c d e> / 2     #=> [["a", "b"], ["c", "d"], ["e"]]

Aliases: I<÷>, I<div>

=cut

=head2 <

    a < b

Less-than array comparison, done term-by-term, returning C<true> or C<false>.

Aliases: I<lt>

=cut

=head2 <=>

    a <=> b

Array comparison, done term-by-term, returning:

     1 when a > b
     0 when a == b
    -1 when a < b

Aliases: I<cmp>

=cut

=head2 ==

    a == b

Returns true if C<a> and C<b> are equal to each other.

Aliases: I<eq>

=cut

=head2 >

    a > b

Greater-than array comparison, done term-by-term, returning C<true> or C<false>.

Aliases: I<gt>

=cut

=head2 ^

    a ^ b

Returns the set difference of two arrays.

    <a a a b c> ^ <a x y a c>   #=> ["a", "b", "x", "y"]

Aliases: I<xor>

=cut

=head2 |

    a | b

Returns the union of two arrays.

    <a a a b c> | <a x y a c>   #=> ["a", "a", "a", "b", "c", "x", "y"]

Aliases: I<or>

=cut

=head2 |>>

    a |>> b

Returns the

Aliases: I<pipeline_map_op>

=cut

=head2 |X>

    a |X> (block1, block2, ...)

Pipeline cross-product operator, mapping each element to each given block.

   say ([1,2,3] |X> ({ .cube }, { _+42 }))     #=> [1, 43, 8, 44, 27, 45]

Aliases: I<pipeline_cross_op>

=cut

=head2 |Z>

    self.|Z>(*callbacks)

Returns the

Aliases: I<pipeline_zip_op>

=cut

=head2 «

    a « b

Returns the

Aliases: I<E<lt>E<lt>>, I<push>, I<append>

=cut

=head2 »

    a » b

Returns the

Aliases: I<E<gt>E<gt>>, I<pop>, I<drop_last>, I<drop_right>

=cut

=head2 ∋

    a ∋ b

Returns the

Aliases: I<has>, I<contain>, I<include>, I<contains>, I<includes>

=cut

=head2 ∌

    a ∌ b

Returns the

=cut

=head2 ≠

    a ≠ b

Returns the

Aliases: I<!=>, I<ne>

=cut

=head2 ≤

    a ≤ b

Returns the

Aliases: I<E<lt>=>, I<le>

=cut

=head2 ≥

    a ≥ b

Returns the

Aliases: I<E<gt>=>, I<ge>

=cut

=head2 abbrev

    arr.abbrev
    arr.abbrev(/pattern/)

Returns an Hash with the unambiguous abbreviations for the given array of strings.

    say ['loved', 'loving', 'lover', 'lost'].abbrev

Output:

    Hash(
        "los"    => "lost",
        "lost"   => "lost",
        "loved"  => "loved",
        "lover"  => "lover",
        "lovi"   => "loving",
        "lovin"  => "loving",
        "loving" => "loving"
    )

When an additionaly regular expression is given, it collects only the abbreviations that will match the regex.

Aliases: I<abbreviations>

=cut

=head2 acc

    self.acc(block)

Returns the

Aliases: I<accumulate>

=cut

=head2 acc_by

    self.acc_by(block)

Returns the

Aliases: I<accumulate_by>

=cut

=head2 all

    self.all(block)

Returns the

=cut

=head2 all_composite

    self.all_composite

Returns the

=cut

=head2 all_prime

    self.all_prime

Returns the

=cut

=head2 any

    self.any(block)

Returns the

=cut

=head2 avg

    arr.avg

Returns the average of a list of numbers.

    say [1,2,3,4].avg   #=> 2.5

=cut

=head2 avg_by

    arr.avg_by { ... }

Returns the average of a list of numbers, by mapping each value to a given block of code.

    say [1,2,3,4].avg_by { _**2 }   #=> 7.5

=cut

=head2 bindex

    arr.bindex(obj)

Returns the index of a given element inside a sorted array, using the I<Binary Search> algorithm.

    var a = ["Alice", "Jane", "Joe", "John", "Kate", "Zerg"]

    say a.bindex('Alice')   #=> 0 (first index)
    say a.bindex('Jane')    #=> 1 (second index)

Aliases: I<bsearch_index>

=cut

=head2 bindex_by

    arr.bindex_by { ... }

Returns the index of any element inside a sorted array, based on a given comparison block, using the I<Binary Search> algorithm.

    var a = ["Alice", "Jane", "Joe", "John", "Kate", "Zerg"]

    say a.bindex { _ <=> 'Joe' }     #=> 2 (third index)
    say a.bindex { _ <=> 'John' }    #=> 3 (fourth index)

Aliases: I<bsearch_index_by>

=cut

=head2 bindex_ge

    self.bindex_ge(obj)

Returns the

=cut

=head2 bindex_ge_by

    self.bindex_ge_by(obj)

Returns the

=cut

=head2 bindex_le

    self.bindex_le(obj)

Returns the

=cut

=head2 bindex_le_by

    self.bindex_le_by(obj)

Returns the

=cut

=head2 bindex_max

    self.bindex_max(obj)

Returns the

=cut

=head2 bindex_max_by

    self.bindex_max_by(block)

Returns the

=cut

=head2 bindex_min

    self.bindex_min(obj)

Returns the

=cut

=head2 bindex_min_by

    self.bindex_min_by(block)

Returns the

=cut

=head2 binsert

    arr.binsert(obj)

Inserts an element into a sorted array, such that the array will still be sorted.

    var a = ['a', 'b', 'd']
    a.binsert('c')                  # inserts 'c' before 'd'
    say a                           # prints: ['a', 'b', 'c', 'd']

Modifies the array in-place.

=cut

=head2 binsplit

    arr.binsplit {|a,b| ... }

Applies the binary splitting algorithm to the self-array, returning the result computed using the given block of code.

    say [1,2,3,4,5].binsplit {|a,b| a*b }   #=> 120

=cut

=head2 bsearch

    self.bsearch(obj)

Returns the

Aliases: I<bsearch_by>

=cut

=head2 bsearch_ge

    self.bsearch_ge(obj)

Returns the

Aliases: I<bsearch_ge_by>

=cut

=head2 bsearch_le

    self.bsearch_le(obj)

Returns the

Aliases: I<bsearch_le_by>

=cut

=head2 bsearch_max

    self.bsearch_max(obj)

Returns the

=cut

=head2 bsearch_min

    self.bsearch_min(obj)

Returns the

=cut

=head2 bshuffle

    arr.bshuffle

Shuffles an array in such a way that no element will be on the same position as in the original array (if possible).

Aliases: I<best_shuffle>

=cut

=head2 cartesian

    arr.cartesian
    arr.cartesian {|*c| ... }

Returns the Cartesian product of a 2D array.

    say [[1,2],[3,4]].cartesian    #=> [[1,3], [1,4], [2,3], [2,4]]

When a block is given, it gets called which each combination:

    [[1,2],[3,4],[5,6]].cartesian {|*c| say c }

Output:

    [1, 3, 5]
    [1, 3, 6]
    [1, 4, 5]
    [1, 4, 6]
    [2, 3, 5]
    [2, 3, 6]
    [2, 4, 5]
    [2, 4, 6]

=cut

=head2 cfrac2num

    arr.cfrac2num

Converts a given continued fraction expansion to a number.

    var c = Num.pi.cfrac(10)    # [3, 7, 15, 1, 292, 1, 1, 1, 2, 1]
    say c.cfrac2num.as_frac     #=> 4272943/1360120

=cut

=head2 change_to

    self.change_to(arg)

Returns the

=cut

=head2 chrs

    self.chrs(encoding)

Returns the

Aliases: I<decode>, I<join_bytes>

=cut

=head2 circular_permutations

    self.circular_permutations

Returns the

=cut

=head2 clear

    self.clear

Returns the

=cut

=head2 collapse

    self.collapse(initial)

Returns the

=cut

=head2 combinations

    self.combinations

Returns the

=cut

=head2 combinations_with_repetition

    self.combinations_with_repetition

Returns the

=cut

=head2 combine

    self.combine(block)

Returns the

=cut

=head2 compact

    self.compact

Returns the

=cut

=head2 cons

    arr.cons(n)

Returns a new array of arrays with n-consecutive elements from the self-array.

    say [1,2,3,4].cons(2)      #=> [[1, 2], [2, 3], [3, 4]]

Aliases: I<map_cons>

=cut

=head2 contains_all

    self.contains_all(array)

Returns the

=cut

=head2 contains_any

    self.contains_any(array)

Returns the

=cut

=head2 contains_type

    self.contains_type(obj)

Returns the

=cut

=head2 count

    self.count(obj)

Returns the

=cut

=head2 count_by

    self.count_by(block)

Returns the

=cut

=head2 cross_op

    self.cross_op(operator, arg)

Returns the

Aliases: I<cross_operator>

=cut

=head2 defined

    self.defined(index)

Returns the

=cut

=head2 delete

    self.delete(obj)

Returns the

Aliases: I<remove>

=cut

=head2 delete_by

    self.delete_by(block)

Returns the

Aliases: I<delete_if>, I<remove_by>, I<remove_if>

=cut

=head2 delete_first

    self.delete_first(obj)

Returns the

Aliases: I<remove_first>

=cut

=head2 delete_first_by

    self.delete_first_by(block)

Returns the

Aliases: I<delete_first_if>, I<remove_first_by>, I<remove_first_if>

=cut

=head2 delete_last

    arr.delete_last(obj)

Removes the last C<obj> element from the array, modifying the array in-place.

    var arr = %w[a b c a]
    arr.delete_last('a')
    say arr                 #=> ["a", "b", "c"]

Returns true if such an element was removed.

Aliases: I<remove_last>

=cut

=head2 delete_last_by

    self.delete_last_by(block)

Returns the

Aliases: I<delete_last_if>, I<remove_last_by>, I<remove_last_if>

=cut

=head2 derangements

    self.derangements

Returns the

Aliases: I<complete_permutations>

=cut

=head2 det

    self.det

Returns the

Aliases: I<determinant>

=cut

=head2 det_bareiss

    self.det_bareiss

Returns the

=cut

=head2 diffs

    arr.diffs(n=1)

Returns the n-th differences of the array (calling C<sub>).

    var a = [43, 97, 128, 999]

    say a.diffs                     #=> [54, 31, 871]
    say a.diffs(2)                  #=> [-23, 840]
    say a.diffs(3)                  #=> [863]

Aliases: I<differences>, I<nth_differences>

=cut

=head2 dig

    self.dig(key, *keys)

Returns the

=cut

=head2 digits2num

    arr.digits2num(base=10)

Converts the list of values returned by Number C<digits(n, base)> back to C<n>.

    say 1234.digits.digits2num              #=> 1234
    say [73, 56, 0, 76, 22].digits2num(100) #=> 2276005673

Aliases: I<from_digits>

=cut

=head2 each_2d

    arr.each_2d {|a,b,c,...| ... }

Iterate over a 2D array.

    [[1,2],[3,4]].each_2d {|a,b|
        say (a**2 + b**2)
    }

=cut

=head2 each_cons

    arr.each_cons(n, { ... })

Iterate over C<n> consecutive values at a time.

    [1,2,3,4,5,6,7].each_cons(3, {|*c| say c })

Outputs:

    [1, 2, 3]
    [2, 3, 4]
    [3, 4, 5]
    [4, 5, 6]
    [5, 6, 7]

=cut

=head2 each_k

    self.each_k(block)

Returns the

Aliases: I<each_key>, I<each_index>

=cut

=head2 each_kv

    self.each_kv(block)

Returns the

=cut

=head2 each_slice

    self.each_slice(n, block)

Returns the

=cut

=head2 end

    self.end

Returns the

Aliases: I<offset>

=cut

=head2 exists

    self.exists(index)

Returns the

Aliases: I<has_index>

=cut

=head2 expand

    arr.expand { ... }

Recursively expand an array, given a block of code.

    say [1,[2,[3,4]],5].expand { _ }    #=> [1, 5, 2, 3, 4]

Aliases: I<expand_by>

=cut

=head2 extract_by

    self.extract_by(block)

Returns the

=cut

=head2 extract_first_by

    self.extract_first_by(block)

Returns the

=cut

=head2 extract_last_by

    self.extract_last_by(block)

Returns the

=cut

=head2 fetch

    arr.fetch(index, default)

Fetches a value at the given index. When the index does not exist, it returns the default value.

    var a = [3,9,27]
    say a.fetch(2, 42)     # fetches index 2 and prints: 27
    say a.fetch(3, 42)     # fails to fetch index 3, therefore prints: 42

=cut

=head2 find

    self.find(block)

Returns the

Aliases: I<first_by>

=cut

=head2 flat

    self.flat

Returns the

Aliases: I<flatten>

=cut

=head2 flat_map

    arr.flat_map { ... }

Similar to C<.map{}>, but it expects the returned block-value to be an array, which will be collected as a list.

    say [1,2,3,4,5].flat_map { .factor }      #=> [2, 3, 2, 2, 5]

=cut

=head2 flip

    self.flip

Returns the

Aliases: I<reverse>

=cut

=head2 for

    self.for(block)

Returns the

Aliases: I<each>, I<foreach>

=cut

=head2 freq

    arr.freq

Returns a frequency Hash for the elements inside the array.

    say ["a","b","a"].freq      #=> Hash(a => 2, b => 1)

=cut

=head2 freq_by

    self.freq_by(block)

Returns the

=cut

=head2 ft

    self.ft

Returns the

=cut

=head2 gauss_jordan_invert

    self.gauss_jordan_invert

Returns the

=cut

=head2 gauss_jordan_solve

    self.gauss_jordan_solve(vector)

Returns the

=cut

=head2 gcd

    self.gcd(block)

Returns the

=cut

=head2 gcd_by

    self.gcd_by(block)

Returns the

=cut

=head2 gcud

    self.gcud(block)

Returns the

=cut

=head2 gcud_by

    self.gcud_by(block)

Returns the

=cut

=head2 getopt

    arr.getopt(...)

Parse an array containing (long) command-line arguments, automatically converting the argument-values based on the types of the default values.

    var file = File('file.dat')
    var length = 42
    var verbose = false

    var args = ['--file', 'foo.txt', '--length', '1234', '--verbose']

    args.getopt(
        'length=i' => \length,
        'file=s'   => \file,
        'verbose!' => \verbose,
    )

    say file.dump           #=> File("foo.txt")
    say length              #=> 1234
    say verbose             #=> true

=cut

=head2 grep

    self.grep(block)

Returns the

Aliases: I<select>

=cut

=head2 grep_2d

    arr.grep_2d {|a,b,c,...| ... }

Filtering of a 2D array, given a block of code.

    say [[1,2],[3,4]].grep_2d {|a,b| a+b == 7 }    #=> [[3,4]]

=cut

=head2 grep_kv

    self.grep_kv(block)

Returns the

Aliases: I<select_kv>

=cut

=head2 group

    self.group(block)

Returns the

Aliases: I<group_by>

=cut

=head2 head

    self.head(arg)

Returns the

Aliases: I<first>

=cut

=head2 imax

    self.imax

Returns the

=cut

=head2 imin

    self.imin

Returns the

=cut

=head2 iminmax

    self.iminmax

Returns the

=cut

=head2 index

    arr.index(obj)
    arr.index { ... }

Returns the first index of a given item inside the array.

    say %w(a b c).index("a")   #=> 0
    say %w(a b c).index("c")   #=> 2

When a block is given, it returns the first index of the element for which the block returns a true value:

    say %w(A B C).index { .lc == 'b' }   #=> 1

Aliases: I<index_by>, I<first_index>, I<first_index_by>

=cut

=head2 inject

    arr.inject {|a,b| ... }
    arr.inject({|a,b| ... }, obj)

Reduce a given array to a single element, given a block of code that is called with a pair C<a,b>, where C<a> is the previous result returned by the block and C<b> is the current element of the array.

The initial value of C<a> is the first element of the array.

    say [1,2,3,4].reduce {|a,b| a + b }        #=> 10

When an additional argument is given, it will be used as the initial value for C<a>:

    say [1,2,3,4].reduce({|a,b| a + b }, 5)    #=> 15

Aliases: I<reduce>

=cut

=head2 insert

    self.insert(i, *objects)

Returns the

=cut

=head2 inv

    self.inv

Returns the

Aliases: I<invert>, I<inverse>

=cut

=head2 is_empty

    self.is_empty

Returns the

=cut

=head2 isort

    self.isort

Returns the

=cut

=head2 isort_by

    self.isort_by(block)

Returns the

=cut

=head2 item

    self.item(index)

Returns the

=cut

=head2 items

    self.items(*indices)

Returns the

=cut

=head2 iter

    self.iter

Returns the

=cut

=head2 iuniq

    self.iuniq

Returns the

=cut

=head2 jaro

    jaro(arr1, arr2, winkler=false)

Calculates the Jaro similarity between two arrays. Jaro distance is a measure of similarity between two sequences of symbols, based on the number of matching symbols and transpositions.

    say jaro("accommodate".chars, "accomodate".chars)         #=> 0.96969696969697

When the third argument is true, it returns the Jaro-Winkler similarity score.

    say jaro("accommodate".chars, "accomodate".chars, true)   #=> 0.981818181818182

=cut

=head2 join

    self.join(delim, block)

Returns the

=cut

=head2 join_insert

    arr.join_insert(obj)

Inserts the given object between every element of the array. Returns a new array.

    say [1,2,3,4].join_insert(0)    #=> [1, 0, 2, 0, 3, 0, 4]

=cut

=head2 keys

    arr.keys

Returns an array with the indices of the self-array.

    say ["x","y","z"].keys   #=> [0, 1, 2]

Aliases: I<indices>

=cut

=head2 keys_by

    arr.keys_by { ... }

Returns an array with the indices for which the given block returns a true value.

    say [41, 42, 43].indices_by { .is_prime }     #=> [0, 2]

Aliases: I<indices_by>

=cut

=head2 keys_of

    arr.keys_of(obj)

Returns an array with the indices of C<obj> inside the self-array.

     say [1,2,3,1,4,1].indices_of(1)         #=> [0, 3, 5]

Aliases: I<indices_of>

=cut

=head2 kv

    self.kv

Returns the

Aliases: I<pairs>, I<zip_indices>

=cut

=head2 last

    self.last(arg)

Returns the

Aliases: I<tail>

=cut

=head2 last_by

    self.last_by(block)

Returns the

=cut

=head2 last_uniq

    self.last_uniq

Returns the

Aliases: I<last_unique>

=cut

=head2 last_uniq_by

    self.last_uniq_by(block)

Returns the

Aliases: I<last_unique_by>

=cut

=head2 lcm

    self.lcm(block)

Returns the

=cut

=head2 lcm_by

    self.lcm_by(block)

Returns the

=cut

=head2 len

    self.len

Returns the

Aliases: I<size>, I<length>

=cut

=head2 lev

    self.lev(arg)

Returns the

Aliases: I<leven>, I<levenshtein>

=cut

=head2 madd

    m1.madd(m2)

Returns the

Aliases: I<matrix_add>

=cut

=head2 make

    self.make(size, obj)

Returns the

=cut

=head2 make_by

    self.make_by(size, block)

Returns the

=cut

=head2 map

    self.map(block)

Returns the

Aliases: I<collect>

=cut

=head2 map_2d

    arr.map_2d {|a,b,c,...| ... }

Mapping of a 2D array, given a block of code.

    say [[1,2],[3,4]].map_2d {|a,b| [a**2, b**2] }   #=> [[1, 4], [9, 16]]

=cut

=head2 map_kv

    self.map_kv(block)

Returns the

Aliases: I<collect_kv>

=cut

=head2 map_op

    self.map_op(operator, *args)

Returns the

Aliases: I<map_operator>

=cut

=head2 map_reduce

    arr.map_reduce {|a,b| ... }

Behaves almost like the C<reduce> method, except that all the intermediary terms are returned as an array.

    say [1,2,3,4,5].map_reduce {|a,b| a+b }         #=> [1, 3, 6, 10, 15]
    say [1,2,3,4,5].map_reduce {|a,b| a*b }         #=> [1, 2, 6, 24, 120]

Aliases: I<reduce_map>

=cut

=head2 match

    arr.match(/regex/)

Recursively match an array against a regular expression.

    say ['a', ['foo'], 'b'].match(/^foo/)

=cut

=head2 max

    self.max

Returns the

=cut

=head2 max_by

    self.max_by

Returns the

=cut

=head2 mdiv

    m1.mdiv(m2)

Returns the

Aliases: I<matrix_div>

=cut

=head2 min

    self.min

Returns the

=cut

=head2 min_by

    self.min_by

Returns the

=cut

=head2 minmax

    self.minmax

Returns the

=cut

=head2 mmul

    a `mmul` b

Multiply two 2D-matrices, returing a Matrix object.

Example:

    say ([[1, 2],
          [3, 4]] `mmul` [[-3, -8, 3],
                          [-2,  1, 4]])

Output:

    Matrix(
        [-7, -6, 11],
        [-17, -20, 25]
    )

Aliases: I<matrix_mul>

=cut

=head2 msolve

    self.msolve(vector)

Returns the

Aliases: I<matrix_solve>

=cut

=head2 msub

    m1.msub(m2)

Returns the

Aliases: I<matrix_sub>

=cut

=head2 new

    self.new

Returns the

Aliases: I<call>

=cut

=head2 next_permutation

    arr.next_permutation

It modifies the self array in place to contain the next unique permutation and returns true if there are more permutations available, or false if the current permutation is the last one.

Example:

    var arr = [1,1,2]
    do { say arr } while arr.next_permutation

Output:

    [1, 1, 2]
    [1, 2, 1]
    [2, 1, 1]

=cut

=head2 none

    arr.none { ... }

Returns true if none of the elements satisfy the condition given in the block of code.

    say [2, 4, 6].none { .is_odd }  #=> true

=cut

=head2 nth_perm

    arr.nth_perm(n)

Efficiently returns the n-th permuation of the self array.

    say nth_perm([0,1,2,3,4,5,6,7,8,9], 10**6)

Aliases: I<nth_permutation>

=cut

=head2 ordered_partitions

    arr.ordered_partitions
    arr.ordered_partitions(k)
    arr.ordered_partitions{|*a| ... }
    arr.ordered_partitions(k, {|*a| ... })

Iterates over the ordered partitions C<P> of C<arr>, such that C<P.flat == arr>.

        [1,2,3,4,5].ordered_partitions(2, {|*a| say a })

Outputs:

        [[1], [2, 3, 4, 5]]
        [[1, 2], [3, 4, 5]]
        [[1, 2, 3], [4, 5]]
        [[1, 2, 3, 4], [5]]

When no block is given, it returns an array containing the ordered partitions (there are C<binomial(n-1, k-1)> ordered partitions, where C<n> is the size of the array):

        say [1,2,3,4].ordered_partitions(2)

Outputs:

        [[[1], [2, 3, 4]], [[1, 2], [3, 4]], [[1, 2, 3], [4]]]

Additionally, when the value for C<k> is ommited, it generates all the ordered partitions (there are C<2^(n-1)> ordered partitions, where C<n> is the size of the array):

        [1,2,3,4].ordered_partitions{|*a| say a }

Outputs:

        [[1], [2], [3], [4]]
        [[1, 2], [3], [4]]
        [[1], [2, 3], [4]]
        [[1, 2, 3], [4]]
        [[1], [2], [3, 4]]
        [[1, 2], [3, 4]]
        [[1], [2, 3, 4]]
        [[1, 2, 3, 4]]

Up to the ordering, the method is equivalent with (but more efficient):

        arr.partitions(k).grep { .flat == arr }

=cut

=head2 pack

    self.pack(format)

Returns the

=cut

=head2 pair_map

    self.pair_map(block)

Returns the

Aliases: I<pairmap>

=cut

=head2 pam_op

    arr.pam_op(operator, obj)

Reversed-mapping of the array, given an operator.

    say [1,2,3].pam_operator('/', 10)   # [10/1, 10/2, 10/3]

This method is used internally by the C<«OP«> hyper-operator:

    say ([1,2,3] «/« 10)

Aliases: I<pam_operator>

=cut

=head2 part

    arr.part(n)

Partition the array into two parts, given an index:

    [1,2,3,4,5].part(3)     # returns: ([1, 2, 3], [4, 5])
    [1,2,3,4,5].part(2)     # returns: ([1, 2], [3, 4, 5])

Negative indices are supported as well:

    [1,2,3,4,5].part(-1)    # returns: ([1, 2, 3, 4], [5])

Aliases: I<partition>

=cut

=head2 partitions

    self.partitions(k, block)

Returns the

=cut

=head2 perm2num

    self.perm2num

Returns the

=cut

=head2 permutations

    self.permutations

Returns the

=cut

=head2 pick

    self.pick(amount)

Returns the

=cut

=head2 pop_at

    self.pop_at(offset)

Returns the

Aliases: I<delete_at>, I<delete_index>

=cut

=head2 pop_rand

    self.pop_rand

Returns the

=cut

=head2 pop_while

    self.pop_while(block)

Returns the

=cut

=head2 prepend

    self.prepend(*args)

Returns the

Aliases: I<unshift>

=cut

=head2 prod

    self.prod(arg)

Returns the

=cut

=head2 prod_2d

    arr.prod_2d {|a,b,c,...| ... }

Product of a 2D array, by mapping each row to the given block.

    say [[2,4],[3,2],[5,1],[7,1]].prod_2d {|p,k| p**k }    #=> 5040

=cut

=head2 prod_by

    arr.prod_by { ... }

Product of an array, by mapping each element to the given block.

    say [1,2,3,4].prod_by {|n| n**3 }    # product of each element cubed

=cut

=head2 prod_kv

    self.prod_kv(block)

Returns the

=cut

=head2 prodmod

    self.prodmod(mod)

Returns the

=cut

=head2 rand

    self.rand(amount)

Returns the

Aliases: I<sample>

=cut

=head2 rand_perm

    arr.rand_perm

Returns a random permutation of the self array.

Example:

    var arr = %w(a b c d e f g)
    say arr.random_permutation

Additionally, by setting a seed value for C<irand> with Number C<iseed()>, the results returned by C<random_permutation> can be reproduced.

Example with iseed():

    iseed(42)
    var arr = %w(a b c d e f g)
    say arr.random_permutation      #=> ["d", "f", "g", "b", "c", "e", "a"]

Aliases: I<random_permutation>

=cut

=head2 range

    self.range

Returns the

=cut

=head2 recmap

    arr.recmap { ... }

Recursively map the value of an array, given a block of code.

    # Generate all the 5-smooth numbers <= 20
    var (a, k, L) = ([1], 5, 20)
    k.primes.each {|p| a.recmap! {|n| n*p <= L ? [n*p] : () } }
    say a.sort    #=> [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20]

=cut

=head2 reduce_op

    self.reduce_op(operator, initial)

Returns the

Aliases: I<reduce_operator>

=cut

=head2 resize

    arr.resize(index)

Efficienlty resize the array to a given index, modifying the array in-place.

    var arr = %w[a b c d e]
    arr.resize(2)            # removes indices > 2
    say arr                  # ['a', 'b', 'c']

Use index C<-1> to empty the array.

Aliases: I<resize_to>

=cut

=head2 rindex

    self.rindex(obj)

Returns the

Aliases: I<rindex_by>, I<last_index>, I<last_index_by>

=cut

=head2 rotate

    self.rotate(num)

Returns the

=cut

=head2 rref

    self.rref

Returns the

Aliases: I<reduced_row_echelon_form>

=cut

=head2 rscalar_op

    self.rscalar_op(operator, scalar)

Returns the

Aliases: I<rscalar_operator>

=cut

=head2 run_length

    arr.run_length
    arr.run_length { ... }

The run-length algorithm, returning an array of pairs C<[a,n]>.

    say [1,1,1,2,3,3].run_length            #=> [[1, 3], [2, 1], [3, 2]]
    say %w(a a b C c c).run_length { .lc }  #=> [['a', 2], ['b', 1], ['C', 3]]

Aliases: I<run_length_by>

=cut

=head2 sadd

    self.sadd(scalar)

Returns the

Aliases: I<scalar_add>

=cut

=head2 scalar_op

    self.scalar_op(operator, scalar)

Returns the

Aliases: I<scalar_operator>

=cut

=head2 sdiv

    self.sdiv(scalar)

Returns the

Aliases: I<scalar_div>

=cut

=head2 segment

    arr.segment(indices...)

Segment an array at the given indices.

    var arr = [1,2,3,4]
    say arr.segment(1)         #=> [[1, 2], [3, 4]]
    say arr.segment(2)         #=> [[1, 2, 3], [4]]
    say arr.segment(0, 1, 2)   #=> [[1], [2], [3], [4]]
    say arr.segment(0, 2)      #=> [[1], [2, 3], [4]]

Negative indices can be used for couting from the end of the array (e.g.: -1 means the end of the array).

=cut

=head2 segment_by

    arr.segment_by { ... }

Segment the array into multiple sub-arrays, whenever the block returns a true value.

Example:

    # Segment the array after each prime number
    say @(1..prime(5)).segment_by { .is_prime }

Output:

    [[1, 2], [3], [4, 5], [6, 7], [8, 9, 10, 11]]

=cut

=head2 shift

    self.shift(num)

Returns the

Aliases: I<drop_left>, I<drop_first>

=cut

=head2 shift_while

    self.shift_while(block)

Returns the

=cut

=head2 shuffle

    self.shuffle

Returns the

=cut

=head2 skip

    self.skip(n)

Returns the

Aliases: I<skip_first>

=cut

=head2 skip_by

    self.skip_by(block)

Returns the

=cut

=head2 skip_last

    self.skip_last(n)

Returns the

=cut

=head2 slice

    arr.slice(offset)
    arr.slice(offset, length)

Extracts a slice out of the self-array and returns it. First entry is at offset zero.

If C<offset> is negative, starts that far back from the end of the array.

If C<length> is omitted, returns everything through the end of the array.

If C<length> is negative, leaves that many entries off the end of the array.

=cut

=head2 slice_after

    self.slice_after(block)

Returns the

=cut

=head2 slice_before

    self.slice_before(block)

Returns the

=cut

=head2 slices

    array.slices(n)

Slices the self-array into multiple sub-arrays, each sub-array having at most C<n> elements.

    say [1,2,3,4].slices(2)         #=> [[1, 2], [3, 4]]
    say [1,2,3,4,5].slices(2)       #=> [[1, 2], [3, 4], [5]]

Aliases: I<map_slice>

=cut

=head2 smul

    self.smul(scalar)

Returns the

Aliases: I<scalar_mul>

=cut

=head2 solve_rec_seq

    arr.solve_rec_seq

Attempts to find a minimal linear recurrence that generates the given array of numbers:

    say 30.of { .fibonacci }.solve_rec_seq      #=> [1, 1]
    say 30.of { .square }.solve_rec_seq         #=> [3, -3, 1]
    say 30.of { .faulhaber(2) }.solve_rec_seq   #=> [4, -6, 4, -1]

Aliases: I<find_linear_recurrence>

=cut

=head2 solve_seq

    arr.solve_seq(offset=0)

Returns a Polynomial object that generates the terms of the given sequence.

Example:

    say 20.of { .square }.solve_seq         #=> x^2
    say 20.of { .faulhaber(2) }.solve_seq   #=> 1/3*x^3 + 1/2*x^2 + 1/6*x

Example with offset:

    say 20.of { (_+10)**3 }.solve_seq       #=> x^3 + 30*x^2 + 300*x + 1000
    say 20.of { (_+10)**3 }.solve_seq(10)   #=> x^3

=cut

=head2 sort

    arr.sort
    arr.sort {|a,b| ... }

Returns a new sorted array:

    say [3,2,1,4].sort        #=> [1,2,3,4]
    say ['c','a','b'].sort    #=> ['a','b','c']

An optional comparison block can be given, which is called with two elements C<a> and C<b> and must return C<-1>, C<0> or C<1>, corresponding to how C<a> and C<b> must be ordered in the returned array:

    say [3,2,1,4].sort {|a,b| a <=> b }     #=> [1,2,3,4]
    say [3,2,1,4].sort {|a,b| b <=> a }     #=> [4,3,2,1]

=cut

=head2 sort_by

    arr.sort_by { ... }

Sort an array by mapping each value to the given block.

    [4,3,1,2].sort_by { _ }            # same as .sort()
    [4,3,1,2].sort_by {|n| -n }        # reversed numerical sorting
    %w(foo fo f).sort_by { .len }      # sort array by length

=cut

=head2 splice

    self.splice(offset, length, *objects)

Returns the

=cut

=head2 split

    self.split(obj)

Returns the

=cut

=head2 split_by

    arr.split_by { ... }

Splits the given array by the objects at which the given block returns a true value.

    say [1,2,0,3,0,4].split_by { _ == 0 }   #=> [[1, 2], [3], [4]]

=cut

=head2 ssub

    self.ssub(scalar)

Returns the

Aliases: I<scalar_sub>

=cut

=head2 stack

    arr.stack
    arr.stack { ... }

Groups runs of identical elements.

    say <a a a b b c>.stack     #=> [["a", "a", "a"], ["b", "b"], ["c"]

When a block of code is given, the stocking is done based on the mapping of each element to the given block:

    say <A B b A b B A>.stack_by { .uc }

Output:

    [["A"], ["B", "b"], ["A"], ["b", "B"], ["A"]]

Aliases: I<stack_by>

=cut

=head2 subsets

    self.subsets

Returns the

=cut

=head2 sum

    self.sum(arg)

Returns the

=cut

=head2 sum_2d

    arr.sum_2d {|a,b,c,...| ... }

Sum of a 2D array, by mapping each row to the given block.

    say [[2,4],[3,2],[5,1],[7,1]].sum_2d {|p,k| p**k }     #=> 37

=cut

=head2 sum_by

    arr.sum_by { ... }

Sum of an array, by mapping each element to the given block.

    say [1,2,3,4].sum_by {|n| n**2 }    # sum of each element squared

=cut

=head2 sum_kv

    self.sum_kv(block)

Returns the

=cut

=head2 summod

    self.summod(mod)

Returns the

=cut

=head2 swap

    self.swap(i, j)

Returns the

=cut

=head2 take_left

    self.take_left(amount)

Returns the

=cut

=head2 take_right

    self.take_right(amount)

Returns the

=cut

=head2 to_a

    self.to_a

Returns the

Aliases: I<to_array>

=cut

=head2 to_bag

    self.to_bag

Returns the

=cut

=head2 to_h

    self.to_h

Returns the

Aliases: I<to_hash>

=cut

=head2 to_m

    self.to_m

Returns the

Aliases: I<to_matrix>

=cut

=head2 to_s

    self.to_s

Returns the

Aliases: I<dump>, I<to_str>

=cut

=head2 to_set

    self.to_set

Returns the

=cut

=head2 to_v

    self.to_v

Returns the

Aliases: I<to_vector>

=cut

=head2 tuples

    self.tuples

Returns the

Aliases: I<variations>

=cut

=head2 tuples_with_repetition

    self.tuples_with_repetition

Returns the

Aliases: I<variations_with_repetition>

=cut

=head2 uniq

    self.uniq(block)

Returns the

Aliases: I<unique>, I<distinct>

=cut

=head2 uniq_by

    self.uniq_by(block)

Returns the

Aliases: I<unique_by>

=cut

=head2 uniq_permutations

    arr.uniq_permutations
    arr.uniq_permutations { ... }

It uses the C<next_permutation> method to create all the unique permutations of the self-array.

    say [1,1,2].unique_permutations         #=> [[1, 1, 2], [1, 2, 1], [2, 1, 1]

Equivalent with C<arr.permutations.uniq>, but more efficient, as it creates the permutations without duplicates.

The method also accepts a callback block as an optional argument:

    [1,1,2].unique_permutations {|*perm|
        say perm
    }

Output:

    [1, 1, 2]
    [1, 2, 1]
    [2, 1, 1]

Aliases: I<unique_permutations>

=cut

=head2 uniq_prefs

    self.uniq_prefs(block)

Returns the

Aliases: I<unique_prefixes>

=cut

=head2 unroll_op

    self.unroll_op(operator, arg)

Returns the

Aliases: I<unroll_operator>

=cut

=head2 unzip_by

    self.unzip_by(block)

Returns the

=cut

=head2 weighted_shuffle_by

    self.weighted_shuffle_by(block)

Returns the

=cut

=head2 wise_op

    m1.wise_op(operator, m2)

Returns the

Aliases: I<wise_operator>

=cut

=head2 zip

    self.zip(block)

Returns the

Aliases: I<transpose>

=cut

=head2 zip_by

    self.zip_by(block)

Returns the

=cut

=head2 zip_op

    self.zip_op(operator, arg)

Returns the

Aliases: I<zip_operator>

=cut
