Angel Costeanu
Angel Costeanu

Reputation: 17

How to selectively run a goal in a clause

I'm trying to generate some latex code with prolog. I'm generating nodes connected by edges with the world they belong to. My code is this:

print_valutations(Stream,Number_of_nodes,[Head|Tail]):-
 Number_of_nodes1 is Number_of_nodes+1,
 single_valutation(Stream,Number_of_nodes1,Head),
 print_valutations(Stream,Number_of_nodes1,Tail).

print_valutations(_,_,_):- !.

single_valutation(Stream,Number_of_nodes,[Head|Tail]):-
 write(Stream, "\\node[circle, minimum size=6mm, draw]"),
 write(Stream, "[left of= 10mm]"),
 write(Stream, "[below of= "),
 Number_of_nodes1 is Number_of_nodes-1,
 write(Stream,Number_of_nodes1),
 write(Stream,"]("),
 write(Stream, Number_of_nodes),
 write(Stream,"){"),
 write(Stream,Head),
 writeln(Stream,"};"),
 val(Stream,Number_of_nodes,Tail).

single_valutation(_,_,_):- !.

val(Stream,Node,[Head|Tail]):-
display_val(Stream,Node,Head),
val(Stream,Node,Tail).

val(_,_,_):- !.

display_val(Stream,[]) :-
    write(Stream,"").

display_val(Stream,Node,[Head|Tail]) :-
   write(Stream,"\\draw[->] ("),
   write(Stream,Node),
   write(Stream,") to ("),
   write(Stream,Head),
   writeln(Stream,");"),
   display_val(Stream,Node,Tail).


prova(FileName):-
 open(FileName, write, Stream),
 print_valutations(Stream, 100,[[a,[4]],[b,[3]],[c,[1]]]),
 close(Stream).

And this code generates the following txt file:

    \node[circle, minimum size=6mm, draw][left of= 10mm][below of= 100](101){a};
    \draw[->] (101) to (4);
    \node[circle, minimum size=6mm, draw][left of= 10mm][below of= 101](102){b};
    \draw[->] (102) to (3);
    \node[circle, minimum size=6mm, draw][left of= 10mm][below of= 102](103){c};
    \draw[->] (103) to (1);

What i want is this(leaving left of = 10mm only for the first row):

    \node[circle, minimum size=6mm, draw][left of= 10mm][below of= 100](101){a};
    \draw[->] (101) to (4);
    \node[circle, minimum size=6mm, draw][below of= 101](102){b};
    \draw[->] (102) to (3);
    \node[circle, minimum size=6mm, draw][below of= 102](103){c};
    \draw[->] (103) to (1);

How can i do it?

Upvotes: 0

Views: 83

Answers (1)

Guy Coder
Guy Coder

Reputation: 24976

First off I agree with Paulo that you should use DCGs.


Concept of answer.

One option is to add a guard around

write(Stream, "[left of= 10mm]")

e.g.

(
    <guard>
->
   write(Stream, "[left of= 10mm]")
;
   true
)

See: Predicate ->/2

The guard needs to check when processing the first item in the list.


Working code.

Only the modified code is here. The rest stays the same. It also threw a file error, but I didn't try to find and fix it as I did not modify the file access code. The generated output is below.

print_valutations(Stream,First, Number_of_nodes,[Head|Tail]):-
    Number_of_nodes1 is Number_of_nodes+1,
    single_valutation(Stream,First,Number_of_nodes1,Head),
    print_valutations(Stream,false,Number_of_nodes1,Tail).
print_valutations(_,_,_,_):- !.

single_valutation(Stream,First,Current_node_position,[Head|Tail]):-
    write(Stream, "\\node[circle, minimum size=6mm, draw]"),
    (
        First
    ->
        write(Stream, "[left of= 10mm]")
    ;
        true
    ),
    write(Stream, "[below of= "),
    Current_node_position1 is Current_node_position-1,
    write(Stream,Current_node_position1),
    write(Stream,"]("),
    write(Stream, Current_node_position),
    write(Stream,"){"),
    write(Stream,Head),
    writeln(Stream,"};"),
    val(Stream,Current_node_position,Tail).
single_valutation(_,_,_,_):- !.

prova(FileName):-
    open(FileName, write, Stream),
    print_valutations(Stream, true, 100, [[a,[4]],[b,[3]],[c,[1]]]),
    close(Stream).

Output

\node[circle, minimum size=6mm, draw][left of= 10mm][below of= 100](101){a};
\draw[->] (101) to (4);
\node[circle, minimum size=6mm, draw][below of= 101](102){b};
\draw[->] (102) to (3);
\node[circle, minimum size=6mm, draw][below of= 102](103){c};
\draw[->] (103) to (1);

Upvotes: 1

Related Questions