Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何使用递归查找和为零的数组的所有子集?(红宝石色)_Ruby_Recursion_Subset Sum - Fatal编程技术网

Ruby 如何使用递归查找和为零的数组的所有子集?(红宝石色)

Ruby 如何使用递归查找和为零的数组的所有子集?(红宝石色),ruby,recursion,subset-sum,Ruby,Recursion,Subset Sum,我对编码和Ruby都是新手。我在业余时间研究这个问题,因为我是ruby新手,很难让我的代码遍历每个创建的子集 这是我的密码: #Given a set of integers, and a value sum, i.e. value sum of 0 #determine if there is a subset of the given set with sum equal to given sum. class Array def SubSetSumtoZero i

我对编码和Ruby都是新手。我在业余时间研究这个问题,因为我是ruby新手,很难让我的代码遍历每个创建的子集

这是我的密码:

#Given a set of integers, and a value sum, i.e. value sum of 0
#determine if there is a subset of the given set with sum equal to given sum.

class Array
    def SubSetSumtoZero
        if self.collect{|sum,x| sum + x  == 0}
            detected = self.select {|sum,x| sum + x == 0}
            puts "\r\n #{detected} Sums to Zero \r\n"
        else self.collect{|sum,x| sum + x  -= 0}
            notdetected = self.select {|sum, x| sum + x -= 0}
            puts "\r\n#{notdetected} Does not sum to Zero\r\n"
        end
    end
end

originalSet = [-9, -7, -2, 2, 7, 9]
arr = []

for i in 2..(originalSet.length) do
    arr = arr + originalSet.combination(i).to_a
    arr.SubSetSumtoZero
end
以下是我的结果:

[[-9, 9], [-7, 7], [-2, 2]] Sums to Zero 

 [[-9, 9], [-7, 7], [-2, 2], [-7, 7, 9], [-2, 2, 7], [-2, 2, 9]] Sums to Zero 

 [[-9, 9], [-7, 7], [-2, 2], [-7, 7, 9], [-2, 2, 7], [-2, 2, 9], [-2, 2, 7, 9]] Sums to Zero 

 [[-9, 9], [-7, 7], [-2, 2], [-7, 7, 9], [-2, 2, 7], [-2, 2, 9], [-2, 2, 7, 9]] Sums to Zero 

 [[-9, 9], [-7, 7], [-2, 2], [-7, 7, 9], [-2, 2, 7], [-2, 2, 9], [-2, 2, 7, 9]] Sums to Zero 
[Finished in 0.1s]

我知道在某个时刻,整个数组的总和将为零。你知道为什么会发生这种情况吗?

我知道你特别要求一个递归解决方案,但既然@hjing已经提供了一个,我想向你展示如何通过使用Ruby的
Enumerable
模块和
Array
类中强大的内置方法,以更简洁、直接的方式回答你的问题

代码

def find_it(array, tot)
  (1..array.size).each_with_object([]) { |n,arr|
    array.combination(n).each { |a| arr << a if a.reduce(:+) == tot } }
end
find_it([-9, -7, -2, 2, 7, 9], 0) #=> [-9, 9]
  #=> [[-9, 9], [-7, 7], [-2, 2],
  #    [-9, 2, 7], [-7, -2, 9],
  #    [-9, -7, 7, 9], [-9, -2, 2, 9], [-7, -2, 2, 7],
  #    [-9, -7, -2, 2, 7, 9]]
解释

array = [-9, -7, -2, 2, 7, 9]
tot   = 0

