Prolog - 检查第二个列表是否包含第一个列表中的所有偶数

发布于 01-16 16:53 字数 816 浏览 3 评论 0原文

我试图在 Prolog 中编写一条规则,首先检查第二个列表中的所有元素是否都包含在第一个列表中,以及第二个列表中的所有元素是否都是偶数。

因此,例如以下查询:

evenSubList([5, 6, 7, 8], [6, 8]). -> True
evenSubList([5, 6, 7, 8], [6, 7, 8]). -> no
evenSubList([5, 6, 7, 8], X). -> X = [6, 8]
evenSubList([6, 7, 8], [6, 8]). -> True
evenSubList([6, 8], [6, 8]). -> True

当我查询当前代码时,仅当两个列表都只有偶数时它才有效。第一个列表不允许有奇数。我也尝试过使用内置子列表规则,但没有成功。我知道问题出在我的第二个定义中,两个列表中的头部不同,但我不确定我做错了什么。

evenSubList([X | _], [X]) :- % base case gets hit if second list only has one element
    mod(X, 2) =:= 0.

evenSubList([X | Y], [Z | T]) :- % If first element of both lists are different
    evenSubList(Y, [Z]),
    evenSubList(Y, T).

evenSubList([X | Y], [X | Z]) :- % If both heads are the same
    mod(X, 2) =:= 0,
    evenSubList(Y, Z).

I am trying to write a rule in Prolog that will first check if all the elements in the second list are contained in the first and if all the elements in the second list are even.

So, for example the following queries:

evenSubList([5, 6, 7, 8], [6, 8]). -> True
evenSubList([5, 6, 7, 8], [6, 7, 8]). -> no
evenSubList([5, 6, 7, 8], X). -> X = [6, 8]
evenSubList([6, 7, 8], [6, 8]). -> True
evenSubList([6, 8], [6, 8]). -> True

When I query my current code, it only works if both lists have even numbers only. The first list is not allowed to have any odd numbers. I've also tried to use the built-in sublist rule with no luck. I know problem is in my second definition where the head in both lists are different, but I'm not sure what I'm doing wrong.

evenSubList([X | _], [X]) :- % base case gets hit if second list only has one element
    mod(X, 2) =:= 0.

evenSubList([X | Y], [Z | T]) :- % If first element of both lists are different
    evenSubList(Y, [Z]),
    evenSubList(Y, T).

evenSubList([X | Y], [X | Z]) :- % If both heads are the same
    mod(X, 2) =:= 0,
    evenSubList(Y, Z).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情泪▽动烟2025-01-23 16:53:38

你有正确的想法,只是在你的情况下,头不一样,你试图一次做两件事并绊倒自己,因为最终,你将得到一个空列表,并且将返回 false。有一个更简单的解决方案。

您从尾部 Y 开始,然后遍历将其与头 Z 进行比较,但如果到达两个头相同的情况,您将有一个 null 调用,这将导致输出为 no

在第二次递归调用 evenSubList(Y, T) 中,如果 T 短于 Y,则会遇到问题一个空列表。

您想做这样的事情,其中​​第一个列表变小,第二个列表保持相同的大小,并将第一个列表中的每个元素与整个第二个列表进行比较,直到满足其他情况为止,第二个列表不会改变您会知道可以安全地获取第二个列表的尾部。

evenSubList([X], [X]) :- 
    mod(X, 2) =:= 0.

evenSubList([X | Y], [X | Z]) :- 
    mod(X, 2) =:= 0,
    filterevens(Y, Z). 

evenSubList([X | Y], [Z | T]) :- 
    evenSubList(Y, [Z | T]). 

You have the right idea, it's just that your case where the heads aren't the same, you are trying to do two things at a time and tripping over yourself because eventually, you will have a null list and that will return false. There is a much simpler solution.

You start off with the tail, Y, then you traverse compare it to the head Z, but if it gets to the case where both heads are the same, you'll have a null call and that will cause the output to be no.

With your second recursive call, evenSubList(Y, T), again, if T is shorter than Y, you'll have an issue with a null list.

You want to do something like this where first list gets smaller and your second list stays the same size and have each of the elements from the first list get compared to the second list as a whole which does not change until or unless other case is met where you'll know it's safe to take the tail of the second list.

evenSubList([X], [X]) :- 
    mod(X, 2) =:= 0.

evenSubList([X | Y], [X | Z]) :- 
    mod(X, 2) =:= 0,
    filterevens(Y, Z). 

evenSubList([X | Y], [Z | T]) :- 
    evenSubList(Y, [Z | T]). 
节枝2025-01-23 16:53:38

这很简单:

even_contains(LstFull, LstEven) :-
    include(is_even, LstFull, LstEven).

is_even(N) :-
    0 is N mod 2.

swi-prolog 的结果:

?- even_contains([5, 6, 7, 8], [6, 8]).
true.

?- even_contains([5, 6, 7, 8], [6, 7, 8]).
false.

?- even_contains([5, 6, 7, 8], X).
X = [6,8].

?- even_contains([6, 7, 8], [6, 8]).
true.

?- even_contains([6, 8], [6, 8]).
true.

This is simply:

even_contains(LstFull, LstEven) :-
    include(is_even, LstFull, LstEven).

is_even(N) :-
    0 is N mod 2.

Result in swi-prolog:

?- even_contains([5, 6, 7, 8], [6, 8]).
true.

?- even_contains([5, 6, 7, 8], [6, 7, 8]).
false.

?- even_contains([5, 6, 7, 8], X).
X = [6,8].

?- even_contains([6, 7, 8], [6, 8]).
true.

?- even_contains([6, 8], [6, 8]).
true.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文