2013-02-15 29 views
4

我正在處理中的作業,該作業掃描數字列表,並應返回列表是否爲有效的羅馬數字和數字的十進制值。例)Prolog羅馬數字(屬性文法)

1 ?- roman(N, ['I'], []). 
N = 1 
true. 

2 ?- 

當我跑,我覺得應該工作程序,十進制值永遠是對的,所以我猜我得到的合成屬性部分的權利,但它總是返回數字列表FALSE的時候返回true。我還想補充說,如果存在超過3個Is,Xs或Cs時,它會中止。

1 ?- roman(N, ['I'], []). 
N = 1 ; 
false. 

2 ?- roman(N, ['I','I','I','I'], []). 
Error: too many I's 
% Execution Aborted 
3 ?- 

當我拿出N和在{write('N = '), write(N)}扔,它工作正常,並返回true

1 ?- roman(['I'], []). 
N = 1 
true. 

當我刪除{N is ValH + ValT + ValU}返回true,但是,它不再顯示十進制值。這裏是我的代碼的頂線(因爲這是當前的任務,我更願意表現出儘可能少的要得到答案):

roman(N) --> hundreds(ValH), tens(ValT), units(ValU), {N is ValH + ValT + ValU}. 

爲什麼這回用N假的,但真沒有,我該如何解決?

分配: 以下BNF規範定義羅馬數字 小於1000的語言:

<roman> ::= <hundreds> <tens> <units> 
<hundreds> ::= <low hundreds> | CD | D <low hundreds> | CM 
<low hundreds> ::= e | <low hundreds> C 
<tens> ::= <low tens> | XL | L <low tens> | XC 
<low tens> ::= e | <low tens> X 
<units> ::= <low units> | IV | V <low units> | IX 
<low units> ::= e | <low units> I 

此語法定義的屬性來進行兩個任務:

一個)限制<low tens>中的X的個數,I的<low units>和 中的C的<low hundreds>不超過三個。

b)爲<roman>提供一個屬性,該屬性給出定義的 羅馬數字的十進制值。

定義這些任務所需的任何其他屬性,但不會更改BNF語法的 。

+1

使用短語/ 2'呼叫'DCG文法 – CapelliC 2013-02-15 15:36:18

+0

我認爲你必須支付嚴格關注細節。看[這個答案](http:// stackoverflow。com/a/13269846/874024)爲一個很好的替代方案。 – CapelliC 2013-02-15 15:53:21

+0

我必須嚴格遵守BNF。如果你喜歡,我可以發佈。 – 2013-02-15 16:04:59

回答

2

您是否注意到語法是由相同的模式(組// 5)重複3次形成的,只是使用不同的符號?我喜歡緊湊...

roman(N) --> 
    group('C','D','M',100, H), 
    group('X','L','C',10, T), 
    group('I','V','X',1, U), 
    {N is H+T+U}. 
group(A,B,C, Scale, Value) --> 
    ( g3(A, T) 
    ; [A, B], {T = 4} 
    % thanks to Daniel and Will for catching bugs 
    ; [B], g3(A, F), {T is 5+F} 
    ; [B], {T is 5} 
    ; [A, C], {T = 9} 
    ; {T = 0} 
    ), {Value is Scale * T}. 


g3(C, 1) --> [C]. 
g3(C, 2) --> [C,C]. 
g3(C, 3) --> [C,C,C]. 

一些測試

?- atom_chars('CMXXX',L), phrase(roman(N),L). 
L = ['C', 'M', 'X', 'X', 'X'], 
N = 930 ; 
false. 

?- atom_chars('CMXLVIII',L), phrase(roman(N),L). 
L = ['C', 'M', 'X', 'L', 'V', 'I', 'I', 'I'], 
N = 943 ; 
false. 

只是好奇,顯示出在工作DCG ...

編輯之後丹尼爾,並會評論...

?- atom_chars('VIII',L), phrase(roman(N),L). 
L = ['V', 'I', 'I', 'I'], 
N = 8 . 

?- phrase(roman(X), ['L','I','X']). 
X = 59 . 
+1

不應該是#2是948嗎? CM = 900,XL = 40,VIII = 8? – 2013-02-23 15:44:36

+0

謝謝丹尼爾,我糾正了這個錯誤... – CapelliC 2013-02-23 16:47:24

+0

你也改變了BNF語法。 – 2013-04-22 14:09:26