1

GPAを計算できる関数を書こうとしています。今では限られた計算(3つだけ)を行うことができますが、ループや再帰(サブジェクトの要件)を使用せずに、n番目の関数を消費する方法を使用せずにさらに計算する方法に固執しましたか?のように:(n番目のn)、もしそうなら、それは私がラムダ式を書く必要があることを意味しますか?初心者として、私は質問を明確に説明できないかもしれません、本当にいくつかの助けが必要です。

Glistは成績ポイントですClistは単位時間です。

GPA =(gradepoint * credithour + gradepoint * credithour)/(credithourの合計)like:(3 * 1 + 3 * 2 + 4 * 1)/(1 + 2 + 1)

これが私のコードです:

(defun gpa (Glist Clist)
     (format t "~3,2f~%" 
      (/ 
        (+(nth 0 (mapcar #' * Glist Clist))
          (nth 1 (mapcar #' * Glist Clist))
          (nth 2 (mapcar #' * Glist Clist)))
        (+ (nth 0 Clist)
           (nth 1 Clist)
           (nth 2 Clist))
                   );end "/"
                   );end "format" 
       (values)    );end 
4

2 に答える 2

7

編集

これは、いくつかの一般的な(小さなc)Lispのアイデアを強調する良い機会のように思われるので、説明するために答えを具体化しました。


sum別の回答で述べたように、 (数値の)リストを操作する関数を使用できます。

(defun sum (nums)
  (reduce #'+ nums))

内積は、2つの(等しい長さの)ベクトルの乗法和です。

(defun dot-product (x y)
  (sum (mapcar #'* x y)))

この関数gpaは、次の2つの単純な組み合わせです。

(defun gpa (grades credits)
  (/ (dot-product grades credits) (sum credits)))

質問の例は、私たちが期待する答えになります(フロートとしてフォーマットされていることを除いて):

(gpa '(3 3 4) '(1 2 1))
> 13/4

この例から言及する価値のあることがいくつかあります。

  1. map、、reduceおよびそれらのバリアントと親戚について学ぶ必要があります。これらの関数はLispにとって非常に重要であり、リストを操作するのに非常に役立ちます。 map*関数は通常、シーケンスをシーケンスにマップし、reduce通常はシーケンスを単一の値に変換します(ただし、のような形式を使用できます(reduce #'cons '(1 2 3)))。

  2. これは、プログラミングへの「ボトムアップ」アプローチの良い例です。このような単純な関数をプログラミングするsumと、多くの場合便利ですが、その上に簡単に記述できますdot-product。これで、このgpa関数は、他の2つの関数の上に構築されたシンプルで読みやすい関数になりました。これらはすべてワンライナーであり、CLの基本的な知識を持っている人なら誰でも簡単に読むことができます。これは、OOPに通常適用される方法論とは対照的です。

  3. コードの繰り返しはありません。確かに、sum複数回使用されていますが、それが理にかなっている場合に限ります。リストの要素の合計の概念を抽象化するために、これ以上何もすることはできません。Schemeでは、関数を使用して関数を作成する方が自然であり、それはまったく別のトピックです。これは単純な例ですが、2つの関数が同じことをしているわけではありません。

于 2011-09-09T05:00:59.163 に答える
1

リストをトラバースするために使用している場合nth、それは間違っています。この場合、合計関数を作成することをお勧めします。

(defun sum (items)
  (reduce #'+ items))
于 2011-09-09T03:45:39.617 に答える