2017-10-19 103 views
1

我试图在Prolog中创建自己的排序规则,经过大量的试验和错误之后,除了按下按钮之外,我能够使其工作。在swipl中,它会将我列表的最后一个值添加到列表中。为什么Prolog在分号后重复列表的最后一个值?

使用的代码如下:

分钟以列表找到的最小值,并返回它

min([H|[]],H). 
min([H|T],Min) :- 
    min(T,CurrentMin), 
    H < CurrentMin, 
    Min = H. 
min([H|T],Min) :- 
    min(T,CurrentMin), 
    CurrentMin =< H, 
    Min = CurrentMin. 

删除发现你想在列表中删除的元素,并返回与列表删除元素

最后,sort_inc尝试使用上述规则以增加顺序创建排序列表。

sort_inc([H|[]],[H]). 
sort_inc(UnOrderedList,[H|OrderedTail]) :- 
    min(UnOrderedList,H), 
    remove(H,UnOrderedList,T), 
    sort_inc(T,OrderedTail). 

分选的伟大工程,但是当我按下swipl分号名单上运行的规则后,它会在列表中重复的最后一个值像这样:

sort_inc([3,6,8,4],List). 
List = [3, 4, 6, 8] ; 
List = [3, 4, 6, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8, 8, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8, 8, 8, 8|...] . 

为什么它重复这最后一个值,而不是在输入分号时返回false?

回答

4

你在你的删除/ 3的实施有问题,试试这个:

remove(X, [X|Rest], Result) :- 
    !, remove_sub(X, [X|Rest], Result). 
remove(X, [Y|Rest], Z) :- 
    X \= Y, 
    remove(X, Rest, RestRemoved), 
    Z = [Y|RestRemoved]. 
remove(_, [], []). 

remove_sub(X, [X|Rest], Rest). 
remove_sub(X, [Y|Rest], Z) :- 
    remove_sub(X, Rest, RestRemoved), 
    Z = [Y|RestRemoved]. 

确切的说,你的删除/ 3的第一款留下列表完好,即使被删除的元素产生不当的解决方案是其成员:

?- remove(1, [1, 2, 3], L). 
L = [2, 3] ; 
L = [1, 2, 3]. 

此外,请注意,该捆绑许多Prolog的实施方式将已删除/ 3和最小/ 2实施方式中(以及排序,当然)。例如,束缚水饱和度,序言包括:

  • 删除/ 3,它做几乎你的你的删除/ 3是应该做的,只是它删除元素的所有实例一次
  • 选择/ 3,这除了不允许删除不在列表中的元素
  • min_list/2和min_member/2,找到列表的最小元素
  • sort/2, msort/2,predsort/3,做实际分类

即使您的目标是创建您的自定义实现,仍然值得使用它们来测试您自己的实现,例如您可以使用delete/3快速替换您的remove/3的调用,以找出问题出在哪里。

+0

通过remove/3的第一个子句,你指的是remove(_,[],[])?我想这只会返回一个空列表,如果有什么试图从空列表中删除。我认为如果元素不属于,这将是一个很好的最后递归步骤。 –

+0

另外,在删除规则中,删除(1,[2],List)返回List = []。如果没有正确的调用,我不希望单个元素列表丢失它的项目。 –

+1

看起来你是对的,我最初的remove/3的实现被打破了,对不起。这现在已经修复(希望),我已经更新了答案。此外,删除/ 3我提到的也不同于我们的remove/3,因为它删除了所有出现的元素“瞬间”,而删除/ 3在回溯期间逐个删除它们。 –

相关问题