home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
prolog
/
library
/
diverses
/
raetsel.pro
< prev
next >
Wrap
Text File
|
1991-10-19
|
12KB
|
290 lines
/* Das folgende PROLOG-Programm ist entnommen aus: Bundeswettbewerb */
/* Informatik, Aufgaben und Lösungen, Band 3 , S. 47 ff. Die */
/* zugrundeliegende Aufgabe (s. Programmtext) wurde in der zweiten */
/* Runde des 6. Wettbewerbs gestellt. */
/* Neben dieser Lösung (in MPROLOG) ist noch eine in ELAN */
/* abgedruckt, die ich z.T. bereits nach PASCAL portiert habe. */
/* Problem: Wer kennt MPROLOG und kann das untenstehende Programm */
/* testen? */
/* Testdaten: kiha : f = ige 1230 : 5 = 246 */
/* : + - : + - */
/* ka + fg = eg 10 + 54 = 64 */
/* =================== ===================== */
/* kih + fb = kci 123 + 59 = 182 */
/* */
/* Infos bitte an: Rainer Fischer, Quellenstr. 12, Tel. 07183/8660 */
/* RAETSEL.PRO */
module mengen.
body.
element (X, [X|_])
element (X, [_|R]) :- element (X,R) .
paare ([], [], []) .
paare ([K1|R1], [K2|R2], [(K1, K2)|R3]) :- paare (R1, R2, R3) .
teilmenge (O, _, []) :- ! .
teilmenge (N, [K|R], [K|R1] :- N > O, N1 is N-1, teilmenge (N1, R, R1) .
teilmenge (N, [K|R], T) :- teilmenge (N, R, T) .
append ([], L, L) .
append ([K|R1], L, [K|R2]) :- append (R1, L, R2) .
anzahl_elemente ([], O) .
anzahl_elemente ([K|R], A) :- anzahl_elemente (R, RA), A is 1+RA .
restmenge (T, [], []) .
restmenge (T, [K|R], REST) :- element (K, T), !, restmenge (T,R,REST) .
restmenge (T, [K|R, [K|REST]) :- !, restmenge (T, R, REST) .
endmod /* mengen */
module eingabe.
/*****************************************************************/
/* Dieses Modul ermöglicht die Eingabe der Symbolmatrix in der */
/* folgenden Form: */
/* XXXX O XXXX = XXXX ZEILE_1 */
/* O O O O-ZEILE */
/* XXXX O XXXX = XXXX ZEILE_2 */
/* ================== */
/* XXXX O XXXX = XXXX ZEILE_3 */
/* X steht für ein Ziffernsymbol [a,b,c,d,e,f,g,h,i,k] oder */
/* ein Leerzeichen für fehlende Stellen am Anfang einer Zahl. */
/* O steht für ein Operatorsymbol [+,-,*,:]. */
/* Die Eingaben werden zeichenweise auf syntaktische Richtig- */
/* keit überprüft. Fehlerhafte Eingaben werden nicht angenom- */
/* men. Der Benutzer muß in diesem Fall die Eingabe solange */
/* wiederholen, bis er eines der erwarteten Zeichen eingegeben */
/* hat. */
/* */
/* Datenstrukturen: */
/* Symbolmatrix (Zeile, Operatorzeile, Zeile, Zeile) */
/* Zeile (Zahl, Operator, Zahl, Zahl) */
/* Operatorzeile(Operator, Operator, Operator) */
/* Zahl (Z-Symbol, Z-Symbol, Z-Symbol, Z-Symbol) */
/*****************************************************************/
body.
symbolmatrix_angefordert :-
write ('Geben Sie jetzt bitte die Symbolmatrix '),
write (' in der folgenden Form ein:'), nl,
write (' xxxx O xxxx = xxxx'), nl,
write (' O O O'), nl,
write (' xxxx O xxxx = xxxx'), nl,
write (' =================='), nl,
write (' xxxx O xxxx = xxxx'), nl, nl,
write ('x ist ein Element aus [a,b,c,d,e,f,g,h,i,k]'),
write (' oder ein Leerzeichen für'), nl,
write ('fehlende Stellen am Anfang einer Zahl.'), nl, nl,
write ('O ist ein Element aus [+-*:].'), nl ,nl,
write ('Bitte:'), nl.
gelesen (sybolmatrix, (ZEILE_1, O_ZEILE, ZEILE_2, ZEILE_3) :-
symbolmatrix_angefordert,
gelesen (zeile, ZEILE_1),
gelesen (o_zeile, O_ZEILE),
gelesen (zeile, ZEILE_2),
write (==================), nl,
gelesen (zeile, ZEILE_3) .
gelesen (zeile, (ZAHL_1, OPERATOR, ZAHL_2, ZAHL_3)) :-
gelesen (zahl, ZAHL_1, display_string(' '),
gelesen (o_symbol, OPERATOR), display_string(' '),
gelesen (zahl, ZAHL_2, display_string (' = '),
gelesen (zahl, ZAHL_3), nl.
gelesen (o_zeile, (O1,O2,O3)) :-
display_string (' '), gelesen (o_symbol, O1),
display_string (' '), gelesen (o_symbol, O2),
display_string (' '), gelesen (o_symbol, O3), nl .
gelesen (zahl, (Z1, Z2, Z3, Z4)) :-
gelesen (xb_symbol, Z1),
((Z1=' ', gelesen (xb_symbol, Z2), (/); gelsen (x_symbol, Z2))),
((Z2=' ', gelesen (xb_symbol, Z3), (/); gelsen (x_symbol, Z3))),
gelesen (x_symbol, Z4) .
gelesen (o_symbol, O) :- eingegeben ([+,-,*,:],O) .
gelesen (x_symbol, X) :- eingegeben ([a,b,c,d,e,f,g,h,i,k], X) .
gelesen (xb_symbol, XB) :- eingegeben ([' ',a,b,c,d,e,f,g,h,i,k], XB) .
transponiert (SM, (Z1, OZ, Z2, Z3)) :-
spalte (1,SM,Z1), spalte (2,SM,Z2), spalte (3,SM,Z3),
spalte (o,SM,OZ) .
belegung (matrix, PAARE, (SZ1,OZ,SZ2,SZ3), (WZ1,OZ,WZ2,WZ3)) :-
belegung (zeile, PAARE, SZ1, WZ1),
belegung (zeile, PAARE, SZ2, WZ2),
belegung (zeile, PAARE, SZ3, WZ3) .
belegung (zeile, PAARE, (Z1,O,Z2,Z3), (W1,O,W2,W3)) :-
belegung (zahl, PAARE, S1, W1),
belegung (zahl, PAARE, S2, W2),
belegung (zahl, PAARE, S3, W3) .
belegung (zahl, PAARE, (S1,S2,S3,Z4),W) :-
belegung (zeile, PAARE, SZ3, WZ3) .
element (((Z1,W1), PAARE), element ((Z2,W2), PAARE),
element ((Z3,W3), PAARE), element ((Z4,W4), PAARE),
W is W4+10*W3+100*W2+1000*W1 .
erfüllt (matrix, (ZEILE_1, O_ZEILE, ZEILE_2, ZEILE_3)) :-
erfüllt (zeile,ZEILE_1), erfüllt(zeile,ZEILE_2),
erfüllt (zeile,ZEILE_3) .
erfüllt (zeile, (Z1, (+), Z2, Z3)) :- Z3 =:= Z1 + Z2 .
erfüllt (zeile, (Z1, (-), Z2, Z3)) :- Z2<=Z1, Z3 =:= Z1 - Z2 .
erfüllt (zeile, (Z1, (*), Z2, Z3)) :- Z3 =:= Z1 * Z2 .
erfüllt (zeile, (Z1, (:), Z2, Z3)) :- Z2>0, Z3 =:= Z1 : Z2 .
spalte (1, ((Z1,_,_,_), (O,_,_), (Z2,_,_,_),Z3,_,_,_), (Z1,O,Z2,Z3)) .
spalte (2, ((_,_,Z1,_), (_,O,_), (_,_,Z2,_),_,_,Z3,_), (Z1,O,Z2,Z3)) .
spalte (3, ((_,_,_,Z1), (_,_,O), (_,_,_,Z2),_,_,_,Z3), (Z1,O,Z2,Z3)) .
spalte (o, ((_,O1,_,_),_, (_,O2,_,_),_,O3,_,_), (O1,O2,O3)) .
eingegeben (ZEICHENVORRAT,ZEICHEN) :-
repeat, current_key (KEY), accept_key,convert_char (ZEICHEN, KEY),
element (ZEICHEN, ZEICHENVORRAT), !,
display_string (ZEICHEN) .
endmod /* eingabe */ .
module primitiv_lösung.
/****************************************************************/
/* Dieses Modul ermittelt die Lösung durch Ausprobieren aller */
/* Permutationen von [0,1,2,3,4,5,6,7,8,9]. */
/* Im Extremfall (unlösbares System) dauert es Stunden, bis eine */
/* Ausgabe erfolgt. */
/*****************************************************************/
body.
primitiv (SYMBOLMATRIX, WERTEMATRIX) :-
permutation ([0,1,2,3,4,5,6,7,8,9], PERMUTATION),
paare ([a,b,c,d,e,f,g,h,i,k], PERMUTATION, PAARE),
belegung (matrix, [(' ',O)|PAARE], SYMBOLMATRIX, WERTEMATRIX) .
erfüllt (matrix (WERTEMATRIX),
transponiert (WERTEMATRIX, TMATRIX), erfüllt (matrix, TMATRIX) .
permutation ([], []) .
permutation ([K|R], P) :- permutation (R,P1), verteilung (K,P1,P).
verteilung (K, P1, [K|P1]) .
verteilung (K, [K1|R1], [K1|R2]) :- verteilung (K, R1, R2) .
endmod /* primitiv_lösung */ .
module zeilenpermutation.
/*****************************************************************/
/* Dieses Modul geht zeilenweise vor und permutiert zunächst nur */
/* die Belegung der Buchstabensymbole mit Ziffern für eine Zeile.*/
/* Dabei werden viele unlösbare Systeme frühzeitig entdeckt. */
/* Dennoch kann es über eine Stunde dauern, bis es zu einer */
/* Ausgabe kommt. Das Beispiel wurde in etwa 34 Minuten gelöst. */
/*****************************************************************/
body.
neue_symbole (zeile, ALTE, (Z1,O,Z2,Z3), NEUE) :_
neue_symbole (zahl, ALTE, Z1, N1),
neue_symbole (zahl, N1, Z2, N2),
neue_symbole (zahl, N2, Z3, NEUE) .
neue_symbole (zahl, ALTE, (A,B,C,D), NEUE) :-
neues_symbol (A, ALTE, NA), neues_symbol (B, NA, NB),
neues_symbol (C. NB, NC), neues_symbol (D, NC, NEUE) .
neues_symbol (X. ALTE, ALTE) :- element (X, ALTE), ! .
neues_symbol (' ',ALTE,ALTE) :- ! .
neues_symbol (X, ALTE, [X|ALTE] .
permutation (WERTE, ALTE, ZEILE, PERMUTATION, RESTWERTE, NEUE,
NEU) :-
neue_symbole (zeile, ALTE, ZEILE, NEUE),
restmenge (ALTE, NEUE, NEU),
anzahl_elemente (NEU, ANZ),
teilmenge (ANZ, WERTE, T),
permutation (T, PERMUTATION),
restmenge (T, WERTE, RESTWERTE) .
zpermut ((Z1, OZ, Z2, Z3), (W1, OZ, W2, W3)) :-
permutation ([0,1,2,3,4,5,6,7,8,9], [],Z1,P1,RW1,ALT1,NEU1),
paare (NEU1, P1, PAARE1);
belegung (zeile, [(' ',O)|PAARE1], Z1, W1),
erfüllt (zeile, W1) .
permutation (RW1, ALT1, Z2, P2, RW2, ALT2, NEU2),
paare (NEU2, P2, TPAARE2),
append (PAARE1, TPAARE2, PAARE2),
belegung (zeile, [(' ',O|PAARE2], Z2, W2),
erfüllt (zeile, W2) .
permutation (RW2, ALT2, Z3, P3, RW3, ALT3, NEU3),
paare (NEU3, P3, TPAARE3),
append (PAARE2, TPAARE3, PAARE3),
belegung (zeile, [(' ',O|PAARE3], Z3, W3),
erfüllt (zeile, W3),
transponiert ((W1, OZ, W2, W3), TMATRIX),
erfüllt (matrix, TMATRIX) .
endmod /* zeilenpermutation */ .
module raetsel.
/******************************************************************/
/* Dieses Modul ermittelt die Lösung nach dem angegebenen Verfah- */
/* ren und gibt sie dann aus. Außerdem wird die verbrauchte Zeit */
/* ermittelt und ausgegeben. */
/******************************************************************/
body.
lösung (VERFAHREN) :-
set_state (evaluation_limit, 8000000),
gelesen (symbolmatrix, SM), nl,
write ('Danke, ich mache mich jetzt an die Arbeit nach dem '),
write ('$"'), write (VERFAHREN), write ('$"-Verfahren. '), nl,
write ('Das kann '), write_zeit (VERFAHREN), write (' dauern.'),
nl,
write (Haben Sie bitte Geduld!'), nl, nl,
structure (LOESUNG, list, [VERFAHREN, SM, WERTEMATRIX]),
state (system_time, T1),
((LOESUNG, ausgegeben (matrix, WERTEMATRIX);
write ('Es gibt keine Lösung.'), nl)), nl,
state (system_time, T2), write_dauer (T1, T2), nl.
write_zeit (primitiv) :- write ('einige Stunden') .
write_zeit (zpermut) :- write ('wer weiß wie lange') .
write_dauer (T1, T2) :-
H1 is T1 div 10000, M1 is T1 mod 10000 div 100, S1 is T1 mod 100,
H2 is T2 div 10000, M2 is T2 mod 10000 div 100, S2 is T2 mod 100,
((S2>=S1, S is S2-S1, US is 0; S2 <S1, S is S2-S1+60, US is -1)),
((M2+US>=M1, M is M2+US-M1, UM is 0; M2+US<M1, M is M2+Us+60-M1,
UM is -1)),
H is H2+UM-H1, write ('Zeitbedarf: '),
write (H), ((H=1, write (' Stunde '),(/); write (' Stunden '))),
write (M), ((M=1, write (' Minute '),(/); write (' Minuten '))),
write (S), ((S=1, write (' Sekunde '),(/);write (` Sekunden'))),
nl .
ausgeben (matrix, (ZEILE_1, O_ZEILE, ZEILE_2, ZEILE_3)) :-
nl, write ('Es gibt die folgende Lösung:'), nl, nl,
ausgegeben (zeile, ZEILE_1),
ausgegeben (o_zeile, O_ZEILE),
ausgegeben (zeile, ZEILE_2),
write (==================), nl,
ausgegeben (zeile, ZEILE3) .
ausgegeben (zeile, (ZAHL1, OPERATOR, ZAHL2, ZAHL3)) :_
ausgegeben (zahl, ZAHL1), write (' '),
write (OPERATOR), write (' '),
ausgegeben (zahl, ZAHL2), write (' '),
ausgegeben (zahl, ZAHL3), nl.
ausgegeben (o_zeile, (O1, O2, O3)) :-
write (' '), write (O1),
write (' '), write (O2),
write (' '), write (=3), nl.
ausgegeben (zahl, Z) :_
((Z >=1000, (/);
Z>=100 , write (' '), (/);
Z>=10, write (' '), (/);
Z< 10, write (' '),(/))), write (Z) .
endmod /* raetsel */ .