在prolog中交叉2列表

时间:2015-10-17 18:11:12

标签: list prolog

我的任务是在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.我看到一些函数返回额外的参数......

1 个答案:

答案 0 :(得分:0)

让我们想一想逻辑语言中的问题。 intersect(X, Y, Z)的含义可能是,ZXY的交集。因此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/2delete/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中执行谓词的时候,它会向你展示变量的可能实例,使其成为现实。所以没有必要写作。