Prolog:获取包含给定整数的子列表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Prolog:获取包含给定整数的子列表相关的知识,希望对你有一定的参考价值。
我正在尝试通过解决Advent Of Code谜题来学习Prolog,并且最终被困在我认为应该非常简单的任务上。有问题的谜题是this one。该任务要求我找到连接到程序ID 0的所有程序ID(整数)。连接是对称的和可传递的,因此如果来自不同连接组的程序之间存在连接,则给定组中的所有程序都相互连接。
我目前的情况是,我已经将拼图中的整数分类为子列表,每个子列表代表他们所属的组。
例如:[[0, 2], [1, 1], [2, 0, 3, 4], [3, 2, 4], [4, 2, 3, 6], [5, 6], [6, 4, 5]]
我需要获得所有以某种方式连接到0的程序。在这个例子中,除了ID为1的程序之外,这将是所有程序。
因此,我正在寻找的逻辑是设法检查包含0的扩展组和我的递归谓词连接当前正在查看的组中是否存在给定整数的东西。我意识到这种方法可能最终忽略了在递归中早先看到的组的新连接,但这是一个单独的问题。
将程序排序到上面的子列表中并不是问题,所以我从目前的情况中省略了这一部分。
main(R) :-
Groups = [[0, 2], [1, 1], [2, 0, 3, 4], [3, 2, 4], [4, 2, 3, 6], [5, 6], [6, 4, 5]],
connected(Groups, [0], R).
connected([H|T], X, R) :-
member(Y, H), member(Y, X) -> flatten([H|X], X1), connected(T, X1, R) ; R = X.
我得到的结果很简单:[0,2,0]
我期望的结果是:[0,2,0,2,0,3,4,3,2,4,4,2,3,6,5,6,6,4,5]
我已经意识到元素[1,1]
可能会过早地停止递归,所以我尝试将上面的最后一行更改为以下内容:
member(Y, H), member(Y, X) -> flatten([H|X], X1), connected(T, X1, R) ; connected(T, X, R).
然而,这只会导致主(R)。由于某种原因评估为假。同样,如果我只是从组中删除[1,1]
而不更改最后一行,则返回false。
我认为我忽略了一些非常简单的事情,并且会欣赏任何输入。
假设您的组具有适当的结构,您可以保留一个“未访问”组的列表,并在每个递归步骤中采用未访问的项目并添加其仍然未访问的邻居。
即:
main(R) :-
Groups = [[0, 2], [1, 1], [2, 0, 3, 4], [3, 2, 4], [4, 2, 3, 6], [5, 6], [6, 4, 5]],
connected([0], [], Groups, R).
connected([], _, _, []).
connected([P|Tail], Visited, Groups, [P|R]):-
select([P|Ps], Groups, NGroups), % Get the item's neighours
subtract(Ps, [P|Visited], NPs), % subtract from it the visited ones
union(Tail, NPs, NTail), % and add these neighours to the unvisited list
connected(NTail, [P|Visited], NGroups, R).
这将获得一组没有重复的“连接”程序:
?- main(R).
R = [0, 2, 3, 4, 6, 5]
以上是关于Prolog:获取包含给定整数的子列表的主要内容,如果未能解决你的问题,请参考以下文章