如何找到列表的子列表,其长度不大于列表长度的三分之一,且其元素的总和最大

时间:2019-01-25 10:53:03

标签: prolog

如何找到长度不大于列表长度的三分之一且其元素之和在Prolog中最大的列表的子列表?

1 个答案:

答案 0 :(得分:0)

由于这里没有足够的问题要回答,因此这里有一些解决此类Prolog问题的一般建议。

您可以使用length/2和未绑定的列表参数来创建指定长度的列表,例如:

?- length(X, 3).
X = [_3192, _3198, _3204].

这在尝试回答涉及列表的问题时通常很有用。您可以使用列表的长度,然后再次使用length/2来构建结果列表。

select/3也是回答此类问题的有用谓语,因为它可用于从列表中选择项目。例如,如果我想从列表中选择两个项目,则可以执行以下操作:

picktwo(L, [X,Y]) :- select(X, L, L0), select(Y, L0, _).

在这里,我将只返回这两个项目,而忽略列表的其余部分,这些位置现在位于我现在_的位置。

?- picktwo([7,18,3,4,19], X).
X = [7, 18] ;
X = [7, 3] ;
X = [7, 4] ;
X = [7, 19] ;
X = [18, 7] ;
X = [18, 3] ;
X = [18, 4] ;
X = [18, 19] ;
X = [3, 7] ;
X = [3, 18] ;
X = [3, 4] ;
X = [3, 19] ;
X = [4, 7] ;
X = [4, 18] .

(像我这样的DCG粉丝可能会因为这种替代实现而感到开心:phrase((select(X), select(Y)), [7,18,3,4,19], _).

有一个内置的求和列表,称为sumlist/2

通常可以通过要求Prolog找到比所有其他解决方案都更大的解决方案,以一种非常漂亮但效率极低的方式解决问题。这样的代码通常看起来像这样:

solve(Solution) :- 
   find_solution(Solution), 
   \+ (find_solution(Solution2), Solution2 > Solution1).

在这里您申明地说解决方案是最好的,因为没有其他解决方案会更好。 Prolog当然必须进行组合才能找到最佳解决方案,因此,这肯定会将O(N log N)搜索转换为O(N ^ 2)搜索,但是对于小数据来说还是可以的套。这是查找最大对值的示例:

sumpairs(List, X, Y, Sum) :- 
    select(X, List, L0), select(Y, L0, _), Sum is X + Y.

largest(List, X, Y) :- 
    sumpairs(List, X, Y, Sum), 
    \+ (sumpairs(List, _, _, ABSum), ABSum > Sum).

这将产生:

?- largest([7,18,3,4,19], X, Y).
X = 18,
Y = 19 ;
X = 19,
Y = 18 ;
false.

因此您可以看到它效率低下,实际上可以通过排列两次找到相同的答案,但是您可能想出了几种方法来防止这种情况的发生。

这盒零件可能足以让您自己找到问题的答案,祝您好运!