we have to create a PROLOG program to print out a square of n x n given character '*' on the screen. use SWIprolog

Viewed 81

write a prolog program to print out a square of n x n given character '*' on the screen.

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

*****
*****
*****
*****
*****
4 Answers

You are talking about squares, no need to pass the width twice.

:- set_prolog_flag(double_quotes, chars).

seq([]) -->
   [].
seq([X|Xs]) -->
   [X],
   seq(Xs).

lines([]) -->
     [].
lines([Line|Lines]) -->
    seq(Line),
    "\n",
    lines(Lines).

n_square_with(N, Sq, Ch) :-
    length(Line, N),
    length(Lines, N),
    maplist(=(Ch), Line),
    maplist(=(Line), Lines),
    phrase(lines(Lines), Sq).

?- n_square_with(N, *, Sq).
   N = 0, Sq = []
;  N = 1, Sq = "*\n"
;  N = 2, Sq = "**\n**\n"
;  N = 3, Sq = "***\n***\n***\n"
;  N = 4, Sq = "****\n****\n****\n****\n"
;  ... .

This predicate n_square_with/3 is true for a size N, some character Ch and a text representing a square of that size. But that is not all you need. Now, you need to do something, you need to print this with format("~s",[Sq]). It is always a good idea to keep that part separated from the pure relations.

do_print_square(N, With) :-
    n_square_with(N, With, Sq),
    format("~s",[Sq]).

?- do_print_square(5,*).
*****
*****
*****
*****
*****
   true.

The obvious solution is a nested loop:

forall(between(1, N, _),
    (   forall(between(1, N, _),
            format("*")),
        format("~n")
    ))

But the answer by false is better for some goodness measure you could come up with.

The format specification ~*c can be used to repeatedly output a given character.

square(N) :-
    forall(between(1, N, _), 
           format('~*c\n', [N, 0'*])).

Example:

?- square(3).
***
***
***
true.

Assuming that this exercise is to teach you something about recursion, you can simply say (in pure ISO Prolog:

square(N,C) :- rectangle(N,N,C) .

rectangle(H,W,C) :- H > 0 , W > 0, lines(H,W,C).

lines(H,W,C) :- H > 0, line(W,C), H1 is H-1, lines(H1,W,C).
lines(0,_,_) .

line(W,C) :- W > 0 , write(C), W1 is W-1, line(W1,C).
line(0,_) :- nl.

Alternatively, using a "failure-driven loop":

square(H,W,C) :- ( between(1,H,_), line(W,C), fail ; true ).

line(W,C) :- ( between(1,W,_), write(C) ; nl ).
Related