Wie kann ich eine Liste wie [[1,2,3][4,5,6][6,7,8]]
zu [[1,4,6],[2,7,8],[3,6,9]]
transponieren?So transponieren Sie eine Matrix in Prolog
Um es darzustellen: Ich möchte die Matrix um 90 Grad nach links kippen. Wie kann ich das machen?
Wie kann ich eine Liste wie [[1,2,3][4,5,6][6,7,8]]
zu [[1,4,6],[2,7,8],[3,6,9]]
transponieren?So transponieren Sie eine Matrix in Prolog
Um es darzustellen: Ich möchte die Matrix um 90 Grad nach links kippen. Wie kann ich das machen?
nicht sicher, Ihr Beispiel richtig ist, aber ich habe die Idee.
:- use_module(library(clpfd)).
so dass Sie das transpose/2
Prädikat verwenden, wie folgt aus::
Wenn SWI-Prolog verwenden, können Sie die CLPFD module, wie so verwenden
1 ?- transpose([[1,2,3],[4,5,6],[6,7,8]], X).
X = [[1, 4, 6], [2, 5, 7], [3, 6, 8]].
Ansonsten (wenn kein SWI-PROLOG), könnten Sie einfach diese Implementierung verwenden (die in SWPs clpfdd eine alte war):
transpose([], []).
transpose([F|Fs], Ts) :-
transpose(F, [F|Fs], Ts).
transpose([], _, []).
transpose([_|Rs], Ms, [Ts|Tss]) :-
lists_firsts_rests(Ms, Ts, Ms1),
transpose(Rs, Ms1, Tss).
lists_firsts_rests([], [], []).
lists_firsts_rests([[F|Os]|Rest], [F|Fs], [Os|Oss]) :-
lists_firsts_rests(Rest, Fs, Oss).
Für eine aktualisierte Version, die fulll- und maplist-Einbauten verwendet, siehe clpfd.pl.
Hier a fragment of a larger answer:
% transposed(+A, ?B) iff matrix B is transposed matrix A
transposed(A, B) :- transposed(A, [], B).
transposed(M, X, X) :- empty(M), !.
transposed(M, A, X) :- columns(M, Hs, Ts), transposed(Ts, [Hs|A], X).
% empty(+A) iff A is empty list or a list of empty lists
empty([[]|A]) :- empty(A).
empty([]).
% columns(+M, ?Hs, ?Ts) iff Hs is the first column
% of matrix M and Ts is the rest of matrix M
columns([[Rh|Rt]|Rs], [Rh|Hs], [Rt|Ts]) :- columns(Rs, Hs, Ts).
columns([[]], [], []).
columns([], [], []).
Thanks :) Vielleicht kann dies nützlich sein. Zuerst bevorzuge ich die Transpose/2-Funktion, wenn ich es irgendwie zur Arbeit bekomme ... – cody
Ein iterativer Ansatz:
trans([H|R],[H1|R1]):-trans2([H|R],[H|R],[],[H1|R1],0),!.
trans2([A|_],_,_,[],N):-length(A,N).
trans2(M,[],H1,[H1|R1],N):-N1 is N+1, trans2(M,M,[],R1,N1).
trans2(M,[H|R],L,[H1|R1],N):-nth0(N,H,X),
append(L,[X],L1),trans2(M,R,L1,[H1|R1],N).
Meine Lösung mit vollständigen Namen für ein besseres Verständnis:
% emptyMatrix(Line, EmptyMatrix)
emptyMatrix([],[]).
emptyMatrix([_|T1],[[]|T2]):-emptyMatrix(T1,T2).
% only length of parameter 'Line' is interesting. It ignores its content.
% appendElement(Element, InputList, OutputList)
appendElement(E,[],[E]).
appendElement(E,[H|T],[H|L]):-appendElement(E,T,L).
% appendTransposed(NestedList, InputMatrix, OutputMatrix)
appendTransposed([],[],[]).
appendTransposed([X|T1],[],[[X]|T3]):-appendTransposed(T1,[],T3).
appendTransposed([X|T1],[R|T2],[C|T3]):-appendElement(X,R,C),appendTransposed(T1,T2,T3).
% transposeMatrix(InputMatrix, TransposedMatrix)
transposeMatrix([L|M],T):-emptyMatrix(L,A),transpose([L|M],T,A).
transpose([],T,T).
transpose([L|M],T,A):-appendTransposed(L,A,B),transpose(M,T,B).
A 'line' kann eine Spalte oder eine Zeile sein.
Die Idee besteht darin, die Elemente in die Listen einer leeren Matrix einzufügen. (zB alle Elemente der ersten Reihe = die ersten Elemente aller cols => alle Elemente der ersten i-n-ten Reihe = die i-te Elemente aller cols)
es auf meiner Maschine wie diese Sitzung funktioniert Protokoll zeigt mir:
5 ?- transposeMatrix([[1,2],[3,4]],T).
T = [[1, 3], [2, 4]] ;
false.
6 ?- transposeMatrix([[1],[2]],T).
T = [[1, 2]] ;
false.
7 ?- transposeMatrix([[1,2,3],[4,5,6]],T).
T = [[1, 4], [2, 5], [3, 6]] ;
false.
8 ?- transposeMatrix([[1]],T).
T = [[1]] ;
false.
einfacheren Ansatz:
trans(M, [P|T]):- first(M, P, A), trans(A, T).
trans(Empty, []):- empty(Empty).
empty([[]|T]):- empty(T).
empty([[]]).
first([[P|A]|R], [P|Ps], [A|As]):- first(R, Ps, As).
first([], [], []).
effizient auch
[debug] 36 ?- time(trans([[1,2,3],[4,5,6],[7,8,9]],A)).
% 21 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips)
A = [[1,4,7],[2,5,8],[3,6,9]] ;
% 12 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips)
false.
Irgendwelche Gründe, die einfacheren Fälle zu dauern? – false
Ich kann die Ergebnisse nicht bestellen. –
Dies ist die kürzeste Antwort, die ich mir vorstellen konnte. Es könnte jedoch verbessert werden, indem Differenzlisten verwendet werden, um die Tail-Rekursion zu aktivieren.
transpose([[]|_], []).
transpose(M, [X|T]) :- row(M, X, M1),
transpose(M1, T).
row([], [], []).
row([[X|Xs]|Ys], [X|R], [Xs|Z]) :- row(Ys, R, Z).
Ein anderer Ansatz:
delete_one_list([], []).
delete_one_list([[_|L]|LLs], [L|Ls]) :-
delete_one_list(LLs, Ls).
transpose_helper([], []).
transpose_helper([[X|_]|Xs], [X|Ys]) :-
transpose_helper(Xs, Ys).
transpose([[]|_], []).
transpose(List, [L|Ls]) :-
transpose_helper(List, L),
delete_one_list(List, NewList),
transpose(NewList, Ls).
Danke! Ich benutze SWI Prolog und habe deine erste Lösung ausprobiert. Aber beim Eingeben von "use_module (library (clpfd))." Ich erhalte den folgenden Fehler: "FEHLER: source_sink' library (clpfd) "existiert nicht" Wissen Sie, wie man das löst? – cody
Ich nehme an, dass Sie entweder die 'clpfd'-Bibliothek nicht haben, oder Ihre Installation von SWI-PL ist kaputt. 'clpfd.pl' sollte im Verzeichnis' library/clp' (unter dem Home-Verzeichnis von SWI-PL) liegen. Wenn es da ist, dann könnte SWI-PL es vielleicht nicht finden; In diesem Fall hat Ihre 'pl'-Programmdatei möglicherweise einen anderen Namen als die' ___.rc'-Konfigurationsdatei, auch im SWI-PL-Stammverzeichnis (sie müssen identisch sein). Ansonsten benutze einfach die Definition, die ich gepostet habe, was die Implementierung von 'clpfd's' transpose/2' ist. – sharky
Ok. Die Bibliothek fehlte und ich kopierte sie in die Bibliothek/clp. Aber es funktioniert immer noch nicht. Ich habe eine Datei namens "plwin.rc" im Verzeichnis pl-root und einen bin-Ordner mit den ausführbaren Dateien. Verschieben der .rc in den Ordner bin löscht es nicht. Also muss ich es ändern? – cody