Ruby 如何使用递归查找和为零的数组的所有子集?(红宝石色)
我对编码和Ruby都是新手。我在业余时间研究这个问题,因为我是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
#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])
结束
结果是那些-=
应该是=代码>?我刚刚更改了代码以反映和!=它没有出错,但对输出没有影响。我最初尝试使用!=并得到一个错误,发现-=似乎具有相同的功能。那些-=
应该是=代码>?我刚刚更改了代码以反映和!=它没有出错,但对输出没有影响。我最初尝试使用!=得到了一个错误,发现-=似乎具有相同的功能。