Prolog: First duplicate value

前端 未结 4 1800
挽巷
挽巷 2020-11-30 15:30

I need to find the first duplicate value in a list.

prep(3,[1,3,5,3,5]). Should be true.

prep(5,[1,3,5,3,5]). Should be false.

4条回答
  •  北海茫月
    2020-11-30 15:34

    Not sure if this is homework/ there are restrictions on which predicates you are allowed to use, but this gets prolog to do the recursion for you.

    It says.. find all duplicates ie. where there is an item with list index I1, and another one with I2, such that they both have the same value N, and the indices are not the same ie.don't consider the same list item as a duplicate.

    These duplicates are put (in the order they are found, from the beginning crucially) in list AllDups, and the predicate is true if the first duplicate found unifies with M, the value you are checking.

    First Attempt: This works but is very inefficient, building a list of ALL duplicates

    prep(M, List) :-
        findall(N,
            (nth0(I1, List, N),
            nth0(I2, List, N),
            not(I1 =:= I2)),
            AllDups),
        nth1(1, AllDups, M).
    
    
    ?- prep(3,[1,3,5,3,5]).
    true.
    
    ?- prep(5,[1,3,5,3,5]).
    false.
    

    Even if you are not allowed to use findall, it might help you work out how to do it 'manually'.

    Second Attempt: This doesn't work / backtracks too far yielding a false positive

    You can even do it without the findall - use nth0 to find the first duplicate item, then if that unifies with the value you are checking, it returns true, otherwise false.

    prep(N, List) :-
            nth0(I1, List, N),
            nth0(I2, List, N),
            not(I1 =:= I2).
    

    Third Attempt : This works, and returns as soon as the first duplicate has been found

    prep(M, List) :-
            nth0(I1, List, N),
            nth0(I2, List, N),
            not(I1 =:= I2), !,
            M == N.
    

提交回复
热议问题