我想知道如何在Ruby中使用基于输入数组中的值的所有正值和负值组合来获取数组。顺序无关紧要,但必须适应所有尺寸的输入数组。它必须是灵活的,因此负数可以在输入中,即使我没有在下面的例子中包含它们。
例如:
输入:
a = [1,2,3,4]
输出:
b = [[1,2,3,4],[1,2,3,-4],[1,2,-3,-4],[-1,2,-3,-4]...[1,-2,3,-4],[1,-2,-3,-4],[-1,-2,-3,-4],[-1,-2,-3,4],[-1,-2,3,4],[-1,2,3,4]]
非常感谢您的帮助!
答案 0 :(得分:3)
当您迭代正面和负面时,您会注意到,应用否定性的模式与您在二进制计数时用于递增位的模式相同。这是因为数组中的每个索引都可以具有两个值中的一个(正数或负数),就像二进制数中的每个位可以具有两个值(0或1)中的一个一样。因此,简单的解决方案是将0和1映射为正和负。然后我们可以只进行正常的Ruby迭代,并检查元素的相应索引位。
a = [1,2,3,4] # => [1, 2, 3, 4]
signed = [a, a.map(&:-@)] # => [[1, 2, 3, 4], [-1, -2, -3, -4]]
(0...2**a.size).each do |n| # => 0...16
p Array.new(a.size) { |i| signed[n[i]][i] } # => [1, 2, 3, 4], [-1, 2, 3, 4], [1, -2, 3, 4], [-1, -2, 3, 4], [1, 2, -3, 4], [-1, 2, -3, 4], [1, -2, -3, 4], [-1, -2, -3, 4], [1, 2, 3, -4], [-1, 2, 3, -4], [1, -2, 3, -4], [-1, -2, 3, -4], [1, 2, -3, -4], [-1, 2, -3, -4], [1, -2, -3, -4], [-1, -2, -3, -4]
end # => 0...16
# >> [1, 2, 3, 4]
# >> [-1, 2, 3, 4]
# >> [1, -2, 3, 4]
# >> [-1, -2, 3, 4]
# >> [1, 2, -3, 4]
# >> [-1, 2, -3, 4]
# >> [1, -2, -3, 4]
# >> [-1, -2, -3, 4]
# >> [1, 2, 3, -4]
# >> [-1, 2, 3, -4]
# >> [1, -2, 3, -4]
# >> [-1, -2, 3, -4]
# >> [1, 2, -3, -4]
# >> [-1, 2, -3, -4]
# >> [1, -2, -3, -4]
# >> [-1, -2, -3, -4]
答案 1 :(得分:2)
另一种方式(@ JoshuaCheek答案的变体):
a = [1,2,3,4]
n = a.size
(2**n).times.map { |i|
("%0#{n}b" % i).split('').zip(a).map { |b,e| (b=='1') ? e : -e } }
#=> [[-1, -2, -3, -4], [-1, -2, -3, 4], [-1, -2, 3, -4], [-1, -2, 3, 4],
# [-1, 2, -3, -4], [-1, 2, -3, 4], [-1, 2, 3, -4], [-1, 2, 3, 4],
# [ 1, -2, -3, -4], [ 1, -2, -3, 4], [ 1, -2, 3, -4], [ 1, -2, 3, 4],
# [ 1, 2, -3, -4], [ 1, 2, -3, 4], [ 1, 2, 3, -4], [ 1, 2, 3, 4]]
答案 2 :(得分:2)
虽然其他答案已经涉及Array
方法,但Array#repeated_permutation
才是真正需要的:
[ 1, -1 ].repeated_permutation( 4 ).map { |p| [ 1, 2, 3, 4 ].zip( p ).map { |u, v| u * v } }
答案 3 :(得分:0)
嗯,Ruby方便地在combination
对象上包含Array
方法,但首先需要为原始数组中的数字创建相反的值:
a = [1,2,3,4]
b = a.map(&:-@)
然后,您希望将两个数组连接成一个数组:
c = a + b
最后,您可以调用包含所有正值和负值的数组的combination
方法:
c.combination(4).to_a # => [[1,2,3,4], [1,2,3,-1], ...]
以下是combination method的文档。
更新:我喜欢Boris Stitnicky提出的建议。以下是对此的修改:
a = [1,2,3,4]
def sign_permutations(arr)
[1, -1].repeated_permutation(arr.length).map do |signs|
signs.map.with_index do |sign, index|
arr[index] * sign
end
end
end
puts sign_permutations(a).inspect
答案 4 :(得分:0)
array=[]
[1,-1].each do |a|
[2,-2].each do |b|
[3,-3].each do |c|
[4,-4].each do |d|
array<<[a,b,c,d]
end
end
end
end
一旦我把手放在键盘上,我就会详细说明一个更完整的问题
<强>更新强>: 很多好的答案,这里是递归方式:
@input = [1,2,3,4] # or whatever
@output = []
def pos_neg(ind,in_array)
a=@input[ind]
[a,-a].each do |b|
arr=in_array.dup
arr[ind]=b
if @input.size > ind+1
pos_neg(ind+1,arr)
else
@output << arr
end
end
end
然后,你运行:
pos_neg(0,[])
@output
[[1, 2, 3, 4],
[1, 2, 3, -4],
[1, 2, -3, 4],
[1, 2, -3, -4],
[1, -2, 3, 4],
[1, -2, 3, -4],
[1, -2, -3, 4],
[1, -2, -3, -4],
[-1, 2, 3, 4],
[-1, 2, 3, -4],
[-1, 2, -3, 4],
[-1, 2, -3, -4],
[-1, -2, 3, 4],
[-1, -2, 3, -4],
[-1, -2, -3, 4],
[-1, -2, -3, -4]]
答案 5 :(得分:0)
以下方法有效 - 基本上,我们在二进制0000到1111(或十进制0到15)之间使用位掩码来决定哪些数字应该是负数(0是正数,1是负数) - 更多细节在评论中以下代码:
require 'pp'
result = []
# consider binary number mask from binary 0000 to 1111,
# where each digit if 0 uses the positive number, and if 1 uses the negative number
(0..15).each do |mask|
combin = [] # each combination
# Next, loop through the four place values (1,2,4,8)
(0..3).each do |pwr|
pv = 2 ** pwr # each place value
if ((mask & pv) == pv) # if the mask has the bit set at this place value,
combin << -(pwr + 1) # use the negative of the number (pwr + 1 gives 1, 2, 3, 4 nicely)
else # if mask doesn't have the bit set at this place value
combin << (pwr + 1) # use the positive value of the number
end
end
result << combin
end
pp result
# Output:
# [[1, 2, 3, 4],
# [-1, 2, 3, 4],
# [1, -2, 3, 4],
# [-1, -2, 3, 4],
# [1, 2, -3, 4],
# [-1, 2, -3, 4],
# [1, -2, -3, 4],
# [-1, -2, -3, 4],
# [1, 2, 3, -4],
# [-1, 2, 3, -4],
# [1, -2, 3, -4],
# [-1, -2, 3, -4],
# [1, 2, -3, -4],
# [-1, 2, -3, -4],
# [1, -2, -3, -4],
# [-1, -2, -3, -4]]