2017-02-13 71 views
1

我從掌握Prolog的書中獲得了以下Prolog,並且我試圖學習一些簡單的遞歸。瞭解序言中的簡單遞歸

mins_to_hours(In, H, M):- 
    In<60, 
    H = 0, 
    M is In. 
mins_to_hours(In, H, M):- 
    In>=60, 
    In1 is In-60, 
    H1 is H+1, 
    mins_to_hours(In1, H1, M). 

我不完全確定它爲什麼不起作用,我已經擺弄了好幾個小時。任何幫助,甚至指向正確的方向我非常感謝。提前致謝。

+0

忘了提及它應該做什麼...它應該將分鐘轉換爲小時和分鐘,例如,如果給了它140它應該返回H = 2 M = 20 – jdoggg

+0

您可以編輯您的問題進行更新。你應該把你的評論中的信息放入問題中。 –

回答

2

在這個例子中你面臨的一個主要困難是所謂的模式的低級算術謂詞。例如,讓我們嘗試最一般的查詢與您發佈的代碼:

 
?- mins_to_hours(In, H, M). 
ERROR: Arguments are not sufficiently instantiated 

爲了擺脫這個缺點,我第一次更換CLP低級謂詞(FD)約束,這在所有主要的Prolog系統中都可用,並簡化了代碼的推理。

對於這一點,我只需更換(<)/2通過(#<)/2(is)/2(#=)/2等(根據您的Prolog的系統上,你也可能仍然必須導入此庫):

 
mins_to_hours(In, H, M):- 
    In #< 60, 
    H = 0, 
    M #= In. 
mins_to_hours(In, H, M):- 
    In #>= 60, 
    In1 #= In-60, 
    H1 #= H+1, 
    mins_to_hours(In1, H1, M). 

現在,讓我們再次嘗試最一般的查詢,所有的參數都是新鮮的變量

 
?- mins_to_hours(In, H, M). 
In = M, 
H = 0, 
M in inf..59 ; 
H = -1, 
In in 60..119, 
M+60#=In, 
M in 0..59 ; 
H = -2, 
In in 120..179, 
_5238+60#=In, 
_5238 in 60..119, 
M+60#=_5238, 
M in 0..59 . 

這裏,似乎很奇怪,H可以假設爲負值的值!

讓我們嘗試一些具體箱子:

 
?- mins_to_hours(30, H, M). 
H = 0, 
M = 30 ; 
false. 

這似乎仍然相當OK!

 
?- mins_to_hours(60, H, M). 
H = -1, 
M = 0 ; 
false. 

這似乎已經很多 OK!

通過一些練習,很容易看出原因:在第二個條款中,您無意中混淆了HH1的角色!假設我們寫的第二句話是這樣的:

 
mins_to_hours(In, H, M):- 
    In #>= 60, 
    In1 #= In-60, 
    H #= H1+1, 
    mins_to_hours(In1, H1, M). 

然後我們得到:

 
?- mins_to_hours(60, H, M). 
H = 1, 
M = 0 ; 
false. 

而對於兩個情況:

 
?- mins_to_hours(500, H, M). 
H = 8, 
M = 20 ; 
false. 

?- mins_to_hours(1000, H, M). 
H = 16, 
M = 40 ; 
false. 

似乎相當不錯!

請注意,如果你堅持低級別的運算,可以沒有,很容易糾正錯誤:使用謂詞像(<)/2(is)/2需要你還要考慮到實際執行順序的Prolog的,這是太幾乎所有初學者都很難。我強烈建議您使用CLP(FD)約束,因爲它們讓您輕鬆嘗試不同目標訂單的效果,同時保持關係正確並且一般