Prolog program: another way to define a functor -
in lastly exam had write prolog predicate called double/2
, according next instructions: double(x, y)
should true if y
list of integers of same length of x
, in every number of x
replace double. that, example, query double([1, 3, 2, 4], x).
should outcome x = [1, 3, 4, 8].
i allowed simplicity utilize functor even/1
, without defining (actually easy define it), true when argument number, , false otherwise. ended writing programme using functor odd/1
. professor said me: "you have written using even, it's not necessary utilize odd!" wonder how have written way.
what wrote following:
double([], []). double([n|l], [n|d]) :- odd(n), !, double(l, d). double([n|l], [m|d]) :- even(n), m 2*n, double(l, d).
remark: if remove even(n)
lastly line of code (so if utilize odd(n)
, practically same using even(n)
, because utilize 1 of them), programme still works. not desirable solution, because way 'cut' becomes reddish cutting (in programme greenish cut).
if interested in right solution, take @paulomoura's solution. here think intention of exercise was. take original program, seems (at first sight), 1 can remove goal even(n)
in sec clause.
but before that, allow me create clear predicate name doubles/2
misnomer. i'd rather list_semidoubled/2
...
however, cutting above little bit more expected. not cutting when odd(n)
true alone, there tiny little status sneaked our program. see it? let's have @ relevant part:
double([n|l], [n|d]) :- odd(n), !, ...
there odd(n)
, above! in head status lying there. , waits until can wreak havoc! "hidden" status is:
if n
equal (unifies) first element in sec argument!
let's seek out!
?- double([1], xs). xs = [1].
worx expected, not. however:
?- double([1], [2]). true.
tiens, happening here? should fail!
a predicate behaves in way lacks steadfastness. expect query fail, prolog did not show solution.
so cutting above not cutting expected, little less that. errors these quite hard locate, thought avoid them right beginning. have several options:
1 stick pure, monotonic prologthis best beginners. , not less efficient. i'd rather:
double(xs, ys) : maplist(n_semidoubled, xs, ys). n_semidoubled(x, y) :- m x mod 2, ( m = 0, y x*2 ; m = 1, y x ).
this can improved — hackerish:
n_semidoubled(x, y) :- y x*(2-x mod 2).
2 utilize (\+)/1
, once/1
, if-then-else @paulmoura showed 1 such possibility. utilize (\+)/1
:
n_semidoubled(x, x) :- odd(x). n_semidoubled(x, y) :- \+odd(x), y x*2.
3 cut down scope of cut if still determined utilize construct, seek restructure programme such scope of cutting local possible. is, instead of placing cutting in recursive rule, rather create local predicate:
doubles([], []). doubles([e|es], [m|ms]) :- n_semidoubled(e, m), doubles(es, ms). n_semidoubled(e, m) :- odd(e), !, m e. n_semidoubled(e, m) :- m e*2.
there anomaly in original programme independent of cutting issue. consider:
?- double([1*1],xs). xs = [1*1].
prolog prolog-cut
No comments:
Post a Comment