For Programmers: Free Programming Magazines  


Home > Archive > Prolog > January 2006 > Beginner's program - too confusing?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Beginner's program - too confusing?
E. Braun

2006-01-27, 7:00 pm

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,R
eplacedListe),
% 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).


Walter

2006-01-28, 7:56 am

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@minet.uni-jena.de> wrote in
message
news:slrn4dtkkum.c5q9. qs206710n5sqn8r56s6pr3s980940ss3@pax07e3
.mipool.uni-jena.de...
> 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,R
eplacedListe),
> % 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).
>
>



Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com