Manipulate list and add list items in Prolog

1

I'm a beginner in Prolog and I have questions about the list manipulation and the sum of your items.

I have a historico(RA,[i1,i2,i3,...,in]) predicate where ra is the Academic Record of a student and each i is an item, with the form item(CM,SM,AN,NT,FQ) , CM being the code of the course, SM is the semester, AN is the year, NT the grade, and FQ the frequency.

In addition, the predicate curriculo(Codigocurso,[i1,i2,...,in]) where each i is the code of a subject, shows the subjects of each course.

The predicate materia(Codigomateria,Nomemateria,Creditosmateria) shows us how many credits each substance has in its third parameter.

Suppose I have the following facts:

historico(08080808,[item(1,1,2008,3.0,0.77),item(1,2,2008,6.5,0.90),item(5,1,2009,8.0,0.80)]).

materia(1,algoritmos_e_programacao_para_computadores_1,4).

materia(2,paradigmas_de_programacao,4).

materia(3,programacao_orientada_a_objetos,4).

curriculo(1,[1,2,3]).

I want to do a function that verifies the percentage of credits already fulfilled by a certain student. For this, I will have the function porcentagemcreditos(RA,Codigocurso,Porcentagemjacumprida) .

I need to first add the credits of all the subjects of the course of the student (considering the subjects present in the curriculum), but I do not know how to add the items of a list so that I have the total credits of a course. >

In addition, the porcentagemcreditos function should disregard any subjects that are extracurricular, that is, if you have taken a course that is not in the curriculum of your course.

To contextualize, I have the following rules that I have already created, but I do not think it will be necessary, just the rules I have already mentioned:

curso(CODIGOCURSO,NOMECURSO).

materia(CODIGOMATERIA,NOMEMATERIA,CREDITOSMATERIA).

curriculo(CODIGOCURSO,[CODIGOMATERIA1,CODIGOMATERIA2,...,CODIGOMATERIAn).

aluno(RA,NOME).

cursa(RA,CODIGOCURSO).

historico(RA,[ITEM1,ITEM2,...,ITEMn).  (como mostrei anteriormente).

pertence_curso(M,C):-curriculo(C,Lista),member(M,Lista).
    
asked by anonymous 23.06.2015 / 15:44

1 answer

1

To do arithmetic in Prolog, use the predicate is/2 : the right side must contain a concrete expression (i.e. can not have free variables), which will be evaluated and the result unified with the left side.

So, a [naive] function to add items to a list would look like this:

somar([], 0).
somar([elemento(_,_,N,_,_)|R], Total) :-
    somar(R, Subtotal),
    Total is N + Subtotal.

Where elemento(A,B,C,D,E) is only an example, and you're interested in adding C s.

The above function can be rewritten to have tail recursion (and thus be more efficient, consuming a constant amount of memory):

somar(Lista,Resultado) :-
    somar(Lista, 0, Resultado). % zero é o valor inicial

somar([], Acc, Acc). % Se a lista acabou, retorne o que foi acumulado até então
somar([elemento(_,_,N,_,_)|R], Acc, Resultado) :-
    NovoAcc is Acc + N,
    somar(R, NovoAcc, Resultado).

(The variable Acc is an "accumulator", which receives the values added so far and - when the recursion is over - corresponds to the final result. It can be seen as a "subtotal", but the name "accumulator "is pretty much used in Prolog, so it's good to get acquainted with it)

In order to do the porcentagemCreditos function you want, you will need the following things:

  • Get all course materials and add up your credits. Your curriculo/2 gives you the code list of course subjects, so you can adapt the somar function above to get each subject code, check your total credits in materia/3 and use that value in the sum;

  • Obtain all the subjects taken by the student and add their credits. Again, you can tailor the somar above to iterate over the items in the student's history, except that in this case you will "skip" subjects that are not part of the course:

    ...
    somar_historico(Curso, [item(M,_,_,N,F)|R], Acc, Resultado) :-
        pertence_curso(M, Curso),
        passou(N,F), % Exemplo: o aluno só ganha créditos se passou, certo?
        !,
        materia(M,_,Creditos),
        NAcc is Acc + Creditos,
        somar_historico(Curso, R, NAcc, Resultado).
    % Se a matéria não fazia parte do curso, ou o aluno não passou, salta esse item
    somar_historico(Curso, [_|R], Acc, Resultado) :-
        somar_historico(Curso, R, Acc, Resultado).
    
  • Split one by the other. Again, using is and the division operator / (or multiplication by 100 via * and integer division via // , depending on how you want the result).

  • >
    23.06.2015 / 16:14