op(add, X, Y, RES) :-
RES is X + Y.
op(sub, X, Y, RES) :-
X > Y,
RES is X - Y.
op(mul, X, Y, RES) :-
RES is X * Y.
op(add, X, Y, RES) :-
X >= Y,
RES is div(X, Y).
countAction([L, HISTO], [RES, [op(OPcode, NUM1, NUM2)|HISTO]]) :-
length(L, Llength),
Llength >= 2,
select(NUM1, L, Linter),
select(NUM2, Linter, Lres),
op(OPcode, NUM1, NUM2, NUMres),
%the user have to append those 3 lines for optimisation
sort([NUMres|Lres], RES),
\+ histo(RES),
asserta(histo(RES)).
goodCount(X, [GoalCount]) :-
member(GoalCount, X).
main :-
solver(countAction, goodCount, [9, 50, 3, 16, 3, 8], [1400], HISTO),
writeln(HISTO).
%
% SYSTEM PART THAT THE BASIC PROLOG PROGRAMMER SHOULD NOT SEE
%
isSolved(_, _, [], _) :- !, fail.
isSolved(P, Pargs, [[INLIST|HISTO]|_], HISTO) :-
call(P, INLIST, Pargs).
isSolved(P, Pargs, [_|L], HISTO) :-
isSolved(P, Pargs, L, HISTO).
solverSub(_, [], []).
solverSub(GENE, [X|Lnodes], LRES) :-
findall(FREE, call(GENE, X, FREE), LLRES),
solverSub(GENE, Lnodes, LINTER),
append(LLRES, LINTER, LRES).
solver(GENE, SUCCESS, NODE_INIT, LargSuccess, HISTO):-
dynamic(histo/1),
dynamic(this/1),
retractall(histo(_)),
retractall(this(_)),
NODESinit = [[NODE_INIT, []]],
asserta(this(NODESinit)),
repeat,
this(Lnodes),
solverSub(GENE, Lnodes, LRES),
retractall(this(_)),
asserta(this(LRES)),
isSolved(SUCCESS, LargSuccess, LRES, HISTO).
On 15 May 2016, at 03:47, Fabrice Bizec <fbi...@gmail.com> wrote:
(It's called "recursion".)Hello,When i was a student, i realised that some of the other students could not learn the concept of recursivity.
Very basic prolog users should writes programs without to deal with it for a time
%% append(?List1, ?List2, ?List1AndList2)%% List1AndList2 is the concatenation of List1 and List2%append([], Ys, Ys).
append([X|Xs], Ys, [X|Zs]) :-append(Xs, Ys, Zs).
Clause 1: Appending an empty list in front of a list equals that list.Clause 2: Appending [X|Xs] in front of a list equals the result of appendingXs in front of the list, and then putting X in front of that result.
[...]
--
You received this message because you are subscribed to the Google Groups "SWI-Prolog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swi-prolog+...@googlegroups.com.
Visit this group at https://groups.google.com/group/swi-prolog.
For more options, visit https://groups.google.com/d/optout.
op(+).
op(-).
op(*).
op(/).
expr(X, Y, E) :-
op(Op),
E =.. [Op, X, Y].
solve :-
permutation([1,60,8,3], [X|Xs]),
foldl(expr, Xs, X, E),
E =:= 50,
writeln(E).
Instead, I prefer to introduce Prolog via declarative readings of Prolog programs, which is something that will not remind them of Basic etc.
On 16 May 2016, at 23:18, Julio Di Egidio <ju...@diegidio.name> wrote:On Sunday, May 15, 2016 at 3:22:54 AM UTC+2, barbara wrote:Instead, I prefer to introduce Prolog via declarative readings of Prolog programs, which is something that will not remind them of Basic etc.I am of the opposite advice: the *operational* semantics of Prolog is primary and should be taught primarily, because that is what a Prolog program actually does.
(As for the usual presumptions, these really prove that a programmer is a programmer, while a non-programmer does not even know what programming means.
And more could be said, about the lack of respect which is really a total lack of perspective, and so on.
Just poor students...)
Julio
Except, the correct operational semantics of Prolog is complicated, IMO vastly too complicated for a newbie.
I.2. Declarative and Procedural Semantics
https://www.cs.cmu.edu/Groups/AI/util/lang/prolog/doc/intro/prolog.doc.% A knight want to kill a Dragoon which have 5 heads and 9 tails
% He can cut 1 or 2 heads or 1 or 2 tails
% When he cut 1 tail, 2 new tails appear
% When he cut 2 tails, 1 new head appear
% When he cut 1 head, 1 new head appear
% When he cut 2 heads, there is nothing new.
% How to kill the dragoon so he have no head and no tail anymore ?
% cut 1 queue => + 2 queues
cut(dragon(H, Q), dragon(H, NovoQ)) :-
Q >= 1,
NovoQ is Q + 1.
% cut 2 queues => + 1 head
cut(dragon(H, Q), dragon(NovoH, NovoQ)) :-
Q >= 2,
NovoQ is Q - 2,
NovoH is H + 1.
% cut 2 heads
cut(dragon(H, Q), dragon(NovoH, Q)) :-
H >= 2,
NovoH is H - 2.
sword([ [dragon(H, Q)], HISTO], [ [dragon(NovoH, NovoQ)], [dragon(NovoH, NovoQ)|HISTO]]) :-
cut(dragon(H, Q), dragon(NovoH, NovoQ)).
dragonKilled([dragon(0, 0)|_], _) :- !.
killDragon :-
reset,
solver(sword, dragonKilled, [dragon(5, 7)], [], HISTO),
writeln(HISTO).
%
% SYSTEM PART THAT THE BASIC PROLOG PROGRAMMER SHOULD NOT SEE
%
use_module(library(gensym)).
isSolved(_, _, [], _) :- !, fail.
isSolved(P, Pargs, [[INLIST, HISTO]|_], HISTO) :-
call(P, INLIST, Pargs).
isSolved(P, Pargs, [_|L], HISTO) :-
isSolved(P, Pargs, L, HISTO).
purge(_, [], []).
purge(H, [[Lnums|Histo]|L], [[LnumsRes|Histo]|LRES]) :-
sort(Lnums, LnumsRes),
\+ histo(H, LnumsRes), !,
asserta(histo(H, LnumsRes)),
purge(H, L, LRES).
purge(H, [_|L], LRES) :-
purge(H, L, LRES).
solverSub(_, _, [], []).
solverSub(H, GENE, [X|Lnodes], LRES) :-
findall(FREE, call(GENE, X, FREE), LLRES),
purge(H, LLRES, PurgeLLRES),
solverSub(H, GENE, Lnodes, LINTER),
append(PurgeLLRES, LINTER, LRES).
solver(GENE, SUCCESS, NODE_INIT, LargSuccess, HISTO):-
dynamic(histo/2),
dynamic(this/2),
gensym(h, H),
gensym(n, N),
NODESinit = [[NODE_INIT, []]],
asserta(this(N, NODESinit)),
repeat,
this(N, Lnodes),
solverSub(H, GENE, Lnodes, LRES),
retractall(this(N, _)),
asserta(this(N, LRES)),
isSolved(SUCCESS, LargSuccess, LRES, HISTO).
reset :-
dynamic(histo/2),
dynamic(this/2),
retractall(histo(_, _)),
retractall(this(_, _)).
Your grammar use recursion ans my goal was to avoid it except in the 'solver engine' part.
--
On 16 May 2016, at 23:18, Julio Di Egidio <ju...@diegidio.name> wrote:On Sunday, May 15, 2016 at 3:22:54 AM UTC+2, barbara wrote:Instead, I prefer to introduce Prolog via declarative readings of Prolog programs, which is something that will not remind them of Basic etc.I am of the opposite advice: the *operational* semantics of Prolog is primary and should be taught primarily, because that is what a Prolog program actually does.Except, the correct operational semantics of Prolog is complicated, IMO vastly too complicated for a newbie. When you introduce Prolog via an operational semantics do you really cover all of: logical variables, the local stack, the heap, garbage collection, the choice stack, and the trail?? That would be massively too much and too foreign for a Prolog beginner. So I assume you use a lot of handwaving to gloss over those items and others which make Prolog very different from Basic etc.
And what a program "actually does" is no more important than what it "actually means".
(As for the usual presumptions, these really prove that a programmer is a programmer, while a non-programmer does not even know what programming means.So your definition of programming is purely procedural? That's archaic (and I'm probably even older than you are, and have coded a lot in assembly and machine languages).
On 26 May 2016, at 05:04, Julio Di Egidio <ju...@diegidio.name> wrote:On Monday, May 16, 2016 at 11:22:09 PM UTC+2, barbara wrote:On 16 May 2016, at 23:18, Julio Di Egidio <ju...@diegidio.name> wrote:On Sunday, May 15, 2016 at 3:22:54 AM UTC+2, barbara wrote:Instead, I prefer to introduce Prolog via declarative readings of Prolog programs, which is something that will not remind them of Basic etc.I am of the opposite advice: the *operational* semantics of Prolog is primary and should be taught primarily, because that is what a Prolog program actually does.
Except, the correct operational semantics of Prolog is complicated, IMO vastly too complicated for a newbie.
When you introduce Prolog via an operational semantics do you really cover all of: logical variables, the local stack, the heap, garbage collection, the choice stack, and the trail?? That would be massively too much and too foreign for a Prolog beginner. So I assume you use a lot of handwaving to gloss over those items and others which make Prolog very different from Basic etc.Are you serious? One should rather conclude that you do not know what the operational semantics of Prolog is: it's unification and backtracking (SLD resolution), i.e. pretty much, at a more practical level, what the execution trace would show. So, after the basics on facts and rules, you rather go on and explain list append...
Incidentally: there is *no need* for any of the implementation details you mention unless one is truly hacking low-level: e.g. in SWI a correct use of an nb_link_val, etc. Definitely unneeded not only in a basic course, but really in 99.99% of the programs.
Incidentally #2: it is wrong that the denotational semantics is equivalent to the operational one as some here seem to believe, they are *not equivalent*, indeed the operational semantics is more restrictice: to begin with, not all programs that have a valid denotational semantics will terminate. And I am not even an expert on these matters not I feel like digging the obvious out for you, but that is the ABC: the semantics of Prolog are not only explained in pretty much any decent book on the language (not on Wikipedia, where I see most articles are exactly as wrong as you and Markus IMO are on this matter),
the semantics are even explicitly specified in the ISO standard...
And what a program "actually does" is no more important than what it "actually means".
Nope, what a program does *is* what a program means.
(As for the usual presumptions, these really prove that a programmer is a programmer, while a non-programmer does not even know what programming means.
So your definition of programming is purely procedural? That's archaic (and I'm probably even older than you are, and have coded a lot in assembly and machine languages).You also keep conflating operational with procedural: so, on a side, do look up what the operational semantics of Prolog actually is, on the other side, it is also worth mentioning that procedural is not even technically meaningful: what you have in mind and keep demeaning (and for inconsistent reasons) is called *imperative*.
HTH, your students. (EOD.)