【问题标题】:Prolog: Trouble sorting a listProlog:对列表进行排序时遇到问题
【发布时间】:2013-12-02 10:49:00
【问题描述】:

我有一个这样的列表,我正在尝试排序:

[(tim,3),(tom,4),(jane,2),(mary,3)]

我想重新排列它,使其按降序排列:

[(tom,4),(mary,3),(tim,3),(jane,2)]

我有一个谓词可以提取给定数字的列表:

extractor([],[],[],_).
extractor([(Name, Number)|List], [(Name, Number)|NewList], Extracted, Number):-
   extractor(List, NewList, Extracted, Number),
   !.
extractor([A|List], NewList,[A|Extracted], Number):-
   extractor(List, NewList, Extracted, Number).

所以给定一个数字,它应该给我一个包含这些数字的元素列表,并有一个没有这些元素的提取列表。

然后我把它通过排序。我有一个最高数字,它应该从 0 循环到那个数字,提取那个数字的任何元素。直到我得到排序列表。

numberSort([], _, 0).
numberSort(Unsorted, Sorted, HighestNumber):-
   extractor(Unsorted, Sorted, ExtractedList, Counter),
   numberSort(ExtractedList, Sorted, Counter),
   HighestNumber is 1 + Counter.
numberSort(Unsorted, Sorted, HighestNumber):-
   numberSort(Unsorted, Sorted, Counter),
   HighestNumber is 1 + Counter.

但是,当我尝试这个时,它只是经历了一个无限循环。有人可以帮助我并告诉我哪里出错了吗?谢谢,

【问题讨论】:

  • 你有没有试过trace看看它在哪里循环?

标签: prolog failure-slice


【解决方案1】:

首先,在详细查看您的代码之前,让我们明确关系应该描述什么。你有一对(Name, Number) 的形式——顺便说一句,通常Prolog 代码更喜欢写Name-Number。并且您想要两个对列表之间的关系,第二个是对按数字降序排列的排列。

负数呢?看来你没有考虑这种情况。至少,0 出现在您的程序中,这表明您打算将其设为最高数字,应列出 []

为什么你的程序会循环?您可能希望通过调试器逐步查看“发生”的情况。那么,为什么不呢?试试看!你会看到你看到很多不相关的事情发生。更有效的是像这样使用

numberSort([], _, 0) :- falsenumberSort(Unsorted, Sorted, HighestNumber) :- false, extractor(Unsorted, Sorted, ExtractedList, Counter), numberSort(ExtractedList, Sorted, Counter), HighestNumber 是 1 + Counter。 numberSort(Unsorted, Sorted, HighestNumber) :- numberSort(Unsorted, Sorted, Counter), false, HighestNumber 是 1 + Counter。 ?- numberSort([(tim,3),(tom,4),(jane,2),(mary,3)], Sorted, H)。

您的程序的这个片段仍然循环,因此您的原始程序也会循环。你不需要看到更多!更糟糕的是:您的程序会循环所有查询!要解决此问题,您必须至少修复剩余可见部分中的某些内容。在您花了一段时间使用 extractor/4 之后,这可能会让您感到惊讶,但不管它的定义如何,都会发生这个循环。

另一个问题是extractor/4:

| ?- extractor([(tim,3),(jane,4)], Xs, Ys, 3).
Xs = [(tim,3)],
Ys = [(jane,4)] ? ;
no
| ?- extractor([(tim,3),(jane,4)], [], Ys, 3).
Ys = [(tim,3),(jane,4)] ? ;
no

这不是很奇怪吗?第一个查询成功(可能根据您的期望),第二个应该因此失败,但它成功了。罪魁祸首是您在规则末尾放置的切口。我们说,谓词不是steadfast。我建议以您根本不需要任何删减的方式编写此谓词。

【讨论】:

    【解决方案2】:

    这是调试代码的方法

    ?- leash(-all),trace,numberSort([(tim,3),(tom,4),(jane,2),(mary,3)],L,N).
       Call: (7) numberSort([ (tim, 3), (tom, 4), (jane, 2), (mary, 3)], _G7370, _G7371)
       ...
       Exit: (8) extractor([ (tim, 3), (tom, 4), (jane, 2), (mary, 3)], [ (tim, 3), (mary, 3)], [ (tom, 4), (jane, 2)], 3)
       Call: (8) numberSort([ (tom, 4), (jane, 2)], [ (tim, 3), (mary, 3)], 3)
        ...
       Call: (11) extractor([], [ (tim, 3), (mary, 3)], _G7590, _G7602)
       Fail: (11) extractor([], [ (tim, 3), (mary, 3)], _G7590, _G7602)
       ...
    

    调用 (8) 似乎对其参数进行了太多实例化,因此提取器失败。纠正代码并不容易,因为我不完全理解逻辑。

    我认为应该有一些附加,或者你应该使用差异列表。

    OTOH,使用该库的一种更简单的方法。有一个内置的predsort 允许指定一个谓词进行比较:

    ?- predsort(\X^Y^Z^(Y=(A,B),Z=(C,D), (B < D -> X = > ; X = <)), [(tim,3),(tom,4),(jane,2),(mary,3)], L).
    L = [ (tom, 4), (tim, 3), (mary, 3), (jane, 2)].
    

    这个“查询”使用 library(lambda) 来构建所需的 arity 3 谓词。

    【讨论】:

    • 这个内置是特定于 SWI 的
    【解决方案3】:

    CapelliC 有一个非常有用的答案,我认为我的实例化方式有问题。 numberSort 谓词有问题。应该是这样的:

    numberSort([], [], 0).
    numberSort(Unsorted, Sorted, HighestNumber):-
         Counter is HighestNumber - 1,
         extractor(Unsorted, SemiSorted, ExtractedList, Counter),
         numberSort(ExtractedList, Sorting, Counter),
         append(SemiSorted, Sorting, Sorted), !.
    numberSort(Unsorted, Sorted, HighestNumber):-
         Counter is HighestNumber - 1,         
         numberSort(Unsorted, Sorted, Counter).
    

    应该可以。如果有人发现它有任何问题,请告诉我。

    【讨论】:

    • 改成逗号后得到numberSort/3: Arguments are not sufficiently instantiated Exception: (6) stackoverflow:numberSort([ (b, 2), (a, 1)], _G2546, _G2547)
    • 抱歉,错字已更正!为此,您需要输入第三个参数。所以对于上面的列表,它应该是 5。因为 Tom 是 4,并且计数器从一开始就减去 1。抱歉,我应该提到这是一个更大的谓词的一部分,我在其中找到最高的数字,然后使用 numberSort。
    • numbersort([(b,2)],[],_) 不会终止。你的剪裁不行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 2013-02-28
    相关资源
    最近更新 更多