2016-11-29 126 views
1

我正在研究一个问题,要求我计算每个学生在课堂上的平均分。计算Lisp中的平均分和平均分

输入是一个Lisp文件格式如下:

(((name studentname) (class hour grade) (class hour grade) ...) 
((name studentname) (class hour grade) (class hour grade) ...) ...) 

对于输出:我需要打印的平均成绩作为排序的学生的名字和他们的GPA(平均成绩为学生)以及班级平均分数(每个独特班级的平均分数)。

到目前为止,这是我

(setq class '(((name Seymore) (eng 3 4.0) (mat 3 3.0) (his 3 4.0) (bio 3 2.0) (biol 1 4.0)) 
((name Ichahbod) (cs 3 3.0) (mat 3 4.0) (spe 2 4.0) (che 3 4.0) (chel 1 3.0) (lit 3 3.0)) 
((name Zackery) (mat 5 3.0) (eng 3 3.0) (jou 2 3.0) (phy 3 3.0) (phyl 1 4.0) (lit 2 4.0)) 
((name Tukerville) (soc 4 3.0) (mus 2 4.0) (jou 3 4.0) (geo 4 4.0) (geol 1 3.0) (eng 3 3.0)) 
((name Simonsays) (css 3 3.0) (ast 3 4.0) (spe 3 4.0) (cs 3 4.0) (spe 2 3.0) (dan 4 4.0)) 
((name Snicker) (eng 3 4.0) (phy 4 4.0) (css 3 2.0) (csl 1 4.0) (ped 2 3.0) (mat 3 3.0)) 
((name Glass) (mat 3 1.0) (eng 3 1.0) (ped 1 1.0) (bio 3 1.0) (biol 1 0.0) (che 3 1.0) (chel 1 1.0)))) 

;this function multiplies the hours * the grades 
(defun product (hours grades) 
    (* hours grades) 
) 

;this function multiplies a set of grades 
(defun sumofGrades (L) 
    (cond 
     ((null L) 0) ;check if it is first 
     (t (+ (product (cdr (cdadar L)) (caddar L)))) ;first val then the second val 
     (sumofGrades (cdr L)) ;the rest of one 
    ) 
) 

;to get the total , same as sum of grades but sum the second variables 
(defun totalHours (L) 
    (cond 
     ((null L) 0) ;check if it is first 
     (t (+ (product (caddar L) (caddar L)))) ;first val then the second val 
     (totalHours() (cdr L)) ;the rest of one 
    ) 
) 


(defun gradepoint (L) 
    (/ (sumofGrades L) (totalHours L)) 
) 

我试图启动与辅助方法,因为我认为这会是最好的方法,它可能没有。当我运行sumofGrades时,我从第一个条目中获得了我需要的4.0,但它说它不是一个数字。我写了这些方法的基本数学,我需要做的数字,但在这一点上,我很困惑下一步该怎么做。

如果我需要倒带和去一个不同的例程我倒了,任何帮助将不胜感激。

+1

下次请粘贴完整的错误消息和函数调用。 – sds

+0

好吧,会对此表示歉意。 – user2762848

回答

2

你可能想尝试reduce

