Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement "For loop" on prolog

How to Implement using recursion and cut-off cycle of the counter (like for i: = 1 downto N do <operator>) ?

like image 225
YURIY KOTSOVSKIY Avatar asked Nov 28 '22 18:11

YURIY KOTSOVSKIY


2 Answers

my naive implementation, to be seen as an extendend between/3

:- module(loop, [upto/4, downto/4]).

upto(Low,High,_Step,Low) :- Low =< High.
upto(Low,High,Step,Var) :-
    Inc is Low+Step,
    Inc =< High,
    upto(Inc, High, Step, Var).

downto(Low,High,_Step,High) :- Low =< High.
downto(Low,High,Step,Var) :-
    Dec is High-Step,
    Dec >= Low,
    downto(Low, Dec, Step, Var).

usage:

8 ?- forall(upto(0,6,3,V),writeln(V)).
0
3
6
true.

9 ?- forall(downto(0,6,3,V),writeln(V)).
6
3
0
true.

another example, the easiest question posed @ this year Prolog programming contest:

icecream(N) :-
    loop(N, top(N)),
    left, loop(N+1, center), nl,
    loop(N+1, bottom(N)).

:- meta_predicate loop(+, 1).

loop(XH, PR) :-
    H is XH,
    forall(between(1, H, I), call(PR, I)).

top(N, I) :-
    left, spc(N-I+1), pop,
    (   I > 1
    ->  pop,
        spc(2*(I-2)),
        pcl
    ;   true
    ),
    pcl, nl.

bottom(N, I) :-
    left, spc(I-1), put(\), spc(2*(N-I+1)), put(/), nl.

center(_) :- put(/), put(\).

left :- spc(4).
pop :- put(0'().
pcl :- put(0')).
spc(Ex) :- V is Ex, forall(between(1, V, _), put(0' )).

yields

?- icecream(4).
        ()
       (())
      ((  ))
     ((    ))
    /\/\/\/\/\
    \        /
     \      /
      \    /
       \  /
        \/
true.

note: loop in the second snippet is unrelated to first...

like image 53
CapelliC Avatar answered Dec 11 '22 03:12

CapelliC


The short answer is that you don't.

Prolog is a declaritive language, not a procedural language. It comes from the predicate calculus. You describe the problem space in terms of facts and rules (the "database"). This forms a collection of connected, directed graphs.

You formulate an initial goal that describes the solution to your "problem" and let the inference engine find the solution(s), if any.

The inference engine starts with the initial goal you give it. It evaluates it in terms of the database, walking the graph as it goes, backtracking on failure, until it finds a solution (or not). Backtracking into the initial goal will cause it to look for the next solution, if any.

So the notion of a procedural construct such as a loop is rather non-idiomatic (to say the least) and (in my experience, at least) is pretty much a guarantee of poor performance.

like image 38
Nicholas Carey Avatar answered Dec 11 '22 03:12

Nicholas Carey