【问题标题】:Prolog: Filter and listProlog:过滤和列表
【发布时间】:2018-12-07 01:14:57
【问题描述】:

构造一个名为 fPairsAtoms/3 的谓词,以便给定一个原子(第一个参数)和一个对列表,通过仅选择将第一个组件作为原子的对,将第三个参数与过滤后的对列表统一起来第一个参数。

例子:

fPairsAtoms(sA,[[basA,absAb],[ab,bbsA],[sA,abbsB],[bsA,sAsB],[sA,bb]],X)  

结果:

X = [[sA,abbsB],[sA,bb]]

我不明白.....我应该面对这些类型的练习吗? 你能帮我找到解决办法吗?

今天我从 prolog 开始,在各方面我都是新手。

【问题讨论】:

  • 如果你今天才开始,这有点太早了。首先,您应该了解 Prolog terms 是什么:atomsVariables、复合术语 foo(x,X)。那你应该明白统一,a = aa = AA = aA = foo(a)foo(A) = foo(a)[atom, B] = [A, bar]。您应该了解列表表示,其中[A, B, C] = [A, B | [C]] = [A | [B,C]] = [A | [B | [C]]] = .... = [A, B, C | []] 以便统一[A | B] = [a] 成功,从而也统一A = aB = [],但统一[A | B] = [] 失败 .等等等等等等等等。
  • 这当然不是初学者的作业。
  • 我建议你先尝试更简单的问题。上面确实不适合作为第一个要解决的问题。

标签: list filter prolog


【解决方案1】:

如果您今天才刚刚开始,那么解决这个问题可能还为时过早。

首先您应该了解 Prolog 术语是什么:atoms、逻辑Variables、复合术语foo(x,X,bar(baz))

那你应该明白统一,a = aa = AA = aA = foo(a)foo(A) = foo(a)[atom, B] = [A, bar]

您应该了解列表表示,其中

[  A,   B,   C     ] 
= [A,   B | [C]    ] 
= [A | [B ,  C    ]] 
= [A | [B | [C]   ]] 
= .... 
= [A ,  B ,  C | []] 

这样统一[A | B] = [a]成功,导致同时统一A = aB = [],但统一[A | B] = []失败

那么你需要理解谓词,在过程解释下意味着,

to_prove(This) :- need_to_prove(This) , and_also(That).

这样

fPairsAtoms(sA, [[basA,absAb],[ab,bbsA],[sA,abbsB],[bsA,sAsB],[sA,bb]], X) :-
            X = [                       [sA,abbsB],           [sA,bb]].

是一个完全有效的定义,虽然非常狭窄。

其实也一样

fPairsAtoms(sA, [[basA,absAb],[ab,bbsA],[sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
            X = [                       [sA,abbsB] | [           [sA,bb]] ].
% and 
fPairsAtoms(sA, [             [ab,bbsA],[sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
            X = [                       [sA,abbsB] | [           [sA,bb]] ].
% and 
fPairsAtoms(sA, [                       [sA,abbsB] | [[bsA,sAsB],[sA,bb]] ], X) :-
            X = [                       [sA,abbsB] | [           [sA,bb]] ].
% and 
fPairsAtoms(sA,                                      [[bsA,sAsB],[sA,bb]]  , Y) :-
            Y =                                      [           [sA,bb]].
% ... and 
fPairsAtoms(sA,                                                        []  , Y) :-
            Y =                                                        [].

还有

fPairsAtoms(sA, [                       [sA,abbsB] | L                    ], X) :- 
            L =                                      [[bsA,sAsB],[sA,bb]], 
            Y =                                      [           [sA,bb]],
            X = [                       [sA,abbsB] | Y                    ].

因此

fPairsAtoms(sA, [                       [sA,abbsB] | L                    ], X) :- 
            L =                                      [[bsA,sAsB],[sA,bb]], 
            fPairsAtoms( L, Y),
            Y =                                      [           [sA,bb]],
            X = [                       [sA,abbsB] | Y                    ].
% and
fPairsAtoms(sA, [                       [sA,abbsB] | L                    ], X) :-
            L =                                      [[bsA,sAsB],[sA,bb]], 
            fPairsAtoms( L, Y),
            X = [                       [sA,abbsB] | Y                    ].
% and
fPairsAtoms(sA, [                       [sA,abbsB] | L                    ], X) :-
            fPairsAtoms( L, Y),
            X = [                       [sA,abbsB] | Y                    ].
% and so
fPairsAtoms(sA, [                       A          | L                    ], X) :-
            A =                         [sA, B   ],
            fPairsAtoms( L, Y),
            X = [                       A          | Y                    ].
% and even
fPairsAtoms(SA, [                       A          | L                    ], X) :-
            A =                         [SA, B   ],
            fPairsAtoms( SA, L, Y),
            X = [                       A          | Y                    ].

但另一方面,如果没有匹配,我们看到它是

fPairsAtoms(SA, [                       A          | L                    ], X) :-
            A =                         [SB, B   ],
            dif( SA, SB),
            fPairsAtoms( SA, L, Y),
            X =                                      Y                     .
% i.e.
fPairsAtoms(SA, [                       [SB, B   ] | L                    ], X) :-
            dif( SA, SB),
            fPairsAtoms( SA, L,                      X)                    .

那么我们最终得到的两个子句中的哪一个,

fPairsAtoms( SA, [ [SA, _] | L ], X) :-
            fPairsAtoms( SA, L, Y),
            X = [A |            Y].

fPairsAtoms( SA, [ [SB, _] | L ], X) :-
            dif( SA, SB),
            fPairsAtoms( SA, L,   X).

是正确的吗?答案是:两者都有!

【讨论】:

    【解决方案2】:

    要过滤列表中的对,您需要遍历它,同时将给定的原子与每对的第一个元素进行比较。遍历列表的简单谓词是:

    traverse([]).
    traverse([Head| Tail]) :-
        traverse(Tail).
    

    您的问题描述中的谓词名称非常糟糕,并且不遵循推荐的 Prolog 编码指南。让我们将其重命名为filter_pairs_by_key/3,并将参数顺序更改为filter_pairs_by_key(Pairs, SearchKey, FilteredPairs)。此外,Prolog 中 pair 的推荐表示为Key-Value。有标准谓词和库谓词需要这种表示(例如keysort/2)。基于traverse/2谓词模板和代码风格推荐,我们可以这样写:

    filter_pairs_by_key([], _, []).
    filter_pairs_by_key([Key-Value| Pairs], SearchKey, [Key-Value| FilteredPairs]) :-
         Key = SearchKey, 
         filter_pairs_by_key(Pairs, Atom, FilteredPairs).
    filter_pairs_by_key([Key-_| Pairs], SearchKey, FilteredPairs) :-
         Key \= SearchKey, 
         filter_pairs_by_key(Pairs, SearchKey, FilteredPairs).
    

    请注意,对于非空列表情况,我使用了两个子句:一个是配对键与原子匹配时,另一个是匹配失败时。

    示例调用:

    | ?- filter_pairs_by_key([basA-absAb,ab-bbsA,sA-abbsB,bsA-sAsB,sA-bb], sA, FilteredPairs).          
    
    FilteredPairs = [sA-abbsB,sA-bb] ? 
    
    yes
    

    关于这个问题和这个特殊的解决方案可以说更多,但是正如 cmets 中提到的,这不是一个初学者练习。考虑 cmets 的建议,并在熟悉 Prolog 列表符号后使用此解决方案。

    【讨论】:

      猜你喜欢
      • 2018-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-07
      相关资源
      最近更新 更多