Ich habe diesen Typ Mat a = [[a]], um eine Matrix in Haskell darzustellen. Ich muss eine Funktion schreiben, die eine Matrix dreht, zum Beispiel wird [[1,2,3],[0,4,5], [0,0,6]] zu [[3,5,6],[2,4,0],[1,0,0]], also habe ich Folgendes gemacht:

rotateLeft :: Mat a->Mat a
rotateLeft [[]] = []
rotateLeft (h:t) = (map last (h:t)):(rotateLeft (map init (h:t)))

Aber die Ausgabe ist

[[3,5,6],[2,4,0],[1,0,0],[*** Exception: Prelude.last: empty list

Ich weiß nicht, was ich in den Basisfall setzen soll, um diese Ausnahme zu vermeiden. Schätzen Sie jede Hilfe.

4
paulo_ferreira 22 Dez. 2015 im 22:40

4 Antworten

Beste Antwort

Ihre Liste wird nicht leer sein, sondern eine Liste mit leeren Listen. Sie können die folgenden Schritte ausführen, um die Musterübereinstimmung basierend auf der ersten Unterliste durchzuführen (vorausgesetzt, Mat stellt die Konsistenz der Datenstruktur sicher).

rl [] = []
rl ([]:_) = []
rl m = map last m : (rl (map init m))

rl mat
[[3,5,6],[2,4,0],[1,0,0]]

Sie vermissen den zweiten Fall.

2
karakfa 22 Dez. 2015 im 19:58

Ich bin ein alter Mann in Eile. Ich würde es so machen (Data.List importieren)

rotl :: [[x]] -> [[x]]
rotl = transpose . map reverse
6
pigworker 23 Dez. 2015 im 00:17
rotateLeft []     = []
rotateLeft ([]:_) = []
rotateLeft (h:t)  = (map last (h:t)):(rotateLeft (map init (h:t)))

Das erste Muster gilt für den Fall, dass der Kopf der Listenliste länger als andere Elemente ist.

Sie haben das zweite Muster falsch verstanden: Wenn wir eine richtige Matrix haben (dh Elemente sind gleich lang), ist der Basisfall eine Liste leerer Listen. Sie haben jedoch [[]] geschrieben, was nur dann zutrifft, wenn die ursprüngliche Liste aus einer einzelnen Liste besteht.

0
dfridman1 22 Dez. 2015 im 19:58

Das Problem ist, dass Ihr Muster nicht übereinstimmt. Wir gehen durch die Funktionen Ihres Codes und beginnen mit:

Prelude> let x = [[1,2,3],[0,4,5],[0,0,6]]
Prelude> :m +Data.List
Prelude Data.List> map last x
[3,5,6]
Prelude Data.List> let y = map init x
Prelude Data.List> y
[[1,2],[0,4],[0,0]]
Prelude Data.List> map last y
[2,4,0]
Prelude Data.List> let z = map init y
Prelude Data.List> z
[[1],[0],[0]]
Prelude Data.List> map last z
[1,0,0]
Prelude Data.List> map init z
[[],[],[]]

Das Grundproblem besteht also darin, dass Ihr Basisfall, mit dem Sie übereinstimmen, nicht [[],[],[]] ist, sondern [[]], sodass das Muster nicht übereinstimmt.

Sie haben jetzt mehr oder weniger drei Möglichkeiten: Sie können (a) versuchen zu beenden, wenn die erste leere Liste angezeigt wird; Dies wird in Haskell als any null geschrieben, wobei die Funktion any und die Funktion null verwendet werden, die beide im Präludium definiert sind. oder (b) Sie können fest codieren, dass dies nur für 3x3-Matrizen funktioniert, und nur mit [[],[],[]] übereinstimmen, oder (c) Sie können versuchen, zu beenden, wenn alle Listen leer sind (all null). In diesem Fall Sie können entweder nicht vorhandene Elemente überspringen oder alles in den Datentyp Maybe x einschließen, sodass fehlende Elemente durch Nothing dargestellt werden, während vorhandene Elemente durch Just x dargestellt werden.

0
CR Drost 22 Dez. 2015 im 19:58