Author |
Message |
Alex MacAskil #1 / 31
|
 Magic Square
Well well, another interesting problem :o) So simple (in C,Java,etc,etc) but yet so hard (in PROLOG) Magic Squares. For those that dont know what one is well here is a definition I grabbed off the net: "A magic square is an arrangement of the numbers from 1 to n^2 (n-squared) in an nxn matrix, with each number occurring exactly once, and such that the sum of the entries of any row, any column, or any main diagonal is the same. It is not hard to show that this sum must be n(n^2+1)/2." Examples (used code below to create): order of 3 order of 5 8 1 6 17 24 1 8 15 3 5 7 23 5 7 14 16 4 9 2 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 The code below (in C) will create these magic squares of the odd numbers. void odd_num(int n) { int i,j,num=1; int nn=n*3/2; for(i=0; i < n; i++) for(j=0; j < n; j++) m[(j-i+nn)%n][(i*2-j+n)%n]=num++; Quote: }
Well basically my question is, in Prolog, how is it (or it is) possible to have an two demensional array m[int][int] and then be able to input numbers into this array? i.e in "random" spots From my prolog experience I dont think this is possible is it? I can see how I could use recursion to do the for loops but once i go to pop in the number I'm stuck. Thanks for any help again Alex
|
Tue, 13 Aug 2002 03:00:00 GMT |
|
 |
Noord G.J.M. v #2 / 31
|
 Magic Square
Quote:
> Well well, another interesting problem :o) > So simple (in C,Java,etc,etc) but yet > so hard (in PROLOG) > Magic Squares. For those that dont know what one > is well here is a definition I grabbed off the > net: > "A magic square is an arrangement of the numbers from > 1 to n^2 (n-squared) in an nxn matrix, with each number > occurring exactly once, and such that the sum of the > entries of any row, any column, or any main diagonal is > the same. It is not hard to show that this > sum must be n(n^2+1)/2." > Examples (used code below to create): > order of 3 order of 5 > 8 1 6 17 24 1 8 15 > 3 5 7 23 5 7 14 16 > 4 9 2 4 6 13 20 22 > 10 12 19 21 3 > 11 18 25 2 9 > The code below (in C) will create these magic squares > of the odd numbers. > void odd_num(int n) { > int i,j,num=1; > int nn=n*3/2; > for(i=0; i < n; i++) > for(j=0; j < n; j++) > m[(j-i+nn)%n][(i*2-j+n)%n]=num++; > } > Well basically my question is, in Prolog, how is it > (or it is) possible to have an two demensional array > m[int][int] and then be able to input numbers into this > array? i.e in "random" spots > From my prolog experience I dont think this is possible > is it?
for a two-dimensional array of n x m you could use a functor with arity n, and then you let each argument be a term with functor m; accessing then needs two arg/3 operations. E.g.: 3x3 array: f(f(_,_,_),f(_,_,_),f(_,_,_)). A generic access predicate for twodimensional `arrays': access(X,Y,Term,Arg) :- arg(X,Term,Ys), arg(Y,Ys,Arg). It gets more complicated if you need to be able to alter values as well. -- Gertjan van Noord Alfa-informatica, RUG, Postbus 716, 9700 AS Groningen vannoord at let dot rug dot nl http://www.let.rug.nl/~vannoord/
|
Tue, 13 Aug 2002 03:00:00 GMT |
|
 |
Alex MacAskil #3 / 31
|
 Magic Square
<snip my old message> Quote: > for a two-dimensional array of n x m you could use a functor > with arity n, and then you let each argument be a term with functor m; > accessing then needs two arg/3 operations. > E.g.: 3x3 array: f(f(_,_,_),f(_,_,_),f(_,_,_)). > A generic access predicate for twodimensional `arrays': > access(X,Y,Term,Arg) :- > arg(X,Term,Ys), > arg(Y,Ys,Arg). > It gets more complicated if you need to be able to alter values as > well.
Wow, I havent heard of functor before, or anything your talking about ;o) Its hard to me to learn Prolog, cause I do not have a good book (any book for that matter). I am relying on internet sites to help me through it. I'll *try* to figure that stuff out :o) Thanks Alex Quote: > -- > Gertjan van Noord Alfa-informatica, RUG, Postbus 716, 9700 AS Groningen > vannoord at let dot rug dot nl http://www.let.rug.nl/~vannoord/
|
Tue, 13 Aug 2002 03:00:00 GMT |
|
 |
Alex MacAskil #4 / 31
|
 Magic Square
Quote:
> <snip my old message> > > for a two-dimensional array of n x m you could use a functor > > with arity n, and then you let each argument be a term with functor m; > > accessing then needs two arg/3 operations. > > E.g.: 3x3 array: f(f(_,_,_),f(_,_,_),f(_,_,_)). > > A generic access predicate for twodimensional `arrays': > > access(X,Y,Term,Arg) :- > > arg(X,Term,Ys), > > arg(Y,Ys,Arg). > > It gets more complicated if you need to be able to alter values as > > well. > Wow, I havent heard of functor before, or anything your > talking about ;o) > Its hard to me to learn Prolog, cause I do not have a good > book (any book for that matter). I am relying on internet > sites to help me through it. > I'll *try* to figure that stuff out :o)
Okay, starting to narrow things down. Here's what I have/know now. If I have f(f(1,2,3),f(4,5,6),f(7,8,9)). I can use: show(A,B,C) :- f(A,B,C). to show the values like so: ?- show(A,B,C). A = f(1, 2, 3) B = f(4, 5, 6) C = f(7, 8, 9) Yes ?- Okay, so thats perfect. But I still have one problem, which is getting values into the functor. Going back to my original problem of the magic squares. I still dont know how to get values INTO the 'array'. Like, how do I start with a empty 3x3 array and place values into it, say put 1 into f(1,2) and 5 into f(3,2) and so on. Using my formula to calculate where the values for the magic square go. Could I have something like this: magic(N, f(f(_,_,_),f(_,_,_),f(_,_,_))) :- A = 5, B=1,C=2, insert( A , f, B, C). % insert 5 into f(1,2) like % f(f(_,5,_),f(_,_,_),f(_,_,_)) insert(A, f, B, C) :- I dont even know where to start So then my magic sqaures would look something like this: /*************************************************/ /* C code of what I want to accomplish */ /* */ /* void odd_num(int n) { */ /* int i,j,num=1; */ /* int nn=n*3/2; */ /* for(i=0; i < n; i++) */ /* for(j=0; j < n; j++) */ /* m[(j-i+nn)%n][(i*2-j+n)%n]=num++; */ /* } */ /*************************************************/ magic(N , f) :- NN is (N*3/2), Num is Num+1, I <= N, I is I+1, J <= N, J is J+1, magic(N,f), % to do first loop magic(N,f), % to do second loop S1 is ((j-i+nn) mod n), S2 is ((i*2-j+n) mod n), insert(Num, f, S1, S2). Thats my basic idea. I know it dont work :o( Also what is mod (remainder) in prolog? Damn, the more I think the more questions Thanks Alex Quote: > Thanks > Alex > > -- > > Gertjan van Noord Alfa-informatica, RUG, Postbus 716, 9700 AS Groningen > > vannoord at let dot rug dot nl http://www.let.rug.nl/~vannoord/
|
Tue, 13 Aug 2002 03:00:00 GMT |
|
 |
Alexander G. Hale #5 / 31
|
 Magic Square
What if you base your array structure as the following.. makelist(0,[]) :- !. makelist(Dim, [[]|MoreList]) :- !, DimLeft is Dim - 1, makelist(Dim,MoreList). createarray([],[]). createarray([Dim],[Array]) :- !, makelist(Dim,Array). createarray([Dim|MoreDim], [Front|Array]) :- !, makelist(Dim,Front), createarray(MoreDim,Array). this would create an `empty' array comprised of `lists-of-lists' that can represent the data. for example, to create a 3 x 3 array, one would do. createarray([3,3],X). X = [ [ [], [], [] ] , [ [], [], [] ] ] that could be used to put in numbers in random spots... Quote:
> Well well, another interesting problem :o) > So simple (in C,Java,etc,etc) but yet > so hard (in PROLOG) > Magic Squares. For those that dont know what one > is well here is a definition I grabbed off the > net: > "A magic square is an arrangement of the numbers from > 1 to n^2 (n-squared) in an nxn matrix, with each number > occurring exactly once, and such that the sum of the > entries of any row, any column, or any main diagonal is > the same. It is not hard to show that this > sum must be n(n^2+1)/2." > Examples (used code below to create): > order of 3 order of 5 > 8 1 6 17 24 1 8 15 > 3 5 7 23 5 7 14 16 > 4 9 2 4 6 13 20 22 > 10 12 19 21 3 > 11 18 25 2 9 > The code below (in C) will create these magic squares > of the odd numbers. > void odd_num(int n) { > int i,j,num=1; > int nn=n*3/2; > for(i=0; i < n; i++) > for(j=0; j < n; j++) > m[(j-i+nn)%n][(i*2-j+n)%n]=num++; > } > Well basically my question is, in Prolog, how is it > (or it is) possible to have an two demensional array > m[int][int] and then be able to input numbers into this > array? i.e in "random" spots > From my prolog experience I dont think this is possible > is it? > I can see how I could use recursion to do the for loops > but once i go to pop in the number I'm stuck. > Thanks for any help again > Alex
|
Tue, 13 Aug 2002 03:00:00 GMT |
|
 |
Noord G.J.M. v #6 / 31
|
 Magic Square
Quote:
> > <snip my old message> > > > for a two-dimensional array of n x m you could use a functor > > > with arity n, and then you let each argument be a term with functor m; > > > accessing then needs two arg/3 operations. > > > E.g.: 3x3 array: f(f(_,_,_),f(_,_,_),f(_,_,_)). > > > A generic access predicate for twodimensional `arrays': > > > access(X,Y,Term,Arg) :- > > > arg(X,Term,Ys), > > > arg(Y,Ys,Arg). > > > It gets more complicated if you need to be able to alter values as > > > well. > > Wow, I havent heard of functor before, or anything your > > talking about ;o) > > Its hard to me to learn Prolog, cause I do not have a good > > book (any book for that matter). I am relying on internet > > sites to help me through it. > > I'll *try* to figure that stuff out :o) > Okay, starting to narrow things down. > Here's what I have/know now. > If I have > f(f(1,2,3),f(4,5,6),f(7,8,9)). > I can use: > show(A,B,C) :- f(A,B,C). > to show the values like so: > ?- show(A,B,C). > A = f(1, 2, 3) > B = f(4, 5, 6) > C = f(7, 8, 9) > Yes > ?- > Okay, so thats perfect. > But I still have one problem, which is getting values > into the functor.
that's what access/4 was supposed to accomplish. e.g. suppose F=f(f(_,_,_),f(_,_,_),f(_,_,_)), then access(1,3,F,27) will bind F to: F=f(f(_,_,27),f(_,_,_),f(_,_,_)) etc. but, reading an introductory book on Prolog might be the best way to proceed. In the old days, there used to be buildings (called `libraries') where you could read books (almost) for free... Gj -- Gertjan van Noord Alfa-informatica, RUG, Postbus 716, 9700 AS Groningen vannoord at let dot rug dot nl http://www.let.rug.nl/~vannoord/
|
Wed, 14 Aug 2002 03:00:00 GMT |
|
 |
Martin Sondergaar #7 / 31
|
 Magic Square
Alex asked : ... Quote: > Well basically my question is, in Prolog, how is it > (or it is) possible to have an two demensional array > m[int][int] and then be able to input numbers into this > array? i.e in "random" spots > From my prolog experience I dont think this is possible > is it?
Yes it is. At least, I can do it for a 3 * 3 array. I show you how below. Its not obvious, but its easy when you know how. Quote: > I can see how I could use recursion to do the for loops > but once i go to pop in the number I'm stuck.
No, don't use recursion, far too complicated. Use "fail" instead of using recursion. If you have a magic square three columns wide, lets use variables "A1, A2, A3, B1, B2, B3, C1, C2, C3" for the 9 positions. Like this :- number( 0 ). number( 1 ). number( 2 ). number( 3 ). number( 4 ). number( 5 ). number( 6 ). number( 7 ). ... etc. ... number( 15 ). find_all_possible_numbers :- number( A1 ), number( A2 ), number( A3 ), number( B1 ), number( B2 ), number( B3 ), number( C1 ), number( C2 ), number( C3 ), % Now write the numbers. nl, write( A1, ' ', A2, ' ', A3 ), write( B1, ' ', B2, ' ', B3 ), write( C1, ' ', C2, ' ', C3 ), % Now go on to find the next set of numbers. fail. % Now write "Finished." find_all_possible_numbers :- n, write( 'Finished.' ). /* Now you need to write a similar program, but exclude most combinations of numbers, so only valid magic squares are printed. Something like this : */ program :- number( A1 ), number( A2 ), number( A3 ), number( B1 ), number( B2 ), number( B3 ), number( C1 ), number( C2 ), number( C3 ), % Add up the numbers. Row_A_total is A1 + A2 + A3, Row_B_total is B1 + B2 + B3, Row_C_total is C1 + C2 + C3, % Fail if the totals are not equal. Row_A_total == Row_B_total, Row_A_total == Row_C_total, % Now write the numbers. nl, write( A1, ' ', A2, ' ', A3 ), write( B1, ' ', B2, ' ', B3 ), write( C1, ' ', C2, ' ', C3 ), % Now go on to find the next set of numbers. fail. program :- n, write( 'Finished.' ). /* You also need to allow for column totals, to make sure they are all identical too. So put this code in the program too : Column_1_total is A1 + B1 + C1, Column_2_total is A2 + B2 + C2, Column_3_total is A3 + B3 + C3, Column_1_total == Row_A_total, Column_2_total == Row_A_total, Column_3_total == Row_A_total, Then do the diagonals in a similar way. Diagonal_1 is A1 + B2 + C3, Diagonal_2 is A3 + B2 + C1, Diagonal_1 == Row_A_total, Diagonal_2 == Row_B_total, */ /* This is quite simple. But I really don't know how to make a version to find magic squares of any size. I'd need to write a different program for each size of square. */ By the way, you can't learn Prolog from the web! I strongly recommend this book as your first book on Prolog : "Prolog Programming for Artificcial Intelligence" by Ivan Bratko, published by Addison-Wesley, in paperback. Martin Sondergaard, London.
|
Thu, 15 Aug 2002 03:00:00 GMT |
|
 |
Daniel Dudle #8 / 31
|
 Magic Square
Quote: > Well well, another interesting problem :o)
Hardly. You are merely trying to apply one known algorithm (of many) to compute a solution for magic squares of odd orders. What is interesting with this mathematical curiosity is finding the number of solutions, excluding mirroring and turning, for a given order. We know that there is1 solution for a MS of the 3rd order and 880 for the 4th order. For a MS of the 5th order there are thought to be in excess of 13 million solutions. Quote: > So simple (in C,Java,etc,etc) but yet > so hard (in PROLOG)
Not necessarily so (see below). [snipped] Quote: > The code below (in C) will create these magic squares > of the odd numbers. > void odd_num(int n) { > int i,j,num=1; > int nn=n*3/2; > for(i=0; i < n; i++) > for(j=0; j < n; j++) > m[(j-i+nn)%n][(i*2-j+n)%n]=num++; > }
You can apply a for-next loop in Prolog too. Let's mimic your C code (keeping a 0-based indexing scheme): odd_num(N):- N1 = N - 1, NN = N * 3 // 2, for(0,N1,I), % row for(0,N1,J), % column I1 is (J - I + NN) mod N, % row offset J1 is (I * 2 -J + N) mod N, % column offset Num is I * N + J + 1, % offset cell's value assert(cell(I1,J1,Num)), next(J,N1), next(I,N1). odd_num(_). for(N,_,N). for(Start,Stop,NumOut):- Start1 is Start + 1, Start1 =< Stop, for(Start1,Stop,NumOut). next(X,X). Quote: > Well basically my question is, in Prolog, how is it > (or it is) possible to have an two demensional array > m[int][int] and then be able to input numbers into this > array? i.e in "random" spots > From my prolog experience I dont think this is possible > is it?
Of course it is. Although Prolog doesn't have arrays, we can mimic them in a number of ways: 1. Single elements: cell(Row,Col,Value) 2. Row elements: row(Row,ColumnValues) 3. Whole array: array(Cells) and variations of these. Which one of these you choose to use will primarily depend upon how values are to be accessed. Single elements are interesting when you often need to access single cells, row elements and the whole array when you often operate on groups of cells. BTW, there's nothing "random" about calculating an offset. [snipped] To display your array you would implement something like this: print_array(N):- N1 = N - 1, for(0,N1,I), % row nl, for(0,N1,J), % column retract(cell(I,J,V)), justify(V,Spaces), write(Spaces), write(V), write(' '), next(J,N1), next(I,N1). print_array(_):- nl, nl. justify(N,' '):- N < 10, !. justify(N, ' '):- N < 100, !. justify(N, ' '):- N < 1000, !. justify(_, ''). To tie it all together: magic_square(N):- (0 is N mod 2 -> fail ; odd_num(N), print_array(N) ). And, finally, to run a query: | ?- magic_square(11). Well, that's a solution for magic squares of odd orders out of the way. It becomes slightly more interesting with even orders. Daniel
|
Thu, 15 Aug 2002 03:00:00 GMT |
|
 |
