Prolog罗马数字(属性语法) [英] Prolog Roman Numerals (Attribute Grammars)

查看:105
本文介绍了Prolog罗马数字(属性语法)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理会扫描数字列表,并应返回该列表是否为有效的罗马数字和数字的十进制值.例)

I am working on an assignment in prolog that scans a list of numerals and should return whether the list is a valid roman numeral and the decimal value of the numerals. Ex)

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

2 ?- 

当我运行应该可以运行的程序时,十进制值总是正确的,因此我猜想合成属性部分正确,但是对于应该返回true的数字列表,它始终返回false.我还想补充一点,当应该存在3个以上的Is,X或C时,它将中止.

When I run the program that I feel should work, the decimal value is always right, so I'm guessing I got the synthesized attributes part right, but it always returns false for numeral lists that should return true. I'd also like to add that it aborts when it is supposed to if more than 3 Is, Xs, or Cs are present.

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.

When I take out the N and throw in a {write('N = '), write(N)}, it works fine and returns true.

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

当我删除{N is ValH + ValT + ValU}时,它返回true,但是,它不再显示十进制值.这是我的代码的第一行(因为这是当前的作业,所以我希望尽可能少地显示以获得答案):

When I remove {N is ValH + ValT + ValU} it returns true, however, it no longer displays the decimal value. Here is the top line of my code (because this is a current assignment, I would prefer to show as little as is necessary to get an answer):

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

为什么返回N时返回false,而没有N时返回true,我该如何解决呢?

Why is this returning false with N, but true without, and how do I fix it?

任务: 以下BNF规范定义了罗马数字的语言 少于1000:

Assignment: The following BNF specification defines the language of Roman numerals less than 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

为此语法定义属性以执行两项任务:

a)限制<low tens>中X的数量,<low units>中I的数量,以及 <low hundreds>中的C不超过三个.

a) Restrict the number of X’s in <low tens>, the I’s in <low units>, and the C’s in <low hundreds> to no more than three.

b)为<roman>提供一个属性,该属性给出了 定义了罗马数字.

b) Provide an attribute for <roman> that gives the decimal value of the Roman numeral being defined.

定义这些任务所需的任何其他属性,但不要更改 BNF语法.

Define any other attributes needed for these tasks, but do not change the BNF grammar.

推荐答案

您是否注意到语法是由重复3次的相同模式(group//5)形成的,只是符号不同?我喜欢紧凑...

Did you noticed the grammar is formed of the same pattern (group//5) repeated 3 times, just with different symbols ? I like the compactness...

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的工作状态...

Just a curiousity, showing DCG at work...

edit ...

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

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

这篇关于Prolog罗马数字(属性语法)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