Convert integers to roman numerals using a syntax-directed translation scheme?
Asked Answered
E

3

9

The Dragon Book includes an exercise on converting integers to roman numerals using a syntax-directed translation scheme.

How can this be completed?

Enlargement answered 6/11, 2008 at 1:3 Comment(2)
looks like a homework question, smells like a homework question... ;-)Honeywell
Yep, I know... I wish I could prove I'm not cheating. It IS actually a homework question, for CS students... Just, not for me, I'm just reading the book on my own, and have no teacher (or knowledgeable enough friend) to go ask.Enlargement
I
2

I would consider parsing from right-to-left.

First, I would map the units column:

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

Then, if there was a second column (e.g. second from the right = tens column), I would use that to map to

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

That would need to be prepended to the initial output.

Repeat for next columns (hundreds, thousands) until you run out of letters.

Double-check the number isn't '0' or negative.

Immersed answered 6/11, 2008 at 3:49 Comment(4)
This means that making a context-free grammar that would then allow me to convert using a sytanx-directed translation scheme, I need to create 10 rules for each "column". (so, about 34 rules to be able to get to 3999) Am I correct?Enlargement
I actually thought about something like this, I was kind of expecting there to be a more elegant method... Is there?Enlargement
Yes, that means 10 rules per column. I guess you could write a single function that works for each of the columns, and takes the letters as parameters... So, for 219, you would output f(2,'C', 'D', 'M') + f(1. 'X', 'L', 'C') + f(9, 'I', 'V', 'X') Doesn't 'feel' context-free though.Immersed
This is wrong answer, because no grammar here. No function at all must be present. Translation must give the result during tree traversal and its not possible do determine how deep in the tree you are.Marutani
M
4

Next is grammar to represent syntax directed translation from number in format 1xxx into roman numerals.

number = OneThousand digit3 digit2 digit1 | nzdigit3 digit2 digit1 | nzdigit2 digit1 | nzdigit1

OneThousand -> 1 {print('M')}

digit3 -> 0 digit3 -> nzdigit3

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

In similar manner write definition for digits in 2 and 1 position and you will have needed translation.

Marutani answered 22/10, 2011 at 15:48 Comment(0)
B
3

Another way is to store in two-dimensional array the roman numerals for 1, 5, 10, 50, 100, 500, 1000 and so on. Example (in PHP array):

$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" ),
);

Then take each digit from right-to-left and apply the following translation. Set a variable $level = 0 and increase its value by 1 after every digit processed:

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]

(in PHP a '.' concats two strings)

Example: 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"

So the translated number is "MCMXLV"

Sorry this might not fully answer your question but I hope it helps in any way ..

Baku answered 9/11, 2008 at 7:10 Comment(0)
I
2

I would consider parsing from right-to-left.

First, I would map the units column:

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

Then, if there was a second column (e.g. second from the right = tens column), I would use that to map to

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

That would need to be prepended to the initial output.

Repeat for next columns (hundreds, thousands) until you run out of letters.

Double-check the number isn't '0' or negative.

Immersed answered 6/11, 2008 at 3:49 Comment(4)
This means that making a context-free grammar that would then allow me to convert using a sytanx-directed translation scheme, I need to create 10 rules for each "column". (so, about 34 rules to be able to get to 3999) Am I correct?Enlargement
I actually thought about something like this, I was kind of expecting there to be a more elegant method... Is there?Enlargement
Yes, that means 10 rules per column. I guess you could write a single function that works for each of the columns, and takes the letters as parameters... So, for 219, you would output f(2,'C', 'D', 'M') + f(1. 'X', 'L', 'C') + f(9, 'I', 'V', 'X') Doesn't 'feel' context-free though.Immersed
This is wrong answer, because no grammar here. No function at all must be present. Translation must give the result during tree traversal and its not possible do determine how deep in the tree you are.Marutani

© 2022 - 2024 — McMap. All rights reserved.