我想找到从[2,3,4,5,6,7,8]中取出3,4或5个数字的所有排列,允许重复,这样它们的总和就是16.所以[8, 5,3],[8,3,5]和[4,3,3,3,3]是有效的排列。还应删除循环排列,因此[3,3,3,3,4]也不会添加到答案中。 我可以在Ruby中执行此操作而不允许这样的重复:
DataFrame DF = sqlContext
.read()
.format("csv")
.option("delimiter", ";")
.option("header", "true")
//mv .option("inferschema", "true")
.load("file:///home/2.csv");
query = "select firstname, lastname, city from mytable"
DataFrame letsgo = sqlContext.sql(query);
letsgo.write().mode(SaveMode.Append).saveAsTable("mytable");
我怎么能允许重复以包括[3,3,3,3,4]?
答案 0 :(得分:5)
对于所有排列,包括重复,可以使用Array#repeated_permutation
:
d = [2,3,4,5,6,7,8]
number_of_divisions = [3,4,5]
number_of_divisions.flat_map do |n|
d.repeated_permutation(n).reject do |p| # no need `to_a`
p.inject(:+) != 16
end
end
或者更好的Array#repeated_combination
:
number_of_divisions.flat_map do |n|
d.repeated_combination(n).reject do |p| # no need `to_a`
p.inject(:+) != 16
end
end
答案 1 :(得分:0)
重复的组合比重复的排列少得多,所以让我们找到与给定值相加的重复组合,然后对每个组合进行置换。此外,通过在计算的几个步骤中的每一步应用uniq
,我们可以显着减少所考虑的重复组合和排列的数量。
<强>代码强>
require 'set'
def rep_perms_for_all(arr, n_arr, tot)
n_arr.flat_map { |n| rep_perms_for_1(arr, n, tot) }
end
def rep_perms_for_1(arr, n, tot)
rep_combs_to_rep_perms(rep_combs_for_1(arr, n, tot)).uniq
end
def rep_combs_for_1(arr, n, tot)
arr.repeated_combination(n).uniq.select { |c| c.sum == tot }
end
def rep_combs_to_rep_perms(combs)
combs.flat_map { |c| comb_to_perms(c) }.uniq
end
def comb_to_perms(comb)
comb.permutation(comb.size).uniq.uniq do |p|
p.size.times.with_object(Set.new) { |i,s| s << p.rotate(i) }
end
end
<强>实施例强>
rep_perms_for_all([2,3,4,5], [3], 12)
#=> [[2, 5, 5], [3, 4, 5], [3, 5, 4], [4, 4, 4]]
rep_perms_for_all([2,3,4,5,6,7,8], [3,4,5], 16).size
#=> 93
rep_perms_for_all([2,3,4,5,6,7,8], [3,4,5], 16)
#=> [[2, 6, 8], [2, 8, 6], [2, 7, 7], [3, 5, 8], [3, 8, 5], [3, 6, 7],
# [3, 7, 6], [4, 4, 8], [4, 5, 7], [4, 7, 5], [4, 6, 6], [5, 5, 6],
# [2, 2, 4, 8], [2, 2, 8, 4], [2, 4, 2, 8], [2, 2, 5, 7], [2, 2, 7, 5],
# [2, 5, 2, 7], [2, 2, 6, 6], [2, 6, 2, 6], [2, 3, 3, 8], [2, 3, 8, 3],
# ...
# [3, 3, 3, 7], [3, 3, 4, 6], [3, 3, 6, 4], [3, 4, 3, 6], [3, 3, 5, 5],
# [3, 5, 3, 5], [3, 4, 4, 5], [3, 4, 5, 4], [3, 5, 4, 4], [4, 4, 4, 4],
# ...
# [2, 2, 4, 5, 3], [2, 2, 5, 3, 4], [2, 2, 5, 4, 3], [2, 3, 2, 4, 5],
# [2, 3, 2, 5, 4], [2, 3, 4, 2, 5], [2, 3, 5, 2, 4], [2, 4, 2, 5, 3],
# ...
# [2, 5, 3, 3, 3], [2, 3, 3, 4, 4], [2, 3, 4, 3, 4], [2, 3, 4, 4, 3],
# [2, 4, 3, 3, 4], [2, 4, 3, 4, 3], [2, 4, 4, 3, 3], [3, 3, 3, 3, 4]]
<强>解释强>
rep_combs_for_1
使用方法Enumerable#sum,它在Ruby v2.4中首次亮相。对于早期版本,请使用c.reduce(:0) == tot
。
在comb_to_perms
中,第一个uniq
只会删除重复项。带有块的第二个uniq
除去了可以通过旋转任何其他p.size
元素获得的p-1
元素(数组)中的所有元素。例如,
p = [1,2,3]
p.size.times.with_object(Set.new) { |i,s| s << p.rotate(i) }
#=> #<Set: {[1, 2, 3], [2, 3, 1], [3, 1, 2]}>