2015-12-22 109 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模块的标准模块。

将切片行转换为列,这几乎像旋转一样,但以错误的顺序离开列,所以我们只是将它们反转。