Search code examples
prolog

I am having problems getting a list of lists into a single list


I am writing a solution to working out distances between numbers in a list using recursion, but have been struggling with getting the intended output. I am trying to get a list of lists into a single list, but attempts at using flatten and append/2 aren't working. I have tried for hours, and keep going around in circles, can someone tell me what i'm doing wrong please?

:- use_module(library(clpfd)).

difference([],_,[]).
differwnce([L|Ls],X,[DST|Ds]) :-
   DST #= abs(X - L),
   difference(Ls,X,Ds).

differences[],[]).
differences([L|Ls], [DST|Tail]) :-
   difference(Ls,X,DST),
   differences(Ls, Tail).

Here is the intended input and output:-

?- differences([1,2,4,9],Ds).
Ds = [1,3,8,2,7,5].

Current Output:

Ds = [[1,3,8],[2,7],[5],[]].

Solution

  • You can convert your distances/3 predicate into a distances/4 predicate that returns a list tail for the elements that will follow, effectively using an open list:

    :- use_module(library(clpfd)).
    
    distances([], _, Tail, Tail).
    distances([BN| Bs], B, [DST| Ds], Tail) :-
       DST #= abs(B - BN),
       distances(Bs, B, Ds, Tail).
    
    triangle([], []).
    triangle([BN| Bs], Ds) :-
        distances(Bs, BN, Ds, Tail),
        triangle(Bs, Tail).
    

    Sample call:

    ?- triangle([1,2,4,9], Ds).
    Ds = [1, 3, 8, 2, 7, 5].
    

    To better understand this solution consider the results of the following query:

    ?- distances([2,4,9], 1, Ds, Tail).
    Ds = [1, 3, 8| Tail].
    

    This solution is more efficient than calling predicates such as append/2 or flatten/3 at the end.

    P.S. If you still need a distances/3 predicate to use elsewhere, you can define it easily:

    distances(Bs, B, Ds) :-
        distances(Bs, B, Ds, []).