Re: Beginner's program - too confusing?



For this type of problem I would use one of the constraint packages.
Alternatively, if the purpose is to have you learn prolog, then you could
write a constraint package.

The constraints would be on the digits (eg C-C=H), as well as the numbers.

Style-wise, I would organize your code slightly differently - eg: single
solution, gnerater/tester, multiple solutions, I/O.
YMMV:
eg:
puzzle(A,B,C,D,E,U,V,W,X) :-
get_numbers(U,V,W,X),
one_solution(U,V,W,X,A,B,C,D,E).

puzzle:-
puzzle(A,B,C,D,E,U,V,W,X),
write_solution(A,B,C,D,E,U,V,W,X),
fail.

or
puzzle(L):-
setof((A,B,C,D,E,U,V,W,X), puzzle(A,B,C,D,E,U,V,W,X), L).
puzzle :- puzzle(L), your_prettyprint(L).

Walter
"E. Braun" <qs206710n5sqn8r56s6pr3s980940ss3@xxxxxxxxxxxxxxxxx> wrote in
message
news:slrn4dtkkum.c5q9.qs206710n5sqn8r56s6pr3s980940ss3@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Hello,
>
> this is my first not absolutely trivial prolog program (it is quite
simple,
> though). Its task is to search the numbers for a puzzle of this form
> (except the very simple ones):
>
> U - V = A
> - - *
> W + X = B
> = = =
> D * E = C
>
> The digits a randomly replaced by letters:
> For example:
>
> 112 - 98 = 14
> - - *
> 62 + 63 = 125
> = = =
> 50 * 35 = 1750
>
> may be printed as:
>
> AAC - BD = AF
> - - *
> GC + GI = ACE
> = = =
> EH * IE = AJEH
>
>
> The program seems to fulfill its task, but can you look over the program,
if I make
> stylistic or programming mistakes, which a native Prolog programmer
doesn't?
>
> thank you!
> Erik
>
>
> The main goal is 'puzzle/0'.
>
>
> puzzle :-
> get_number(U),
> get_number(V), U-11>V,
> get_number(W), V=\=W, U-11>W,
> get_number(X), V-11>X,
> A is U-V,
> B is W+X, not_ten(B),
> D is U-W,
> E is V-X, not_ten(E),
> C is A*B,
> C is D*E,
> % output_eq([U,V,A,W,X,B,D,E,C]),
> rnd_permu(['A','B','C','D','E','F','G','H','I','J'],Liste),
> replace_list([U,V,A,W,X,B,D,E,C],Liste,ReplacedListe),
> % output_short(ReplacedListe),
> output_eq(ReplacedListe),
> fail.
>
>
> % get a number between Under and Upper, but not divisible by 10
> get_number(X) :-
> Under=61,Upper=222,between(Under,Upper,X),not_ten(X).
>
> % number shall not be divisible by 10
> not_ten(X) :-
> Y is X mod 10, Y=\=0.
>
> % print the equation (9 variables)
> output_eq([A,B,C,D,E,F,G,H,I]) :-
> nl,write(A),write(' - '),write(B),write(' = '),write(C),nl,
> write(' - - *'),nl,
> write(D),write(' + '),write(E),write(' = '),write(F),nl,
> write(' = = ='),nl,
> write(G),write(' * '),write(H),write(' = '),write(I),nl,nl.
>
> % print the input list (9 variables)
> output_short([U,V,A,W,X,B,D,E,C]) :-
> writef("%w, %w, %w, %w, %w, %w, %w, %w, %w\n",
> [U,V,A,W,X,B,D,E,C]).
>
> % In1: Inputnumbers (List of Integers)
> % In2: Permutated list of variablenames
> % Out: Digits of Inputnumbers replaced by variablenames (List of Atoms)
> %
> % replace_list([222, 191, 31, 67, 148, 215, 155, 43, 6665],
> % ['J', 'F', 'I', 'A', 'C', 'D', 'E', 'H', 'G','B'],ReplacedListe).
> % ReplacedListe = ['III', 'FBF', 'AF', 'EH', 'FCG', 'IFD', 'FDD', 'CA',
'EEED']
> %
> replace_list([],_,[]).
> replace_list([Hin1|In1], In2, [Hout|Out]) :-
> name(Hin1,Hin1atom),
> replace_char(Hin1atom,In2,Houtatom),
> name(Hout,Houtatom),
> replace_list(In1,In2,Out).
>
> % In1: Inputnumber (list of atomised digits)
> % In2: Permutated list of variablenames
> % Out: Digits replaced by variablenames
> %
> % replace_char([50,53,57],['J', 'F', 'I', 'A', 'C', 'D', 'E', 'H', 'G',
'B'],X).
> % X = [73, 68, 66] ;
> %
> replace_char([],_,[]).
> replace_char([Hin1|In1],In2,[Hout|Out]) :-
> between(48,57,Digit), % digits 0-9
> Digit=:=Hin1,
> Hindex2 is Hin1-48,
> nth0(Hindex2,In2,Hin2),
> name(Hin2,[Hout]),
> replace_char(In1,In2,Out).
>
> %%% end %%%
>
> %% important (almost) standard predicates from R.A.O'Keefe
> %%
> remove_at(X,[X|Xs],1,Xs).
> remove_at(X,[Y|Xs],K,[Y|Ys]) :- K > 1,
> K1 is K - 1, remove_at(X,Xs,K1,Ys).
>
> rnd_select(_,0,[]).
> rnd_select(Xs,N,[X|Zs]) :- N > 0,
> length(Xs,L),
> I is random(L) + 1,
> remove_at(X,Xs,I,Ys),
> N1 is N - 1,
> rnd_select(Ys,N1,Zs).
>
> rnd_permu(L1,L2) :- length(L1,N), rnd_select(L1,N,L2).
>
>


.