我的任务是在prolog中交叉2个列表。但是我似乎找不到我的功能不起作用的原因。我不知道prolog想要什么。这是我尝试解决任务的问题:
public static void ValidatePhone()
{
List<Clients> clients = Program.GetAllClients();
Regex regex = new Regex(@"Someregex");
for (int i = 0; i < clients.Count; i++)
{
if (!regex.IsMatch(clients[i].Phone))
clients[i].Phone = "[Invalid phone number]";
}
}
}
我尝试将其称为write_list([]).
write_list([Head|Tail]) :-
write(Head), nl,
write_list(Tail).
intersect(L,[],X) :- write_list(X).
intersect([],L,X) :- write_list(X).
intersect([H1|T1],[H2|T2], X) :-
H1 == H2,
append([H1],X,Y),
intersect(T1,T2,Y).
intersect([H1|T1],[H2|T2], X) :-
H1 > H2,
intersect(T1,[H2|T2],X).
intersect([H1|T1],[H2|T2], X) :-
H1 < H2,
intersect([H1|T1],T2,X).
,我得到的答案是intersect([1,2,3],[2,3,4],X).
。谁能告诉我为什么?
Update1:另外作为一个侧面的问题,如何在没有我调用write_list(X)的情况下使用prolog打印X.我看到一些函数返回额外的参数......
答案 0 :(得分:0)
让我们想一想逻辑语言中的问题。 intersect(X, Y, Z)
的含义可能是,Z
是X
和Y
的交集。因此intersect(L, [], X) :- write_list(X).
的基本情况可能不正确,除非X = []
。对于基本情况,我们可以说,然后:
intersect([], _, []).
由于任何(_
)与空集([]
)相交都是空的。
然后对于递归案例,你有:
intersect([H1|T1],[H2|T2], X) :-
H1 == H2,
append([H1],X,Y),
intersect(T1,T2,Y).
让我们简化一下,因为我们可以将列表头部的统一放在谓词的头部,我们不需要append
,因为append([H1], X, Y)
与[H1|X] = Y
相同,{ {1}}:
intersect([H|T1],[H|T2], X) :-
intersect(T1, T2, [H|X]).
我们已经遇到了一些麻烦,因为递归调用应该有更短的列表作为结果。它可能意味着:
intersect([H|T1],[H|T2], [H|X]) :-
intersect(T1, T2, X).
但即便如此,虽然有所改进,但它假设相同的元素将在两个列表中相互串联,可能并非如此。
另一种方法是使用member/2
和delete/3
:
intersect([], _, []).
intersect([H|X], Y, Z) :-
member(H, Y)
-> delete(Y, H, Y1),
intersect(X, Y1, Z1),
Z = [H|Z1]
; intersect(X, Y, Z).
这里,如果第一个列表的当前头是第二个列表的成员,我们从第二个列表中删除所有出现的这个元素,并确定该结果与第一个列表的其余部分的交集,后者成为尾部该条款的结果。否则,我们将第一个列表的尾部与第二个列表的尾部相交。
请注意,这是一个有点必要(并且可能有点天真)的问题方法,并且在命令意义上工作,“给定两个列表X和Y,找到它们的交集”。但它不是关系型或陈述性的(“Z是X和Y的交集”),这将是Prolog的真正优势。
至于你关于避免“写”结果的问题,你可以看到在prolog中执行谓词的时候,它会向你展示变量的可能实例,使其成为现实。所以没有必要写作。