使用prolog将主列表分类为替代品

时间:2015-12-02 15:15:28

标签: list prolog

我正在尝试检查第一个列表中的任何元素是否在第二个列表中匹配。如果找到匹配对该元素进行分类并与该元素分开,那么我们再次检查列表的其余部分。如果在特定分类中找到更多匹配项,则附加这些列表。

我尝试下面的一些分类代码,但它没有正确工作。这种格式的顺序只有效。

?- classify_substituens([1,2,ab,hj,de,as,t,pq,js,xy,ac],Ab,De,Pq,Xy,Rest).
Ab = [1, 2, ab],
De = [hj, de],
Pq = [as, t, pq],
Xy = [js, xy],
Rest = [ac].

我的代码:

classify_ab(N,Ab,R):-append(B,[ab|R],N),append(B,ab,Ab),!.
classify_de(N,De,R):-append(B,[de|R],N),append(B,de,De),!.
classify_pq(N,Pq,R):-append(B,[pq|R],N),append(B,pq,Pq),!.
classify_xy(N,Xy,R):-append(B,[xy|R],N),append(B,xy,Xy),!.

classify_substituens(List,Ab,De,Pq,Xy,Rest):-
    classify_ab(List,Ab_1,Rest_1),
    classify_de(Rest_1,De_1,Rest_2),
    classify_pq(Rest_2,Pq_1,Rest_3),
    classify_xy(Rest_3,Xy_1,Rest4),
classify_substituens(Rest_4,Ab_2,De_2,Pq_2,Xy2,Rest),
    append(Ab_1,Ab_2,Ab),
    append(De_1,De_2,De),
    append(Pq_1,Pq_2,Pq),
    append(Xy_1,Xy_2,Xy),
    !.
classify_substituens(List,[],[],[],[],List).

我想要下面的目标。

?- classify_substituens([1,2,ab,a,b,xy,as,t,xy,ac],Ab,De,Pq,Xy,Rest).
Ab = [1, 2, ab],
De = [],
Pq = [],
Xy = [a,b,xy,as,t,xy],
Rest = [ac].
?- classify_substituens([1,2,ab,a,b,de,s,t,ab,i,ac],Ab,De,Pq,Xy,Rest).
Ab = [1, 2, ab,s,t,ab],
De = [a,b],
Pq = [],
Xy = [],
Rest = [i,ac].

1 个答案:

答案 0 :(得分:1)

为了简化我的生活,我称之为原子abdepqxy“endcaps。”

endcap(ab).
endcap(de).
endcap(pq).
endcap(xy).

您的代码恰好与此匹配,我认为这更简单:

takeUpto(Token, List, PrefixToken, Remainder) :-
    append(Prefix, [Token|Remainder], List),
    append(Prefix, [Token], PrefixToken).

classify_substituens(List, Ab, De, Pq, Xy, Rest) :-
    takeUpto(ab, List, Ab, R0),
    takeUpto(de, R0, De, R1),
    takeUpto(pq, R1, Pq, R2),
    takeUpto(xy, R2, Xy, Rest).

遗憾的是,这仍然不起作用。你要做的是制作垃圾箱并将所有东西放入正确的箱子里。我看到了通过一次通过的方法,但它相当严重。我花了大约30分钟,发现调试太难了。一个口头草图就是这样:委托给一个带有累加器的辅助方法,一个“rest”变量,每个bin有两个变量:一个用于输入,一个用于输出。辅助方法有一个获取空列表的情况;将输入变量映射到输出变量,将累加器映射到“rest”变量。现在帮助器有一个每个“endcap”的大小写,它们看起来几乎相同:将累加器附加到endcap的单例列表,并将其转发给递归调用作为此endcap的新状态变量。这听起来很容易但是涉及11个变量并且有很多复制/粘贴。

我确实提出了一个解决方案,但对我来说,这似乎很容易读写。效率不高。遗憾。

首先,我希望得到感兴趣的“替代品”。我将它们组合在一起,然后用它们具有的特殊风味标记它们。

substituens(Acc, [], [], Acc).
substituens(Acc, [X|Xs], Subs, Rem) :-
    (   endcap(X) ->
        append(Acc, [X], Substituen),
        substituens([], Xs, RemainingSubs, Rem),
        append([X-Substituen], RemainingSubs, Subs)
    ;   append(Acc, [X], Acc1),
        substituens(Acc1, Xs, Subs, Rem)
    ).

这样工作原理如下:

?- substituens([], [1,2,ab,a,b,de,s,t,ab,i,ac], Y, Rem).
Y = [ab-[1, 2, ab], de-[a, b, de], ab-[s, t, ab]],
Rem = [i, ac] ;
false.

我没有为此制作substituens/2包装器,因为我只打算从classify_substituens/6调用它。现在我说,假设我有一些endcap类别。让我从这个类似查找表的结构中获取所有东西

condense(Category, Groups, Condensed) :-
    findall(Group, member(Category-Group, Groups), MyGroups),
    append(MyGroups, Condensed).

这取决于append/2,它不是ISO,但可能不是很难写,因为它只是append/3的定点。

这两位助手做了classify_substituens/6的简短工作:

classify_substituens(List, Ab, De, Pq, Xy, Rest) :-
    substituens([], List, Subs, Rest),
    condense(ab, Subs, Ab),
    condense(de, Subs, De),
    condense(pq, Subs, Pq),
    condense(xy, Subs, Xy).

你有它:

?- classify_substituens([1,2,ab,a,b,de,s,t,ab,i,ac],Ab,De,Pq,Xy,Rest).
Ab = [1, 2, ab, s, t, ab],
De = [a, b, de],
Pq = Xy, Xy = [],
Rest = [i, ac] ;
false.

?- classify_substituens([1,2,ab,a,b,xy,as,t,xy,ac],Ab,De,Pq,Xy,Rest).
Ab = [1, 2, ab],
De = Pq, Pq = [],
Xy = [a, b, xy, as, t, xy],
Rest = [ac] ;
false.

顺便说一句,这也告诉我你的一个测试用例是错误的。 :) De必须始终以de结尾。

我确实有一种挥之不去的感觉,即使用DCG或差异列表可能有一种高效的可读方式,但我的DCG功率不够强大,无法看到它。也许其他人会尝试一下?

所以,对于一个没有意义的难题感到荣幸!这是我在很长一段时间内可以回忆的最奇怪的问题之一!我真的不明白为什么你会想要这个,但我希望我的代码有所帮助,即使它效率非常低效。