写一个函数 计算玫瑰树中元素的数量。
我尝试计算玫瑰树中的元素数量。
#!/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 )
答案 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.Tree
的containers
:
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.Tree
是Foldable
,因此可以在其上使用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
中的concat
,map
或concatMap
。
使用库玫瑰树还具有其他优点,例如,一堆其他类型类实例(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