1
votes

Write a Prolog program to print out a square of n*n given characters on the screen. Call your predicate square/2. The first argument should be a (positive) integer. the second argument the character (any Prolog term) to be printed. Example:

?-square(5, '*').
*****
*****
*****
*****
*****
Yes

I just start to learn this language. I did this:

square(_,'_').
square(N, 'B') :-
        N>0,
        write(N*'B').

It doesn't work at all. Can anyone help me?

4
can you write one character? ?- write_one('c'). will print c. Can you write this predicate?Will Ness
write(N*'B') is asking Prolog to write out the expression N*'B'. Prolog does not evaluate arithmetic expressions outside is/2 expressions, and besides that there is no facility to create atoms through repetition of other atoms this way. Try harder. You can do it, you just have to be very explicit.Daniel Lyons

4 Answers

3
votes

So your question is, basically, "how do I write a loop nested in a loop?"

This is how you write an empty loop with an integer for a counter:

loop(0).
loop(N) :- N > 0, N0 is N-1, loop(N0).

which in C would be:

for(i=0; i < n; ++i) { }

And you seem to know already how to print (write(foo)).

0
votes

Decompose the problem. To write an NxN square, you need to do two things:

  1. Write N lines
  2. Write a single line, consisting of N characters followed by a newline character.

The second is easy:

do_line(0,_) :-
  nl
  .
do_line(N,C) :-
  N > 0 ,
  write(C) ,
  N1 is N-1 ,
  do_line(N1,C)
  .

The first isn't much more difficult:

do_lines(0,_,_).
do_lines(M,N,C) :-
  M > 0 ,
  do_line(N,C) ,
  M1 is M-1 ,
  do_lines(M1,N,C)
  .

The all you need to do is wrap it:

write_square(N,C) :- do_lines(N,N,C) .

Easy!

0
votes

You need to draw a line of N stars/characters

line(N,X):- N>0, N1 is N-1, line(N1,X), write(X), fail; true.

Then you will draw a column of N lines of stars/characters.

s(N,Chr):-sAux(N,0,Chr). sAux(N,N,Chr). sAux(N,C,Chr):-C<N, C1 is C+1, sAux(N, C1, Chr), line(N,Chr),nl. s(N,Chr):- N>0, N1 is N-1, s(N1,X), linie(N,X), nl, fail;true.

0
votes

Doing this:

square2(0,_). % base case, recursion stops when X reaches 0, second argument is irrelevent    

square2(X,Symbol):-
  X1 is X - 1,
  write(Symbol),
  square2(X1,Symbol).

With the query, which results in:

?- square2(5,'* ').
* * * * *

Therefore, we need another loop to make it write X times.

square1(0,_,_). % base case, recursion stops when X reaches 0

square1(X,Y,Symbol):-
  X1 is X - 1,
  square2(Y,Symbol), % with the same Y passed in square2 predicate to print a line of symbols
  nl, % creates a new line
  square1(X1,Y,Symbol).

However, the question is asking for the format with square(5, '* '). Therefore,

square(X,Symbol):-
  square1(X,X,Symbol).

To wrap up:

square(X,Symbol):-
  square1(X,X,Symbol).

square1(0,_,_).      
square1(X,Y,Symbol):-
  X1 is X - 1,
  square2(Y,Symbol), 
  nl,
  square1(X1,Y,Symbol).

square2(0,_).    
square2(X,Symbol):-
  X1 is X - 1,
  write(Symbol),
  square2(X1,Symbol).