2016-05-19 6 views
0

Ich arbeite mit Matrix, wobei jede sublist eine Zeile:Prolog Matrixspalt Behandlung

Matrix =[[-,-,-,-,a,-], 
     [-,-,-,-,b,-], 
     [-,-,-,-,a,-], 
     [-,-,-,-,d,a], 
     [-,-,-,-,a,a], 
     [-,-,a,a,a,a], 
     [-,-,-,-,d,a]]. 

Mein Ziel zu finden ist, wenn vier aufeinanderfolgende Positionen in einer Unterliste mit dem gleichen Charakter sind, die gesendet.

veryRow(_,[]). 
veryRow(X,[T|TS]) :- row(X,T), veryRow(X,TS). 
row(X,[A,B,C,D|_]) :- A \= X; B \= X; C \= X; D \= X. 
row(X,[_|Xs]):- row(X,Xs). 

Muss True zurückgegeben werden, wenn eine Unterliste vier aufeinander folgende Elemente.

meine Inputs ist:

veryRow(a,[[-,-,-,-,a,-], 
     [-,-,-,-,b,-], 
     [-,-,-,-,a,-], 
     [-,-,-,-,d,a], 
     [-,-,-,-,a,a], 
     [-,-,a,a,a,a], 
     [-,-,-,-,d,a]]). 

Da nicht gefunden?

Dank

+0

'veryRow 'wird fehlschlagen, sobald eine Zeile gefunden wird, die für' row' nicht erfolgreich ist. – lurker

+0

aber mit dem Schnitt „!“. Stoppt die Ausführung nicht, wenn Row wahr ist? – Merche

+0

So weit kommt es nie. Der Schnitt verhindert nur das Zurückverfolgen von mehr Solutinen * wenn * der Aufruf von 'row' erfolgreich ist. Für die erste Zeile in der zweiten Argument 'veryRow (X, [T | TS])' schlägt fehl, da 'T' nicht über 4 aufeinanderfolgende' X's. Und 'veryRow (_, [])' schlägt fehl, weil das zweite Argument nicht die leere Liste ist. Das Prädikat schlägt also vollständig fehl. Ihre Logik für 'veryRow' erfordert, dass' row' erfolgreich ist. – lurker

Antwort

1

Beginnend von oben, denke ich, dass veryRow Bedarf überdacht werden. Der Name ist nicht zufriedenstellend, weil er nicht beschreibt, was die Regel sehr gut macht. Aber ich werde es so lassen wie es ist und es Ihnen überlassen, einen passenderen Namen zu wählen (vielleicht four_in_a_row oder etwas ähnliches).

Der Basisfall veryRow(_, []). ist problematisch. Es ist gelungen, jedes Element als erstes Argument und die leere Liste als zweites Argument zu verwenden, aber diese Argumente erfüllen logischerweise nicht die Anforderung, dass diese Regel entscheiden soll (dass das erste Argument viermal hintereinander als ein Element im zweiten auftritt) Streit). Also lass uns diese Regel auslassen.

Ihre zweite Regel ist ebenfalls problematisch:

veryRow(X,[T|TS]) :- row(X,T),!, veryRow(X,TS). 

Diese Regel besagt, dass X Mal in Folge ist in [T|TS]wennX ist in Folge in TundX ist in Folge in TS. Dies ist offensichtlich falsch, da Sie wollen, dass es erfolgreich ist, wenn X in mindestens eine der Zeilen in [T|TS], nicht alle die Reihen ist. Der Schnitt, den Sie eingefügt haben, ändert diese Bedeutung nicht.

Sicher wäre folgende wahr sein als einen einfacher Basisfall, der das Element in der Spitze der Liste erfolgt nacheinander ist:

veryRow(X, [T|_]) :- row(X, T). 

Hinweis: Das ist alles, was Sie für den Basisfall benötigen. Es ist erfolgreich, sobald row(X, T) erfolgreich ist und keine weiteren Anrufe getätigt werden sollten. Aber was, wenn es scheitert (X ist nicht in T hintereinander)? Dann müssen Sie Ihre andere Klausel den Rest der Liste zu handhaben:

veryRow(X, [_|Ts]) :- veryRow(X, Ts). 

Das sagt einfach X sind in Folge in [_|Ts] wenn X in Ts in Folge ist.

Dies wird letztlich fehlschlagen, wenn Ts[] ist, was in Ordnung ist, da es nicht wahr wäre.

Sie sollten Ihre Schnitte loszuwerden, und diese Regel wird für jeden Fall arbeiten und erfolgreich zu sein, dass es vier aufeinander folgende Elemente findet. Wenn es mehrere solcher Fälle gibt, erhalten Sie mehrere Erfolge/Lösungen. Wenn Sie es nur einmal erfolgreich sein wollen, können Sie once/1 verwenden:

onceVeryRow(X, L) :- once(veryRow(X, L)). 


Ihre erste Implementierung von row/2 war in Ordnung, bevor Sie es geändert wird (und mit dem Schnitt entfernt):

row(X, [X, X, X, X|_]). 
row(X, [_|T]) :- 
    row(X, T). 
+1

vielen dank !! Ja wirklich. Es funktioniert richtig und am wichtigsten zu verstehen. Vielen Dank – Merche