简体   繁体   中英

SWI-Prolog: finding the second minimum in a list

I'm new to Prolog and I'm having trouble figuring out how to find the second minimum in the list that includes numbers and letters. When it includes a letter it should display an error and when it has one number then it should display an error. So far I have this but I'm not sure how to start off my code for having letters...

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).

The output should look like this:

?- 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.

The easiest, but imperative, approach is to use maplist to determine whether there are any non-numbers. Then use sort to get the unique, second min.

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")
    ).


As @repeat has pointed out in his comment, the above solution is "naive" in the sense that, although it produces a correct result for a valid input, it doesn't have appropriate error handling other than to display a diagnostic message but then succeed.

Here's a more thorough implementation which raises on exception when the first argument isn't defined as expected:

 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, _)) ). 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM