Question

I'm currently working on a Prolog program and having a lot of trouble figuring out how to implement it.

I want to put a list such as [1,2,2,1] into a function. I want it to multiply into itself to make a new matrix by doing this example.

1 * [1,2,2,1] which would yield [1,2,2,1]
2 * [1,2,2,1] which would yield [2,4,4,2]
2 * [1,2,2,1] which would yield [2,4,4,2]
1 * [1,2,2,1] which would yield [1,2,2,1]

And I want it to create all those together in a matrix like:

[[1,2,2,1],[2,4,4,2],[2,4,4,2],[1,2,2,1]].

Last part would be I want to zero out when I multiply by itself. So the 2nd spot would zero out the second spot making the final matrix:

[[0,2,2,1],[2,0,4,2],[2,4,0,2],[1,2,2,0]].

I want to have a predicate that calls another which makes each list. So heres my thoughts:

main(A,O):-
    second(A,A,O).

second([],_,[]).
second([A|As],B,[O|Os]):- %creates the list of lists.
    third(A,B,O),
    second(As,B,Os).

third(_,[],[]).
third(A,[B|Bs],[O|Os]):-
    fourth(A,B,O),
    third(A,Bs,Os). %multiplies single digit by list.
fourth(A,B,0):- A == B.
fourth(A,B,O):- O is A * B.

I am getting the correct matrix but can not get the zero diagonal.

I just cant figure out a correct way to get the matrix with zeros down the diagonal. Any thoughts?

Was it helpful?

Solution

You can do the zeroes by introducing indices that indicate row and column you are at and check for a match:

main(A, O) :-
    second(A, A, 0, O).

second([], _, _, []).
second([A|As], B, R, [O|Os]) :- %creates the list of lists.
    third(A, B, 0, R, O),
    R1 is R + 1,
    second(As, B, R1, Os).

third(_, [], _, _, []).
third(A, [B|Bs], C, R, [O|Os]) :-
    fourth(A, B, C, R, O),
    C1 is C + 1,
    third(A, Bs, C1, R, Os). %multiplies single digit by list.

fourth(_, _, X, X, 0).
fourth(A, B, C, R, O) :- C \== R, O is A * B.

Check:

| ?-  main([1,2,2,1], L).

L = [[0,2,2,1],[2,0,4,2],[2,4,0,2],[1,2,2,0]] ? ;

no


Another interesting approach would be to create a maplist_with_index predicate which works just like maplist but manages an index and implicitly assumes the given predicate accepts the index as its first argument:

maplist_with_index(Pred, L, M) :-
    maplist_with_index_(Pred, 0, L, M).
maplist_with_index_(Pred, I, [H|T], [M|Ms]) :-
    Pred =.. [P|Pt],
    append([P,I|Pt], [H], NewPred),
    Call =.. NewPred,
    call(Call, M),
    I1 is I + 1,
    maplist_with_index_(Pred, I1, T, Ms).
maplist_with_index_(_, _, [], []).

Then, the matrix program, using this predicate, looks like:

main(A, O) :-
    second(A, A, O).

second(M, A, O) :-
    maplist_with_index(third(A), M, O).

third(R, A, E, O) :-
    maplist_with_index(fourth(R, E), A, O).

fourth(X, X, _, _, 0).
fourth(C, R, A, B, O) :- C \== R, O is A * B.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top