Magic square : Help with my homework

  • Follow


This is a multi-part message in MIME format.

------=mesnews_0_1116091355
Content-Type: text/plain; charset="iso-8859-15"
Content-Transfer-Encoding: quoted-printable

Hello!

Yes it is a homework. We've been asked to make a generic magic squares generator (N x N).

I've done a 3 x 3 generator, but whenever it must deal with an arbitrary number of things I am stuck!!

I am not asking for a full solution but some hints on data structure and how to loop through data...

Thank you


------=mesnews_0_1116091355
Content-Type: text/html
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content=3D"text/html; charset=3Dwindows-1252" http-equiv=3DContent-Type>
<META name=3DGENERATOR content=3D"MSHTML 8.00.6001.18852"></HEAD>
<BODY>
<DIV>Hello!</DIV>
<DIV>&nbsp;</DIV>
<DIV>Yes it is a homework. We've been asked to make a generic magic squares 
generator (N x N).</DIV>
<DIV>&nbsp;</DIV>
<DIV>I've done a 3 x 3 generator, but whenever it must deal with an arbitrary 
number of things I am stuck!!</DIV>
<DIV>&nbsp;</DIV>
<DIV>I am not asking for a full solution but some hints on data structure and 
how to loop through data...</DIV>
<DIV>&nbsp;</DIV>
<DIV>Thank you</DIV></BODY></HTML>


------=mesnews_0_1116091355--

0
Reply Thriller 11/16/2009 12:55:47 PM

On 2009-11-16, Thriller <rthriller@gmail.com> wrote:
> This is a multi-part message in MIME format.
>

> Content-Type: text/html
> Content-Transfer-Encoding: quoted-printable
>
><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
> [...]

Please change your settings not to post HTML content.

-- 
Jon Solberg (remove "nospam." from email address).
0
Reply Jon 11/16/2009 2:00:34 PM


On Mon, 16 Nov 2009 13:55:47 +0100, Thriller wrote:


> I've done a 3 x 3 generator

Please post it so we can comment on it.

Cheers

Bart Demoen
0
Reply Bart 11/16/2009 2:32:55 PM

On Nov 16, 8:55=A0pm, Thriller <rthril...@gmail.com> wrote:
> Yes it is a homework. We've been asked to make a generic magic squares ge=
nerator (N x N).
> I've done a 3 x 3 generator, but whenever it must deal with an arbitrary =
number of things I am stuck!!
> I am not asking for a full solution but some hints on data structure and =
how to loop through data...
> Thank you

There're many methods to make a magic square. Some methods are too
easy and tricky that, for example, you put 1 in the lower middle cell
and put 2, 3, ..., 9 one by one right-downwardly, excepting that when
the target cell is occupied you treat the upper cell as new target
cell, and the magic square is done. Do not waste time to write this
kind of program.

It also can be done by generating many alternative magic square. A
very brute method is to compute permutations of 9 numbers,

?- permu([1,2,3,4,5,6,7,8,9], Sq).
Sq =3D [[1,2,3],[4,5,6],[7,8,9]];
Sq =3D [[1,2,3],[4,5,6],[7,9,8]];
etc.,

and check whether they are magic squares. However, it wastes time on
checking useless data.

The method I prefer is that it construct the structure of magic square
step by step according some rules.

0
Reply YauHsienHuang 11/16/2009 2:48:21 PM

On Mon, 16 Nov 2009 13:55:47 +0100, Thriller <rthriller@gmail.com>
wrote:

>Hello!
>
>Yes it is a homework. We've been asked to make a generic magic squares generator (N x N).
>
>I've done a 3 x 3 generator, 

Show the code

A.L.
0
Reply A 11/16/2009 4:08:25 PM

On Nov 16, 7:55=A0am, Thriller <rthril...@gmail.com> wrote:
> Hello!
>
> Yes it is a homework. We've been asked to make a generic magic squares ge=
nerator (N x N).
>
> I've done a 3 x 3 generator, but whenever it must deal with an arbitrary =
number of things I am stuck!!
>
> I am not asking for a full solution but some hints on data structure and =
how to loop through data...
>
> Thank you

