只有一个问题:你想做什么?
我只是找不到这个功能的实际用途。我认为你做了一些奇怪的事情。看来你刚刚从 O(NM^2) 提高到 O(NM*logM) 但还是很糟糕。
编辑:
当我综合什么是目标时,您似乎正在尝试使用蒙特卡洛方法来确定球队在英超联赛中“完成位置”的概率。但我仍然不确定。您可以确定最可能的位置[1,1,2] -> 1 或作为某种平均值 1.33 的小数 - 例如,最后一个可以比其他人更轻松地实现。
在函数式编程语言中,数据结构比过程或 OO 语言更重要。他们更多的是关于工作流程。你会做这个,然后做这个,然后做......在像 Erlang 这样的函数式语言中,你应该以一种方式思考,我有这个输入,我想要那个输出。我可以从这个和这个等中确定所需的输出。可能没有必要像您过去在程序方法中那样列出事物。
在程序方法中,您习惯于使用数组进行存储,并具有恒定的随机访问。清单不是那样的东西。 Erlang 中没有可以编写的数组(即使是实际上是平衡树的数组模块)。您可以将元组或二进制用于只读数组,但不能进行读写。我可以写很多关于根本不存在具有恒定访问时间的数据结构(从 RAM,通过过程语言中的数组到 HASH 映射)但是这里没有足够的空间来详细解释它(来自 RAM 技术,通过 L{1,2,3} 个 CPU 缓存,当 key 数量增加和 key HASH 计算依赖于 key 长度时,必然增加 HASH 长度。
列表是具有 O(N) 随机访问时间的数据结构。这是存储数据的最佳结构,您希望以与存储在列表中相同的顺序一一获取。对于小N,当对应的常数很小时,它可以是对小N进行随机访问的结构。例如,当 N 是您的问题中的团队数(20)时,它可能比 O(logN) 访问某种树更快。但是你必须注意你的常数有多大。
算法的一个常见组件是键值查找。在某些情况下,可以使用数组作为过程世界中的支持数据结构。键必须是整数,可能键的空间不能稀疏等。除了这里的 N 非常小之外,List 不能很好地用作此目的的替代品。我了解到编写功能代码的最佳方法是避免在不必要的地方进行键值查找。它经常需要重新安排工作流程或重构数据结构等等。有时它看起来像是像手套一样翻转问题解决方案。
如果我忽略了您的概率模型是错误的。根据您提供的信息,您的模型团队的赛季积分似乎是独立的随机事件,这当然不是真的。不可能所有球队都获得高分,例如 82 分,仅仅因为所有球队在一个赛季中获得的分数都有一定的限制。所以暂时忘记了这个。然后我将模拟一个“路径” - 赛季并以[{78,'Liverpool'}, {81,'Man Utd'}, ...] 的形式获取结果,然后我可以使用 lists:sort 对其进行排序,而不会丢失哪个团队在哪里的信息。我将使用按路径迭代收集的结果。对于每条路径,我将遍历排序的模拟结果并将其收集到字典中,其中团队是关键(来自 atom 和常量存储的常量和非常便宜的哈希计算,因为键集是固定的,有可能使用元组/记录,但似乎过早优化)。值可以是大小为 20 的元组,元组中的位置是最终位置,值是它的计数。
类似:
% Process simulation results.
% Results = [[{Points, Team}]]
process(Results) ->
lists:foldl(fun process_path/2,
dict:from_list([{Team, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} ||
Team <- ['Liverpool', 'Man Utd', ...]]),
Results).
% process simulation path result
process_path(R, D) ->
process_path(lists:reverse(lists:sort(R)), D, 1).
process_path([], _, D) -> D;
process_path([{_, Team}|R], D, Pos) ->
process_path(R, update_team(Team, Pos, D), Pos + 1).
% update team position count in dictionary
update_team(Team, Pos, D) ->
dict:update(Team, fun(T) -> add_count(T, Pos) end, D).
% Add final position Pos to tuple T of counts
add_count(T, P) -> setelement(P, T, element(P, T) + 1).
请注意,没有什么像 lists:index_of 或 lists:nth 函数。对于少数 M 个团队,产生的复杂度看起来像 O(NM) 或 O(NMlogM),但真正的复杂度是 O(NM^2) O(M) setelement/3 在add_count/2。对于更大的 M,您应该将 add_count/2 更改为更合理的值。