Re: Avoiding to repeat code ? (B-Prolog)



On Nov 3, 7:13 am, Ecirbaf <fabrice.march...@xxxxxxxxx> wrote:
Hi,

I've just discovered B-Prolog here on the group.
It's quite amazing how it can easily solve problems.

Hacking an example Neng-Fa Zhou provided, here is below a program
that solves a 'still life problem' ( Conway game of life ) in a 3x3
square.

However I'm aware my coding is obviously bad.
Some code is duplicated several time, for example, each sum ( like Pm
+Zm+Zz+Zp+Pp ) is repeated 4 times.
Worse, the code that assert a cell is stable is repeated 9 times !

Please, how to avoid this code muliplication ?
Would it be possible to define some kind of "function" like in a
procedural language ?

Apologize for this very newbie stupid question.

Thanks for any advice.

Fabrice

solve(Vars):-
Vars=[Mp, Zp, Pp,
Mz, Zz, Pz,
Mm, Zm, Pm],
Vars :: 0..1,

% Stable corners
((#\Mm) #/\ ( ((Zm+Zz+Mz) #=< 2)
#\/((Zm+Zz+Mz) #>= 4) ))
#\/( Mm #/\ ( ((Zm+Zz+Mz) #= 2)
#\/((Zm+Zz+Mz) #= 3) )),

((#\Pm) #/\ ( ((Zm+Zz+Pz) #=< 2)
#\/((Zm+Zz+Pz) #>= 4) ))
#\/( Pm #/\ ( ((Zm+Zz+Pz) #= 2)
#\/((Zm+Zz+Pz) #= 3) )),

((#\Pp) #/\ ( ((Zp+Zz+Pz) #=< 2)
#\/((Zp+Zz+Pz) #>= 4) ))
#\/( Pp #/\ ( ((Zp+Zz+Pz) #= 2)
#\/((Zp+Zz+Pz) #= 3) )),

((#\Mp) #/\ ( ((Zp+Zz+Mz) #=< 2)
#\/((Zp+Zz+Mz) #>= 4) ))
#\/( Mp #/\ ( ((Zp+Zz+Mz) #= 2)
#\/((Zp+Zz+Mz) #= 3) )),

% Stable middle sides
((#\Zm) #/\ ( ((Pm+Pz+Zz+Mz+Mm) #=< 2)
#\/((Pm+Pz+Zz+Mz+Mm) #>= 4) ))
#\/( Zm #/\ ( ((Pm+Pz+Zz+Mz+Mm) #= 2)
#\/((Pm+Pz+Zz+Mz+Mm) #= 3) )),

((#\Pz) #/\ ( ((Pm+Zm+Zz+Zp+Pp) #=< 2)
#\/((Pm+Zm+Zz+Zp+Pp) #>= 4) ))
#\/( Pz #/\ ( ((Pm+Zm+Zz+Zp+Pp) #= 2)
#\/((Pm+Zm+Zz+Zp+Pp) #= 3) )),

((#\Zp) #/\ ( ((Mp+Mz+Zz+Pz+Pp) #=< 2)
#\/((Mp+Mz+Zz+Pz+Pp) #>= 4) ))
#\/( Zp #/\ ( ((Mp+Mz+Zz+Pz+Pp) #= 2)
#\/((Mp+Mz+Zz+Pz+Pp) #= 3) )),

((#\Mz) #/\ ( ((Mp+Zp+Zz+Zm+Mm) #=< 2)
#\/((Mp+Zp+Zz+Zm+Mm) #>= 4) ))
#\/( Mz #/\ ( ((Mp+Zp+Zz+Zm+Mm) #= 2)
#\/((Mp+Zp+Zz+Zm+Mm) #= 3) )),

% Stable center
((#\Zz) #/\ ( ((Mm+Zm+Pm+Pz+Pp+Zp+Mp+Mz) #=< 2)
#\/((Mm+Zm+Pm+Pz+Pp+Zp+Mp+Mz) #>= 4) ))
#\/( Zz #/\ ( ((Mm+Zm+Pm+Pz+Pp+Zp+Mp+Mz) #= 2)
#\/((Mm+Zm+Pm+Pz+Pp+Zp+Mp+Mz) #= 3) )),

% Really in 3 x 3
Mm #\/ Zm #\/ Pm,
Pm #\/ Pz #\/ Pp,
Pp #\/ Zp #\/ Mp,
Mp #\/ Mz #\/ Mm,

labeling(Vars).

I think what you want is to introduce some predicates
of your own and rules that define them.

For example, the code for "stable corners":

((#\Mm) #/\ ( ((Zm+Zz+Mz) #=< 2)
#\/((Zm+Zz+Mz) #>= 4) ))
#\/( Mm #/\ ( ((Zm+Zz+Mz) #= 2)
#\/((Zm+Zz+Mz) #= 3) ))

can be encapsulated in a clause for certain values:

stable_corner(Mm,Zm,Zz,Mz) :-
((#\Mm) #/\ ( ((Zm+Zz+Mz) #=< 2)
#\/((Zm+Zz+Mz) #>= 4) ))
#\/( Mm #/\ ( ((Zm+Zz+Mz) #= 2)
#\/((Zm+Zz+Mz) #= 3) )).

Then you can use the appropriate calls to this
predicates as goals, rather than repeating the
formula itself:

stable_corner(Mm,Zm,Zz,Mz),
stable_corner(Pm,Zm,Zz,Pz),
stable_corner(Pp,Zp,Zz,Pz),
stable_corner(Mp,Zp,Zz,Mz),...

followed by similar "abstractions" of the logic
for stable middle sides and stable center. In
fact you'll probably want to abstract the entire
rule for "still life", e.g.

still_life(Vars):-
Vars =[Mp, Zp, Pp,
Mz, Zz, Pz,
Mm, Zm, Pm],
Vars :: 0..1,
stable_corner(Mm,Zm,Zz,Mz),
stable_corner(Pm,Zm,Zz,Pz),
stable_corner(Pp,Zp,Zz,Pz),
stable_corner(Mp,Zp,Zz,Mz),
stable_mdside(Zm,Pm,Pz,Zz,Mz,Mm),
stable_mdside(Pz,Pm,Zm,Zz,Zp,Pp),
stable_mdside(Zp,Mp,Mz,Zz,Pz,Pp),
stable_mdside(Mz,Mp,Zp,Zz,Zm,Mm),
stable_center(Zz,Mm,Zm,Pm,Pz,Pp,Zp,Mp,Mz).

In fact using predicates/rules/clauses will
probably allow you to express the underlying
Game of Life in a more natural fashion.

See section 1.5 of the the B-Prolog User's
Manual for how to compile and load a file of
predicate definitions before interactively
querying against them:

[B-Prolog User's Manual by Neng-Fa Zhou]
http://www.probp.com/download/manual.pdf


regards, chip

.