summaryrefslogtreecommitdiffhomepage
path: root/mrbgems
diff options
context:
space:
mode:
authorEmiliano Lesende <[email protected]>2013-11-01 11:44:40 -0300
committerEmiliano Lesende <[email protected]>2013-11-01 11:44:40 -0300
commitd8cc37cdf95b72933ff3d8466b8ea3c4e3ff8010 (patch)
tree15d493371ceec9a1fd6c4fc6d532aca8df88cc08 /mrbgems
parent92825660ea94cde3b588ae0b1e4b0e9d311f718e (diff)
downloadmruby-d8cc37cdf95b72933ff3d8466b8ea3c4e3ff8010.tar.gz
mruby-d8cc37cdf95b72933ff3d8466b8ea3c4e3ff8010.zip
Added shuffle and shuffle! to the Array class in the Random gem.
Diffstat (limited to 'mrbgems')
-rw-r--r--mrbgems/mruby-random/src/random.c52
-rw-r--r--mrbgems/mruby-random/test/random.rb14
2 files changed, 66 insertions, 0 deletions
diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c
index 771167f2a..47977b393 100644
--- a/mrbgems/mruby-random/src/random.c
+++ b/mrbgems/mruby-random/src/random.c
@@ -7,6 +7,7 @@
#include "mruby.h"
#include "mruby/variable.h"
#include "mruby/data.h"
+#include "mruby/array.h"
#include "mt19937ar.h"
#include <time.h>
@@ -207,9 +208,57 @@ static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self)
return old_seed;
}
+/*
+ * call-seq:
+ * ary.shuffle! -> ary
+ *
+ * Shuffles elements in self in place.
+ */
+
+static mrb_value
+mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int i;
+ mrb_value seed;
+
+ seed = mrb_gv_get(mrb, mrb_intern2(mrb, GLOBAL_RAND_SEED_KEY, GLOBAL_RAND_SEED_KEY_CSTR_LEN));
+ if (mrb_nil_p(seed)) {
+ mrb_random_mt_g_srand(mrb, mrb_nil_value());
+ }
+
+ if (RARRAY_LEN(ary) > 1) {
+ mrb_ary_modify(mrb, mrb_ary_ptr(ary));
+ for (i = RARRAY_LEN(ary) - 1; i > 0; i--) {
+ mrb_int j = mrb_fixnum(mrb_random_mt_g_rand(mrb, mrb_fixnum_value(RARRAY_LEN(ary))));
+ mrb_value t = RARRAY_PTR(ary)[i];
+ RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j];
+ RARRAY_PTR(ary)[j] = t;
+ }
+ }
+
+ return ary;
+}
+
+/*
+ * call-seq:
+ * ary.shuffle -> new_ary
+ *
+ * Returns a new array with elements of self shuffled.
+ */
+
+static mrb_value
+mrb_ary_shuffle(mrb_state *mrb, mrb_value ary)
+{
+ mrb_value new_ary = mrb_ary_new_from_values(mrb, RARRAY_LEN(ary), RARRAY_PTR(ary));
+ mrb_ary_shuffle_bang(mrb, new_ary);
+
+ return new_ary;
+}
+
void mrb_mruby_random_gem_init(mrb_state *mrb)
{
struct RClass *random;
+ struct RClass *array = mrb->array_class;
mrb_define_method(mrb, mrb->kernel_module, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1));
mrb_define_method(mrb, mrb->kernel_module, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1));
@@ -221,6 +270,9 @@ void mrb_mruby_random_gem_init(mrb_state *mrb)
mrb_define_method(mrb, random, "initialize", mrb_random_init, MRB_ARGS_OPT(1));
mrb_define_method(mrb, random, "rand", mrb_random_rand, MRB_ARGS_OPT(1));
mrb_define_method(mrb, random, "srand", mrb_random_srand, MRB_ARGS_OPT(1));
+
+ mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_NONE());
+ mrb_define_method(mrb, array, "shuffle!", mrb_ary_shuffle_bang, MRB_ARGS_NONE());
}
void mrb_mruby_random_gem_final(mrb_state *mrb)
diff --git a/mrbgems/mruby-random/test/random.rb b/mrbgems/mruby-random/test/random.rb
index 01d231d5c..b35acaafd 100644
--- a/mrbgems/mruby-random/test/random.rb
+++ b/mrbgems/mruby-random/test/random.rb
@@ -30,3 +30,17 @@ end
assert("float") do
rand.class == Float
end
+
+assert("Array#shuffle") do
+ ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ shuffled = ary.shuffle
+
+ ary == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and shuffled != ary and 10.times { |x| ary.include? x }
+end
+
+assert('Array#shuffle!') do
+ ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ ary.shuffle!
+
+ ary != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary.include? x }
+end \ No newline at end of file