%% Predicado resolve: tenta resolver uma chapa. %% Ha' quatro fases. Quanto mais avancada uma fase, %% mais poderosos sao os recursos tentados, mas tambem %% mais demorados. %% Na fase 1, tentam-se os seguintes unarios: %% fat de 0, 3, 4 e 5; sqrt de 4, 9 e 16. %% Na fase 2, tenta-se ver onde existem pares %% consecutivos de numeros iguais, que serao %% transformados no resultado 2 fazendo %% [log,[sqrt,X],X]. Alem disso, tentam-se %% fat de 0 e sqrt de 4, 9 e 16. %% Na fase 3, tentam-se os seguintes unarios: %% fat de 0, 6, 7 e 8; sqrt de 4, 9 e 16. resolve(Chapa,NovaExpr) :- fase(Fase), binTreeNodes(Expr,Chapa,topo), % write(Expr), nl, avalia(Expr,NovaExpr,Fase), decSintaxe(NovaExpr). fase(1). fase(2). fase(3). binario(+). binario(-). binario(*). binario(/). binario(mod). binario(^). binario(log). binario(dec). binario(raiz). %%------------------------------------------ %% binTreeNodes(-Arv,+Folhas,+Altura) %% gera todas as arvores binarias com conjunto %% de Folhas dado, e tais que os nos internos %% tenham operadores binarios. O parametro %% Altura quando tem valor topo forca a %% presenca do operador = (que ficara' portanto %% na raiz). binTreeNodes(Digito,[Digito],_) :- !. binTreeNodes([Bin,Esq,Dir],Folhas,Altura) :- jmAppend(FolhasEsq,FolhasDir,Folhas), FolhasEsq \== [], FolhasDir \== [], operador(Altura,Bin), % escolhe operador conforme % altura: no topo so' pode = binTreeNodes(Esq,FolhasEsq,nao_topo), binTreeNodes(Dir,FolhasDir,nao_topo). %% pega operador conforme altura (no topo so' pode =) %% (em outras alturas pode qualquer binario) operador(topo,=) :- !. operador(_,Bin) :- binario(Bin). %%------------------------------------------------------- %% Avaliacao da expressao. %% %% O predicado valor(+Expr,-NovaExpr,-NovoVal,+Fase) %% retorna %% o valor de uma expressao "proxima" da expressao %% dada, proximidade esta medida pela inclusao de %% alguns operadores unarios pelo caminho. %% A expressao proxima tambem e' retornada em Nova. %% O parametro Fase determina que unarios serao %% tentados. avalia(Expr,Nova,Fase) :- valor(Expr,Nova,true,Fase). valor(X,Nova,Novo,Fase) :- number(X), !, alt(X,X,Nova,Novo,Fase). valor([Bin,Ex1,Ex2], Nova, Novo,Fase) :- valor(Ex1,Nova1,Novo1,Fase), valor(Ex2,Nova2,Novo2,Fase), jmCalcBin(Bin,Novo1,Novo2,Val), alt([Bin,Nova1,Nova2],Val,Nova,Novo,Fase). %% regra especial, so' usada na fase 2: se houver dois %% valores iguais, fabricar 2 fazendo [log,[sqrt,X],X] valor([_,Ex1,Ex2], [log,[sqrt,Nova1],Nova2], 2, 2) :- valor(Ex1,Nova1,Novo1,2), valor(Ex2,Nova2,Novo2,2), Novo1 == Novo2, Novo1 > 0, Novo1 =\= 1. %%---------------------------------------------- %% Alternativas alt(Expr,Val,Expr,Val,_). % a propria, tentada % em todas as fases. alt(Expr,Val,Nova,Novo,Fase) :- % fatorial validoFat(Fase,Val), jmFat(Val,Res), alt([fat,Expr],Res,Nova,Novo,Fase). alt(Expr,Val,Nova,Novo,Fase) :- % raiz quadrada validoSqrt(Fase,Val), Res is sqrt(Val), alt([sqrt,Expr],Res,Nova,Novo,Fase). %% quais sao validos validoFat(1,Val) :- (Val == 0; Val == 3; Val == 4; Val == 5). validoFat(2,Val) :- Val == 0. validoFat(3,Val) :- (Val == 0; Val == 6; Val == 7; Val == 8). validoSqrt(_,Val) :- (Val == 4; Val == 9; Val == 16). %%-------------------------------------------------------- %% Verifica a maldita sintaxe do DEC %% digito decSintaxe(D) :- jmDigito(D). %% operador unario. decSintaxe([_,Ex]) :- decSintaxe(Ex). %% operador binario diferente de DEC. decSintaxe([Bin,Ex1,Ex2]) :- Bin \== dec, decSintaxe(Ex1), decSintaxe(Ex2). %% operador DEC - seu primeiro argumento deve ser %% digito ou DEC; seu segundo argumento deve ser digito. decSintaxe([dec,Ex1,Ex2]) :- decSintDec(Ex1), jmDigito(Ex2). %% auxiliar para verificar sintaxe do DEC %% decSintDec(X) satiseito quando X e' valido como %% primeiro argumento de DEC. decSintDec(D) :- jmDigito(D), !. decSintDec([dec,Ex1,Ex2]) :- decSintDec(Ex1), jmDigito(Ex2).