4

数字のリストをスキャンし、リストが有効なローマ数字であるかどうかと数字の10進数値を返す必要があるの割り当てに取り組んでいます。元)

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

2 ?- 

動作するはずのプログラムを実行すると、10 進数の値は常に正しいので、合成された属性の部分は正しいと思いますが、true を返すはずの数値リストに対しては常に false を返します。また、3 つ以上の Is、X、または C が存在する場合は、中止するはずであるということも付け加えたいと思います。

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

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

N を取り出して a を投げると、{write('N = '), write(N)}正常に動作して が返されますtrue

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

削除する{N is ValH + ValT + ValU}と が返さtrueれますが、10 進数値は表示されなくなります。これが私のコードの一番上の行です (これは現在の割り当てであるため、回答を得るために必要なだけ表示することをお勧めします)。

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

これが N では false を返すのに、N なしでは true を返すのはなぜですか?どうすれば修正できますか?

割り当て: 次の 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

この文法の属性を定義して、次の 2 つのタスクを実行します。

a) の X の数<low tens>、 の I の数<low units>、および C の<low hundreds>数を 3 つ以下に制限します。

b)<roman>定義されているローマ数字の 10 進値を与える属性を提供します。

これらのタスクに必要なその他の属性を定義しますが、BNF 文法は変更しないでください。

4

1 に答える 1

2

文法は、同じパターン (group//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 .
于 2013-02-15T23:23:35.730 に答える