Method: Array#repeated_permutation

Defined in:
array.c

#repeated_permutation(size) {|permutation| ... } ⇒ self #repeated_permutation(size) ⇒ Object

With a block given, calls the block with each repeated permutation of length size of the elements of self; each permutation is an array; returns self. The order of the permutations is indeterminate.

If a positive integer argument size is given, calls the block with each size-tuple repeated permutation of the elements of self. The number of permutations is self.size**size.

Examples:

  • size is 1:

    p = []
    [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
    p # => [[0], [1], [2]]
    
  • size is 2:

    p = []
    [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
    p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
    

If size is zero, calls the block once with an empty array.

If size is negative, does not call the block:

[0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }

With no block given, returns a new Enumerator.

Related: see Methods for Combining.

Overloads:

  • #repeated_permutation(size) {|permutation| ... } ⇒ self

    Yields:

    Returns:

    • (self)


7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
# File 'array.c', line 7338

static VALUE
rb_ary_repeated_permutation(VALUE ary, VALUE num)
{
    long r, n, i;

    n = RARRAY_LEN(ary);                  /* Array length */
    RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size);      /* Return Enumerator if no block */
    r = NUM2LONG(num);                    /* Permutation size from argument */

    if (r < 0) {
        /* no permutations: yield nothing */
    }
    else if (r == 0) { /* exactly one permutation: the zero-length array */
        rb_yield(rb_ary_new2(0));
    }
    else if (r == 1) { /* this is a special, easy case */
        for (i = 0; i < RARRAY_LEN(ary); i++) {
            rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
        }
    }
    else {             /* this is the general case */
        volatile VALUE t0;
        long *p = ALLOCV_N(long, t0, r);
        VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
        RBASIC_CLEAR_CLASS(ary0);

        rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
        ALLOCV_END(t0);
        RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
    }
    return ary;
}