0

我需要一些关于检查和操作列表的三个 prolog 谓词的帮助。我是 prolog 的新手,任何帮助将不胜感激。

三个谓词是:

  • double_up(+List1, -List2)List2当每个元素为List1两次时为真。查询double_up([a,b,c],X)应该给出X=[a,a,b,b,c,c]. 输出列表中元素的顺序无关紧要。
  • pivot(+List1, +Pivot, -Smaller, -GreaterEq)SmallerList1小于的数字列表Pivot并且GreaterEqList1大于或等于的数字列表时为真Pivot
  • fancy_replace(+List, +Takeout,+Putin, -NewList, -Count)NewList当与输入相同的列表时为真List,但列表中的每个Takeout元素都被替换为Putin元素。Count 应该是被替换的 Takeouts 的数量。例如,查询fancy_replace([9,10,1,9,2],9,0, X, C)应该给出X = [0,10,1,0,2]and C = 2。输出列表中元素的顺序无关紧要。
4

2 回答 2

1

Prolog 中处理列表的更简单模式强加了一个带有 2 个参数的递归谓词,通常匹配输入和输出数据,以及一个基本情况,停止递归,匹配空列表。然后

double_up([X|Xs], [X,X|Ys]) :- double_up(Xs, Ys).
double_up([], []).

这个谓词比所需的更通用double_up(-List1, +List2),因为它也适用于 mode 。例如

?- double_up(L,[1,1,2,2]).
L = [1, 2].

为了根据需要限制其模式,我认为有必要无用地使代码复杂化,将干净的循环移动到服务谓词中,并让 double_up 仅用于测试参数:

double_up(I, O) :- is_list(I), var(O), double_up_(I, O).
double_up_([X|Xs], [X,X|Ys]) :- double_up_(Xs, Ys).
double_up_([], []).

pivot/4 可以是 SWI-Prolog 中的“单线”:

pivot(List1, Pivot, Smaller, GreaterEq) :-
    partition(>(Pivot), List1, Smaller, GreaterEq).

像 partition, foldl from library( apply ) 它是最后一个必需谓词的简单实现:

fancy_replace(List, Takeout, Putin, NewList, Count) :-
    foldl(swap_n_count(Takeout, Putin), List, NewList, 0, Count).
swap_n_count(Takeout, Putin, L, N, C0, C) :-
    (   L == Takeout
    ->  N = Putin, C is C0 + 1
    ;   N = L, C = C0
    ).
于 2013-04-23T06:49:46.960 回答
-1

老实说,我讨厌prolog……尽管学习后它很有趣也很容易

我认为这是一个很好的参考,因为几周前我无法理解 prolog 的工作原理。 以下序言代码有什么作用?

无论如何..这是您第一个问题的答案;希望你能自己解决剩下的问题:D

double([]).
double([H|[]], [H,H|[]]).
double([H|T],[H,H|T1]):- double(T, T1).

顺便说一句,这可能不是唯一的解决方案......但它有效

于 2013-04-23T04:17:40.337 回答