编写一个计算玫瑰树中元素数量的函数

时间:2019-05-09 13:01:33

标签: haskell

写一个函数 计算玫瑰树中元素的数量。

我尝试计算玫瑰树中的元素数量。

#!/bin/bash
python predict.py model_cn config.json images/tom.jpg tom_out.jpg

应该为27,但是返回4。

编辑:这是我的尝试:

Array ( [0] => Traceback (most recent call last): [1] => File "predict.py", line 3, in [2] => import torch [3] => ImportError: No module named torch )

2 个答案:

答案 0 :(得分:6)

  

应该为27,但是返回4。

roseSize x = case x of
  RoseNode a [] -> 0
  RoseNode a (x:xs) -> 1 + roseSize (RoseNode a xs)

因此,您无需递归计算子树。尝试尝试(已修复:基本情况为1 ),

roseSize (RoseNode _ []) = 1
roseSize (RoseNode a (t:ts)) = roseSize t + roseSize (RoseNode a ts)

缺少的部分是roseSize t

否则,您只对树的第一层进行递归调用。

如果您手动评估功能,这很明显

roseSize things
  ~> roseSize (RoseNode "thing" [ animals, metals, fruits, astronomical_objects ]
  ~> 1 + roseSize (RoseNode "thing" [ metals, fruits, astronomical_objects ])
  ~> 1 + 1 + roseSize (RoseNode "thing" [ fruits, astronomical_objects ])
  ~> 1 + 1 + 1 + roseSize (RoseNode "thing" [ astronomical_objects ])
  ~> 1 + 1 + 1 + 1 + roseSize (RoseNode "thing" [])
  ~> 1 + 1 + 1 + 1 + 0

函数主体中带有roseSize t的求值结果变为

roseSize things
  ~> roseSize (RoseNode "thing" [ animals, metals, fruits, astronomical_objects ]
  ~> roseSize animals
      + roseSize (RoseNode "thing" [ metals, fruits, astronomical_objects ])
  ~> roseSize (RoseNode "animal" [ cat, dog ])
      + roseSize (RoseNode "thing" [ metals, fruits, astronomical_objects ])
  ~> roseSize cat
      + roseSize (RoseNode "animal" [ dog ])
      + roseSize (RoseNode "thing" [ metals, fruits, astronomical_objects ])
  ~> 1 -- given the base case of 1 instead of 0
      + roseSize (RoseNode "animal" [ dog ])
      + roseSize (RoseNode "thing" [ metals, fruits, astronomical_objects ])
  ~> ...

作为练习,使此函数显式递归是可以的。

但是您可能想考虑一种更通用的方法,要么使用高阶函数like PF. Castro does it,要么使用现有数据结构,例如Data.Treecontainers

import qualified Data.Tree as T
import           Data.Tree (Tree(..))

things :: Tree String
things = Node "thing" [ animals, metals, fruits, astronomical_objects ]
  where
    animals = Node "animal" (map pure [ "cat", "dog" ])
    metals = Node "metal" [ alloys, elements ]
    alloys = Node "alloy" (map pure [ "steel", "bronze" ])
    elements = Node "element" (map pure [ "gold", "tin", "iron" ])
    fruits = ...
    astronomical_objects = ...

由于Data.TreeFoldable,因此可以在其上使用length

因此不必定义自定义roseSize函数。


此时,您正在计算树中的节点,而不是树的,其中是实际的对象,而不是它们所属的类别。因此,您实际上可能对计数感兴趣。

您可以通过创建一个查找叶子的函数来做到这一点:

leaves :: Tree a -> [a]
leaves (Node x []) = ... -- x is a leaf
leaves (Node _x ts) = ... -- _x isn't a leaf

使用此模板,您将无法轻松地使用显式递归,即在Node x (t:ts)上进行匹配并在leaves上调用ts,因为这样,非叶子的情况最终以基本情况结束,使用尽的类别显示为叶子。但是您可以使用高阶函数来抽象出递归,例如Prelude中的concatmapconcatMap


使用库玫瑰树还具有其他优点,例如,一堆其他类型类实例(Applicative为您提供pure "foo"来构造单例树/叶子)和漂亮的打印件功能:

> putStrLn $ T.drawTree things
thing
|
+- animal
|  |
|  +- cat
|  |
|  `- dog
|
`- metal
   |
   +- alloy
   |  |
   |  +- steel
   |  |
   |  `- bronze
   |
   ...

答案 1 :(得分:4)

您应将地图和RoseTrees一起使用,例如:

size (RoseNode x xs) = 1 + (sum (map size xs))

总和为:

sum = foldl (+) 0