r = 1..array.size             #=> 1..6 (Range object)
该范围的每个值都是将要考虑的子集的大小。我们将首先检查大小为1的子集,然后是大小为2的子集,依此类推,直到大小为6的子集,其中只有一个(
array

创建由块变量
arr
表示的初始空数组。第一个值
enum
传递到其块的是数组
[0,[]]
,导致按如下方式分配块变量:

n   => 1
arr => []

enum2 = array.combination(n) #=> array.combination(1)
  #=> #<Enumerator: [-9, -7, -2, 2, 7, 9]:combination(1)>
a => [-9]
第一个元素
enum2
传递到它的块是
[-9]
,导致按如下方式分配bloc block变量:

n   => 1
arr => []

enum2 = array.combination(n) #=> array.combination(1)
  #=> #<Enumerator: [-9, -7, -2, 2, 7, 9]:combination(1)>
a => [-9]
因此块表达式变为:

arr << a if a.reduce(:+) == tot #=> arr << [-9] if [-9].reduce(:+) == 0
导致:

enum2 = array.combination(n) #=> array.combination(2)
  #=> #<Enumerator: [-9, -7, -2, 2, 7, 9]:combination(2)>
enum2.to_a
  #=> [[-9, -7], [-9, -2], [-9, 2], [-9, 7], [-9, 9], [-7, -2], [-7, 2],
  #    [-7,  7], [-7,  9], [-2, 2], [-2, 7], [-2, 9], [ 2,  7], [ 2, 9], [7, 9]]

在列举了两个元素的所有组合之后。接下来将考虑三种方法的组合,以此类推。

我知道您特别要求使用递归解决方案,但既然@hjing提供了一种,我想向您展示如何使用强大的,Ruby的
可枚举
模块和
数组
类中的内置方法

代码

def find_it(array, tot)
  (1..array.size).each_with_object([]) { |n,arr|
    array.combination(n).each { |a| arr << a if a.reduce(:+) == tot } }
end
find_it([-9, -7, -2, 2, 7, 9], 0) #=> [-9, 9]
  #=> [[-9, 9], [-7, 7], [-2, 2],
  #    [-9, 2, 7], [-7, -2, 9],
  #    [-9, -7, 7, 9], [-9, -2, 2, 9], [-7, -2, 2, 7],
  #    [-9, -7, -2, 2, 7, 9]]
解释

array = [-9, -7, -2, 2, 7, 9]
tot   = 0

r = 1..array.size             #=> 1..6 (Range object)
该范围的每个值都是将要考虑的子集的大小。我们将首先检查大小为1的子集,然后是大小为2的子集,依此类推,直到大小为6的子集,其中只有一个(
array

创建由块变量
arr
表示的初始空数组。第一个值
enum
传递到其块的是数组
[0,[]]
,导致按如下方式分配块变量:

n   => 1
arr => []

enum2 = array.combination(n) #=> array.combination(1)
  #=> #<Enumerator: [-9, -7, -2, 2, 7, 9]:combination(1)>
a => [-9]
第一个元素
enum2
传递到它的块是
[-9]
,导致按如下方式分配bloc block变量:

n   => 1
arr => []

enum2 = array.combination(n) #=> array.combination(1)
  #=> #<Enumerator: [-9, -7, -2, 2, 7, 9]:combination(1)>
a => [-9]
因此块表达式变为:

arr << a if a.reduce(:+) == tot #=> arr << [-9] if [-9].reduce(:+) == 0
导致:

enum2 = array.combination(n) #=> array.combination(2)
  #=> #<Enumerator: [-9, -7, -2, 2, 7, 9]:combination(2)>
enum2.to_a
  #=> [[-9, -7], [-9, -2], [-9, 2], [-9, 7], [-9, 9], [-7, -2], [-7, 2],
  #    [-7,  7], [-7,  9], [-2, 2], [-2, 7], [-2, 9], [ 2,  7], [ 2, 9], [7, 9]]

在列举了两个元素的所有组合之后。接下来将考虑三者的组合,依此类推。

一个简单的递归解决方案是编写一个函数来计算数组的功率集。然后,选择电源集中满足所需谓词的所有元素

一个示例实现:

def powerset(array)
  if array.empty?
    [[]]
  else
    first_elem, *rest_elems = array
    subsets = []
    powerset(rest_elems).each do |subset|
      subsets.push(subset)
      subsets.push(subset.clone.push(first_elem))
    end
    subsets
  end
end

def sums_to_zero?(array)
  array.reduce(0, :+) == 0
end

def subsets_that_sum_to_zero(array)
  powerset(array).select { |subset| sums_to_zero?(subset) }
end

original_set = [-9, -7, -2, 2, 7, 9]
subsets_that_sum_to_zero(original_set).each do |subset|
  puts "The subset #{subset} sums to zero!"
end

# The subset [] sums to zero!
# The subset [2, -2] sums to zero!
# The subset [7, -7] sums to zero!
# The subset [7, 2, -9] sums to zero!
# The subset [7, 2, -2, -7] sums to zero!
# The subset [9, -9] sums to zero!
# The subset [9, -2, -7] sums to zero!
# The subset [9, 2, -2, -9] sums to zero!
# The subset [9, 7, -7, -9] sums to zero!
# The subset [9, 7, 2, -2, -7, -9] sums to zero!

有关powerset算法的解释,请参阅。

一个简单的递归解决方案是编写一个函数来计算数组的powerset。然后,选择电源集中满足所需谓词的所有元素

一个示例实现:

def powerset(array)
  if array.empty?
    [[]]
  else
    first_elem, *rest_elems = array
    subsets = []
    powerset(rest_elems).each do |subset|
      subsets.push(subset)
      subsets.push(subset.clone.push(first_elem))
    end
    subsets
  end
end

def sums_to_zero?(array)
  array.reduce(0, :+) == 0
end

def subsets_that_sum_to_zero(array)
  powerset(array).select { |subset| sums_to_zero?(subset) }
end

original_set = [-9, -7, -2, 2, 7, 9]
subsets_that_sum_to_zero(original_set).each do |subset|
  puts "The subset #{subset} sums to zero!"
end

# The subset [] sums to zero!
# The subset [2, -2] sums to zero!
# The subset [7, -7] sums to zero!
# The subset [7, 2, -9] sums to zero!
# The subset [7, 2, -2, -7] sums to zero!
# The subset [9, -9] sums to zero!
# The subset [9, -2, -7] sums to zero!
# The subset [9, 2, -2, -9] sums to zero!
# The subset [9, 7, -7, -9] sums to zero!
# The subset [9, 7, 2, -2, -7, -9] sums to zero!

有关powerset算法的解释,请参阅。

这里是一个关于零和的直接递归解决方案:

def find_subsets(arr)
  return arr if arr.empty?
  result = (0...arr.length).flat_map do |i|
     find_subsets(arr[0...i] + arr[i+1..-1])
  end
  result << arr if arr.inject(:+) == 0
  result.uniq
end
def find_子集(arr)
如果arr.empty返回arr?
结果=(0…arr.length)|
查找_子集(arr[0…i]+arr[i+1..-1])
结束

结果这里是零和的直接递归解:

def find_subsets(arr)
  return arr if arr.empty?
  result = (0...arr.length).flat_map do |i|
     find_subsets(arr[0...i] + arr[i+1..-1])
  end
  result << arr if arr.inject(:+) == 0
  result.uniq
end
def find_子集(arr)
如果arr.empty返回arr?
结果=(0…arr.length)|
查找_子集(arr[0…i]+arr[i+1..-1])
结束

结果是那些
-=
应该是
=?我刚刚更改了代码以反映和!=它没有出错,但对输出没有影响。我最初尝试使用!=并得到一个错误,发现-=似乎具有相同的功能。那些
-=
应该是
=?我刚刚更改了代码以反映和!=它没有出错,但对输出没有影响。我最初尝试使用!=得到了一个错误,发现-=似乎具有相同的功能。