2016-07-28 227 views
1

我是新来的Prolog和我有麻烦搞清楚如何找到包含数字和字母列表中的第二个最低寻找第二最小值。当它包含一个字母时,它应该显示一个错误,当它有一个数字时,它应该显示一个错误。到目前为止,我有这个,但我不知道如何开始我的编码具有信件...SWI-Prolog的:在列表中

secondMin([_]) :- 
    print("ERROR: List has fewer than two unique elements."), 
    !. 
secondMin(List, M2) :- 
    min_list(List, M1), 
    delete(List, M1, List1), 
    min_list(List1, M2). 

输出应该是这样的:

?- secondMin([17,29,11,62,37,53], M2). 
M2 = 17 
?- secondMin([512], M2). 
ERROR: List has fewer than two unique elements. 
?- secondMin([7,5.2,3,6,-3.6,9,-2], M2). 
M2 = -2 
?- secondMin([12,2,b,7], M2). 
ERROR: "b" is not a number. 
?- secondMin([3,3,3], M2). 
ERROR: List has fewer than two unique elements. 
+0

如果它所具有既不是一个整数,也不是字母元素?例如'abc'或'1.23'? – lurker

+0

对不起,我不是故意说整数只是任何唯一的数字 – tadashi

+2

“第二最小”听起来很好定义。然而,secondMin([1,1,2,3],M)'现在是'M = 1'还是'M = 2'? – false

回答

0

最简单的,而且是必须的,方法是使用maplist来确定是否有任何非数字。然后使用sort获得独特的第二分钟。

secondMin(L, M) :- 
    ( maplist(number, L) 
    -> ( sort(L, [_,Second|_]) 
     -> M = Second 
     ; print("List has fewer than two unique elements.") 
     ) 
    ; print("List has non-numeric elements") 
    ). 


作为@Repeat指出在他的评论,上述方案是在这个意义上“天真”,虽然它产生了一个有效输入一个正确的结果,它没有相应的错误处理除了显示诊断消息,但然后成功。

这里有一个更彻底的执行,当预期没有定义的第一个参数上异常引发:

secondMin(L, M) :- 
    ( ground(L) 
    -> ( is_list(L), 
      maplist(number, L) 
     -> ( sort(L, [_,Second|_]) 
      -> M = Second 
      ; throw('List has fewer than two unique elements') 
      ) 
     ; throw('First argument is not a list of numbers') 
     ) 
    ; throw(error(instantiation_error, _)) 
    ). 
+0

你的答案(这在错误的情况下打印出“ERROR”和*然后成功*)是**路*​​关闭!而不是使用例外! IIRC你的主要Prolog处理器是GNU Prolog ...所以请阅读http://www.gprolog.org/manual/gprolog.html#sec32并重新提供/改进你的答案。我知道使用例外有点令人厌烦,但要走高速公路。 – repeat

+0

你可能要开始像'(接地(L) - > ...;掷(误差(instantiation_error,_)))'如果你想在代码中使用'排序/ 2' ... – repeat

+0

另一个事情......应该推迟“排序/ 2”目标中的隐含统一,以避免问题的严重性。为什么不这样做:'(sort(L,[_,Second | _]) - > M = Second; throw(...))' – repeat