2015-12-22 141 views
1

我有這種類型Mat a = [[a]]來表示haskell中的矩陣。 我必須寫一個旋轉矩陣的功能,對於如[[1,2,3],[0,4,5][0,0,6]]將成爲[[3,5,6],[2,4,0],[1,0,0]]所以我做了這個:在Haskell中旋轉矩陣

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

但輸出

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

我不知道該怎麼放入基本情況以避免此例外。 Apreciate任何幫助。

+0

當你修好你的功能之後,你可能會考慮如何從現有的功能中構建出來,而不需要顯式的遞歸。 (破壞者:base64解碼'cm90YXRlTGVmdCA9IHJldmVyc2UgLiB0cmFuc3Bvc2UK'。) –

回答

2

您的列表將不會爲空,但空列表的列表,你可以做以下基於第一子列表模式匹配(假設墊保證了數據的一致性結構)

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

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

你錯過第二種情況。

0
rotateLeft []  = [] 
rotateLeft ([]:_) = [] 
rotateLeft (h:t) = (map last (h:t)):(rotateLeft (map init (h:t))) 

第一種模式適用於列表列表的頭部長於其他元素的情況。

你得到了第二個模式錯誤:如果我們有一個適當的矩陣(即元素是相同的長度),那麼基本情況是一個空列表的列表。但是,您編寫了[[]],只有當初始列表由單個列表組成時,纔會發生這種情況。

0

問題是您的模式不匹配。通過您的代碼做什麼步進,我們先從:

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 
[[],[],[]] 

因此,根本的問題是,你匹配你的基本情況是不是[[],[],[]]但反而[[]],使模式不匹配。你現在有三個或多或少的選擇:你可以(a)當看到第一個空列表時試圖終止;這是使用any函數和null函數在Haskell中編寫爲any null,這兩個函數都在Prelude中定義;或者(b)您可以硬編碼,這隻適用於3x3矩陣,只匹配[[],[],[]],或(c)您可以嘗試在所有列表爲空(all null)時終止,在這種情況下,您可以跳過不需要「 t存在或將所有內容都包含在Maybe x數據類型中,以便丟失的元素由Nothing表示,而當前的元素由Just x表示。

4

我是一個匆忙的老人。我會做這樣的(進口Data.List

rotl :: [[x]] -> [[x]] 
rotl = transpose . map reverse 
2

我認爲最簡單的解決辦法是:

import Data.List 

rotateLeft :: [[a]] -> [[a]] 
rotateLeft = reverse . transpose 

rotateRight :: [[a]] -> [[a]] 
rotateRight = transpose . reverse 

是Data.List模塊的標準模塊。

將切片行轉換爲列,這幾乎像旋轉一樣,但以錯誤的順序離開列,所以我們只是將它們反轉。