Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
instance method
Array#permutation
(?::int? count) { (::Array[Elem] permutation) -> void } -> self
(?::int? count) -> ::Enumerator[::Array[Elem], self]
permutation(count = self.size) {|permutation| ... } → self
permutation(count = self.size) → new_enumerator
array.c
View on GitHub ↗
static VALUE
rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
{
rb_len_t r, i;
RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
r = NUM2LEN(argv[0]); /* Permutation size from argument */
}
else {
r = RARRAY_LEN(ary);
}
rb_len_t n = RARRAY_LEN(ary);
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;
rb_len_t *p = ALLOCV_N(rb_len_t, t0, r+roomof(n, sizeof(rb_len_t)));
char *used = (char*)(p + r);
VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
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;
}
Iterates over permutations of the elements of self; the order of permutations is indeterminate.
With a block and an in-range positive integer argument count (0 < count <= self.size) given, calls the block with each permutation of self of size count; returns self:
Example
a = [0, 1, 2] perms = [] a.permutation(1) {|perm| perms.push(perm) } perms # => [[0], [1], [2]] perms = [] a.permutation(2) {|perm| perms.push(perm) } perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]] perms = [] a.permutation(3) {|perm| perms.push(perm) } perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
When count is zero, calls the block once with a new empty array:
Example
perms = [] a.permutation(0) {|perm| perms.push(perm) } perms # => [[]]
When count is out of range (negative or larger than self.size), does not call the block:
Example
a.permutation(-1) {|permutation| fail 'Cannot happen' } a.permutation(4) {|permutation| fail 'Cannot happen' }
With no block given, returns a new Enumerator.
Related: Methods for Iterating.