似乎我必须详细说明;这是我的功课。我不 想要复制你写的代码。我是新手;我在想什么 学习是如何将主题分解为单件,然后 专注于我应该用什么功能来解决问题。它是 我自己很难完成这些问题,因为我完全是这样 Lisp的新手,实际上是如何编程的。我希望你能帮帮我 进行。
问题在于:有一个给定的常数
(defconstant *storms* '((bob 65)
(chary 150)
(jenny 145)
(ivan 165)
(james 120)))
每个风暴都由其名称和风速列表表示。
风速分类如下:
39-74→tropical
75-95→cat-1
96-110→cat-2
111-130→cat-3
131-155→cat-4
156或更多→cat-5
现在我必须写两个函数:
storm-categories
应生成类别名称,如下所示:(bob
tropical)
,(chary cat-1)
,...
和storm-distribution
应该会产生风暴的数量
每个类别,例如:(cat-1 1)
,(cat-2 0)
,...
我尝试解决这个问题的方法是:
使用if
语句来判断风速的类型:
(如果(和(> x 39)(< x 73))(打印'热带)) (if(和(> x 74)(< x 95))(print'cat-1)) (if(和(> x 96)(< x 110))(打印'cat-2)) (if(和(> x 111)(< x 130))(print'cat-3)) (if(和(> x 131)(< x 155))(print'cat-4)) (if(和(> x 156))(print'cat-5))
用windtype替换windspeed(如65
)(如cat-1
)
( storms 中的x循环 do(rplacd x'windtype)
我只是对第一个函数有一个简单的想法,但仍然不知道 如何实现它。我没有触及分配功能, 因为我仍然坚持第一个。
答案 0 :(得分:4)
DEFCONSTANT错了。使输入保持不变是没有意义的。用DEFVAR或DEFPARAMETER定义的变量很好。
而不是IF使用COND。 COND允许测试几种条件。
您不想使用PRINT。为什么打印东西。您想要计算一个值。
RPLACA也错了。那用于破坏性修改。你不希望这样。您想要创建一个新值。像RPLACA这样的东西可能会在函数DISTRIBUTION中使用(见下文)。
使用功能抽象。哪些功能有用?
BETWEEN-P是a和b之间的值X?
STORM-CATEGORY,对于给定的风速,返回类别
STORM-CATEGORIES,对于项目列表(风暴风速)返回项目列表(风暴类别)。映射输入列表以创建结果列表。
DISTRIBUTION,对于项目列表(标记类别),返回包含项目的列表(类别编号为此类别中的标记)。
STORM-DISTRIBUTION,对于项目列表(风暴类别)返回一个包含项目的列表(类别风暴数量在此类别中)。这基本上使用正确的参数调用DISTRIBUTION。
函数DISTRIBUTION是上面最复杂的。通常,人们会使用哈希表或关联列表作为中间帮助来保持事件的计数。映射输入列表并更新相应的计数。
另外:对基本Lisp的一个很好的介绍是书Common Lisp: A Gentle Introduction to Symbolic Computation - 它可以免费下载PDF格式。 Lisp的更有趣和基本的介绍是书Land of Lisp。
答案 1 :(得分:1)
好的roccia,你已经发布了答案。几分钟后我就被黑了,但它应该给你一些想法:
首先让我们从数据开始:
(defparameter *storms2004*
'((BONNIE 65)
(CHARLEY 150)
(FRANCES 145)
(IVAN 165)
(JEANNE 120)))
(defparameter *storm-categories*
'((39 73 tropical-storm)
(74 95 hurricane-cat-1)
(96 110 hurricane-cat-2)
(111 130 hurricane-cat-3)
(131 155 hurricane-cat-4)
(156 nil hurricane-cat-5)))
检查值是否在两个边界之间的函数。如果右边界也可能丢失(NIL)。
(defun between (value a b)
(<= a value (if b b value)))
请注意,Lisp允许比较谓词具有两个以上的参数。
让我们找一个风暴的类别。 Lisp函数FIND
和FIND-IF
在列表中查找内容。
(defun storm-category (storm-speed)
(third (find-if (lambda (storm)
(between storm-speed (first storm) (second storm)))
*storm-categories*)))
让我们计算每场风暴的类别。由于我们得到(风暴风速)列表,我们只是映射在计算列表上的类别的函数上。我们需要返回一系列风暴和类别。
(defun storm-categories (list)
(mapcar (lambda (storm)
(list (first storm)
(storm-category (second storm))))
list))
现在我们采用相同的风暴列表,但使用哈希表来跟踪每个类别中有多少风暴。 MAPC
与MAPCAR
类似,但仅限于更新哈希表的副作用。 ÌNCF递增计数。当我们填充哈希表时,我们需要使用MAPHASH
对其进行映射。对于表中的每对键和值,我们只需将该对推送到结果列表中,然后返回该结果。
(defun storm-distribution (storms)
(let ((table (make-hash-table)))
(mapc (lambda (storm)
(incf (gethash (second storm) table 0)))
(storm-categories storms))
(let ((result nil))
(maphash (lambda (key value)
(push (list key value) result))
table)
result)))
测试:
CL-USER 33 > (storm-category 100)
HURRICANE-CAT-2
CL-USER 34 > (storm-categories *storms2004*)
((BONNIE TROPICAL-STORM)
(CHARLEY HURRICANE-CAT-4)
(FRANCES HURRICANE-CAT-4)
(IVAN HURRICANE-CAT-5)
(JEANNE HURRICANE-CAT-3))
CL-USER 35 > (storm-distribution *storms2004*)
((HURRICANE-CAT-5 1)
(HURRICANE-CAT-4 2)
(HURRICANE-CAT-3 1)
(TROPICAL-STORM 1))
对我来说很好。
答案 2 :(得分:0)
终于完成了这个问题。第二部分真的让我发疯了。我无法弄清楚如何使用哈希表或关联列表来解决它。无论如何,任务已完成,但我想知道如何简化它...希望你们能帮助我。感谢你的帮助,Joswing,你的想法真的对我很有帮助......
(defconstant *storms2004* '((BONNIE 65)(CHARLEY 150)(FRANCES 145)(IVAN 165)(JEANNE 120)))
(defun storm-category (x) ; for given windspeed return the category
(cond
((and (> x 39) (< x 73) 'tropical-storm))
((and (> x 74) (< x 95) 'hurricane-cat-1))
((and (> x 96) (< x 110) 'hurricane-cat-2))
((and (> x 111) (< x 130) 'hurricane-cat-3))
((and (> x 131) (< x 155) 'hurricane-cat-4))
( t 'hurricane-cat-5)
)
);end storm-category
(defun storm-categories (lst) ;for a list of storm and windspeed return storm's name and wind type
(let ((result nil))
(dolist (x lst (reverse result)) ;
(push
(list (first x) (storm-category (second x)) ) result)
)
)
);end storm-categories
(defun storm-distribution (lst)
(setq stormcategories '(tropical-storm hurricane-cat-1 hurricane-cat-2 hurricane-cat-3 hurricane-cat-4 hurricane-cat-5))
(setq stormlist (storm-categories lst))
(let( (tropicalcount 0)
(hurricane-cat-1count 0)
(hurricane-cat-2count 0)
(hurricane-cat-3count 0)
(hurricane-cat-4count 0)
(hurricane-cat-5count 0)
(result nil)
)
(dolist (y stormlist )
(cond
((eql (second y) 'tropical-storm) (setq tropicalcount (+ tropicalcount 1)))
((eql (second y) 'hurricane-cat-1) (setq hurricane-cat-1count (+ hurricane-cat-1count 1)))
((eql (second y) 'hurricane-cat-2) (setq hurricane-cat-2count (+ hurricane-cat-2count 1)))
((eql (second y) 'hurricane-cat-3) (setq hurricane-cat-3count (+ hurricane-cat-3count 1)))
((eql (second y) 'hurricane-cat-4) (setq hurricane-cat-4count (+ hurricane-cat-4count 1)))
((eql (second y) 'hurricane-cat-5)(setq hurricane-cat-5count (+ hurricane-cat-5count 1)))
)
);ebd dolist
(push
(list (list 'tropicalstorm tropicalcount )
(list 'hurricane-cat-1 hurricane-cat-1count)
(list 'hurricane-cat-2 hurricane-cat-2count )
(list 'hurricane-cat-3 hurricane-cat-3count )
(list 'hurricane-cat-4 hurricane-cat-4count )
(list 'hurricane-cat-5 hurricane-cat-5count )
) ;end list
result) ;end push
);end let
);end distribution