This is a problem where the only data structures you need,
other than the integer you are encoding and the string you
are building, is a small number of array literals.

Here is pseudo-code.
If self is negative, emit a negative sign.
If self is zero, emit N and finish.
Let n be the absolute value of self.
Emit M (n//1000) times -- use #next:put:
Encode n // 100 \\ 10 using M D C.
Encode n // 10 \\ 10 using C L X.
Encode n \\10 using X V I
To encode a digit using x v i,
write the characters of
 #('' 'i' 'ii' 'iii' 'iv' 'v' 'vi' 'vii' 'viii' 'ix' 'x')
 at the digit + 1 (use #nextPutAll:).

I have checked this pseudocode by writing
#asRomanPrintString (2 lines including header) calling
#asRomanPrintOn: (9 lines including header)
and verified that each number from -4000 to +4000
gets the same result from #printStringRoman and
#asRomanPrintString (except 0, which Pharo gets wrong).

Now we *could* do the "encode a digit" using smaller
or no tables, but it would take more code.  In this
case we can check that the right output for a digit
is produced just by LOOKING at the table, rather than
by checking complicated code.



On Sat, 19 Sep 2020 at 02:13, Pablo Navarro <pablo...@gmail.com> wrote:

> Hi! Maybe you can use this algorithm:
>
> Define a dictionary with these elements:
>
> 1000:'M',
> 900:'CM',
> 500: 'D',
> 400: 'CD',
> 100:"C",
> 90:'XC',
> 50:'L',
> 40:'XL',
> 10:'X',
> 9:'IX',
> 5:'V',
> 4:'IV',
> 1:'I'
>
> Using this dictionary (romansDic), you define a recursive function:
>
> toRomans(number){
>   i = return the greatest key less than or equal to given key from
> ‘romansDic'  .
>   if (number == i ){
> return romansDic.get(number)
> }
>   return string_concat(romansDic.get(i), toRomans(number-i))
> }
>
> Sorry for the pseudocode.
>
> Saludos Pablo.
>
>
> El 18 de sep. de 2020 10:46 -0300, Roelof Wobben via Pharo-users <
> pharo-users@lists.pharo.org>, escribió:
>
> Op 18-9-2020 om 06:45 schreef Richard O'Keefe:
>
> Roman numerals are much more complicated and much less consistent
> than most people realise.  The regular M DC LX VI system is both
> more modern and less capable than anything the Romans would have
> recognised.  In particular,
>  - in the 8th century, N (short for "nulla") was adopted for zero
>  - the Roman system always had fractions like S for 1/2, . for 1/12
>  - there were numerals for much larger numbers.
> Unicode code block [2150] has characters for the Roman numerals
> including
> 216C L ROMAN NUMERAL FIFTY
> 216D C ROMAN NUMERAL ONE HUNDRED
> 216E D ROMAN NUMERAL FIVE HUNDRED
> 216F M ROMAN NUMERAL ONE THOUSAND
> 2181 ↁ ROMAN NUMERAL FIVE THOUSAND
> 2182 ↂ ROMAN NUMERAL TEN THOUSAND
> 2187 ↇ ROMAN NUMERAL FIFTY THOUSAND
> 2188 ↈ ROMAN NUMERAL ONE HUNDRED THOUSAND
> (In fact these are ligated versions of forms using "apostrophic" brackets;
> the pattern goes as high as you want, e.g., (((|))) for a million.
> D and M were originally |) and (|).   There is
>
> So the first thing is to make sure that you understand the
> requirements for the problem.
> - Are you required to produce ASCII characters, required to
>   produce Unicode ones, or allowed to produce either?
>
>
> as far as I can see from the tests only ASCI characters.
>
> - Are you required to support zero?
>
>
> No
>
> - Are you required to support n/12 fractions (1<=n<=11)?
>
>
> NO
>
> - Are you allowed, required, or forbidden to use the "overline"
>   convention, where an overline means "multiply by 1000"?
>   =-------
>
>
> In the test that one is not used.
>
>   ICCXXXIVDLXVII = 1,234,567
> - Are you allowed, required, or forbidden to use "additive"
>   form "IIII" as well as/instead of "subtractive" form "IV"?
> - Are you to use upper case or lower case letters?
> - And so on.
>
>
>
>
> the number 4 needs to be  "IV"
>
> Roelof
>
>

Reply via email to