使用赛马投注方案,假设我有多个单独的投注来预测比赛的前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/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
算法会是什么样的?
答案 0 :(得分:2)
我发现用漂亮的照片来思考这种事情是最容易的。我们试着建立一些图表怎么样?
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
...可能会以图表形式显示:
红色节点3
和4
具有相同的集合(即{3,4,5}
),因此它们会被替换。红色节点5
与红色节点3
和4
的设置不同,所以我们不管它。
和以前一样,通过简化树的每条路径代表输出的一行。
(我还没有说明如果你有曾孙子后代替孩子/孙子会发生什么。可能你应该从最底层开始向上工作。)
答案 1 :(得分:0)
通过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
*)