Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 帮助计算(四叉树)矩阵的列和的算法?_Algorithm_Haskell_Matrix_Quadtree - Fatal编程技术网

Algorithm 帮助计算(四叉树)矩阵的列和的算法?

Algorithm 帮助计算(四叉树)矩阵的列和的算法?,algorithm,haskell,matrix,quadtree,Algorithm,Haskell,Matrix,Quadtree,根据此定义和测试矩阵: data (Eq a, Show a) => QT a = C a | Q (QT a) (QT a) (QT a) (QT a) deriving (Eq, Show) data (Eq a, Num a, Show a) => Mat a = Mat {nexp :: Int, mat :: QT a} deriving (Eq, Show) -- test matrix, exponent is 2, that is matrix i

根据此定义和测试矩阵:

data (Eq a, Show a) => QT a = C a | Q (QT a) (QT a) (QT a) (QT a)
    deriving (Eq, Show)

data (Eq a, Num a, Show a) => Mat a = Mat {nexp :: Int, mat :: QT a}
    deriving (Eq, Show)

-- test matrix, exponent is 2, that is matrix is 4 x 4
test = Mat 2 (Q (C 5) (C 6) (Q (C 1) (C 0) (C 2) (C 1)) (C 3))

|     |     |
|  5  |  6  |
|     |     |
-------------
|1 | 0|     |
|--|--|  3  |
|2 | 1|     |
我正在尝试编写一个函数,它将输出一个列总和的列表,比如:
[13,11,18,18]
。基本思想是对每个子四叉树求和:

  • 如果四叉树是
    (C C)
    ,则输出a重复
    2^(n-1)
    乘以值
    C*2^(n-1)
    。示例:第一个四叉树是
    (c5)
    ,所以我们重复
    5*2^(2-1)=10次,
    2^(n-1)=2次,得到[5,5]
  • 否则,给定
    (qabcdd)
    ,我们使用
    a和c(以及b和d)的colsum
当然,这不起作用(甚至不编译),因为经过一些递归之后,我们有:

zipWith (+) [[10, 10], [12, 12]] [zipWith (+) [[1], [0]] [[2], [1]], [6, 6]]
因为我从Haskell开始,我觉得我遗漏了一些东西,需要一些关于我可以使用的函数的建议不工作列和定义为:

colsum :: (Eq a, Show a, Num a) => Mat a -> [a]
colsum m = csum (mat m)
    where
        n = nexp m
        csum (C c)       = take (2 ^ n) $ repeat (c * 2 ^ n)
        csum (Q a b c d) = zipWith (+) [colsum $ submat a, colsum $ submat b]
                                       [colsum $ submat c, colsum $ submat d]
        submat q = Mat (n - 1) q

任何想法都是非常好的,非常感谢……

< P> >让我们考虑一下你的代码> CalSuth<代码>:

colsum :: (Eq a, Show a, Num a) => Mat a -> [a]
colsum m = csum (mat m)
    where
        n = nexp m
        csum (C c)       = take (2 ^ n) $ repeat (c * 2 ^ n)
        csum (Q a b c d) = zipWith (+) [colsum $ submat a, colsum $ submat b]
                                       [colsum $ submat c, colsum $ submat d]
        submat q = Mat (n - 1) q
它几乎是正确的,除了定义csum(qabcd)=……
的那一行之外

让我们想想类型
colsum
返回数字列表<代码>ZipWith(+)
按元素对两个列表求和:

ghci> :t zipWith (+)
zipWith (+) :: Num a => [a] -> [a] -> [a]
这意味着您需要将两个数字列表传递给
zipWith(+)
。而是创建两个数字列表,如下所示:

[colsum $ submat a, colsum $ submat b]
此表达式的类型是
[[a]]
,而不是您需要的
[a]

您需要做的是连接两个数字列表以获得单个数字列表(这可能就是您想要做的):


类似地,您将
c
d
的部分和列表连接起来,然后您的函数应该开始工作。

让我们进行更一般的讨论,回到手头的目标

考虑如何将四叉树投影到2n×2n矩阵中。我们可能不需要创建这个投影来计算它的列和,但它是一个有用的概念

  • 如果我们的四叉树是一个单元,那么我们就用该单元的值填充整个矩阵
  • 否则,如果n≥ 1,我们可以将矩阵分成四个象限,让每个子象限树填充一个象限(即,让每个子象限树填充一个2n-1×2n-1矩阵)
  • 请注意,还有一个案例。如果n=0(也就是说,我们有一个1×1的矩阵),并且四叉树不是一个单元,会怎么样?我们需要为这种情况指定一些行为-也许我们只是让其中一个子四叉树填充整个矩阵,或者我们用一些默认值填充矩阵

现在考虑这样的投影的列和。

  • 如果我们的四叉树是一个单元,那么2n列和都是2n 乘以存储在该单元格中的值

    (提示:查看hoogle上的
    replicate
    genericplicate

  • 否则,如果n≥ 1,则每列重叠两个不同的象限。 我们一半的专栏将完全由西部象限决定, 另一半由东象限表示,即特定列的总和 可以定义为该列贡献的总和 从其北半部(即,北象限中该列的列和), 和它的南半部(同样)

    (提示:我们需要将西方列和附加到东方列和 获取所有列的和,并将北半列和南半列的和合并 获取每列的实际总和)

  • 同样,我们还有第三种情况,这里的列和取决于 将四个子四叉树投影到1×1矩阵上。幸运的是,1×1矩阵意味着 只有一列和

现在,我们只关心一个特定的投影-在一个大小为2dd×2d的矩阵上的投影 其中d是四叉树的深度。所以你也需要计算深度。自从 单个细胞“自然地”适合大小为1×1的矩阵,这意味着它具有 深度为0。四边形分支的深度必须足够大,以允许其每个子四边形都适合 可能“某人”应该向担心四叉树深度的人解释,矩阵类型中的nexp字段正是用来确定a(C)的实际大小的

关于第一个答案中给出的解决方案,好的,它是有效的。然而,构造和解构Mat是非常无用的,这是可以很容易避免的。此外,调用fromIntegral来“绕过”由于使用replicate而产生的类型检查问题可以解决,而不必先进入Integral,然后再返回,如

设m=2^n;k=2^n,重复k(m*x)

无论如何,这里的挑战是避免由于++而产生的二次行为,这是我所期望的


干杯,

为什么第二列和是21?他们不是18岁吗?@Vitek博士:你说得对,谢谢。想法?看起来你在这里问了很多问题,这些都是家庭作业问题。也许问一个同学会是一个更好的解决办法,因为他们也会有同样的问题?要清楚的是,如果你给他提供了提示,告诉他编译错误的来源以及如何纠正(除了为他重写代码之外),问他引导性问题,或者给他一个有细节要填写的草图,我会投+1。这似乎无助于任何人从中学习。我不确定你对基本情况做了什么。更多的单词,更少的代码?我更新了答案:删除了完整的工作代码,并解释了@Gremo的错误所在。另外,就我个人而言,我总是觉得解释性的例子是更好的学习方法,而模糊的暗示则认为我知道一些我不知道的东西。因此,如果一个人问答案,对我来说,这意味着他想要答案(这里:解决任务的代码,完成h所需的代码)
((colsum $ submat a) ++ (colsum $ submat b))