Abderrahmane TAHRI JOUTI
Abderrahmane TAHRI JOUTI

Reputation: 4273

How to print a set of numbers using repeat/0 in prolog?

in an exercice I have to write a predicate that prints numbers < N using repeat/0, here is what I have tried :

loop(N) :-
    repeat,
        write(N), nl,
        N is N-1,
        write(N),
        N > 0,
    !.

but it only prints the given number N Endlessly.

Any Idea how to implement this using repeat/0 ?? thank you

Upvotes: 1

Views: 6231

Answers (7)

rashedcs
rashedcs

Reputation: 3725

A simple way :

loop(N) :-
    between(1, N, X),
    writeln(X),
    X >= N, !.
    loop(X).

Upvotes: 0

Anniepoo
Anniepoo

Reputation: 2162

Abderrahmane asked about how to decrement.

Couple ways to do this. Most people would do

dec(0).
dec(N) :-
   write(N), nl,
   NewN is N - 1,
   dec(NewN).

if you insist on a failure driven loop, how about

dec(N) :-
    between(1,N,X),
    Dec is 11 - X,
    write(Dec), nl,
    Dec = 1.

or, and this is ugly and bad style (and slow as molasses):

dec(N) :-
      assert(current_n(N)),
      repeat,
      current_n(Y),
      write(Y), nl,
      NewY is Y - 1,
      retractall(current_n(_)).
      assert(current_n(NewY)),
      Y > 0.

Upvotes: 1

CapelliC
CapelliC

Reputation: 60024

I would introduce a service predicate

isint(I) :- I = 0 ; isint(T), I is T + 1.

this is needed to scope in a new variable (practically solve the point that Anniepoo highlighted in her first response).

Then I could write

loop(N) :-
  repeat,
  isint(I),
  write(I), nl,
  I >= N, !.

Upvotes: 1

Abderrahmane TAHRI JOUTI
Abderrahmane TAHRI JOUTI

Reputation: 4273

I finally got to make it work using the predicate between/3 this is my final code :

loop(N) :-
    repeat,
        between(1, N, X),
        writeln(X),
        X = N,
    !.

Edit : as @CookieMonster said, repeat/0 is not needed, so here is the last version of the code :

loop(N) :-
        between(1, N, X),
        writeln(X),
        false.

Upvotes: 2

Anniepoo
Anniepoo

Reputation: 2162

Your original one doesn't work for various reasons, but in particular

loop(N) :-
    repeat,
        write(N), nl,
        N is N-1,                <--- no!
        write(N),
        N > 0,
    !.

"is" unifies if the left side is the mathematical result of the right. the left side will be bound to the right. you can't change the value of a var once you've set it in Prolog.

Upvotes: 2

mat
mat

Reputation: 40768

What about:

loop(N) :-
        between(1, N, X),
        writeln(X),
        false.

Upvotes: 2

joel76
joel76

Reputation: 5645

you can use assert/retract eg

:- dynamic value/1.
loop(N) :-
    retractall(value(_)),
    assert(value(N)),
    repeat,
            retract(value(V)),
            writeln(V),
            V1 is V - 1,
            assert(value(V1)),
            V = 0,
    !.

Upvotes: 2

Related Questions