使用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].

为了简化我的生活,我将原子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分钟在上面,发现它太难调试了。一个口头的草图是这样的:委托给一个带有累加器的helper方法,一个"rest"变量,每个bin有两个变量:一个用于输入,一个用于输出。helper方法有一个获取空列表的情况;将输入变量映射到输出变量,将累加器映射到"rest"变量。现在,helper为每个"endcap"都有一个case,它们看起来几乎相同:将累加器附加到endcap的singleton列表中,并将其转发到递归调用中,作为该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调用它。现在我说,假设我有一些尾数类别。让我从这个类似查找表的结构中获取所有内容

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能力还不够强大。也许其他人会尝试一下?

所以,为一个毫无意义的难题喝彩!这是我很长一段时间以来在序言中回忆起的最奇怪的问题之一!我真的不明白你为什么会想要这个,但我希望我的代码能有所帮助,尽管它的效率非常低。

相关内容

  • 没有找到相关文章

最新更新