Search code examples
prolog

How can I create a function in prolog that iterates through a list of lists and before passing to the next list goes through the one it´s pointing at?


Iam trying to make a function that iterartes through a list of lists, but before passing to the next element, it iterates trught the list it´s pointing at. I already have a function that separates a list in triplets (triplets(List, Triplets)), if I have the list Triplets which is a list of lists of three elements [[o,o,x],[o,x,x],[x,x,o],[x,o,x],[o,x,o],[x,o,o]], I want to go through Triplets, get the elements of the first list, and use them in a function that applies a set of rules to the triplets and so on. The function Apply_rule would take the the triplet and convert the middle element ('x' or 'o') into an 'x' or an 'o' depending on the elements on the sides.

This are the functions I want to use

% Color definition
color(o).
color(x).

% Rule definition
rule(o,o,o,_,o). % Null rule
rule(x,o,o,r(A,_,_,_,_,_,_),A) :- color(A).
rule(o,x,o,r(_,B,_,_,_,_,_),B) :- color(B).
rule(o,o,x,r(_,_,C,_,_,_,_),C) :- color(C).
rule(x,o,x,r(_,_,_,D,_,_,_),D) :- color(D).
rule(x,x,o,r(_,_,_,_,E,_,_),E) :- color(E).
rule(o,x,x,r(_,_,_,_,_,F,_),F) :- color(F).
rule(x,x,x,r(_,_,_,_,_,_,G),G) :- color(G).

%Creates a list of lists of triplets form a list given
triplets(List, Triplets) :-
    triplets_helper([o|List], Triplets).          % insert null at beginning   

triplets_helper([X1,X2], [[X1,X2,o]]) :- !.       % insert null at the end
triplets_helper([X1,X2,X3|Xs], [[X1,X2,X3]|Ys]) :-
    triplets_helper([X2,X3|Xs], Ys).

%Applies the rules to each triplet    
apply_rule(X,Y,Z,Re) :- 
 R=r(x,o,x,x,x,x,o), rule(X,Y,Z,R,Sol),
 Re = Sol.

As an example I would have to introduce the list [o,x,x,o,x,o] into the function Triplets, giving [[o,o,x],[o,x,x],[x,x,o],[x,o,x],[o,x,o],[x,o,o]] then the function I don´t know how to code would pass each triplet through the function Apply_rule and introduce that value 'x' or 'o' in a result list.


Solution

  • One way is to call apply_rule on each triplet while it is constructed in triplets_helper. The results can be stored in a third list similar to how you store [[X1,X2,X3]|Ys] currently, i.e., as [Sol|Sols].

    % Color definition
    color(o).
    color(x).
    
    % Rule definition
    rule(o,o,o,_,o). % Null rule
    rule(x,o,o,r(A,_,_,_,_,_,_),A) :- color(A).
    rule(o,x,o,r(_,B,_,_,_,_,_),B) :- color(B).
    rule(o,o,x,r(_,_,C,_,_,_,_),C) :- color(C).
    rule(x,o,x,r(_,_,_,D,_,_,_),D) :- color(D).
    rule(x,x,o,r(_,_,_,_,E,_,_),E) :- color(E).
    rule(o,x,x,r(_,_,_,_,_,F,_),F) :- color(F).
    rule(x,x,x,r(_,_,_,_,_,_,G),G) :- color(G).
    
    %Creates a list of lists of triplets form a list given
    triplets(List, Triplets, Sols) :-
        triplets_helper([o|List], Triplets, Sols).          % insert null at beginning   
    
    triplets_helper([X1,X2], [[X1,X2,o]], [Sol]) :- 
        apply_rule(X1,X2,o,Sol),
        !.                                                  % insert null at the end
    triplets_helper([X1,X2,X3|Xs], [[X1,X2,X3]|Ys], [Sol|Sols]) :-
        apply_rule(X1,X2,X3,Sol),
        triplets_helper([X2,X3|Xs], Ys, Sols).
    
    %Applies the rules to each triplet    
    apply_rule(X,Y,Z,Re) :- 
     R=r(x,o,x,x,x,x,o), rule(X,Y,Z,R,Sol),
     Re = Sol.
    

    Query:

    ?- triplets([o,x,x,o,x,o],L,Sols).
    L = [[o, o, x], [o, x, x], [x, x, o], [x, o, x], [o, x, o], [x, o, o]],
    Sols = [x, x, x, x, o, x] .
    

    If you want to add fixed elements to the list then you can do that in the triplets() predicate. An o in front can be done by [o|Sols], however for an o at the end you need to use append().

    triplets(List, Triplets, [o|Solso]) :-
        triplets_helper([o|List], Triplets, Sols),          % insert null at beginning
        append(Sols,[o],Solso).