2016-12-07 200 views
0

我正在創建一個啓發式函數,它返回它應該是的,但也有堆棧溢出問題,我無法理解問題出在哪裏。下面是我創建的功能代碼:Lisp堆棧溢出遞歸函數

(defun nextPositions (position) 
    (let*((listaPosAdjacentes) 
     (positionFinal position) 
     (listaFinal NIL)) 
    (setf listaPosAdjacentes (possible-actions2)) 
    (dolist (posAdjacente listaPosAdjacentes) 
     (setf positionFinal position) 
     (setf positionFinal (list (+ (nth 0 positionFinal) (nth 0 posAdjacente)) 
           (+ (nth 1 positionFinal) (nth 1 posAdjacente)))) 
     (push positionFinal listaFinal)) 
    listaFinal)) 

(defun push-unique (element lista) 
    (let ((auxlist lista)) 
    (dolist (i lista) 
     (if (and (equal (nth 0 i) (nth 0 element)) (equal (nth 1 i) (nth 1 element))) 
      (return-from push-unique auxlist))) 

    (push element auxlist) 
    auxlist)) 

(defun recursive (track1 positionslist distance track) 
    (let ((NextValidPositions NIL)) 
    (dolist (position positionslist) 
     (if (equal (track-startpos track) position) 
      (return-from recursive track1) 
     (progn (dolist (i (nextPositions position)) 
       (if (equal (nth (nth 1 i) (nth (nth 0 i) track1)) T) 
        (progn 
         (setf NextValidPositions (push-unique i NextValidPositions)) 
         (setf (nth (nth 1 i) (nth (nth 0 i) track1)) (+ 1 distance)))))))) 
    (recursive track1 NextValidPositions (+ 1 distance) track))) 

(defun compute-heuristic(st) 
    (let* ((track (state-track st)) 
     (distance 0) 
     (track1Final nil) 
     (track1heuristica (track-env track))) 
    (dolist (position (track-endpositions track)) 
     (setf (nth (nth 1 position) (nth (nth 0 position) track1heuristica)) distance)) 
    (setf track1Final (recursive track1heuristica (track-endpositions track) distance track)) 
    (print track1Final) 
    (return-from compute-heuristic track1Final))) 

結果如下: result

返回列表是什麼是應該返回,但我不明白的堆棧溢出問題。

的代碼被稱爲是這樣的:

(format t "~&Exercise 3.1 - Heuristic~&") 
    (with-open-file (str "out3.1.txt" 
    :direction :input) 
    (format t "~% Solution is correct? ~a~&" (equal (list (compute-heuristic (initial-state *t1*)) (compute-heuristic (make-state :pos '(1 6) :track track)) (compute-heuristic (make-state :pos '(2 8) :track track))) (read str)))) 

這是一個本地測試和驗證碼是由我們的教授提供測試我們的代碼,這就是爲什麼我認爲這個問題是不存在的。

任何想法可能是什麼問題? 謝謝。

+0

在深入研究之前,您能告訴我們您是如何調用代碼的嗎?另外,一般調試提示:(跟蹤)遞歸中涉及的所有或部分功能。 –

+0

僅供參考,有一個內置宏「PUSHNEW」,就像你的「PUSH-UNIQUE」一樣。 – Barmar

+0

我不認爲問題出現在您發佈的代碼中。由於'(print track1Final)'正在成功執行,*之後問題就會發生*,所以它必須位於調用'compute-heuristic'的代碼中。 – Barmar

回答

0

關於風格

一般來說,代碼寫得不好,因爲它使用了實際上並不需要太多的控制結構和變量。

實施例:

(defun push-unique (element lista) 
    (let ((auxlist lista)) 
    (dolist (i lista) 
     (if (and (equal (nth 0 i) 
         (nth 0 element)) 
       (equal (nth 1 i) 
         (nth 1 element))) 
      (return-from push-unique auxlist))) 
    (push element auxlist) 
    auxlist)) 
  • 不必要可變auxlist
  • 沒有dolist需要,可使用member
  • 沒有return-from需要,只返回值。在很多情況下使用return-from代碼異味,表示代碼太複雜。
  • 沒有push需要的,只是返回的cons

更好的結果:

(defun push-unique (element list) 
    (if (member element list 
       :test (lambda (a b) 
         (and (equal (first a) (first b)) 
          (equal (second a) (second b))))) 
     list 
     (cons element list))) 

的功能存在已經

功能push-unique標準Common Lisp中已經存在。這就是所謂的adjoin

CL-USER 34 > (adjoin 1 '(2 3 4 1 3)) 
(2 3 4 1 3) 

CL-USER 35 > (adjoin 1 '(2 3 4 3)) 
(1 2 3 4 3) 

只是通過正確的測試功能,爲您的目的...

(defun push-unique (element list) 
    (adjoin element list 
      :test (lambda (a b) 
        (and (equal (first a) (first b)) 
         (equal (second a) (second b)))))) 

評論&文檔

也許這也是寫評論一個好主意,文檔。否則,人們不得不猜測/推斷這些功能的目的是什麼。