【问题标题】:Convert integers to roman numerals using a syntax-directed translation scheme?使用语法导向的翻译方案将整数转换为罗马数字?
【发布时间】:2010-09-21 00:11:38
【问题描述】:

Dragon Book 包含一个使用语法指导的翻译方案将整数转换为罗马数字的练习。

如何完成?

【问题讨论】:

  • 看起来像作业题,闻起来像作业题... ;-)
  • 是的,我知道...我希望我能证明我没有作弊。对于 CS 学生来说,这实际上是一个家庭作业问题……只是,不适合我,我只是自己看书,没有老师(或知识渊博的朋友)可以问。

标签: compiler-construction roman-numerals translation-scheme


【解决方案1】:

接下来是表示从 1xxx 格式的数字到罗马数字的语法定向翻译的语法。

数字 = 千位 3 位 2 位 1 | nzdigit3 digit2 digit1 | nzdigit2 digit1 | nzdigit1

一千 -> 1 {print('M')}

digit3 -> 0 digit3 -> nzdigit3

nzdigit3 -> 1 打印('C') nzdigit3 -> 2 打印('CC') nzdigit3 -> 3 打印('CCC') nzdigit3 -> 4 打印('CCCC') nzdigit3 -> 5 打印('D') nzdigit3 -> 6 打印('DC') nzdigit3 -> 7 打印('DCC') nzdigit3 -> 8 print('DCCC') nzdigit3 -> 9 print('DCCCc')

以类似的方式为 2 和 1 位置的数字编写定义,您将需要翻译。

【讨论】:

    【解决方案2】:

    另一种方法是将1、5、10、50、100、500、1000等罗马数字存储在二维数组中。示例(在 PHP 数组中):

    $roman = array(
      [0] = array( 1=>"I", 5=>"V", 10=>"X" ),
      [1] = array( 1=>"X", 5=>"L", 10=>"C" ),
      [2] = array( 1=>"C", 5=>"D", 10=>"M" ),
      [3] = array( 1=>"M", 5=>"^V", 10=>"^X" ),
    );
    

    然后从右到左取每个数字并应用以下翻译。设置一个变量 $level = 0 并在处理完每个数字后将其值增加 1:

    1 => $roman[$level][1]
    2 => $roman[$level][1].$roman[$level][1]
    3 => $roman[$level][1].$roman[$level][1].$roman[$level][1]
    4 => $roman[$level][1].$roman[$level][5]
    5 => $roman[$level][5]
    6 => $roman[$level][5].$roman[$level][1]
    7 => $roman[$level][5].$roman[$level][1].$roman[$level][1]
    8 => $roman[$level][5].$roman[$level][1].$roman[$level][1].$roman[$level][1]
    9 => $roman[$level][1].$roman[$level][10]
    

    (在 PHP 中一个 '.' 连接两个字符串)

    例如:1945 年

    5 => $roman[0][5] = "V"
    4 => $roman[1][1].$roman[1][5] = "XL"
    9 => $roman[2][1].$roman[2][10] = "CM"
    1 => $roman[3][1] = "M"
    

    所以翻译后的数字是“MCMXLV”

    抱歉,这可能无法完全回答您的问题,但我希望它对您有所帮助..

    【讨论】:

      【解决方案3】:

      我会考虑从右到左解析。

      首先,我将映射单位列:

      0 -> ''
      1 -> 'I'
      2 -> 'II'
      3 -> 'III'
      4 -> 'IV'
      ...
      9 -> 'IX'
      

      然后,如果有第二列(例如,右数第二列 = 十列),我会用它来映射到

      0 -> ''
      1 -> 'X'
      2 -> 'XX'
      ...
      9 -> 'XC'
      

      这需要预先添加到初始输出中。

      重复下一列(数百、数千),直到用完字母。

      仔细检查数字不是“0”或负数。

      【讨论】:

      • 这意味着制作一个上下文无关的语法,然后允许我使用 sytanx 导向的翻译方案进行转换,我需要为每个“列”创建 10 条规则。 (所以,大约 34 条规则可以达到 3999)我正确吗?
      • 我其实想过这样的事情,我有点期待有一个更优雅的方法......有吗?
      • 是的,这意味着每列 10 条规则。我想您可以编写一个适用于每一列的函数,并将字母作为参数...因此,对于 219,您将输出 f(2,'C', 'D', 'M') + f(1. 'X', 'L', 'C') + f(9, 'I', 'V', 'X') 不过“感觉”不是上下文无关的。
      • 这是错误的答案,因为这里没有语法。根本没有任何功能必须存在。翻译必须在树遍历期间给出结果,它不可能确定你在树中的深度。
      猜你喜欢
      • 2019-01-09
      • 2011-10-25
      • 2012-10-09
      • 1970-01-01
      • 2020-05-11
      • 2021-12-15
      • 2014-10-19
      相关资源
      最近更新 更多