Daniel Dudle #9 / 31
|
 Magic Square
[snipped] Quote: > % Add up the numbers. > Row_A_total is A1 + A2 + A3, > Row_B_total is B1 + B2 + B3, > Row_C_total is C1 + C2 + C3, > % Fail if the totals are not equal. > Row_A_total == Row_B_total, > Row_A_total == Row_C_total, [snipped] > /* You also need to allow for column totals, > to make sure they are all identical too. > So put this code in the program too : > Column_1_total is A1 + B1 + C1, > Column_2_total is A2 + B2 + C2, > Column_3_total is A3 + B3 + C3, > Column_1_total == Row_A_total, > Column_2_total == Row_A_total, > Column_3_total == Row_A_total, > Then do the diagonals in a similar way. > Diagonal_1 is A1 + B2 + C3, > Diagonal_2 is A3 + B2 + C1, > Diagonal_1 == Row_A_total, > Diagonal_2 == Row_B_total,
The sum of a row, column and main diagonal must be: (N^3 + N) / 2 where N is the magic square's order and ^ is "to the power of". [snipped] Quote: > By the way, you can't learn Prolog from the web! > I strongly recommend this book as your first book on Prolog : > "Prolog Programming for Artificcial Intelligence" by Ivan Bratko, > published by Addison-Wesley, in paperback.
Very good advice and an excellent choice of book (ISBN 0-201-41606-9). Daniel
|
Thu, 15 Aug 2002 03:00:00 GMT |
|
 |
Stefan Kra #10 / 31
|
 Magic Square
Quote:
> So simple (in C,Java,etc,etc) but yet so hard (in PROLOG).
I don't agree. Quote: > Magic Squares. For those that dont know what one is well here is a > definition I grabbed off the net: > "A magic square is an arrangement of the numbers from > 1 to n^2 (n-squared) in an nxn matrix, with each number > occurring exactly once, and such that the sum of the > entries of any row, any column, or any main diagonal is > the same. It is not hard to show that this > sum must be n(n^2+1)/2."
This can easily be expressed in clp(FD), ie. a extension availible for various Prolog-systems that allows you to work with "constraints over a finite-domain". In the following I will give a translation of the definition above for magic-squares of size 3. This code can easily be extended to an arbitrary problem-size. magicsquare3(Mss) :- magicsquare3_(Mss, Zs), labeling([ffc], Zs). magicsquare3_([[M11,M12,M13],[M21,M22,M23],[M31,M32,M33]], Zs) :- Zs = [M11,M12,M13,M21,M22,M23,M31,M32,M33], domain(Zs, 1, 9), all_different(Zs), M11+M12+M13 #= Sum, % rows M21+M22+M23 #= Sum, M31+M32+M33 #= Sum, M11+M21+M31 #= Sum, % columns M12+M22+M32 #= Sum, M13+M23+M33 #= Sum, M11+M22+M33 #= Sum, % diagonals M31+M22+M13 #= Sum, Sum #= 15. Quote: > [code omitted]
This will construct ONE solution for the problem, given a problem-size N. Using Prolog (and clpfd) you can not only generate one solution, but also: . check if some given square is a magic square. . work with partial instatiation (some parts of the square are already known, others are still unknown). . "create" all solutions to the problem. If you want to do the same in C, you would have to implement some algorithm for constraint-satisfaction search (+ backtracking). Conclusion: . Think about the various relations that can be identified. Think of WHAT you want to express. Do not think of HOW this should be executed by the computer. (Remember: Prolog is a declarative language, not an imperative one) . Do NOT try to translate a program from C or another imperative language. This will almost always be a waste of time. . Do NOT use: fail, assert, retract, write, format, !, functor, arg. This list is -- of course -- incomplete... Some of these "predicates" require profund knowledge of prolog-internals. Others indicate a poor programming-style. ciao, Stefan
|
Thu, 15 Aug 2002 03:00:00 GMT |
|
 |
Daniel Dudle #11 / 31
|
 Magic Square
Quote:
> >> void odd_num(int n) { > >> int i,j,num=1; > >> int nn=n*3/2; > >> for(i=0; i < n; i++) > >> for(j=0; j < n; j++) > >> m[(j-i+nn)%n][(i*2-j+n)%n]=num++; > >> } > >You can apply a for-next loop in Prolog too. > Yes, as the saying goes, real programmers can write fortran in _any_ > language. > But using assert/1 and failure-driven loops is not a very > elegant or efficient style for Prolog programming, I believe. > Using recursion tends to lead to more elegant code, IMHO, > and avoiding the use of assert/1 often improves efficiency.
On a general level I agree, although IMHO it's a disservice to newcomers to blindly preach this gospel. To reiterate a statement from one of my recent postings, a good craftsman maintains and uses the right tools for the work in hand. I venture to suggest this is one of those cases where use of failure-driven loops and the internal database can be justified. It provides for short and highly readable code and it is relatively efficient, although there are a couple of places that warrant minor improvements. It's also very fast - a magical square of 21st order is displayed IMMEDIATELY, despite 441 asserts and retracts (and the handicap of running on the Windows' platform). Quote: > So I'd suggest using recursion, and using functor/3 and arg/3 to access > the array. Note that in the code that follows, I've kept the variable > names the same as in the original example, to make it easier to see > the correspondence. But I would suggest that using more meaningful > names (e.g. `Array' rather than `M') would make this code easier to > understand. > % mode odd_num(in, out) is det. > odd_num(N, M) :- > make_array(N, M), > NN is N * 3 // 2, > odd_num_1(N, NN, 0, 1, M). > % recursive loop over I > % mode odd_num_1(in, in, in, in, partial -> ground) is det. > odd_num_1(N, NN, I, Num0, M) :- > ( I = N -> > true > ; > odd_num_2(N, NN, I, 0, Num0, Num1, M), > I1 is I + 1, > odd_num_1(N, NN, I1, Num1, M) > ). > % recursive loop over J > % mode odd_num_2(in, in, in, in, in, out, partial -> ground) is det. > odd_num_2(N, NN, I, J, Num0, Num, M) :- > ( J = N -> > Num = Num0 > ; > X is (J - I + NN) mod N + 1, > Y is (I * 2 - J + N) mod N + 1, > arg(X, M, Vector), > arg(Y, Vector, Num0), > Num1 is Num0 + 1, > J1 is J + 1, > odd_num_2(N, NN, I, J1, Num1, Num, M) > ). > % make_array(N, Array) creates an 2-dimensional NxN array, > % whose elements are unbound variables. > % mode make_array(in, out(partial)) is det. > make_array(N, Array) :- > functor(Array, array, N), > make_array_args(1, N, Array). > % mode make_array_args(in, in, partial -> partial) is det. > make_array_args(I, N, Array) :- > ( I > N -> > true > ; > arg(I, Array, Row), > functor(Row, row, N), > I1 is I + 1, > make_array_args(I1, N, Array) > ). > Note that I documented the mode and determinism of each procedure > (using Mercury-style mode declarations, as it happens). > For production code I would recommend also documenting the data > representation and the types of each predicate's arguments.
Unfortunately, you have not written a complete program, which would serve as a comparison. We can, however, note a considerable increase in code volume and complexity. I therefore have my doubts that a newcomer would benefit from being served such code; indeed, IMO it's much more likely to scare newcomers away from Prolog. (Did I hear a "hurra" from the Mozart/Oz camp?) Quote: > >> Well basically my question is, in Prolog, how is it > >> (or it is) possible to have an two demensional array > >> m[int][int] and then be able to input numbers into this > >> array? i.e in "random" spots > >> From my prolog experience I dont think this is possible > >> is it? > Yes, you can do this using functor/3 and arg/3, see the code above. > Note that this only works for cases where you only need write-once, > but that is indeed all you need for this example. > >BTW, there's nothing "random" about calculating an offset. > I think Alex McAskill means "random" in the sense of > "random access" as opposed to "sequential access".
Mmmm... [snipped] Quote: > >To display your array you would implement something like this:
[snipped] > The side-effect there is a rather {*filter*} -- what happens if you Quote: > want to display the array twice?
Again, on a general level I agree with you but doubt very much that this is applicable here. Anyway, there is nothing to stop you retracting the facts elsewhere, f.ex. on termination of the program, should you so prefer. Daniel
|
Fri, 16 Aug 2002 03:00:00 GMT |
|
 |
Stefan Kra #12 / 31
|
 Magic Square
Quote:
>> But using assert/1 and failure-driven loops is not a very >> elegant or efficient style for Prolog programming, I believe. >> Using recursion tends to lead to more elegant code, IMHO, >> and avoiding the use of assert/1 often improves efficiency. > On a general level I agree, although IMHO it's a disservice to > newcomers to blindly preach this gospel.
No. IMO, newcomers should be taught the "core parts" of prolog programming (Recursion, universal termination, declarative reading of programs, program-development methodology, ...). After some time they can be confronted with the procedural aspects of Prolog. (existential termination, procedural reading of programs, chronological backtracking). Quote: > To reiterate a statement from one of my recent postings, a good > craftsman maintains and uses the right tools for the work in hand.
If you do not need to save information over backtracking, using "assert/retract" is NOT the right tool. (use a data-structure instead) Quote: > I venture to suggest this is one of those cases where > use of failure-driven loops and the internal database can be > justified. It provides for short and highly readable code [...]
Code that is purely based on side-effects is a nightmare to debug. Some code that uses imperative language-features has no declarative reading; it can only be read procedurally. Quote: > and it is relatively efficient ...
I believe you. But this is not a matter of efficiency (since this algorithm is in P anyway) ... Quote: > Again, on a general level I agree with you but doubt very much that > this is applicable here. Anyway, there is nothing to stop you > retracting the facts elsewhere, f.ex. on termination of the program, > should you so prefer.
"cleanup" is another issue when using "assert/retract". How should one handle code that uses both exceptions AND "assert/retract"? ciao, Stefan
|
Fri, 16 Aug 2002 03:00:00 GMT |
|
 |
Daniel Dudle #13 / 31
|
 Magic Square
Quote:
> >> But using assert/1 and failure-driven loops is not a very > >> elegant or efficient style for Prolog programming, I believe. > >> Using recursion tends to lead to more elegant code, IMHO, > >> and avoiding the use of assert/1 often improves efficiency. > > On a general level I agree, although IMHO it's a disservice to > > newcomers to blindly preach this gospel. > No. IMO, newcomers should be taught the "core parts" of prolog > programming (Recursion, universal termination, declarative > reading of programs, program-development methodology, ...). After > some time they can be confronted with the procedural aspects of > Prolog. (existential termination, procedural reading of programs, > chronological backtracking).
Oh no, not another person with blinkers/blinders? A person with previous programming experience in an imperative programming language will quickly find him/herself "at home" by first reviewing the procedural aspects of the Prolog language. When this is combined with alternative examples of declarative programming the advantages of programming "the Prolog way" become transparent. The result is increased motivation for continued learning. Quote: > > To reiterate a statement from one of my recent postings, a good > > craftsman maintains and uses the right tools for the work in hand. > If you do not need to save information over backtracking, using > "assert/retract" is NOT the right tool. (use a data-structure instead)
In this case we did need to save information over backtracking (having chosen to implement failure-driven for-next loops). Quote: > > I venture to suggest this is one of those cases where > > use of failure-driven loops and the internal database can be > > justified. It provides for short and highly readable code [...] > Code that is purely based on side-effects is a nightmare to debug.
Agreed, but hardly applicable in this case. Quote: > Some code that uses imperative language-features has no declarative > reading; it can only be read procedurally.
Is that so bad? Just because one is programming in Prolog doesn't mean that one shouldn't program procedurally where this may be seen to be appropriate. Honestly, I don't know whether to laugh or cry at such "tunnel"' ways of thinking. Quote: > > and it is relatively efficient ... > I believe you. But this is not a matter of efficiency (since this > algorithm is in P anyway) ...
So what? Quote: > > Again, on a general level I agree with you but doubt very much that > > this is applicable here. Anyway, there is nothing to stop you > > retracting the facts elsewhere, f.ex. on termination of the program, > > should you so prefer. > "cleanup" is another issue when using "assert/retract". How should > one handle code that uses both exceptions AND "assert/retract"?
Again, hardly applicable in this case. The internal database is merely being used as a temporary container for "global variables". In the case where the generated data is to be subsequently used there are many options available. One could, f.ex., collect and store the data in a balanced binary tree (to facilitate fast random access), and then program "the Prolog way". Perhaps it's time to throw your blinkers/blinders away? Daniel
|
Fri, 16 Aug 2002 03:00:00 GMT |
|
 |
Bart Demo #14 / 31
|
 Magic Square
|> Oh no, not another person with blinkers/blinders? A person with previous |> programming experience in an imperative programming language will quickly find |> him/herself "at home" by first reviewing the procedural aspects of the Prolog |> language. Let me try to see whether I understand this by putting it in a different context ... A person with previous programming experience in assembly language programming, when introduced to Pascal, will quickly find him/herself "at home" by first reviewing the Pascal "goto" statement. Yeah, sounds very reasonable to me. Of course, you'll have to spend a lifetime later to explain that goto is considered harmful ... And when a Brittish person starts to drive in Belgium, why not let him drive on the left side for a while, so that he feels "at home" at first. Maybe he should also wear blinkers/blinders at the beginning - just a matter of ignoring better what's going on in the rest of the world. Oh, and while we are at it, the preferred way to teach parachute jumping to a benjee jumper, is of course to tie the parachute to his feet - this way is much more familiar to him ! Cheers Bart Demoen
|
Fri, 16 Aug 2002 03:00:00 GMT |
|
 |
Stefan Kra #15 / 31
|
 Magic Square
Quote:
>> No. IMO, newcomers should be taught the "core parts" of prolog. >> [...] After some time they can be confronted with procedural aspects... > Oh no, not another person with blinkers/blinders?
Learning a programming language (and a new paradigma) is just like learning to play guitar. An error made in the early stages of the learning process can hardly be corrected (or only with huge efforts) in the later stages. It is thus evident that the "core parts" MUST be taught/learned first. You certainly agree with me that the imperative parts are not a part of the "core" of prolog. Quote: > A person with previous programming experience in an imperative > programming language will quickly find him/herself "at home" by > first reviewing the procedural aspects of the Prolog language.
People SHOULD not feel "too much at home" until they have really understood the very basics. Quote: > [Procedural aspects] Is that so bad?
No, it is not. But it is only a crutch, not more. Remember that Prolog was intended to be a way of "programming in logic". Quote: > Just because one is programming in Prolog doesn't mean that one > shouldn't program procedurally where this may be seen to be appropriate.
Estimating that requires a person to understand the basics. Quote: > Honestly, I don't know whether to laugh or cry at such "tunnel"' ways ...
If I were you, I'd rather laugh than cry... Quote: >> > and it is relatively efficient ... >> I believe you. But this is not a matter of efficiency ... > So what?
So "Speed" and "Optimization" is irrelevant. Quote: >> "cleanup" is another issue when using "assert/retract". How should >> one handle code that uses both exceptions AND "assert/retract"? > Again, hardly applicable in this case.
My statement did not refer to this concrete problem. Quote: > The internal database is merely being used as a temporary container > for "global variables".
Even in an imperative language the use of global variables should be avoided whenever possible. Quote: > Perhaps it's time to throw your blinkers/blinders away?
You call it blinders. I call it "focussing on the problem". And -- IMHO -- that is what Prolog is all about. ciao, Stefan
|
Fri, 16 Aug 2002 03:00:00 GMT |
|
|
Page 1 of 3
|
[ 31 post ] |
|
Go to page:
[1]
[2] [3] |
|