Search code examples
listrecursionprolog

How to get all elements in a nested list where the first element of each list is a particular number?


I'm new to Prolog and I am having trouble with recursion and nested lists.

I want a predicate called getCommon(Number, List, X) which does the following:

getCommon(2, [[2,3], [2,5], [3,5]], X).
X = [[2,3], [2,5]].

I tried this but it returns an empty list and I am very confused as to why:

getCommon(_,[],_).
getCommon(Elem, [PointsH|PointsT], CommonPoints):-
    nth0(0, PointsH, CurrElem),
    (CurrElem = Elem -> append(CommonPoints,[PointsH],NewCommonPoints) ;append(CommonPoints,[],NewCommonPoints)),
    getCommon(Elem, PointsT, NewCommonPoints).

Solution

  • Your code does not work because the recursion base case is not well defined and also because predicate append/3 is not properly used. Try the following code:

    get_common(_, [], []).
    
    get_common(K, [[K,Y]|Points], [[K,Y]|Rest]) :- 
        get_common(K, Points, Rest).
    
    get_common(K, [[X,_]|Points], Rest) :- 
        dif(K,X), 
        get_common(K, Points, Rest).
    

    Examples:

    ?- get_common(2, [[2,3], [3,2], [2,5], [3,7]], Common).
    Common = [[2, 3], [2, 5]] ;
    false.
    
    ?- get_common(3, [[2,3], [3,2], [2,5], [3,7]], Common).
    Common = [[3, 2], [3, 7]] ;
    false.
    
    ?- get_common(2, [[2,3], [K,2], [2,5], [3,7]], Common).
    K = 2,
    Common = [[2, 3], [2, 2], [2, 5]] ;
    Common = [[2, 3], [2, 5]],
    dif(K, 2) ;
    false.