【问题标题】:Algorithm for condensing/consolidating number combinations浓缩/合并数字组合的算法
【发布时间】:2012-06-05 04:29:05
【问题描述】:

使用赛马投注场景,假设我有多个单独的投注来预测比赛的前 4 名完赛者(superfecta)。

投注如下……

1/2/3/4  
1/2/3/5  
1/2/4/3  
1/2/4/5  
1/2/5/3  
1/2/5/4 

我想做的是尽可能地组合或压缩这些单独的组合。上面的赌注,都可以浓缩成1条线……

1/2/3,4,5/3,4,5

但如果我从列表中删除最后一个赌注:1/2/5/4 ...

1/2/3/4  
1/2/3/5  
1/2/4/3  
1/2/4/5  
1/2/5/3  

浓缩的赌注现在必须是 2 行:

1/2/3,4/3,4,5  
1/2/5/3  

算法会是什么样子?

【问题讨论】:

  • 压缩线中的每个插槽是否在单独的投注中获得该插槽中出现的数字的并集?在您的示例中,浓缩集完全代表单独的投注,但通常它也代表不在原始集中的投注。这个可以吗?还是您打算制定其他规则?
  • 我编辑了我的问题,希望能更好地解释规则并回答您的评论。
  • 这很好地说明了问题。这有点像集合覆盖问题,但不完全是。有趣的问题。

标签: algorithm combinations


【解决方案1】:

我发现用漂亮的图片来思考这种事情是最容易的。我们尝试构建一些图表如何?

第一个例子

1/2/3/4  
1/2/3/5  
1/2/4/3  
1/2/4/5  
1/2/5/3  
1/2/5/4 

...可能看起来像这样,以图表的形式:

从上到下的每条路径(例如1->2->4->3)对应于初始格式中的一行。

如果我们从该图开始,那么(也许)我们可以在该图上运行一个小算法,以您正在寻找的方式简化它。我们将尝试以下方法:

  • 从图表顶部开始,逐级向下移动。 (第一层只包含蓝色节点1。)
  • 对于当前关卡中的每个节点,计算子节点的数量。如果只有一个孩子,则跳过该节点。 (由于蓝色节点1只有一个孩子,我们将跳到绿色节点2。)
  • 对于多个子项中的每一个,构建一个包含该子项及其孙子项的集合。 (红色节点3有一个集合{3,4,5},红色4有一个集合{3,4,5},红色5有一个集合{3,4,5}。)
  • 如果这些集合中的任何一个相同,将关联的子/孙替换为包含子的单个节点,指向包含该集合的孙。 (因为所有三个红色节点都有相同的集合,所以它们都被替换了。)


第二个例子

1/2/3/4  
1/2/3/5  
1/2/4/3  
1/2/4/5  
1/2/5/3 

...可能看起来像这样,以图表的形式:

红色节点34 具有相同的集合(即{3,4,5}),因此它们被替换。红色节点5 与红色节点34 的集合不同,所以我们不用管它。

和以前一样,通过简化树的每条路径代表输出的一行。

(我没有介绍如果在有曾孙时替换子/孙会发生什么。可能你实际上应该从最底行开始,然后向上工作。)

【讨论】:

  • 哇,感谢您抽出时间来说明这一点。这让我走上了正轨。
【解决方案2】:

按 F#

open System
open System.Collections.Generic

let data =
  [|
    "1/2/3/4"
    "1/2/3/5"
    "1/2/4/3"
    "1/2/4/5"
    "1/2/5/3"
    "1/2/5/4"
  |]
let conv (xs:string []) =
  let xs = xs |> Array.map (fun x -> x.Split('/'))
  let len = xs.[0] |> Array.length
  let sa = Array.init len (fun _ -> new SortedSet<string>())
  xs |> Array.iter (fun xa -> xa |> Array.iteri (fun i x -> sa.[i].Add(x) |>ignore))
  String.Join("/", sa |> Array.map (fun x -> if Seq.length x = 1 then Seq.head x else String.Join(",", x |> Seq.toArray)))

let _ = 
  conv data |> printfn "%s"
//result:1/2/3,4,5/3,4,5

  //use 0-3 and 4 element of data
  [|data.[0..3]; data.[4..4] |]
  |> Array.map (fun x -> conv x)
  |> Array.iter (printfn "%s")
(* result:
1/2/3,4/3,4,5
1/2/5/3
*)

【讨论】:

  • 感谢您的回答。我不熟悉这里的编程语言,但我认为这只是将每个位置的唯一数字组合起来并构建一个列表。我附加了我原来的问题,表明你不能这样做。
  • 如果和上一个问题是同一个问题,我误解了问题。但它属于似乎任意的。例如。是 ([1/2/3,4/3,4,5], [1/2/5/3]) 而不是 ([1/2/3/4,5],[1/2] 的原因/4/3,5],[1/2/5/3])?
猜你喜欢
  • 1970-01-01
  • 2012-01-25
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-25
  • 2018-03-15
  • 1970-01-01
相关资源
最近更新 更多