0
+# = rand.rb -- library for picking random elements and shuffling
0
+# Copyright (C) 2004 Ilmari Heikkinen
0
+# Documentation:: Christian Neukirchen <mailto:chneukirchen@gmail.com>
0
+ # Choose and return a random element of the Enumerable.
0
+ # [1, 2, 3, 4].pick #=> 2 (or 1, 3, 4)
0
+ # Return an array of the elements in random order.
0
+ # [1, 2, 3, 4].shuffle #=> [3, 4, 1, 2]
0
+ # Calls _block_ once for each element in _self_ in random order,
0
+ # passing that element as a parameter.
0
+ def each_random(&block)
0
+ # Invokes _block_ once for each element of _self_ in random order.
0
+ # Creates a new array containing the values returned by the block.
0
+ def map_random(&block)
0
+ # Choose and return a random element of _self_.
0
+ # [1, 2, 3, 4].pick #=> 2 (or 1, 3, 4)
0
+ # Deletes a random element of _self_, returning that element.
0
+ # Return the index of an random element of _self_.
0
+ # ["foo", "bar", "baz"].pick_index #=> 1 (or 0, or 2)
0
+ # Destructive pick_index. Delete a random element of _self_ and
0
+ # a = [11, 22, 33, 44]
0
+ # Return a random element of _self_ with its index.
0
+ # a = ["a", "b", "c", "d"]
0
+ # a.pick_with_index #=> ["b", 1]
0
+ # a #=> ["a", "b", "c", "d"]
0
+ # Delete and return a random element of _self_ with its index.
0
+ # a = ["a", "b", "c", "d"]
0
+ # a.pick_with_index! #=> ["b", 1]
0
+ # a #=> ["a", "c", "d"]
0
+ # Return an array of the elements in random order.
0
+ # [11, 22, 33, 44].shuffle #=> [33, 11, 44, 22]
0
+ # Destructive shuffle. Arrange the elements of _self_ in new order.
0
+ # Using Fisher-Yates shuffle.
0
+ # a = [11, 22, 33, 44]
0
+ # a #=> [33, 11, 44, 22]
0
+ (size-1).downto(1) {|index|
0
+ other_index = Kernel.rand(index+1)
0
+ next if index == other_index
0
+ self[index] = self[other_index]
0
+ self[other_index] = tmp
0
+ # Choose and return a random key-value pair of _self_.
0
+ # {:one => 1, :two => 2, :three => 3}.pick #=> [:one, 1]
0
+ # Deletes a random key-value pair of _self_, returning that pair.
0
+ # a = {:one => 1, :two => 2, :three => 3}
0
+ # a.pick #=> [:two, 2]
0
+ # a #=> {:one => 1, :three => 3}
0
+ # Return a random key of _self_.
0
+ # {:one => 1, :two => 2, :three => 3}.pick_key #=> :three
0
+ # Return a random value of _self_.
0
+ # {:one => 1, :two => 2, :three => 3}.pick_value #=> 3
0
+ # Delete a random key-value pair of _self_ and return the key.
0
+ # a = {:one => 1, :two => 2, :three => 3}
0
+ # a.pick_key! #=> :two
0
+ # a #=> {:one => 1, :three => 3}
0
+ # Delete a random key-value pair of _self_ and return the value.
0
+ # a = {:one => 1, :two => 2, :three => 3}
0
+ # a #=> {:one => 1, :three => 3}
0
+ # Return the key-value pairs of _self_ with _keys_ and _values_
0
+ # shuffled independedly.
0
+ # {:one => 1, :two => 2, :three => 3}.shuffle_hash_pairs
0
+ # #=> [[:one, 3], [:two, 1], [:three, 2]]
0
+ def shuffle_hash_pairs
0
+ keys.shuffle.zip(values.shuffle)
0
+ # Return a copy of _self_ with _values_ arranged in random order.
0
+ # {:one => 1, :two => 2, :three => 3}.shuffle_hash
0
+ # #=> {:two=>2, :three=>1, :one=>3}
0
+ shuffle_hash_pairs.each{|k, v|
0
+ # Destructive shuffle_hash. Arrange the values of _self_ in
0
+ # h = {:one => 1, :two => 2, :three => 3}
0
+ # h #=> {:two=>2, :three=>1, :one=>3}
0
+ shuffle_hash_pairs.each{|k, v|
0
+ # Return the string with characters arranged in random order.
0
+ # "Ruby rules".shuffle_chars #=> "e lybRsuur"
0
+ # Destructive shuffle_chars. Arrange the characters of the string
0
+ # in new, random order.
0
+ # s = "Ruby rules".shuffle_chars
0
+ i = Kernel.rand(size-j)
0
+ self[j], self[j+i] = self[j+i], self[j]
0
+ # Return a random byte of _self_.
0
+ # "Ruby rules".pick_byte #=> 121
0
+ # Return a single-character string of a random character in _self_.
0
+ # "Ruby rules".pick_char #=> "y"
0
+ # Destructive pick_char. Delete a random character of the string
0
+ # and return it as a single-character string.
0
+ # s.pick_char! #=> "y"
0
+ # Destructive pick_byte. Delete a random byte of _self_ and return it.
0
+ # s.pick_byte! #=> 121
0
+ # Return a random byte index of _self_.
0
+ # "Ruby rules".pick_index #=> 3
0
+ # Destructive pick_index. Delete a random byte of _self_ and
0
+ # Return a two element array consisting of an random byte of _self_
0
+ # "Ruby rules".pick_byte_with_index #=> [121, 3]
0
+ def pick_byte_with_index
0
+ # Destructive pick_byte_with_index. Delete a random byte of _self_
0
+ # and return it and it's index.
0
+ # s.pick_byte_with index! #=> [121, 3]
0
+ def pick_byte_with_index!
0
+ rv = pick_byte_with_index
0
+ # Return a single-character string of a random character in _self_
0
+ # "Ruby rules".pick_char_with_index #=> ["y", 3]
0
+ def pick_char_with_index
0
+ byte, index = pick_byte_with_index
0
+ # Destructive pick_char_with_index. Delete a random character of
0
+ # the string and return it as a single-character string together
0
+ # s.pick_char_with_index! #=> ["y", 3]
0
+ def pick_char_with_index!
0
+ byte, index = pick_byte_with_index!
0
+ s, index = tokens.pick_with_index
0
+ start = tokens[0, index].join
0
+ self[start.size, s.size] = ""
0
+module RandTestHelpers # :nodoc:
0
+ def picker(enum, enum_check, method, n=50)
0
+ (1..n).all?{ enum_check.include? enum.send(method) }
0
+ def try_shuffling(enum, enum_c, method)
0
+class RandArrayTest < Test::Unit::TestCase # :nodoc:
0
+ include RandTestHelpers
0
+ results = (0...a.size).map{ a.pick }
0
+ assert true, results.all? {|r| a.include? r }
0
+ results = (0...a.size).map{ a.pick! }
0
+ assert true, results.sort == (0..99).to_a and a.empty?
0
+ results = (0...a.size).map{ a.pick_index }
0
+ assert true, results.all? {|r| r.between?(0, a.size-1) }
0
+ # side-effect-relying block; a.size = a.size-1 after pick_index!,
0
+ # so the picked index max value is the new a.size
0
+ assert true, (0...a.size).all?{ a.pick_index!.between?(0, a.size) } and a.empty?
0
+ shuffled = try_shuffling(a, a, :shuffle)
0
+ assert true, shuffled.sort == a and shuffled != a
0
+ try_shuffling(a, ar, :shuffle!)
0
+ assert true, a != ar and a.sort == ar
0
+class RandHashTest < Test::Unit::TestCase # :nodoc:
0
+ include RandTestHelpers
0
+ assert true, picker(ha, ha.entries, :pick)
0
+ assert true, picker(h, ha.entries, :pick!) and h.empty?
0
+ assert true, picker(ha, ha.keys, :pick_key)
0
+ assert true, picker(h, ha.keys, :pick_key!) and h.empty?
0
+ assert true, picker(ha, ha.values, :pick_value)
0
+ assert true, picker(h, ha.values, :pick_value!) and h.empty?
0
+ hs = try_shuffling(ha, h, :shuffle_hash)
0
+ assert true, hs != h and (hs.keys + hs.values).sort == (h.keys + h.values).sort
0
+ def test_shuffle_hash!
0
+ try_shuffling(hs, h, :shuffle_hash!)
0
+ assert true, hs != h and (hs.keys + hs.values).sort == (h.keys + h.values).sort
0
+ hs = try_shuffling(ha, h, :shuffle)
0
+ assert true, hs != h and hs.entries.sort == h.entries.sort
0
+class RandStringTest < Test::Unit::TestCase # :nodoc:
0
+ include RandTestHelpers
0
+ def self.pick_tests(endings)
0
+ endings.each{|ending, compare_str_f|
0
+ define_method("test_pick#{ending}"){
0
+ assert true, picker(s, instance_eval(&compare_str_f), "pick#{ending}", s.size)
0
+ def self.pick_tests!(endings)
0
+ endings.each{|ending, compare_str_f|
0
+ define_method("test_pick#{ending}!"){
0
+ assert true, picker(s, instance_eval(&compare_str_f), "pick#{ending}!", s.size) and s.empty?
0
+ (("a".."z").to_s + "\n") * 10
0
+ ss = try_shuffling(s, s.to_a, :shuffle)
0
+ assert true, ss != s.to_a and ss.sort == s.to_a.sort
0
+ def test_shuffle_chars
0
+ ss = try_shuffling(s, s.split(//), :shuffle_chars)
0
+ assert true, ss != s and ss.split(//).sort == s.split(//).sort
0
+ def test_shuffle_chars!
0
+ try_shuffling(ss, s.split(//), :shuffle_chars!)
0
+ assert true, ss != s and ss.split(//).sort == s.split(//).sort
0
+ pick_tests({ "" => lambda{str.to_a},
0
+ :_char => lambda{str.split(//)},
0
+ :_byte => lambda{str.split(//).map{|c| c[0]}},
0
+ :_index => lambda{(0...str.size).to_a}
0
+ pick_tests!({ :_char => lambda{str.split(//)},
0
+ :_byte => lambda{str.split(//).map{|c| c[0]}},
0
+ :_index => lambda{(0...str.size).to_a}
Comments
No one has commented yet.