Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9ac895a94709
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: cd382cfe52ae
Choose a head ref
  • 3 commits
  • 3 files changed
  • 2 contributors

Commits on Mar 11, 2015

  1. Copy the full SHA
    66a2351 View commit details
  2. Copy the full SHA
    b45b4fb View commit details
  3. Merge pull request #2683 from bjfish/truffle_array_product

    [Truffle] Adding Array#product to array.rb
    nirvdrum committed Mar 11, 2015
    Copy the full SHA
    cd382cf View commit details
8 changes: 0 additions & 8 deletions spec/truffle/tags/core/array/product_tags.txt

This file was deleted.

9 changes: 0 additions & 9 deletions spec/truffle/tags/core/array/repeated_combination_tags.txt

This file was deleted.

70 changes: 70 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/array.rb
Original file line number Diff line number Diff line change
@@ -584,6 +584,46 @@ def keep_if(&block)
replace select(&block)
end

# Implementation notes: We build a block that will generate all the
# combinations by building it up successively using "inject" and starting
# with one responsible to append the values.
def product(*args)
args.map! { |x| Rubinius::Type.coerce_to(x, Array, :to_ary) }

# Check the result size will fit in an Array.
sum = args.inject(size) { |n, x| n * x.size }

if sum > Fixnum::MAX
raise RangeError, "product result is too large"
end

# TODO rewrite this to not use a tree of Proc objects.

# to get the results in the same order as in MRI, vary the last argument first
args.reverse!

result = []
args.push self

outer_lambda = args.inject(result.method(:push)) do |trigger, values|
lambda do |partial|
values.each do |val|
trigger.call(partial.dup << val)
end
end
end

outer_lambda.call([])

if block_given?
block_result = self
result.each { |v| block_result << yield(v) }
block_result
else
result
end
end

def rassoc(obj)
each do |elem|
if elem.kind_of? Array and elem.at(1) == obj
@@ -594,6 +634,36 @@ def rassoc(obj)
nil
end

def repeated_combination(combination_size, &block)
combination_size = combination_size.to_i
unless block_given?
return Enumerator.new(self, :repeated_combination, combination_size)
end

if combination_size < 0
# yield nothing
else
Rubinius.privately do
dup.compile_repeated_combinations(combination_size, [], 0, combination_size, &block)
end
end

return self
end

def compile_repeated_combinations(combination_size, place, index, depth, &block)
if depth > 0
(length - index).times do |i|
place[combination_size-depth] = index + i
compile_repeated_combinations(combination_size,place,index + i,depth-1, &block)
end
else
yield place.map { |element| self[element] }
end
end

private :compile_repeated_combinations

def repeated_permutation(combination_size, &block)
combination_size = combination_size.to_i
unless block_given?