home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / lang / perl / 5736 < prev    next >
Encoding:
Internet Message Format  |  1992-09-07  |  6.4 KB

  1. Xref: sparky comp.lang.perl:5736 sci.classics:683
  2. Path: sparky!uunet!ogicse!uwm.edu!rutgers!psinntp!psinntp!avernus!mgfrank
  3. From: mgfrank@avernus.com (Marc G. Frank)
  4. Newsgroups: comp.lang.perl,sci.classics
  5. Subject: SCRIPT: Roman numeral conversion
  6. Message-ID: <1992Sep3.002639.8834@avernus.com>
  7. Date: 3 Sep 92 00:26:39 GMT
  8. Article-I.D.: avernus.1992Sep3.002639.8834
  9. Organization: Maryland Appreciation Society
  10. Lines: 187
  11.  
  12.  
  13. How many times have you said:
  14.  
  15. "Gee, perl looks pretty neat.  Too bad it doesn't handle Roman numerals."
  16.  
  17. or:
  18.  
  19. "DAMN!  If perl's such a great language, then why the hell can't it use
  20. Roman numerals?"
  21.  
  22. or:
  23.  
  24. "I'd like to recommend perl, sir, but I'm afraid I can't until the Roman
  25. numeral matter is resolved."
  26.  
  27. or:
  28.  
  29. "I'd send Larry lots and lots of money for writing such a useful
  30. utility, but I won't because it doesn't do Roman numerals."
  31.  
  32. vel:
  33.  
  34. "Stercus!  Cur non margarita potest numeros Romanos computare?'
  35.  
  36. Hundreds if not thousands of times, I reckon.  Well, relax, because
  37. the wait is over!  Included below is a package to convert to and from
  38. Roman numerals.
  39.  
  40. While ator, the routine to convert to Roman numerals, could be
  41. marginally useful on occasion (page numbers, perhaps), as far as I can
  42. tell rtoa, which converts from Roman numerals, is useless unless you
  43. want to use it to cheat on^H^H^H^H^H^H^H^Hcheck your Latin I homework.
  44. I pretty much just wrote that one for the fun of it.  Note that this
  45. package hasn't been thoroughly tested (it converts the numbers I need it
  46. to convert, so hey, why test further?), so you might not want to use it
  47. for mission-critical applications.  If you *have* a mission-critical
  48. application that needs Roman numeral conversion, then perhaps it's time
  49. to *seriously* reconsider your mission.  :-)
  50.  
  51. Also included is testromn.pl.  Feed it either Arabic or Roman numerals
  52. on stdin, and it spits out the other on stdout.  Rather useful for
  53. checking Latin I homework.  Other documentation is to found in the
  54. comments in roman.pl.
  55.  
  56. Enjoy.  BTW, this article is crossposted(!), so if you follow up be sure
  57. to edit the Newsgroups: line accordingly.
  58.  
  59.  
  60. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  61. | Marc G. Frank                                  mgfrank@avernus.com |
  62. |                   I'd rather be in Eldersburg.                     |
  63. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  64.  
  65. # This is a shell archive.  Save it in a file, remove anything before
  66. # this line, and then unpack it by entering "sh file".  Note, it may
  67. # create directories; files and directories will be owned by you and
  68. # have default permissions.
  69. #
  70. # This archive contains:
  71. #
  72. #    roman.pl
  73. #    testromn.pl
  74. #
  75. echo x - roman.pl
  76. sed 's/^X//' >roman.pl << 'END-of-roman.pl'
  77. X#
  78. X# roman.pl -- package to convert to and from Roman numerals
  79. X#
  80. X# Marc G. Frank
  81. X# mgfrank@avernus.com
  82. X# Written August , 992
  83. X# Author got around to documenting it September 2, 992
  84. X#
  85. X# This amazingly useful package makes a modest attempt to convert between
  86. X# Roman and Arabic numerals.  It will convert Arabic integers to Roman
  87. X# numerals in the range  <= x <= 4999, after which things get a bit messy:
  88. X# the Roman numerals have to have bars over them (or something like that)
  89. X# which isn't easily representable in ASCII.  If you feed ator something
  90. X# that isn't an integer in this range it returns ''.
  91. X#
  92. X# Converting the other way around is a bit trickier as far as error
  93. X# detection is concerned, so rtoa doesn't do much of it.  Suffice it to
  94. X# say that if you feed it a valid Roman numeral you'll get the Arabic
  95. X# equivalent back.  If you feed it something that obviously isn't a
  96. X# Roman numeral it returns ''.  If you feed it an invalid Roman numeral
  97. X# (like XXCMDLM) you'll get something back, but if the input isn't valid
  98. X# there's no reason the output should be.  :-)
  99. X#
  100. X# Usage:
  101. X# require "roman.pl";
  102. X# $something = &ator($some_number);
  103. X# $something_else = &rtoa($some_roman_numeral);
  104. X#
  105. X# Note that Roman numerals are returned in uppercase.  If you don't like this,
  106. X# use tr on the resulting string.
  107. X#
  108. X# Bugs to mgfrank@avernus.com
  109. X
  110. X
  111. Xpackage roman;
  112. X
  113. X
  114. Xsub main'ator {          # Convert Arabic integers to Roman numerals
  115. X  local($n) = @_;
  116. X  local($i, $roman);
  117. X  return '' if ($n =~ /[\D.Ee]/ || $n <  || $n > 4999); # Rudimentary error-
  118. X  local(@numerals) = (I,X,C,M);                          # checking
  119. X
  120. X  # I'm bad at math so I found it easier to do the conversion stringly.  This
  121. X  # bit converts the Arabic numeral in each position to the corresponding
  122. X  # number of equivalent Roman numerals.  That is, if the number to be
  123. X  # converted is 992, the 9 in the hundreds place is converted to CCCCCCCCC.
  124. X
  125. X  $n = reverse($n);
  126. X  for($i = length($n) -  ; $i >= 0 ; $i--) {
  127. X    $roman .= @numerals[$i] x substr($n, $i, );
  128. X  }
  129. X
  130. X  # Once that's been done, all that's left to do is convert strings like
  131. X  # CCCCCCCCC to strings like XC.
  132. X
  133. X  $roman =~ s/C{9}/CM/;
  134. X  $roman =~ s/C{5}/D/;
  135. X  $roman =~ s/C{4}/CD/;
  136. X  $roman =~ s/X{5}/L/;
  137. X  $roman =~ s/X{4}/XL/;
  138. X  $roman =~ s/LXL/XC/;
  139. X  $roman =~ s/I{9}/IX/;
  140. X  $roman =~ s/I{5}/V/;
  141. X  $roman =~ s/I{4}/IV/;
  142. X  $roman;
  143. X}
  144. X
  145. X
  146. X
  147. Xsub main'rtoa {          # Convert Roman numerals into Arabic
  148. X  local($n) = @_;
  149. X  $n =~ tr/mdclxvi/MDCLXVI/; # Canonicalize to uppercase
  150. X  return '' if $n =~ /[^MDCLXVI]/; # *Very* rudimentary error-checking
  151. X  local($arabic, $i);
  152. X  local(%numerals) = ('M', 000,
  153. X              'D', 500,
  154. X              'C', 00,
  155. X              'L', 50,
  156. X              'X', 0,
  157. X              'V', 5,
  158. X              'I', );
  159. X
  160. X  # Do the reverse of before.  Translate strings like XC to strings like
  161. X  # CCCCCCCCC.
  162. X
  163. X  $n =~ s/CM/CCCCCCCCC/;
  164. X  $n =~ s/CD/CCCC/;
  165. X  $n =~ s/XL/XXXX/;
  166. X  $n =~ s/XC/XXXXXXXXX/;
  167. X  $n =~ s/IX/IIIIIIIII/;
  168. X  $n =~ s/IV/IIII/;
  169. X
  170. X  # Now just add the value of every character in the string to the result.
  171. X
  172. X  for($i = 0 ; $i < length($n) ; $i++) {
  173. X    $arabic += $numerals{substr($n, $i, )};
  174. X  }
  175. X  $arabic;
  176. X}
  177. X
  178. X; # Return an end-of-package true.
  179. END-of-roman.pl
  180. echo x - testromn.pl
  181. sed 's/^X//' >testromn.pl << 'END-of-testromn.pl'
  182. X#!/usr/bin/perl
  183. X
  184. Xrequire "roman.pl";
  185. X
  186. Xwhile(<STDIN>) {
  187. X    chop;
  188. X    if(/\d+/) { print &ator($_), "\n"; }
  189. X    else { print &rtoa($_), "\n"; }
  190. X}
  191. END-of-testromn.pl
  192. exit
  193.  
  194.  
  195. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  196. | Marc G. Frank                                  mgfrank@avernus.com |
  197. |                   I'd rather be in Eldersburg.                     |
  198. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  199.