2016-07-28 2 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» и * then successs *) ** ** off ** Вместо этого используйте исключения! IIRC ваш основной процессор Prolog - это GNU Prolog ... поэтому, пожалуйста, прочитайте http://www.gprolog.org/manual/gprolog.html#sec32 и перефразируйте/улучшите свой ответ. Я знаю, что использование исключений - это немного утомительно, но идти по высокой дороге. – repeat

+0

Возможно, вы захотите начать с чего-то вроде '(ground (L) -> ...; throw (error (instantiation_error, _)))', если вы хотите использовать 'sort/2' в коде ... – repeat

+0

Другой вещь ... неявное объединение цели «sort/2» должно быть лучше отложено, чтобы избежать проблем с устойчивостью. Почему бы не сделать это так: '(sort (L, [_, Second | _]) -> M = Second; throw (...))' – repeat

Смежные вопросы