Ruby Newbie homepage Ruby Newbie homepage

How to use

Quick guide

Official content
When invoked with a block, yield all permutations of elements of self; returns self. The order of permutations is indeterminate.
When a block and an in-range positive Integer argument n (0 < n <= self.size) are given, calls the block with all n-tuple permutations of self.
Example:
a = [0, 1, 2]
a.permutation(2) {|permutation| p permutation }
Output:
[0, 1]
[0, 2]
[1, 0]
[1, 2]
[2, 0]
[2, 1]
Another example:
a = [0, 1, 2]
a.permutation(3) {|permutation| p permutation }
Output:
[0, 1, 2]
[0, 2, 1]
[1, 0, 2]
[1, 2, 0]
[2, 0, 1]
[2, 1, 0]
When n is zero, calls the block once with a new empty Array:
a = [0, 1, 2]
a.permutation(0) {|permutation| p permutation }
Output:
[]
When n is out of range (negative or larger than self.size), does not call the block:
a = [0, 1, 2]
a.permutation(-1) {|permutation| fail 'Cannot happen' }
a.permutation(4) {|permutation| fail 'Cannot happen' }
When a block given but no argument, behaves the same as a.permutation(a.size):
a = [0, 1, 2]
a.permutation {|permutation| p permutation }
Output:
[0, 1, 2]
[0, 2, 1]
[1, 0, 2]
[1, 2, 0]
[2, 0, 1]
[2, 1, 0]
Returns a new Enumerator if no block given:
a = [0, 1, 2]
a.permutation # => #<Enumerator: [0, 1, 2]:permutation>
a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
 
               static VALUE
rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
{
    long r, n, i;

    n = RARRAY_LEN(ary);                  /* Array length */
    RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);   /* Return enumerator if no block */
    r = n;
    if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
        r = NUM2LONG(argv[0]);            /* Permutation size from argument */

    if (r < 0 || n < r) {
        /* 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+roomof(n, sizeof(long)));
        char *used = (char*)(p + r);
        VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
        RBASIC_CLEAR_CLASS(ary0);

        MEMZERO(used, char, n); /* initialize array */

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

Was this page useful?