prolog - 检查列表是否在 Prolog 中被展平
问题描述
给定一个列表,我想使用 prolog 检查给定列表是否平坦。
Example:-
1. ?- is_flat([1,2,3]) should return true
2. ?- is_flat([1,f,2,r(p),8]) should return true
3. ?- is_flat([1,2,[3,e,w],u]) should return false
我正在考虑逻辑,即遍历列表的每个元素,然后使用 is_list 检查头部是否为列表。我试过:
is_flat([]).
is_flat([H|T]) :- is_list(H), is_flat(T).
但我不认为我走在正确的轨道上。请建议我如何解决这个问题。
解决方案
给出的方法是正确的,我们只需要“反转真值”is_list/2
测试(或者更准确地说,一旦遇到列表就宣布证明失败)。为了更好地衡量,我添加了一个完全不必要的消息编写指令:
is_flat([]).
is_flat([X|Xs]) :-
format("Examining ~q\n",[X]),
\+ is_list(X),
is_flat(Xs).
然后:
?- is_flat([a,b,c]).
Examining a
Examining b
Examining c
true.
但:
?- is_flat([a,[x,y,z],c]).
Examining a
Examining [x,y,z]
false.
这可以用 紧凑地完成maplist/2
,它将谓词应用于每个元素,并在此类应用程序出现故障时立即中断:
another_is_flat(List) :- maplist(not_is_list,List).
not_is_list(L) :- \+ is_list(L).
然后:
?- another_is_flat([a,b,c]).
true.
?- another_is_flat([a,[x,y,z],c]).
false.
使用forall/2
或者使用 CapelliC 的解决方案。forall/2
正是为此而设计的:它\+is_list(E)
为每个成功的条件(在这种情况下)执行测试(在这种情况下, member(E,L)
),并且表现得像短路 AND(在成功时也不会留下意外绑定):
another_another_is_flat(L) :- forall(member(E,L),\+is_list(E)).
然后:
?- another_another_is_flat([a,b,c]).
true.
?- another_another_is_flat([a,[x,y,z],c]).
false.
边缘案例:
?- another_another_is_flat([]) .
true.
“空洞的真相”:正确接受空列表。
推荐阅读
- java - 在 Mac 中使用 Java 15 (openjdk)
- spring-boot - 如何在 Spring Boot 中使用 sql 文件填充 H2 DB UUID 主键
- javascript - bootstrapValidator.min.js:10 Uncaught TypeError: Cannot read property 'group' of undefined at b.updateStatus (VM35395 bootstrapValidator.min.js:10)
- amazon-redshift - 如何在 AWS REDSHIFT 中使现有列不为空?
- angular - 如何测试异步函数中设置的变量?
- html - 最大化图像大小、居中并在其周围拟合列
- r - 如何在 gganimate 中将 geom_density_2d_filled 设置为背景
- bash - 如何选择少于 n 行的文件?
- javascript - php动态元标记fb打开图形sdk不起作用
- swift - 在带有全屏封面的视图中使用全屏封面