質問

私はLisp初心者です。監督-選手コメンmemoize、再帰関数計算の数 Collatz配列 (例題14 プロジェクトオイラー).私のコードとしては:

(defun collatz-steps (n)
  (if (= 1 n) 0
       (if (evenp n) 
           (1+ (collatz-steps (/ n 2)))
           (1+ (collatz-steps (1+ (* 3 n)))))))

(defun p14 ()
  (defvar m-collatz-steps (memoize #'collatz-steps))
  (let 
      ((maxsteps (funcall m-collatz-steps 2))
       (n 2)
       (steps))
    (loop for i from 1 to 1000000
          do 
          (setq steps (funcall m-collatz-steps i))
          (cond 
            ((> steps maxsteps) 
             (setq maxsteps steps)
             (setq n i))
            (t ())))
    n))


(defun memoize (fn)
  (let ((cache (make-hash-table :test #'equal)))
    #'(lambda (&rest args)
        (multiple-value-bind 
              (result exists)
            (gethash args cache)
          (if exists
              result
              (setf (gethash args cache)
                    (apply fn args)))))))

のmemoize機能と同様に、指定されたもの にLisp ます。

このコードはなんとして高速に比べて非memoizedバージョン。と思いますの再帰呼び出しで呼び出しのmemoized数のある種の敗戦です。その場合は、何が正しい方向でのmemoization。れる方法はありましてすべての通話の機能を呼び出memoized版自体が不要で、特m-collatz階シンボル?

編集:を修正したコードを

(defvar m-collatz-steps (memoize #'collatz-steps))

では何をしています。編集前の私は誤り:

(defvar collatz-steps (memoize #'collatz-steps))

見るとエラーにしてくれた別のフィラデルフィを使ってみましたこの最後のdefvar自体を変更する再帰呼び出しに

       (1+ (funcall collatz-steps (/ n 2)))
       (1+ (funcall collatz-steps (1+ (* 3 n))))

これはそうに行うのmemoization(高速から約60秒間15秒)が必要になりますの変更に独自の機能です。りクリーナーソリューションになる、機能しているのでしょうか。

役に立ちましたか?

解決

思いを共Lispで、別の名前空間のための変数や関数名です。するためmemoizeの機能名シンボルを変更する必要があり、その機能結合を通じて、アクセス用メソッド`fdefinition':

(setf (fdefinition 'collatz-steps) (memoize #'collatz-steps))

(defun p14 ()
  (let ((mx 0) (my 0))
    (loop for x from 1 to 1000000
          for y = (collatz-steps x)
          when (< my y) do (setf my y mx x))
    mx))

他のヒント

のようなこと:

(setf collatz-steps (memoize lambda (n)
  (if (= 1 n) 0
    (if (evenp n) 
        (1+ (collatz-steps (/ n 2)))
        (1+ (collatz-steps (1+ (* 3 n))))))))

IOW:オリジナル(非memoized)関数は匿名のみファイル名をつけたいときの結果memoizingます。

こちらはmemoize機能rebindsのシンボル機能:

(defun memoize-function (function-name)
  (setf (symbol-function function-name)
    (let ((cache (make-hash-table :test #'equal)))
         #'(lambda (&rest args)
             (multiple-value-bind 
                 (result exists)
                (gethash args cache)
               (if exists
                   result
                   (setf (gethash args cache)
                         (apply fn args)))))))

おいしいて思ったこと。

(defun collatz-steps (n)
  (if (= 1 n) 0
      (if (evenp n) 
          (1+ (collatz-steps (/ n 2)))
          (1+ (collatz-steps (1+ (* 3 n)))))))

(memoize-function 'collatz-steps)

だができるunmemoizeです。

を変更する"オリジナルの"機能が必要なので、あなたの言葉を借りれはありませんの再帰呼出し(s)が更新されるmemoizedバージョン。

幸いなことに、lispの作品ではの機能 名前 各時間が必要で呼び出されます。これで十分に置き換え機能との結合にmemoized版の機能、その再帰呼び出しまで自動的に検索および再突入のmemoization.

huaiyuanのコードをキーステップ:

(setf (fdefinition 'collatz-steps) (memoize #'collatz-steps))

このトリックもPerlです。言語のようにし、memoizedバージョンの機能コードす。

一部のlispの実装を提供するシステム"の助言を提供する、標準化された構造のための交換機能を強化したバージョンです。のほか、機能アップのようなmemoization、このに役立つ高性能なデバッグを挿入しデバッグ版画(または完全に止まるとcontinuable迅速な変更は元のコードです。

ご注意いくつかの:

(defun foo (bar)
   ... (foo 3) ...)

である、上記の機能を呼び出します。

共通のLispファイルをコンパイラではFOOは変わりません。いませ------------更新したFOOます。変更した場合の機能結合FOO、その通話の機能ますが、古い機能です。

でmemoizing自己再帰の機能は使用できませんの。特にないご利用の場合良いコンパイラです。

きであり、常に行くのシンボルの例:(funcall'foo3)

(DEFVAR...)をトップレベル。で使用しない内で機能する。の場合を宣言した変数で設定SETQはSETFます。

お問いうハッシュテーブルの中間ます。

この機能は同一ピーター Norvigを事例として機能するように思えるので良い候補者memoizationができます。

図3(機能を'Hailstone')を独自に論文memoization("自動Memoizationとしてのソフトウェアエンジニアリングツールの実世界のAIシステム").

さんの顔をもに取得する場合の力学memoization、なん化とスピードアップを図っている。

前に書いた少しmemoizationルーチンのスキームを用いた連鎖の閉鎖のmemoized状態:

(define (memoize op)
  (letrec ((get (lambda (key) (list #f)))
           (set (lambda (key item)
                  (let ((old-get get))
                    (set! get (lambda (new-key)
                                (if (equal? key new-key) (cons #t item)
                                    (old-get new-key))))))))
    (lambda args
      (let ((ans (get args)))
        (if (car ans) (cdr ans)
            (let ((new-ans (apply op args)))
              (set args new-ans)
              new-ans))))))

このニーズを使用するように:

(define fib (memoize (lambda (x)
                       (if (< x 2) x
                           (+ (fib (- x 1)) (fib (- x 2)))))))

っていると確信していき移植にお好きな語彙的に小scoped Lisp風味。

思うように:

(let ((memo (make-hash-table :test #'equal)))
  (defun collatz-steps (n)
    (or (gethash n memo)
    (setf (gethash n memo)
          (cond ((= n 1) 0)
            ((oddp n) (1+ (collatz-steps (+ 1 n n n))))
            (t (1+ (collatz-steps (/ n 2)))))))))

でも機能的なものではないものを手でいます。レストランも得られないときには、いくつかのハンディunmemoizedのバージョンを試験および清算キャッシュが隣接する"非常に難しい".

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top