2016-11-29 129 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