2014-02-10 37 views
0

我是Prolog的新手。我正在努力學習這一點。我正在構建一個後綴到前綴轉換謂詞。我搜索了很多谷歌和github等prolog遞歸語法是非常混亂。通過搜索很多,我只是found this one link on stackoverflow。我正在處理同樣的問題,但指定的解決方案非常混亂。追加/ 2功能的實現不在我腦海裏,那麼非法經營者又如何呢?現在我已經有3天多的時間了,我一直在解決這個問題,並且被吸引了。任何人都可以幫助我實現這個邏輯或任何書籍參考或鏈接,以便更好地理解同一個問題。由於Postfix在prolog前綴轉換中使用一元運算符sin cos tan等

我想解決這個問題這樣

post2pre([A,B,C|Rem],Pre) :- Pre=[C,A,B], isop(C). 

但問題是如何處理雷姆怎麼辦?如果我有什麼列表中的一個或兩個項目 我認爲要解決像這樣

post2pre([A|[]],Pre) :- Pre=[A]. 
    post2pre([A,B|[]) :- Pre=[A,B]. 

和ISOP()我將它們定義爲

isop(+). isop(-). isop(*). isop(/). isop(sin). isop(cos). isop(exp). 

,但我不知道是什麼與非正式經營者有關?

+0

我已經運行鏈接I post中指定的代碼。但問題是我的思想仍然無法用思路的方式思考。 –

回答

2

那麼,正如我在答案中所建議的那樣,pos2pre/2只是一個草圖,由學生完成。但這也是一個棘手的解決方案,而不是聲明式的。因此,它很容易擴展到處理一元運算符(我將重新命名ISOP/1 is_binary_op/1,清理的代碼):

pos2pre(Pos, Pre) :- 
    append([A, B, [O]], Pos), is_binary_op(O), A \= [], B \= [], 
    pos2pre(A, APre), 
    pos2pre(B, BPre), 
    !, append([[O], APre, BPre], Pre). 
pos2pre(Pos, Pre) :- 
    append([A, [O]], Pos), is_unary_op(O), A \= [], 
    pos2pre(A, APre), 
    !, append([[O], APre], Pre). 
pos2pre([P], [P]). 

is_binary_op(O) :- memberchk(O,[+,*]). 
is_unary_op(O) :- memberchk(O,[sin,tan]). 

測試

?- pos2pre([1,2,3,+,*,sin],Pre) . 
Pre = [sin, *, 1, +, 2, 3]. 

另一種方式,我會嘗試遵循將使用完全不同的方案,建立一個中文表達式解析器(一個DCG),然後讓後綴/前綴訪問的樹在格式之間進行轉換。

編輯這裏是附加/ 2謂詞從SWI-Prolog的庫被盜(列表):

append(ListOfLists, List) :- 
    must_be(list, ListOfLists), 
    append_(ListOfLists, List). 

append_([], []). 
append_([L|Ls], As) :- 
    append(L, Ws, As), 
    append_(Ls, Ws). 

的!符號被命名爲cut,它不是一個運算符,而是一個系統謂詞(更準確地說,是一個控制謂詞)。它總是成功,修剪替代品,可能在執行點處於待決狀態,從而承諾到目前爲止做出的選擇。您應該閱讀一些關於此主題的在線documentation ...

+0

gnu編譯器不支持追加/ 2功能,我認爲。並通過互聯網我尋找Append函數他們這樣做與append/3如何實現這兩個函數是不同的?你能告訴一下!運營商在這裏用? –

+1

@AbdulRehman,SWI Prolog有'append/2'和'append/3'。 'append/3'也在GNU prolog中。如果您在SWI Prolog網站上查找這些謂詞的描述,您將看到不同之處。簡單的答案是'append/2'假設第一個參數是一個「列表列表」,它附加到單個列表中(第二個參數)。 'append/3'在單個列表級別運行,第三個參數代表第二個參數附加到第一個參數的末尾。請注意,對於這些謂詞中的每一個,都可以給它任何參數,併爲其餘部分生成解決方案。 – lurker

0

這裏是一個替代版本。這一個構建從後綴列表第一爲2-或3-元素列表嵌套列表結構(每個一元或二元運算)前綴結構,然後只在平坦化結束時的嵌套列表:

post2pre(Post, Pre) :- 
    post2pre(Post, [], Pre). 

post2pre([E|T], PreNest, Pre) :- 
    ( unary_op(E) 
    -> PreNest = [Term|PNT], 
     post2pre(T, [[E,Term]|PNT], Pre) 
    ; binary_op(E) 
    -> PreNest = [Term2,Term1|PNT], 
     post2pre(T, [[E,Term1,Term2]|AP], Pre) 
    ; post2pre(T, [E|PreNest], Pre) 
    ). 
post2pre([], PreNest, Pre) :- 
    flatten(PreNest, Pre). 

unary_op(X) :- 
    memberchk(X, [sin, cos, tan]). 

binary_op(X) :- 
    memberchk(X, [+, -, /, *]). 

在上面的代碼,「原子項」隱含地定義爲不是運算符的任何東西。

每爲例:

| ?- post2pre([1,2,3,+,*,sin],Pre). 

Pre = [sin,*,1,+,2,3] 

yes 

在這種情況下,「中間」嵌套形式,發生flatten之前,將是:

[sin, [*, 1, [+, 2, 3]]] 

的非如果 - 則 - 否則版本上面的代碼可以寫成如下。我選擇了上面的if-then-else構造,因爲它避免了冗餘地檢查運算符:

post2pre(Post, Pre) :- 
    post2pre(Post, [], Pre). 

post2pre([E|T], PreNest, Pre) :- 
    atomic_term(E), 
    post2pre(T, [E|PreNest], Pre). 
post2pre([E|T], [Term|PNT], Pre) :- 
    unary_op(E) 
    post2pre(T, [[E,Term]|PNT], Pre). 
post2pre([E|T], [Term2,Term1|PNT], Pre) :- 
    binary_op(E) 
    post2pre(T, [[E,Term1,Term2]|AP], Pre). 
post2pre([], PreNest, Pre) :- 
    flatten(PreNest, Pre). 

atomic_term(X) :- % This defines a term explicitly as anything but an operator 
    \+ unary_op(X), 
    \+ binary_op(X). 

unary_op(X) :- 
    memberchk(X, [sin, cos, tan]). 

binary_op(X) :- 
    memberchk(X, [+, -, /, *]).