Criada: 2014-07-27 Modificada: 2015-02-07
Enunciado distribuído na sala.
(defun comum (x y)
(lca x y)
)
(defun lca (x y)
(or (descends y x)
(lca-list (inset x) y)
)
)
(defun lca-list (l y)
(if (null l)
nil
(or (lca (car l) y)
(lca-list (cdr l) y))
)
)
(defun descends (y x)
(if (equal x y)
x
(descends-list (inset y) x)
)
)
(defun descends-list (l x)
(if (null l)
nil
(or (descends (car l) x)
(descends-list (cdr l) x)
)
)
)
;;; Para testar: função inset refletindo a figura da prova.
(defun inset (x)
(cond
((eql x 'a) '(b))
((eql x 'b) '(j))
((eql x 'c) '(b j e))
((eql x 'd) '(c))
((eql x 'e) '(j))
((eql x 'f) '(c g))
((eql x 'g) '(h))
((eql x 'h) '())
((eql x 'i) '(h))
((eql x 'j) '())
)
)
ancestrais(X, [X|RX]) :-
inset(X, PX),
ancList(PX, RX).
%%% ancList(L, A) satisfeito quando A é a lista de todos os ancestrais
%%% dos elementos de L
ancList([], []).
ancList([X|R], A) :-
ancestrais(X, AX),
ancList(R, AR),
union(AX, AR, A).
%%% Para testar: predicado inset refletindo a figura da prova.
inset(a,[b]).
inset(b,[j]).
inset(c,[b,j,e]).
inset(d,[c]).
inset(e,[j]).
inset(f,[c,g]).
inset(g,[h]).
inset(h,[]).
inset(i,[h]).
inset(j,[]).
(defun amigos (n m) (and (= n (somadiv m)) (= m (somadiv n)) ) ) (defun somadiv (n) (somadiv-ateh (1- n) n) ) (defun somadiv-ateh (k n) (cond ((<= k 1) 1) ((= 0 (mod n k)) (+ k (somadiv-ateh (1- k) n))) (t (somadiv-ateh (1- k) n)) ) )
%%% soma_div(N, S) eh satisfeito quando S eh a soma dos divisores de N menores que ele proprio
soma_div(N, S) :- N1 is N - 1, soma_div_ateh(N, N1, S).
%%% soma_div_ateh(N, L, S) eh satisfeito quando S eh a soma dos dividores de N ateh L
%%% (ou seja, dividores menores ou iguais a L)
soma_div_ateh(_, 0, 0) :- !.
soma_div_ateh(N, L, S) :-
L1 is L - 1,
soma_div_ateh(N, L1, S1),
parcela(N, L, P),
S is S1 + P.
%%% parcela(N, L, P) eh satisfeito quando P eh a parcela a somar nos dividores de N relativa a L.
%%% em outras palavras, se L divide N, a parcela eh L; se L nao divide N, a parcela eh zero.
parcela(N, L, 0) :- 0 =\= N mod L, !.
parcela(N, L, L) :- 0 =:= N mod L.
%%% amigos
amigos(N, M) :-
soma_div(N, M),
soma_div(M, N).
O critério de correção começou por decidir como seria a pontuação: de cima para baixo ou de baixo para cima. Se a resposta estava bem escrita, com sintaxe Lisp correta, resolução do problema pedido (e não de outro) e com comprimento proporcional à complexidade da questão, então a correção procedeu de cima para baixo, ou seja, parte-se do valor integral e vão sendo subtraidas frações de pontos para cada defeito encontrado.
Por outro lado, se a resposta estava mal escrita, com sintaxe errada, resolvendo o problema errado ou incompleta, então a correção procedeu de baixo para cima: parte-se de zero e vão sendo adicionadas frações de pontos a cada indício de conhecimento importante encontrado. Embora em geral a correção de cima para baixo resulte em notas maiores numa questão, é possível ter exceções a esta tendência.
Em todas as questões, os seguintes critérios foram universalmente aplicados:
is usado em contexto não aritmético: -0,5is: -0,5append, cons, list: -0,5car, list, etc.) a mais ou a menos: -0,5A seguir, critérios específicos para cada questão. Nas questões de código, são todos critérios de cima para baixo.
nullp em Lisp em vez de null: -0,5defun na definição de função: -0,5if com apenas dois elementos: -0,5_ em vez de [ ]: -0,5append e merge: -0,5apply: -0,5!= em lugar de /=: -0,5integer em lugar de integerp: -0,5N entre os divisores próprios de N: -0,5NIL no lugar de zero: -0,5:= em lugar de :-: -0,5fail: -0,5A/B em lugar de B/A: -0,5is: -0,5is: -0,5© 2014 João Meidanis