2015-11-29 5 views
6

In dieser Übung sollte ich eine Funktion schreiben, die eine Liste von ganzen Zahlen als Argument erhält und eine Matrix oder eine Liste von Listen gibt. Der Punkt bei der Herstellung der Matrix besteht darin, dass die ganzen Zahlen die Anzahl von True s in jeder Spalte der Matrix darstellen.So transformieren Sie eine Liste von Ganzzahlen in eine Matrix von Wahr und Falsch in Haskell

enter image description here

, die im System als eine Liste von Listen dargestellt: Zum Beispiel

[2,4,1] 

muss übersetzt werden

[ [0,1,0], [0,1,0], [1,1,0], [1,1,1] ] 

Da es nicht einfach ist, Matrizen zu manipulieren (Liste von Listen) nach Spalten Ich habe einen Trick benutzt und rotiere die Matrix um 90 Grad nach links unter Verwendung von transpose, was die Matrix so aussehen lässt unten:

enter image description here

Dann entwickelte ich den folgenden Algorithmus, um das Problem zu lösen:

  1. Nehmen Sie das erste Element der Eingabeliste
  2. Erstellen Sie eine Liste der Länge maximum xs (die Länge jedes Liste ist gleich dem maximalen Element in der Liste)
  3. Setzen Sie so viele True in der Liste als das erste Element bestimmt.
  4. Füllen Sie den Rest der Liste mit False
  5. das gleiche für alle Elemente und drehen Sie die Matrix

ich versucht habe zwei Lösungen zu implementieren, aber jeder hat ein Problem, das ich nicht lösen kann:

  1. Dieser funktioniert für das erste Element nur gut, aber ich weiß nicht, wie es von der Eingabeliste auf alle Elemente anwenden

    listToMatrix x = (replicate ((maximum x) - (head x)) False) ++ (replicate (head x) True)` 
    
  2. Dies funktioniert für alle Elemente, kann aber die Länge der inneren Liste nicht beibehalten, so dass die Listen unterschiedliche Längen haben.

    listToMatrix [email protected](x:xs) = ((replicate ((maximum lst) - x) False) ++ (replicate x True)) : listToMatrix xs` 
    

Frage 1: Wie kann ich diese Funktionen machen mit minimalen Änderungen arbeiten?

Frage 2: Sind elegante und kompakte Lösungen?

P.S. Ich verwendete 1 und 0 in den Matrizen, um sie lesbarer zu machen, aber sie sind in der Tat True und False

+0

Ist das Hausaufgaben? –

+0

Es ist eine Art Projekt. Warum? – Infinity

+0

Nun, zumindest zeigt es Anstrengung, im Gegensatz zu den meisten SO Hausaufgaben Fragen. Es fragt nicht einfach "gimme code", sondern bietet einen Lösungsansatz. – chi

Antwort

3

Ich würde den folgenden Ansatz verwenden, der mit Ihrem kompatibel ist.

Wie Sie vorgeschlagen haben, verwenden wir am Ende transpose, da die transponierte Matrix einfacher zu generieren aussieht.

f :: [Int] -> [[Bool]] 
f xs = transpose (...) 

Dann wird jedes Element der xs hat eine neue Zeile zu erzeugen. Wir können entweder ein Listenverständnis verwenden (siehe unten) oder alternativ map verwenden.

f :: [Int] -> [[Bool]] 
f xs = transpose [ row x | x <- xs ] 
    where row :: Int -> [Bool] 
     row x = ... 

Wie Sie vorschlagen, wir brauchen maximum auch jede Zeile zu erzeugen, so berechnen wir es einmal:

f :: [Int] -> [[Bool]] 
f xs = transpose [ row x | x <- xs ] 
    where m = maximum xs 
     row :: Int -> [Bool] 
     row x = ... -- we know x and m, we need m-x Falses and x Trues 

Nun müssen Sie nur Ihren Code anzupassen.

+0

Es funktioniert perfekt. Danke für die ausführliche Erklärung :) – Infinity

3

Dies ist, wie ich es tun würde:

toMatrix' :: [[Bool]] -> [Int] -> [[Bool]] 
toMatrix' acc xs 
    | or bools = toMatrix' (bools : acc) (map pred xs) 
    | otherwise = acc 
    where bools = map (> 0) xs 

toMatrix :: [Int] -> [[Bool]] 
toMatrix = toMatrix' [] 

Einfach und unkompliziert

. Keine Notwendigkeit, zu transponieren.

Hier ist die Visualisierung meines Programms. Ich werde 0 und 1 für False und True jeweils verwenden.

toMatrix [2,4,1] = toMatrix' []        [ 2, 4, 1] 
       = toMatrix' [[1,1,1]]       [ 1, 3, 0] 
       = toMatrix' [[1,1,0],[1,1,1]]     [ 0, 2,-1] 
       = toMatrix' [[0,1,0],[1,1,0],[1,1,1]]   [-1, 1,-2] 
       = toMatrix' [[0,1,0],[0,1,0],[1,1,0],[1,1,1]] [-2, 0,-3] 
       = [[0,1,0], 
        [0,1,0], 
        [1,1,0], 
        [1,1,1]] 

Wenn wir toMatrix' acc xs nennen wir zuerst bools = map (> 0) xs berechnen. Wenn alle Elemente von boolsFalse sind, dann sind wir fertig. Wir geben einfach acc zurück. Ansonsten fügen wir bools an den Anfang von acc an und subtrahieren eins von jedem Element von xs. Spülen und wiederholen.

Keine Notwendigkeit, das größte Element von xs zu verfolgen und keine Notwendigkeit, die Matrix zu transponieren. Einfach.

+1

Dies ist eine nette Antwort, eine Zusammenfassung, warum Sie es so strukturiert haben, wie Sie es getan hätten, es noch schöner machen würde. – Greg

+0

Dies erzeugt die Matrix auf den Kopf gestellt aus dem Beispiel in der Post des OP. Wenn Sie anstelle der einzelnen Elemente des Quell-Arrays einen zusätzlichen Countdown übergeben, der am Maximum beginnt und schließlich 0 erreicht, und jedes Element mit einem Countdown füllen, der kleiner oder gleich dem Quellelement ist, erhalten Sie die richtige Reihenfolge . –

+0

@SebastianRedl Nein. Er erzeugt die Matrix mit der richtigen Seite nach oben. Ich weiß es, weil ich die Funktion geschrieben und getestet habe. Sie sollten es selbst testen. –

Verwandte Themen