(mapcar (lambda (l) 
      (cons (second (first l)) 
       (/ (reduce #'+ (rest l) :key #'third) 
        (1- (length l))))) 
     class) 
==> 
((SEYMORE . 3.4) (ICHAHBOD . 3.5) (ZACKERY . 3.3333333) (TUKERVILLE . 3.5) 
(SIMONSAYS . 3.6666667) (SNICKER . 3.3333333) (GLASS . 0.85714287)) 

那么你可以使用sort排序是:

(sort * #'< :key #'cdr) 
==> 
((GLASS . 0.85714287) (ZACKERY . 3.3333333) (SNICKER . 3.3333333) (SEYMORE . 3.4) 
(ICHAHBOD . 3.5) (TUKERVILLE . 3.5) (SIMONSAYS . 3.6666667)) 

这里*是以前的表达式的值。

PS。由于这可能是h/w,我提供了一个代码示例而不是一个完整的解决方案,我建议您使用我的代码,然后询问另一个非常具体的问题,如果不清楚。

PPS。一些文体备注:

  1. 没有定义喜欢你product功能,它只是混乱的噪音
  2. 不要使用首字母大写,使用正常口齿不清破折号代替
  3. 不要用挂的括号
  4. 使用Emacs缩进你的代码,现在它是不可读的。
+0

非常感谢您的解释。我对lisp很新,这对我有很大的帮助。我用你的建议纠正我的代码,如果我有问题会通知你。再次感谢你。 – user2762848

3

您的代码

(defun sumofGrades (L) 
    (cond 
    ((null L) 0) ;check if it is first 
    (t (+ (product (cdr (cdadar L)) (caddar L)))) ;first val then the second val 
    (sumofGrades (cdr L)) ;the rest of one 
    ) 
) 

让我们来看看它

(defun sumofGrades (L) ; please no camelCase in Lisp 

    (cond 


    ((null L) 0) ;check if it is first <- what does this comment mean??? 


    (t (+ (product (cdr (cdadar L)) (caddar L)))) 

    ; what is (+ (product (cdr (cdadar L)) (caddar L))) ? 
    ; you are calling + with one argument. Why? 

    ; what does a function like caddar mean? 
    ; what is it supposed to do? 
    ; no one reading your code will have an idea why 
    ; caddar and not cdaadar, cdadaadr, or cdddddr... 
    ; write better documented, or self-documenting code. 


    (sumofGrades (cdr L)) ;the rest of one <- what does this comment mean? 

    ; what is (sumofGrades (cdr L)) ? 
    ; is sumofGrades a variable checked in COND? 
    ; should it be a function call? 
    ; just as it is alone here, it does not make any sense. 
    ; since T is always true, this clause is also never reached... 

    ) ; <- please no dangling parentheses in Lisp 
) 

当编译上述功能,LispWorks说:

; (TOP-LEVEL-FORM 0) 
;;;*** Warning in SUMOFGRADES: The following cond clause 
;;; will never be processed: ((SUMOFGRADES (CDR L))) 

摘要sumofGrades将不起作用。一个Lisp编译器已经在抱怨它了。


更多风格

全局变量:它们是由DEFPARAMETER或DEFVAR定义。请勿使用SETQ

不要写

(setq class ...) 

,而不是写:

(defparameter *class* ... 
    "the global variable *class* is a list of ...") 
+0

谢谢你的回应。我使用cdadar,cdr和其他功能从不同的列表中获得一个小时的等级。我想基本上抓住个人数字并添加他们,他们乘以获得产品。我的教授用这些代码帮助了一些人,所以我正在喂他。我是非常新的lisp,所以我为语法怪癖道歉。 – user2762848

+0

@ user2762848:问题是你永远不会记得CADAR的含义。如果它意味着GET-HOURS,那么请使用GET-HOURS函数。如果它意味着别的东西,那么就说出其他的东西。但给它一个有用的名字。你可能需要写... –

+0

,我做到了。谢谢!我应该发布我的工作代码吗? – user2762848

3

首先定义一些通用的功能平均:

(defun average (lst &key (key #'identity)) 
    (when lst 
    (/ (reduce #'+ lst :key key) (length lst)))) 

还定义了一个档次函数来获取的等级给予学生在给定的班级(没有必要,但会更清楚):

(defun grade (class) (caddr class)) 

和档次函数来检索一个学生的成绩:通过调用

(average (grades 'seymore) :key #'grade) 
=> 3.4 

根据这个实例

(defun grades (student) 
    (cdr (find student class :key #'cadar))) 

现在你可以找到一个学生的成绩的平均值,你应该能够自己写出所有课程的平均水平。

+0

非常感谢您的帮助。这帮了一大笔钱。 – user2762848