我可以从这个哈希中获得多少种可能的组合?

时间:2014-04-11 13:52:33

标签: ruby algorithm big-o

这是一个组合:

OPTIONS = {
  :tense =>     [:present,    :past,       :future],
  :person =>    [:third,      :first,      :second],
  :plurality => [:singular,   :plural],
  :diathesis => [:active,     :passive],
  :mood =>      [:indicative, :imperative, :subjunctive],
  :aspect =>    [:habitual,   :perfective, :habitual, :progressive, :perfect, :prospective]  
}

只有一个规则,一个键可以使用一个值

这意味着这些对可能

1. :present, :third, :singular, :active, :indicative, :habitual
2. :present, :third
3. :present, :third, :indicative, :habitual 
4. ... etc

然而这些不是:

1. :present, :past, :future
2. :first, :third, :present
3. ... etc

如果有公式,请分享

感谢所有答案。

2 个答案:

答案 0 :(得分:4)

如果我正确理解了这个问题,公式是:

(|A1|+1)*(|A2|+1)*...*(|An|+1) - 1

Ai代表集合#i(例如时态,人物),而|Ai|代表集合Ai的大小。 这个想法是每个N大小的集合都有N + 1个选项 - N个值中的一个,或者这个集合中没有值。这些组合是唯一的,因为任何两种组合在至少一组的代表中不同。

最后的减号用于消除空组合。 根据您提供的数据,结果为4031.

答案 1 :(得分:2)

要获取所有组合的列表,您可以执行以下操作:

OPTIONS.values.map{ |v| v + [nil]}.inject(&:product).map(&:flatten).map(&:compact).uniq

它的作用是:

  • nil添加到每个列表(未选择的选项)
  • 创建每个列表之一的每个组合
  • 上面创建了列表列表,因此我们将它们展平为列表
  • 从任何组合中删除任何nil

样本组合:

[:future, :first, :active, :perfect] 

以上内容将包含空组合([]),但如果您只想包含两个或更多元素的组合,则可以添加.select { |cmb| cmb.length > 1 }

现在你可以算一下:

OPTIONS.values.map{ |v| v + [nil]}.inject(&:product).map(&:flatten).uniq.
  map(&:compact).count
# => 3456
OPTIONS.values.map{ |v| v + [nil]}.inject(&:product).map(&:flatten).uniq.
  map(&:compact).select { |cmb| cmb.length > 1 }.count
# => 3437

<强>更新
@EyalSchneider建议我将他的公式添加到我的答案中,以便更完整:

(|A1|+1)*(|A2|+1)*...*(|An|+1) - 1

基本上它意味着product中的组合数量是所有相关数组的所有大小的乘积:

OPTIONS.values.map { |x| x.length + 1 }.inject(:*) - 1
# => 4031