list - 尝试在 Prolog 中实现拆分谓词
问题描述
我正在尝试partition
在 Prolog 中实现一个谓词,它将一个列表分成两半,一个前缀和一个后缀,长度大致相同。
partition(L,P,S)
前缀和后缀的定义如下:
prefix(P,L) :- append(P,_,L).
suffix(S,L) :- append(_,S,L).
- 如果
L
是[]
,那么Prefix
和S
是[]
。 - 如果
L
是[H]
,那么P
是[H]
并且S
是[]
。 - 如果
L
有两个或更多元素,这就是列表如何划分为其前缀和后缀的方式:L
is的长度和isN
的长度。的长度为。P
div(N,2)
S
N - div(N,2)
例如:
?- partition([a,b,c,d],X,Y).
X = [a,b]
Y = [c,d]
?- partition([a],X,Y).
X = [a]
Y = [ ]
这是我的代码和我得到的错误:
partition([],[],[]).
partition([H],[H],[]).
partition(L, P, S) :-
length(L, N),
Plen is div(N,2),
Slen is N - div(N,2),
length(Pre, Plen),
length(Suff, Slen),
prefix(Pre, L),
suffix(Suff, L),
P is Pre,
S is Suff.
partition([a,b,c,d],X,Y).
>>> Type error: `[]' expected, found `[a,b]' (a list)
("x" must hold one character)
解决方案
如果您按照 David Tonhofer 的回答所建议的更改is
为,则整个过程都有效。=
但是我想补充一点,您使事情变得有些复杂。您已正确识别出append/3
可用于计算列表前缀和后缀的内容。但是对于任何要分区的列表和任何前缀,后缀都是唯一的,并且已经由append/3
! 反之亦然:如果你要求它计算后缀,它也会计算你寻找的前缀。但是随后您将这些答案扔掉并尝试重新计算匹配的前缀或后缀。没有必要这样做。
如果我们让你的前缀和后缀谓词更明确一点:
list_prefix_theonlypossiblematchingsuffix(List, Prefix, TheOnlyPossibleMatchingSuffix) :-
append(Prefix, TheOnlyPossibleMatchingSuffix, List).
list_suffix_theonlypossiblematchingprefix(List, Suffix, TheOnlyPossibleMatchingPrefix) :-
append(TheOnlyPossibleMatchingPrefix, Suffix, List).
我们可以看到,一旦我们为列表指定了前缀,就真的没有更多的后缀选择(反之亦然):
?- list_prefix_theonlypossiblematchingsuffix([a, b, c, d], Prefix, MatchingSuffix).
Prefix = [],
MatchingSuffix = [a, b, c, d] ;
Prefix = [a],
MatchingSuffix = [b, c, d] ;
Prefix = [a, b],
MatchingSuffix = [c, d] ;
Prefix = [a, b, c],
MatchingSuffix = [d] ;
Prefix = [a, b, c, d],
MatchingSuffix = [] ;
false.
因此无需尝试分别计算前缀和后缀并匹配它们的长度。限制前缀就足够了,因为后缀如下:
partition(List, Prefix, TheOnlyPossibleMatchingSuffix) :-
length(List, N),
PrefixLength is N div 2,
length(Prefix, PrefixLength),
list_prefix_theonlypossiblematchingsuffix(List, Prefix, TheOnlyPossibleMatchingSuffix).
这可以按您的意愿工作:
?- partition([a, b, c, d], Prefix, Suffix).
Prefix = [a, b],
Suffix = [c, d].
?- partition([a, b, c, d, e], Prefix, Suffix).
Prefix = [a, b],
Suffix = [c, d, e].
list_prefix_verylongpredicatename
一旦你有了这个,用真正的意思替换目标就更清楚了:
partition(List, Prefix, Suffix) :-
length(List, N),
PrefixLength is N div 2,
length(Prefix, PrefixLength),
append(Prefix, Suffix, List).
来自其他编程语言的谓词可能有点不寻常,比如append/3
一次计算多个相互之间有很深关系的事物,即前缀和唯一匹配的后缀。但这是使 Prolog 如此富有表现力和强大的原因之一。习惯它并从中获利!
推荐阅读
- javascript - How to set two root endpoints in one file Restful API with node.js & EXPRESS
- python - 使用 Python 从 Excel 文件中删除行而不丢失格式
- flutter - Fetch state-object from database
- data-binding - Knockout binding a font awesome icon to a property
- selenium - Selenium 在 Jenkins Pipeline 中运行 WCT 时在启动错误之前退出
- php - 数组中不区分大小写
- windows - win32 草莓 perl PAR Packer 制作 exe 文件
- mysql - 如何进行复杂的查询
- java - 微服务中的 Spring 会话问题
- mysql - MySQL to not return same results