【问题标题】:How to return in prolog all elements from right to left greater than an integer in one predicate?如何在序言中从右到左返回大于一个谓词中的整数的所有元素?
【发布时间】:2020-11-24 19:56:46
【问题描述】:

我必须编写一个代码来返回给定列表中严格大于给定整数的所有元素,它从左到右返回。除了内置函数,我不能使用递归或任何其他函数:append/3、append/2、member/2、select/3、reverse/2、findall/3、bagof/3、setof/3、sumlist/2

示例案例:

greater_list([1,9,2,8,3,7,12],7, X).
 X = 12 ? ;
 X = 8 ? ;
 X = 9 ? ;
 no

我可以用递归或帮助谓词来编写它,但没有它们我不知道如何开始。我可以使用 findall/3 但它不会逐个返回元素,而是返回大于给定数字的元素列表。

【问题讨论】:

    标签: recursion prolog


    【解决方案1】:

    我可以用递归或帮助谓词来编写它,但没有它们我不知道如何开始。

    我很想知道您认为如何使用辅助谓词解决这个问题,但不是没有。

    但首先,考虑一下:您需要做的是枚举列表的某些元素。也就是说,枚举列表中具有某些属性的元素。

    首先,您需要知道如何枚举列表的元素。一旦您知道如何做到这一点,您就可以担心他们必须履行的财产。

    你可以使用member/2枚举列表元素:

    ?- member(X, [1,9,2,8,3,7,12]).
    X = 1 ;
    X = 9 ;
    X = 2 ;
    X = 8 ;
    X = 3 ;
    X = 7 ;
    X = 12.
    

    现在,我们要枚举元素,但只枚举满足属性X > 7 的元素。这相当于说“X 是列表的成员, X > 7”。在 Prolog 中,(类似于)“and”用逗号(,)编写:

    ?- member(X, [1,9,2,8,3,7,12]), X > 7.
    X = 9 ;
    X = 8 ;
    X = 12.
    

    您的谓词应该采用可变限制,而不是硬编码限制 7。这将类似于:

    ?- Limit = 7, member(X, [1,9,2,8,3,7,12]), X > Limit.
    Limit = 7,
    X = 9 ;
    Limit = 7,
    X = 8 ;
    Limit = 7,
    X = 12.
    

    将其打包在谓词定义中将使您开始。看起来这里枚举元素的顺序是预期的reverse。也许您的一个内置插件可以帮助您解决这个问题...

    (另外,如果您知道如何使用findall 编写此代码,则可以使用member 枚举findall ed 列表的元素。但您不应该养成使用@ 的习惯一般为 987654333@,尤其是如果所需的解决方案甚至不是列表,则不会。初学者和糟糕的老师往往过分强调将事物放入列表中,因为这是您在较小的情况下必须做的编程语言。即使你的老师不能,也不要用其他语言思考。)

    【讨论】:

    • 所以基本上整个程序就是:greater(List,Limit,X) :- reverse(List,L), member(X,L),X>Limit. 我错误地理解了这些内置程序是如何工作的,我把这个简单的问题复杂化了。谢谢你的详细解释!!
    • 是的,应该就是这样。我很高兴能帮上忙!
    • 倾向于过分强调将事物放入列表中:翻译:在 Prolog 中,Java Streams 的等价物自 70 年代以来一直存在。
    【解决方案2】:

    您可以使用findall/3 获取搜索元素的列表,然后使用member/2 枚举该列表的成员:

    greater_list(L,Limit,X) :- 
       findall(E,(member(E,L),E>Limit),Es),
       member(X,Es).
    

    然后:

    ?- greater_list([1,9,2,8,3,7,12],7, X).
    X = 9 ;
    X = 8 ;
    X = 12.
    
    ?- greater_list([],7, X).
    false.
    

    还有一个迂回的方式:

    ?- findall(X, greater_list([1,9,2,8,3,7,12],7, X), Xs).
    Xs = [9, 8, 12].
    

    【讨论】:

    • 谢谢!把member/2理解错了,原来是几十行代码。
    【解决方案3】:

    注意。这依赖于递归,我一开始没有注意到你不能使用它

    您可以编写没有其他辅助谓词的谓词,而不是反转列表,并首先考虑递归情况。这可确保要针对 N 检查的第一个元素将是列表的最后一个元素。

    greater_list([_|L], N, X) :- greater_list(L,N,X).
    greater_list([X|_], N, X) :- X > N.
    

    空列表缺少子句意味着空列表的谓词失败。

    上面的第一个子句声明X 是大于N 的列表中的项目,如果它是子列表L 中的这样一个项目。

    尝试回溯的第二个子句声明如果X 是列表的前元素并且它大于N,则谓词也为真。

    这两个子句都使 Prolog 在子列表中首先搜索,并且只有在回溯时,才考虑存储在列表中的值。随着回溯首先从更深的递归级别展开,规则将以首先检查最后一个元素,然后是倒数第二个等的方式应用。

    [eclipse 2]: greater_list([1,9,2,8,3,7,12],7, X).
    
    X = 12
    Yes (0.00s cpu, solution 1, maybe more) ? ;
    
    X = 8
    Yes (0.00s cpu, solution 2, maybe more) ? ;
    
    X = 9
    Yes (0.00s cpu, solution 3, maybe more) ? ;
    
    No (0.00s cpu)
    

    【讨论】:

    • 很遗憾提问者不允许使用递归。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-07
    相关资源
    最近更新 更多