Project

General

Profile

Feature #5584 ยป patch.diff

Glass_saga (Masaki Matsushita), 11/07/2011 03:43 PM

View differences:

array.c
4049 4049
    return result;
4050 4050
}
4051 4051

  
4052
/*
4053
 *  call-seq:
4054
 *     ary.sample! -> obj
4055
 *     ary.sample!(random: rng) -> obj
4056
 *     ary.sample!(n) -> new_ary
4057
 *     ary.sample!(n, random: rng) -> new_ary
4058
 *
4059
 *  Choose and delete a random element or +n+ random elements from the array. The elements
4060
 *  are chosen by using random and unique indices into the array in order to
4061
 *  ensure that an element doesn't repeat itself unless the array already
4062
 *  contained duplicate elements. If the array is empty the first form returns
4063
 *  <code>nil</code> and the second form returns an empty array.
4064
 *
4065
 *  If +rng+ is given, it will be used as the random number generator.
4066
 */
4067

  
4068
static VALUE
4069
rb_ary_sample_bang(int argc, VALUE *argv, VALUE ary)
4070
{
4071
    VALUE nv, result, *ptr_result;
4072
    VALUE opts, randgen = rb_cRandom;
4073
    VALUE a, b, c;
4074
    long n, len, i, j, k;
4075
    double rnds[3];
4076

  
4077
    if (OPTHASH_GIVEN_P(opts)) {
4078
	randgen = rb_hash_lookup2(opts, sym_random, randgen);
4079
    }
4080
    len = RARRAY_LEN(ary);
4081
    if (argc == 0) {
4082
	if (len == 0) return Qnil;
4083
	if (len == 1) {
4084
	    i = 0;
4085
	}
4086
	else {
4087
	    double x = rb_random_real(randgen);
4088
	    if (len == 0) return Qnil;
4089
	    i = (long)(x * len);
4090
	}
4091
	return rb_ary_delete_at(ary, i);
4092
    }
4093
    rb_scan_args(argc, argv, "1", &nv);
4094
    n = NUM2LONG(nv);
4095
    if (n < 0) rb_raise(rb_eArgError, "negative sample number");
4096
    if (n > len) n = len;
4097
    if (n <= numberof(rnds)) {
4098
	for (i = 0; i < n; ++i) {
4099
	    rnds[i] = rb_random_real(randgen);
4100
	}
4101
    }
4102
    switch (n) {
4103
	case 0:
4104
	    return rb_ary_new2(0);
4105
	case 1:
4106
	    i = (long)(rnds[0] * len);
4107
	    return rb_ary_new3(1, rb_ary_delete_at(ary, i));
4108
	case 2:
4109
	    i = (long)(rnds[0] * len);
4110
	    j = (long)(rnds[1] * (len-1));
4111
	    a = rb_ary_delete_at(ary, i);
4112
	    b = rb_ary_delete_at(ary, j);
4113
	    return rb_ary_new3(2, a, b);
4114
	case 3:
4115
	    i = (long)(rnds[0] * len);
4116
	    j = (long)(rnds[1] * (len-1));
4117
	    k = (long)(rnds[2] * (len-2));
4118
	    a = rb_ary_delete_at(ary, i);
4119
	    b = rb_ary_delete_at(ary, j);
4120
	    c = rb_ary_delete_at(ary, k);
4121
	    return rb_ary_new3(3, a, b, c);
4122
    }
4123
    result = rb_ary_new2(n);
4124
    ptr_result = RARRAY_PTR(result);
4125
    for (i=0; i<n; i++) {
4126
	j = (long)(rb_random_real(randgen) * --len);
4127
	ptr_result[i] = rb_ary_delete_at(ary, j);
4128
    }
4129
    ARY_SET_LEN(result, n);
4130

  
4131
    return result;
4132
}
4052 4133

  
4053 4134
/*
4054 4135
 *  call-seq:
......
4998 5079
    rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
4999 5080
    rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
5000 5081
    rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
5082
    rb_define_method(rb_cArray, "sample!", rb_ary_sample_bang, -1);
5001 5083
    rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
5002 5084
    rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
5003 5085
    rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);