prolog - 使用 Prolog 查找列表的回文:- Ivan Btrako 的练习 3.5“人工智能的 Prolog 编程”
问题描述
在过去的 3 年里,我一直在用 java 编程,而我刚刚开始学习 Prolog。我下载了 SWI-Prolog 来运行我的代码并进行跟踪,但我在这个特定问题上遇到了麻烦。
/*concatinates 2 Lists together*/
conc([],L,L).
conc([X|T],L2,[X|T1]):-
conc(T,L2,T1).
/*Finds the reverse a List*/
reverse([],[]).
reverse([H|T],ReversedList):-
reverse(T,Reverse),
conc(Reverse,[H],ReversedList).
palindrome(L):-
reverse(L,L1),
L is L1.
例如,如果我输入
palindrome([m,a,d,a,m]).
L 是 [m,a,d,a,m] & L1 应该是从反向谓词返回的 [m,a,d,a,m]。
L = L1
并且输出应该是真的。但是打印了一个我不明白的错误
ERROR: Type error: `[]' expected, found `[m,a,d,a,m]' (a list) ("x" must hold one character)
ERROR: In:
ERROR: [9] [m,a|...]is[m,a|...]
ERROR: [8] palindrome([m,a|...]) at c:/users/d/desktop/trial.pl:97
ERROR: [7] <user>
我的代码只有在我将谓词更改为:
palindrome(L):-
reverse(L,L).
我不明白为什么因为逻辑是相同的......L = L1
与调用 L1, L 开始时相同。
此外,这是不使用 reverse 函数的谓词代码。我无法理解为什么我们有 palidrome1([_]) 基本情况以及为什么如果我没有在 conc 函数的 [First] 周围放置一个括号,它会返回 false。
palindromel( [] ).
palindromel( [_] ).
palindromel( [First | Rest]) :-
conc( Middle, [First], Rest), /*Do I have to put First in a list bracket?*/
palindromel( Middle).
任何帮助,将不胜感激。
解决方案
但是打印了一个我不明白的错误。
导致该行的错误是
L is L1
是/2说:
-Number is +Expr True when Number is the value to which Expr evaluates. Typically, is/2 should be used with unbound left operand. If equality is to be tested, =:=/2 should be used.
由于左边不是数字,右边不是表达式 is/2
,所以不能使用。
我不明白为什么,因为逻辑是一样的。
其实逻辑不一样。is/2
不等于统一,=/2
。
原因
palindrome(L):-
reverse(L,L).
有效,因为 . 的两个参数只有一个变量reverse/2
。因此输入reverse/2
和结果reverse/2
必须统一。在这种情况下,由于输入和输出是相同的,如果它们是回文,它们可以统一。
另一种看待这一点的方法是使用这种变化
palindrome(L1):-
reverse(L1,L2),
L1 = L2.
这次我使用了两个不同的变量,reverse/2
但随后将统一作为一个单独的步骤进行。第一种方式
palindrome(L):-
reverse(L,L).
与此变体相同,但在第一种方式中,统一是通过使用reverse(L,L)
.
我无法理解为什么我们有 palidrome1([_]) 基本案例。
当我开始编写代码来解决问题时,我会在脑海中或在纸上手动解决问题。我从最简单的案例开始,然后朝着更复杂的方向努力。对于回文,最简单的情况是没有字母的单词。
因此,如果输入是一个空列表[]
,则回文是一个空列表[]
palindromel( [] ).
下一个更难的情况是一个带有一个字母的单词[_]
。
palindromel( [_] ).
下一个更难的情况是一个有两个字母的单词[A,A]
。
palindromel( [A,A] ).
等等
palindromel( [A,B,A] ).
palindromel( [A,B,B,A] ).
palindromel( [A,B,C,B,A] ).
palindromel( [A,B,C,C,B,A] ).
为了避免不得不创建无穷无尽的子句列表,使用了递归。然而,对于回文,两个简单的案例成为递归的基本案例,其余的都是使用带有递归子句的基本案例来完成的。
如果我没有在 conc 函数的 [First] 周围放置一个括号,它会返回 false。
我问 Bratko 的“人工智能的 Prolog 编程”的原因是,在他的书中,他让学生创建conc/3
,但没有注意到它真的是append/3。如果您正在使用这本书,请帮自己一个忙并改用append/3
它,因为它没有错误,而且很可能conc/3
会失败,而append/3
会起作用。
append/3
附加两个列表以创建第三个列表。如果您不放置[]
单个字符,那么它不是一个列表而是一个字符,并且append/3
或conc/3
将失败。
推荐阅读
- http - HTTP 服务器是否应该使用比请求更具体的 Content-Type 进行响应?
- javascript - 使用 d3.js scale ordinal 返回不在域中的项目的默认颜色
- javascript - 带有当前位置和标记位置的网页上的地图
- node.js - GCP Cloud Function & BigQuery:插入行但所有列均为空
- php - Woocommerce 模板和 CSS 问题
- c++ - C++17
模板参数扣除不适用于 Xcode 10.1 - python-3.x - 寻找 Lambda 函数以根据文件类型将文件移动到不同的 S3 存储桶
- scala - Apache Spark - 实现分布式四叉树
- java - 通过 Selenium 3 启动 Edge 浏览器时出错
- css - 控制 Flexbox 代码中溢出的意外行为