我想生成所有可能的方法来安排一定数量的元素number_of_elements
。现在,我只想打印出可能性upto
的所有可能性。
编辑:说number_of_elements
为3,然后我想要所有可能的方法来安排0
,1
和2
。 数字可以出现0次或多次,订单很重要。所以0
!= 00
!= 01
!= 10
!= 11
。
例如,all_combinations(3,14)应该打印:
0
1
2
00
01
02
10
11
12
20
21
22
000 # updated. I originally put 100 here by mistake.
001
...
我试过了:
def all_combinations(number_of_elements, upto)
0.upto upto do |n|
puts n.to_s(number_of_elements)
end
end
all_combinations(3, 10)
我的想法是获取所有整数,将它们转换为基数number_of_elements
并将该数字解释为可能性。
它几乎可以工作,除了我缺少一些元素。
(这是我上面代码得到的输出):
0
1
2
# 00 missing
# 01 missing
# 02 missing
10
11
12
20
21
22
# 0.. elements missing
100
101
...
任何想法或其他简单的方法来获得这些?
答案 0 :(得分:1)
授予this question。以下是对我答案的略微修改。
class Numeric
def sequence b
s, q = "", self
(q, r = (q - 1).divmod(b)) && s.prepend(r.to_s) until q.zero?
s
end
end
def foo(number_of_elements, upto)
1.upto upto do |n|
puts n.sequence(number_of_elements)
end
end
foo(3, 14)
结果:
0
1
2
00
01
02
10
11
12
20
21
22
000
001
答案 1 :(得分:1)
您可以使用Array#repeated_permuation执行此操作:
def all_combinations(nbr, upto)
(1..nbr).each_with_object([]) do |n, arr|
arr.concat(('0'...nbr.to_s).to_a
.repeated_permutation(n)
.to_a) if arr.size < upto
end.first(upto).each { |e| puts e.join }
end
all_combinations(3, 14)
0
1
2
00
01
02
10
11
12
20
21
22
000
001
如果number_of_elements
很大,这种方法的缺点是可能会向阵列arr
添加大量排列,但不会使用。另一种方法是创建一个枚举器对象,该对象可用于使用Enumerator#next和Enumerator#peek枚举重复的排列,精确枚举upto
个值。我向permutation
here展示了如何做到这一点,并解释了repeated_permutation
如何更容易。
答案 2 :(得分:0)
可能最简单的攻击方法是 - 不幸的是,如果你不熟悉递归 - 使用递归方法。
你想在每个可能的地方尝试每一个可能的数字,基本上。
def all_combinations(s, number_of_elements, upto)
if number_of_elements < 1
puts s
return
end
0.upto upto - 1 do |n|
all_combinations(s + n.to_s, number_of_elements - 1, upto)
end
end
all_combinations("", 3, 10)
前提是,无论你在哪个阶段(s
;想象它是12
),你想要将所有可能的数字附加到它并继续。但是,我们不想永远地去,我们放置的每个数字都会让我们更接近,所以减少number_of_elements
;当number_of_elements
为零时,我们没有别的事可做,所以是时候打印了。
一些问题:
- upto
不知道它有多大。如果你拨打all_combinations("", 3, 500)
,你就会得到格式错误的字符串。
- 如前所述,如果您只是在学习编程,那么递归可能不是潜水的最佳选择。
- 同样地,如果这是用于家庭作业而你没有覆盖递归,这将是一个好的迹象,你要求互联网上的随机人员寻求帮助,这可能不会产生理想的等级
但是,有了这些警告,我认为这是最简单的方法。想到的其他一切都需要手动跟踪位置和最近的输出,这些...... ick 。
答案 3 :(得分:0)
以下是使用repeated_permutations
:
def all_combinations(number_of_elements, upto)
elements = (0...number_of_elements).map(&:to_s)
combinations = (1..1.0/0).lazy.flat_map do |i|
elements.repeated_permutation(i).map do |permutation|
permutation.join
end
end
puts combinations.take(upto).to_a
end
all_combinations(3, 14)
0
1
2
00
01
02
10
11
12
20
21
22
000
001
答案 4 :(得分:0)
这是另一种方法,使用String#to_i和Fixnum#to_s,每个参数base
(默认为10)设置等于“元素数量”:
def all_combinations(n_elements, upto)
s = '10'
upto.times.with_object([]) do |_,arr|
arr << s
candidate = (s.to_i(n_elements)+1).to_s(3)
(candidate = '1'+'0' * s.size) unless candidate[0] == '1'
s = candidate
end.map { |str| str[1..-1] }
end
all_combinations(3, 15)
#=> ["0", "1", "2",
# "00", "01", "02",
# "10", "11", "12",
# "20", "21", "22",
# "000", "001", "002"]