2015-05-25 62 views
1

我在prolog中的代碼出現在相反的預期順序。下面是代碼:爲什麼我的Prolog代碼反向打印?

room(homermargeroom, donuts). 
room(homermargeroom, tv). 
room(ensuite, nothing). 
room(lisaroom, beer). 
room(bartroom, donuts). 
room(hallway, nothing). 
room(bathroom, nothing). 
room(maggieroom, nothing). 


/* These are the locations where Bart, Lisa and Maggie are hiding */ 
hiding(bart, cupboard). 
hiding(lisa, ensuite). 
hiding(maggie, bathroom). 

canHomerGet(Start, End, Item) :- 
    homermove(Start, End), 
    canTravelThrough(Start, Item), 
    canTravelThrough(End, Item), 
    write('Homer moves from '), write(Start), write(' to '), write(End), nl. 

canHomerGet(Start, End, Item) :- 
    homermove(Start, Somewhere), 
    canTravelThrough(Somewhere, Item), 
    canHomerGet(Somewhere, End, Item), 
    write('Homer moves from '), write(Start), write(' to '), write(Somewhere), nl. 


canTravelThrough(Somewhere, _Item) :- 
    room(Somewhere, nothing). 

canTravelThrough(Somewhere, Item) :- 
    room(Somewhere, tv), 
    Item == portableTV. 

canTravelThrough(Somewhere, Item) :- 
    room(Somewhere, donuts), 
    Item == nachos. 

canTravelThrough(Somewhere, Item) :- 
    room(Somewhere, sistersinlaw), 
    Item == blindfold. 

canTravelThrough(Somewhere, Item) :- 
    room(Somewhere, beer), 
    Item == margarita. 


canHomerFind(Child, Item) :- 
    hiding(Child, Destination), 
    canHomerGet(garage, Destination, Item). 

這裏是輸出:從門廳

荷馬移動到櫥櫃
荷馬從餐室移動到門廳
荷馬從廚房移動到餐室
荷馬從移動sidehall到廚房
荷馬從車庫移到側廳

我寫這個的方式,我希望能打印出'Homer從車庫移動到sidehall'的拳頭,然後按照與它相反的順序打印該列表。對於如何解決這個問題,有任何的建議嗎?

+1

你確定你提供了所有的源代碼嗎?這個輸出是由哪個查詢產生的? –

回答

2

您對謂詞canHomerGet/3的定義只在末尾寫入移動輸出。在第二個條款中,遞歸調用的優先級爲。這使得這個謂詞非尾遞歸。即這些動作的寫入將保存在隱式遞歸堆棧上,然後在對謂詞的調用成功時從堆棧中彈出。因此,打印的第一個動作是最後一個,最後一個打印的動作是第一個。

你可能會傾向於第二條修改來解決這個問題:

canHomerGet(Start, End, Item) :- 
    homermove(Start, Somewhere), 
    canTravelThrough(Somewhere, Item), 
    write('Homer moves from '), write(Start), write(' to '), write(Somewhere), nl, 
    canHomerGet(Somewhere, End, Item). 

這將使謂語尾遞歸,從而在不斷的堆棧空間運行,但上升一個新的問題:運動引起任何地方也不會打印回溯,以找到成功的路線不會撤消運動的打印。通常的解決方案是構建一個步驟列表(使用額外的參數),然後在最後打印列表(反轉後)。我將把這些留給你作爲練習。

+0

感謝您的幫助!你能否更多地瞭解「額外論點」?我不確定你在暗示我應該做什麼。 – user3414510

+1

搜索SO for「prolog path」。 SO中已經存在很多類似的問題。 –