Here is a program in B-Prolog. This is not meant to be a solution, but
you may get some hints from it. This program contains too much ad hoc
syntax. I strongly feel that Prolog (and CLP(FD) needs standard syntax
for arrays and loop & list comprehension constructs.

magicSquare(N) :-
    new_array(Matrix,[N,N]),
    NN is N*N,
    term_variables(Matrix,Vars),
    Vars :: 1..NN,
    Sum is NN*(NN+1)//(2*N),
    Matrix^rows @=3DRows,
    foreach(Row in Rows, sum(Row)#=3DSum),
    Matrix^columns @=3DCols,
    foreach(Col in Cols, sum(Col)#=3DSum),
    Matrix^diagonal1 @=3D Diag1,
    sum(Diag1) #=3D Sum,
    Matrix^diagonal2 @=3D Diag2,
    sum(Diag2) #=3D Sum,
    all_different(Vars),
    labeling([ffc],Vars),
    foreach(Row in Rows, writeln(Row)).

Cheers,
Neng-Fa


This program contains too much nonstandard
0
Reply afa 11/16/2009 4:13:52 PM

afa <neng.zhou@gmail.com> writes:
>Here is a program in B-Prolog. This is not meant to be a solution, but
>you may get some hints from it. This program contains too much ad hoc
>syntax. I strongly feel that Prolog (and CLP(FD) needs standard syntax
>for arrays and loop & list comprehension constructs.
>
>magicSquare(N) :-
>    new_array(Matrix,[N,N]),
>    NN is N*N,
>    term_variables(Matrix,Vars),
>    Vars :: 1..NN,
>    Sum is NN*(NN+1)//(2*N),
>    Matrix^rows @=Rows,
>    foreach(Row in Rows, sum(Row)#=Sum),
>    Matrix^columns @=Cols,
>    foreach(Col in Cols, sum(Col)#=Sum),
>    Matrix^diagonal1 @= Diag1,
>    sum(Diag1) #= Sum,
>    Matrix^diagonal2 @= Diag2,
>    sum(Diag2) #= Sum,
>    all_different(Vars),
>    labeling([ffc],Vars),
>    foreach(Row in Rows, writeln(Row)).

Let's start with the good news first!

You are using strict ISO syntax!  Fine!  That is, you do not need to
plead the very hairy 5.5.1 Syntax for a syntax extension.  Every
standard conforming processor should be able to read your program -
syntactically - by using appropriate operator declarations *only*.  I
wish things would be that easy in other areas.  There are many ad hoc
syntax extensions that render programs entirely unreadable by other
systems.

What you effectively extended was in some sense 5.5.2 Predefined
operators.


Let's start with the basic syntax for domains.  Markus Triska had
this ingenious idea to improve the syntax for domains as follows (see
SWI or YAP's library(clpfd).  For the query

?- X in 0..9, X #\= 3, #\= 5.

The domain of X develops traditionally as follows (SICStus 3 syntax):

| ?- X in 0..9, ( true ; X #\= 3, ( true ; X #\= 5 ) ).
X in 0..9 ? ;
X in(0..2)\/(4..9) ? ;
X in(0..2)\/{4}\/(6..9) ? ;
no

Now, in SWI thanks to :- op( 450, xfx, ..).  we have:

?- X in 0..9, ( true ; X #\= 3, ( true ; X #\= 5 ) ).
X in 0..9 ?
X in 0..2\/4..9 ?
X in 0..2\/4\/6..9.

So this was a minimal syntax tree change: singletons are now
represented as the integers themselves.  That removed the { }.  And
then the slight change of the operator declaration for .. results in
the removal of all the other parentheses.

In fact, in my running SICStus 3 programs I changed the predefined
operator declaration op(550, xfx, ..) to the one above.  This makes
things not only much smoother to look at.  It is als much less of a
chore when writing things down.


To keep this posting short only one more comment:

Using library(apply)'s maplist/2 - common practice since at least 1984
(originally 1981 under the name have_property/2 with the less
fortunate argument order) and using library(lambda) in - of course -
ISO syntax:

>    foreach(Row in Rows, sum(Row)#=Sum),

  maplist(Sum+\Row^sum(Row,#=,Sum), Rows)

http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl
0
Reply ulrich 11/16/2009 4:36:19 PM

This solution seems using Prolog to write a procedural program.


On Nov 17, 12:13=A0am, afa <neng.z...@gmail.com> wrote:
> Here is a program in B-Prolog. This is not meant to be a solution, but
....
> magicSquare(N) :-
> =A0 =A0 new_array(Matrix,[N,N]),
> =A0 =A0 NN is N*N,
> =A0 =A0 term_variables(Matrix,Vars),
> =A0 =A0 Vars :: 1..NN,
> =A0 =A0 Sum is NN*(NN+1)//(2*N),
> =A0 =A0 Matrix^rows @=3DRows,
> =A0 =A0 foreach(Row in Rows, sum(Row)#=3DSum),
> =A0 =A0 Matrix^columns @=3DCols,
> =A0 =A0 foreach(Col in Cols, sum(Col)#=3DSum),
> =A0 =A0 Matrix^diagonal1 @=3D Diag1,
> =A0 =A0 sum(Diag1) #=3D Sum,
> =A0 =A0 Matrix^diagonal2 @=3D Diag2,
> =A0 =A0 sum(Diag2) #=3D Sum,
> =A0 =A0 all_different(Vars),
> =A0 =A0 labeling([ffc],Vars),
> =A0 =A0 foreach(Row in Rows, writeln(Row)).
>
> Cheers,
> Neng-Fa
>
> This program contains too much nonstandard

0
Reply YauHsienHuang 11/16/2009 4:59:56 PM

On Nov 16, 8:55=A0pm, Thriller <rthril...@gmail.com> wrote:
> Hello!
> Yes it is a homework. We've been asked to make a generic magic squares ge=
nerator (N x N).
> I've done a 3 x 3 generator, but whenever it must deal with an arbitrary =
number of things I am stuck!!
> I am not asking for a full solution but some hints on data structure and =
how to loop through data...
> Thank you

Back to the problem. When thinking of what properties cause a magic
square, we say that if a number X is picked out from the list
[1,2,3,4,5,6,7,8,9], other numbers can be paired two by two and the
sum of each pair is (45/3 - X), e.g., [(1, 9), (2, 8), (3, 7), (4,
6)]. Surrounding numbers are made of four of these pairs. The property
implies one of vertical lines, one of horizontal lines, and two
diagonal lines have the same sum. Then, the other property for
checking sums of other lines must be added.

You may need some domain definition which Ulrich described. My domain
definition and operation was achieved by defining two goals: range/3
and element_at/3,

range(M, N, []) :- M > N, !.
range(N, N, [N]) :- !.
range(M, N, [M|Z]) :- M1 is M+1, range(M1, N, Z).

element_at([X|_], 1, X).
element_at([_|Y], N, Z) :- element_at(Y, N1, Z), N is N1+1.
0
Reply YauHsienHuang 11/16/2009 6:36:39 PM

YauHsienHuang <g9414002.pccu.edu.tw@gmail.com> writes:
>On Nov 16, 8:55=A0pm, Thriller <rthril...@gmail.com> wrote:
>> Hello!
>> Yes it is a homework. We've been asked to make a generic magic squares ge=
>nerator (N x N).
>> I've done a 3 x 3 generator, but whenever it must deal with an arbitrary =
>number of things I am stuck!!
>> I am not asking for a full solution but some hints on data structure and =
>how to loop through data...
>> Thank you
>
>Back to the problem. When thinking of what properties cause a magic
>square, we say that if a number X is picked out from the list
>[1,2,3,4,5,6,7,8,9], other numbers can be paired two by two and the
>sum of each pair is (45/3 - X), e.g., [(1, 9), (2, 8), (3, 7), (4,
>6)]. Surrounding numbers are made of four of these pairs. The property
>implies one of vertical lines, one of horizontal lines, and two
>diagonal lines have the same sum. Then, the other property for
>checking sums of other lines must be added.
>
>You may need some domain definition which Ulrich described. My domain
>definition and operation was achieved by defining two goals: range/3
>and element_at/3,
>
>range(M, N, []) :- M > N, !.
>range(N, N, [N]) :- !.
>range(M, N, [M|Z]) :- M1 is M+1, range(M1, N, Z).

?- range(1,0,Xs), Xs=[1].
false.

?- Xs = [1], range(1,0,Xs).
Xs = [1].

It is for such reasons, that constraints are often preferable even
in "simple" programs.   In fact, I consider constraint programs
most often easer to write and debug than their traditional counterparts
(for similar purposes indeed).
0
Reply ulrich 11/16/2009 6:55:59 PM

We use ECLiPSe CLP
Here is my code for 3 * 3 square:

/* carre(C1,C2,C3,C4,C5,C6,C7,C8,C9). */
:- lib(ic).

carre(C1,C2,C3,C4,C5,C6,C7,C8,C9):-
	Dcarre=[C1,C2,C3,C4,C5,C6,C7,C8,C9],
	Dcarre #::1..9,
	alldifferent(Dcarre),
	C1+C2+C3 #= C4+C5+C6,
	C1+C2+C3 #= C7+C8+C9,
	C1+C2+C3 #= C1+C5+C9,
	C1+C2+C3 #= C3+C5+C7,
	labeling(Dcarre).




Apr�s m�re r�flexion, Thriller a �crit :
> Hello!
>
> Yes it is a homework. We've been asked to make a generic magic squares 
> generator (N x N).
>
> I've done a 3 x 3 generator, but whenever it must deal with an arbitrary 
> number of things I am stuck!!
>
> I am not asking for a full solution but some hints on data structure and how 
> to loop through data...
>
> Thank you


0
Reply Thriller 11/16/2009 7:43:56 PM

On Nov 16, 11:36=A0am, ulr...@mips.complang.tuwien.ac.at (Ulrich
Neumerkel) wrote:

>
> Let's start with the good news first!
> You are using strict ISO syntax!  Fine!  That is, you do not need to

Good and bad. The Prolog syntax is very old. After 35 years, maybe
it's time to reconsider it. For example, for the constraint

    Matrix^rows @=3DRows,
    foreach(Row in Rows, sum(Row)#=3DSum),

I would like to write it using list comprehension as follows:

    foreach(I in 1..N,sum([Matrix[I][J] || J in 1..N])#=3D3),

and for the constraint

    Matrix^diagonal1 @=3D Diag1,
    sum(Diag1) #=3D Sum,

I'd like to write it as follows:

    sum([Matrix[I][I] || I in 1..N]) #=3D 3,

Earlang and most functional languages have list comprehensions and
loop constructs. We should learn from them now.

> > =A0 =A0foreach(Row in Rows, sum(Row)#=3DSum),
>
> =A0 maplist(Sum+\Row^sum(Row,#=3D,Sum), Rows)
>
> http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl

I think foreach is more readable than maplist for this case. I just
realized that the last line of my program should be like the
following:

    foreach(Row in Rows, (foreach(I in Row, format("~4d ",[I])),nl)).

which prints the matrix more neatly.

Cheers,
Neng-Fa


0
Reply afa 11/16/2009 8:30:58 PM

afa <neng.zhou@gmail.com> writes:
>On Nov 16, 11:36=A0am, ulr...@mips.complang.tuwien.ac.at (Ulrich
>Neumerkel) wrote:
>
>>
>> Let's start with the good news first!
>> You are using strict ISO syntax!  Fine!  That is, you do not need to
>
>Good and bad. The Prolog syntax is very old. After 35 years, maybe
>it's time to reconsider it. For example, for the constraint

How often have I heard similar complaints.  So far it always
turned out that coming back to Prolog is the better option.
Maybe it's just that Prolog is much more stable than all
experimental languages due to its dual use both for pure
and impure things alike.

For long, people said that lambda expressions need special syntax
support.  Now we know: no need for that.

Then (some time ago) higher order programming was claimed
to be not (elegantly) possible in Prolog - while ignoring
call/N, indeed.  Then, that some particular versatile higher
order styles (apply/3) were not possible with call/N.  False
again.

You know the age of s-expressions - just to put 35 years into
perspective?  Maybe, after 35 years, it's time to fully exploit
it.

>I would like to write it using list comprehension as follows:
>
>    foreach(I in 1..N,sum([Matrix[I][J] || J in 1..N])#=3),

Only looking at Matrix[I][J] - something like m(M, I, J) would
not do? Probably not, some nesting seems to be useful - but
I do not see any reason why the current syntax could not
support this adequately.  Why not Matrix^I^J or similar...

After all, the most complex question involved is that of
variable scoping.

>Erlang and most functional languages have list comprehensions and
>loop constructs. We should learn from them now.

On the other hand, comprehensions are often used to simulate
Prolog's capabilities in FP.  Haven't we recently attended a
talk on some constraint monad?

Certainly I agree with you that we need more in that direction.

>>  maplist(Sum+\Row^sum(Row,#=,Sum), Rows)
>>
>> http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl
>
>I think foreach is more readable than maplist for this case. I just
>realized that the last line of my program should be like the
>following:
>
>    foreach(Row in Rows, (foreach(I in Row, format("~4d ",[I])),nl)).
>
>which prints the matrix more neatly.

What is very unituitive in maplist/2 is this unnatural separation
of Rows and Row above.  I do not like that in Lisp as well.  The
things that belong together should be next to each other visually.
In your foreach construct they are very close.   There are examples
were the distance is even larger - if more than one goal is
involved - or some nested goal.

But are you sure of the scoping involved?

call/N - although presented the first time publicly in 1987 -
has still not received the attention it deserves.  By consequence,
there has not been much work on methodologies based on call/N.
We have maplist/N. Fine, but there is more to it.  Much more -
if you look into FP.  There, comprehensions were not created
ex nihilo, but they developed out of various existing higher
order methodologies.

It seems that we would have to take a somewhat similar path
to reach the same goals.  Certainly if we would reach the goals,
it would be much more general - as usual in Prolog.

For pure, monotonic relations - such constructs should preserve
monotonicity as well as termination properties.  So far I have
not seen an approach that offers all that.  While maplist/N
does guarantee these properties, it is not expressible
enough.  We need much more than that.

The property of monotonicity is very precious.  It helps
e.g. to diagnose failure.  To illustrate this I have written
a very tiny library to explain failures by generalizing a query:

http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/diadem.pl
0
Reply ulrich 11/16/2009 9:43:51 PM

Thriller wrote:
> We use ECLiPSe CLP
> Here is my code for 3 * 3 square:
> 
> /* carre(C1,C2,C3,C4,C5,C6,C7,C8,C9). */
> :- lib(ic).
> 
> carre(C1,C2,C3,C4,C5,C6,C7,C8,C9):-
>     Dcarre=[C1,C2,C3,C4,C5,C6,C7,C8,C9],
>     Dcarre #::1..9,
>     alldifferent(Dcarre),
>     C1+C2+C3 #= C4+C5+C6,
>     C1+C2+C3 #= C7+C8+C9,
>     C1+C2+C3 #= C1+C5+C9,
>     C1+C2+C3 #= C3+C5+C7,
>     labeling(Dcarre).

The ECLiPSe web site http://eclipse-clp.org/examples/ has a
number of examples of this kind, including a magic square one
http://eclipse-clp.org/examples/magicsquare.ecl.txt


-- Joachim
0
Reply Joachim 11/17/2009 12:54:10 AM

On 16 nov, 17:59, YauHsienHuang <g9414002.pccu.edu...@gmail.com>
wrote:
> This solution seems using Prolog to write a procedural program.
>
> On Nov 17, 12:13=A0am, afa <neng.z...@gmail.com> wrote:
>
> > Here is a program in B-Prolog. This is not meant to be a solution, but
> ...
> > magicSquare(N) :-
> > =A0 =A0 new_array(Matrix,[N,N]),
> > =A0 =A0 NN is N*N,
> > =A0 =A0 term_variables(Matrix,Vars),
> > =A0 =A0 Vars :: 1..NN,
> > =A0 =A0 Sum is NN*(NN+1)//(2*N),
> > =A0 =A0 Matrix^rows @=3DRows,
> > =A0 =A0 foreach(Row in Rows, sum(Row)#=3DSum),
> > =A0 =A0 Matrix^columns @=3DCols,
> > =A0 =A0 foreach(Col in Cols, sum(Col)#=3DSum),
> > =A0 =A0 Matrix^diagonal1 @=3D Diag1,
> > =A0 =A0 sum(Diag1) #=3D Sum,
> > =A0 =A0 Matrix^diagonal2 @=3D Diag2,
> > =A0 =A0 sum(Diag2) #=3D Sum,
> > =A0 =A0 all_different(Vars),
> > =A0 =A0 labeling([ffc],Vars),
> > =A0 =A0 foreach(Row in Rows, writeln(Row)).
>
> > Cheers,
> > Neng-Fa
>
> > This program contains too much nonstandard

Hy,
I'm interesting in that exercice too.
Cause I wanted to know how using variable (N) instead of fixed values
like square of 3x3.

I Have tried your code but it doesn't works. Perhaps you need to
declare a lib for that ? For example to use Vars::1..N you need ic
library :
:- lib(ic).

But I have tried with it and I have some errors with foreach function.
I don't how how it works but it seem to have a mistake.
And what means the @=3D ? and the ^ ?

thank you for your help to understand how i works.

0
Reply PrologBob 11/18/2009 5:36:31 PM

14 Replies
455 Views

(page loaded in 0.702 seconds)

Similiar Articles:


















7/25/2012 11:29:57 PM


Reply: