【问题标题】:Generate all way of arranging a given number of elements生成排列给定数量元素的所有方式
【发布时间】:2014-07-06 18:21:24
【问题描述】:

我想生成所有可能的方式来排列一定数量的元素number_of_elements。现在,我只想打印所有可能性,直到可能性 upto

编辑:假设number_of_elements 是3,那么我想要所有可能的排列方式012一个数字可以出现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
...

有什么想法或其他简单的方法来获得这些吗?

【问题讨论】:

  • 什么不清楚?我很乐意解释。
  • 10 的组合在什么意义上与01 不同?
  • 我想要所有可能的方式来排列这 3 个字符。一个角色可以出现多次。所以00不同于01,后者不同于10,后者不同于11。这种列举可能性的方式也许有一个词……
  • 你的意思是你想要排列?如果是这样,你为什么要写组合?
  • 可以,一个元素可以出现多次。

标签: ruby combinations


【解决方案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#nextEnumerator#peek 的重复排列,精确枚举upto 值。我向permutation here 展示了如何做到这一点,并解释了repeated_permutation 如何更容易。

【讨论】:

  • 不错的解决方案。我会保留@sawa 的答案,因为我认为它更简洁一些。
【解决方案2】:

这是另一种方法,使用String#to_iFixnum#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"]

【讨论】:

    【解决方案3】:

    这是使用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】:

      授予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
      

      【讨论】:

        【解决方案5】:

        可能最简洁的解决方法是——不幸的是,如果你不精通递归——使用递归方法。

        基本上,您想在每个可能的地方尝试每个可能的数字。

        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

        【讨论】:

        • 如果number_of_elements 是3,我只想要0, 1, and 2 的。也许我不够清楚。 number_of_elements 不是我的序列长度。另外,我总是想要各种大小的序列。在我的问题中,我已经展示了输出应该是什么样的(参见For example, all_combinations(3, 14) should print)。你的开头是 001, 002, 003, 004...
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-13
        • 1970-01-01
        • 2018-05-21
        • 2014-03-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多