【问题标题】:ruby - How can I generate an array of every combination of letters and numbers of a given length?ruby - 如何生成给定长度的字母和数字的每个组合的数组?
【发布时间】:2016-12-22 00:14:52
【问题描述】:

我正在尝试创建一个脚本,该脚本生成一个数组,该数组列出了用户提供的特定长度的字母和数字(以及最终符号)的每个重复排列。例如:

User input: 4
Output:
a
b
...
zzzy
zzzz

我尝试了多种方法来实现这一点,并通过嵌套的 .each 循环在包含 a-z 和 0-9 的数组上获得了我正在寻找的效果。

alphanum.each do |s|
  output << s
  alphanum.each do |t|
    output << s + t
    alphanum.each do |r|
      output << s + t + r
      alphanum.each do |i|
        output << s + t + r + i
      end
    end
  end
end

但是,这不能由输入来确定,而且对我来说似乎不是有效的或 ruby​​esque 的。我尝试了各种其他循环组合,但似乎都没有。一个例子:

# User input
puts "Max length: "
input = gets.chomp
length = input.to_i

# Iterates over the array
length.times do
  modded.each do |s|
    alphanum.each do |t|
      r = s + t
      puts r # To test output
      modded << r
    end
  end
end

这会输出 aaaaaaaaaaaaa1 之类的东西,以及其他长度输入仅为 1 或 2 的废话。我该怎么做?

【问题讨论】:

  • @Rilcon42 我认为这是一个很好的考虑方法,但你也必须考虑到可能有重复的字符,这会让事情变得有点复杂
  • 没错,我没有注意到他想要那些。也许生成一个组合然后该组合的所有可能排列?上帝,这将是内存密集型的......
  • @Rilcon42 不必如此,除非您打算将数组存储在内存中。 Ruby 的方式是定义一个按需发出值的枚举器,而不是将它们全部存储在内存中。事实上,Ruby 已经提供了一个返回这个枚举器的函数。
  • 你说你想要“每一个组合......”,但你的例子表明你想要每一个 repeated 组合或可能每一个 repeated permutaton。 (注意到目前为止发布的两个答案对问题的解释不同。)给定a = [1,2,3],大小为2,组合(转换为字符串后)为["12", "13", "23"],重复组合为["11", "12", "13", "22", "23", "33"],排列为["12", "13", "21", "23", "31", "32"],重复排列为["11", "12", "13", "21", "22", "23", "31", "32", "33"]。请编辑澄清。

标签: arrays ruby


【解决方案1】:
alphanum = [*?a..?z, *?0..?9]
length.times.flat_map { |l|
  alphanum.repeated_permutation(l + 1).map(&:join)
}

请注意,length &gt; 3 将为您提供很多的结果。

编辑:正如 meagar 所说,这是非常占用内存的。基于枚举器的答案(不那么漂亮,但不会扼杀你的记忆):

e = Enumerator.new do |y|
  length.times do |l|
    alphanum.repeated_permutation(l + 1).each do |p|
      y << p.join
    end
  end
end

【讨论】:

  • 这很好用,但是有没有办法只计算一定长度的排列?前任。我已经有长度为 1-6 的排列,但需要通过 8,我只能得到长度为 7 和 8 的排列吗?
  • @HunterRobertson:用length.times代替7.upto(8)
【解决方案2】:
def fixed_size_repeated_combos(n)
  [*0..9, *'a'..'z'].repeated_combination(n).map(&:join)
end

def all_size_repeated_combos(n)
  (1..n).flat_map { |i| fixed_size_repeated_combos(i) }
end

all_size_repeated_combos(2)
  #=> ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
  #    "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
  #    "s", "t", "u", "v", "w", "x", "y", "z", "00", "01", "02", "03", "04",
  #    "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
  #    ...
  #    "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "2g", "2h", "2i",
  #    ...
  #    "ww", "wx", "wy", "wz", "xx", "xy", "xz", "yy", "yz", "zz"] 

all_size_repeated_combos(1).size #=> 36 
all_size_repeated_combos(2).size #=> 702 
all_size_repeated_combos(3).size #=> 9138 
all_size_repeated_combos(4).size #=> 91389 
all_size_repeated_combos(5).size #=> 749397 

Array#repeated_combination

对于“permuations”,而不是“combinations”,将“combos”替换为“permbos”,将“combination”替换为“permutation”。

【讨论】:

  • 这里的数学似乎没有加起来。每组的大小应为36^n。看来您的解决方案正在做一些有趣的事情并省略了一些应该包括的结果(至少在我阅读问题时)。例如,在1z 之后,您的解决方案循环到22,并且字符串2021 丢失。在gg 之后,您的解决方案会直接跳转到hh,并且缺少字符串h0..hg
  • 抱歉,36^n 假设您只想要长度为 n 的结果。正确的集合大小应该是 (36^n) + (36^(n-1)) + (36^(n-2)) + ... + 36,这仍然比您输出的结果多得多。 N = 5 的正确术语数是 62,193,780,而不是 749,397。
  • @meagar,您将计算排列和重复排列。你会看到我正在计算重复的组合。请参阅我对这个问题的评论。
  • 你说得对,我认为排列是他们所追求的。
猜你喜欢
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 2015-03-17
  • 2011-02-19
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
相关资源
最近更新 更多