给定五个元素的数组ary
:
ary = [true, true, true, false, false]
我想考虑最后一个位置(索引ary
)绕到第一个位置(index {false
,其中两个4
值是非连续的0
的所有排列{1}}):
[true, false, true, false, true] #=> Selected
[true, true, false, true, false] #=> Selected
[false, true, true, true, false] #=> Rejected
我认为答案可能归结为select
和each_with_index
方法。我不确定如何使用逻辑表达式关联数组中的元素。
答案 0 :(得分:3)
这种递归方法直接生成排列,而不是生成大量排列并丢弃那些不符合规范的排列。
<强>代码强>
def all_perms(arr_size, nbr_false)
return nil if nbr_false > arr_size/2
return [true]*arr_size if nbr_false.zero?
recurse(arr_size, nbr_false, true)
end
def recurse(arr_size, nbr_false, full_arr)
last_first = arr_size + 1 - 2*nbr_false
(0..last_first).each_with_object([]) do |i,a|
pre = [true]*i << false
case nbr_false
when 1
a << pre + [true]*(arr_size-pre.size)
else
pre << true
sub_arr_size = arr_size - pre.size - (i.zero? && full_arr ? 1 : 0)
post = [true]*(arr_size-pre.size-sub_arr_size)
recurse(sub_arr_size, nbr_false-1, false).each { |aa| a << pre + aa + post }
end
end
end
<强>实施例强>
arr_size = 5
nbr_false = 2
b = all_perms(arr_size, nbr_false)
#=> [[false, true, false, true, true],
# [false, true, true, false, true],
# [true, false, true, false, true],
# [true, false, true, true, false],
# [true, true, false, true, false]]
b == b.uniq
#=> true
b.any? { |a| a.each_cons(2).any? { |x,y| x == false && y == false} }
#=> false
b.any? { |a| a.first == false && a.last == false }
#=> false
arr_size = 8
nbr_false = 3
b = all_perms(arr_size, nbr_false)
#=> [[false, true, false, true, false, true, true, true],
# [false, true, false, true, true, false, true, true],
# [false, true, false, true, true, true, false, true],
# [false, true, true, false, true, false, true, true],
# [false, true, true, false, true, true, false, true],
# [false, true, true, true, false, true, false, true],
# [true, false, true, false, true, false, true, true],
# [true, false, true, false, true, true, false, true],
# [true, false, true, false, true, true, true, false],
# [true, false, true, true, false, true, false, true],
# [true, false, true, true, false, true, true, false],
# [true, false, true, true, true, false, true, false],
# [true, true, false, true, false, true, false, true],
# [true, true, false, true, false, true, true, false],
# [true, true, false, true, true, false, true, false],
# [true, true, true, false, true, false, true, false]]
b == b.uniq
#=> true
b.any? { |a| a.each_cons(2).any? { |x,y| x == false && y == false} }
#=> false
b.any? { |a| a.first == false && a.last == false }
#=> false
备注强>
false
元素的给定大小的所有数组,有效排列是相同的。因此,我将all_perms
的参数设置为所需数组的大小以及要包含的false
元素的数量(其他元素都是true
)。recurse
的第三个参数full_arr
是一个布尔值,当true
从recurse
调用但等于all_perms
时等于false
从recurse
调用recurse
时。这对于避免以false
开始和结束的排列(要避免的循环条件)是必要的。当full_arr
为true
和i #=> 0
时,正在构造的子数组的最后一个元素必须为true
。在所有其他情况下,它可能是true
或false
。 i
是指正在构造的第一个false
所在的子数组的索引。例如,如果arr_size #=> 4
,nbr_false #=> 2
和full_arr #=> false
,则第一个i
的索引false
可以是0
或{{1} }。它不能是1
,因为这需要最后两个元素2
。 答案 1 :(得分:1)
一个这样的数组的明显例子是:
[true,false,true,false,true]
如果您使用中间false
切换一个true
,则该数组将无效。
如果您使用左侧或右侧false
切换一个true
,则左侧或右侧会显示相同的阵列rotated。
因此,要获得所有可能的数组,您只需要:
base_array = [true,false,true,false,true]
Array.new(5){ |i| base_array.rotate(i) }
输出:
[[true, false, true, false, true],
[false, true, false, true, true],
[true, false, true, true, false],
[false, true, true, false, true],
[true, true, false, true, false]]
强力解决方案将创建ary
的每个唯一排列,并检查没有连续元素都是错误的。为了考虑换行,第一个元素被附加到数组中:
ary = [true, true, true, false, false]
ary.permutation.to_a.uniq.select do |a|
(a + [a.first]).each_cons(2).all? { |x, y| x || y }
end
如果你想获得幻想,你可以写:
ary = [true, true, true, false, false]
n = ary.size
ary.permutation.to_a.uniq.select do |a|
a.cycle.take(n+1).each_cons(2).all?(&:any?)
end
答案 2 :(得分:0)
快速而脏的方法可能是扩展数组以考虑包装:
array = [ true, true, true, false, false ]
array.permutation.to_a.uniq.map do |set|
[ set[-1] ] + set + [ set[0 ] ]
end.select do |set|
set.chunk_while { |b,a| b == a }.all? do |chunk|
chunk[0] == true or chunk.length == 1
end
end.map do |set|
set[1, set.length - 2]
end
这会产生:
# => [
# [true, true, false, true, false],
# [true, false, true, true, false],
# [true, false, true, false, true],
# [false, true, true, false, true],
# [false, true, false, true, true]]
答案 3 :(得分:0)
没有任何明智的考虑,一种方法是:
ary.permutation
.to_a.uniq
.reject do
|a|
i, j = a.each_index.select{|i| a[i] == false}
(i + 1) == j || j - 4 == i
end