Mercurial > repo
comparison interps/clc-intercal/inst/lib/perl5/Language/INTERCAL/ReadNumbers.pm @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
1 package Language::INTERCAL::ReadNumbers; | |
2 | |
3 # Convert numbers to Roman numerals | |
4 | |
5 # This file is part of CLC-INTERCAL | |
6 | |
7 # Copyright (c) 2006-2008 Claudio Calvelli, all rights reserved. | |
8 | |
9 # CLC-INTERCAL is copyrighted software. However, permission to use, modify, | |
10 # and distribute it is granted provided that the conditions set out in the | |
11 # licence agreement are met. See files README and COPYING in the distribution. | |
12 | |
13 use strict; | |
14 use vars qw($VERSION $PERVERSION); | |
15 ($VERSION) = ($PERVERSION = "CLC-INTERCAL/Base INTERCAL/ReadNumbers.pm 1.-94.-2") =~ /\s(\S+)$/; | |
16 | |
17 use Carp; | |
18 use Language::INTERCAL::Exporter '1.-94.-2'; | |
19 use Language::INTERCAL::Splats '1.-94.-2', qw(SP_ROMAN faint); | |
20 use vars qw(@EXPORT @EXPORT_OK); | |
21 @EXPORT = (); | |
22 @EXPORT_OK = qw(roman_type roman_name roman_type_default read_number roman); | |
23 | |
24 my (@roman_types, %roman_types); | |
25 | |
26 BEGIN { | |
27 @roman_types = ( | |
28 ['CLC' => \&_roman_clc], # CLC-INTERCAL's "roman" | |
29 ['UNDERLINE' => \&_roman_underline], # alternative CLC-INTERCAL's | |
30 ['ARCHAIC' => \&_roman_archaic], # as used when Rome was new | |
31 ['MEDIAEVAL' => \&_roman_mediaeval], # as used in the middle ages | |
32 ['MODERN' => \&_roman_modern], # as used today | |
33 ['TRADITIONAL' => \&_roman_1972], # INTERCAL-1972 | |
34 ['WIMPMODE' => \&_roman_wimpmode], # not Roman at all | |
35 ); | |
36 | |
37 %roman_types = | |
38 map { ( $roman_types[$_][0] => $_ + 1 ) } (0..@roman_types - 1); | |
39 | |
40 my $d = $roman_types{'CLC'}; | |
41 use vars '*roman_type_default'; | |
42 *roman_type_default = sub () { $d }; | |
43 } | |
44 | |
45 sub roman_type { | |
46 @_ == 1 or croak "Usage: roman_type(TYPE)"; | |
47 my ($type) = @_; | |
48 $type =~ s/\s+//g; | |
49 if ($type =~ /^\d+$/) { | |
50 return roman_type_default if $type == 0; | |
51 return $type < 1 || $type > @roman_types ? undef : $type; | |
52 } else { | |
53 return exists $roman_types{$type} ? $roman_types{$type} : undef; | |
54 } | |
55 } | |
56 | |
57 sub roman_name { | |
58 @_ == 1 or croak "Usage: roman_name(TYPE)"; | |
59 my ($type) = @_; | |
60 $type = roman_type_default if $type == 0; | |
61 return undef if $type < 1 || $type > @roman_types; | |
62 return $roman_types[$type - 1][0]; | |
63 } | |
64 | |
65 sub read_number { | |
66 @_ == 3 or croak "Usage: read_number(NUMBER, TYPE, FILEHANDLE)"; | |
67 my ($number, $type, $fh) = @_; | |
68 my $rtype = roman_type($type); | |
69 defined $rtype or faint(SP_ROMAN, $type); | |
70 for my $line (&{$roman_types[$rtype - 1][1]}($number)) { | |
71 $fh->read_text($line . "\n"); | |
72 } | |
73 } | |
74 | |
75 sub roman { | |
76 @_ == 2 or croak "Usage: read_number(NUMBER, TYPE)"; | |
77 my ($number, $type, $fh) = @_; | |
78 my $rtype = roman_type($type); | |
79 defined $rtype or faint(SP_ROMAN, $type); | |
80 return &{$roman_types[$rtype - 1][1]}($number); | |
81 } | |
82 | |
83 sub _roman_clc { | |
84 my ($number) = @_; | |
85 if ($number == 0) { | |
86 return "NIHIL"; | |
87 } | |
88 my $result = ''; | |
89 if ($number >= 4000000000) { | |
90 my $val = lc(_numeral(int($number / 1000000000))); | |
91 $val =~ s/(.)/\\$1/g; | |
92 $result .= $val; | |
93 $number %= 1000000000; | |
94 } | |
95 if ($number >= 4000000) { | |
96 my $val = uc(_numeral(int($number / 1000000))); | |
97 $val =~ s/(.)/\\$1/g; | |
98 $result .= $val; | |
99 $number %= 1000000; | |
100 } | |
101 if ($number >= 4000) { | |
102 $result .= lc(_numeral(int($number / 1000))); | |
103 $number %= 1000; | |
104 } | |
105 if ($number > 0) { | |
106 $result .= uc(_numeral($number)); | |
107 } | |
108 $result; | |
109 } | |
110 | |
111 sub _roman_underline { | |
112 my ($number) = @_; | |
113 if ($number == 0) { | |
114 return "NIHIL"; | |
115 } | |
116 my $result = ''; | |
117 if ($number >= 4000000000) { | |
118 my $val = lc(_numeral(int($number / 1000000000))); | |
119 $val =~ s/(.)/_\b$1/g; | |
120 $result .= $val; | |
121 $number %= 1000000000; | |
122 } | |
123 if ($number >= 4000000) { | |
124 my $val = uc(_numeral(int($number / 1000000))); | |
125 $val =~ s/(.)/_\b$1/g; | |
126 $result .= $val; | |
127 $number %= 1000000; | |
128 } | |
129 if ($number >= 4000) { | |
130 $result .= lc(_numeral(int($number / 1000))); | |
131 $number %= 1000; | |
132 } | |
133 if ($number > 0) { | |
134 $result .= uc(_numeral($number)); | |
135 } | |
136 $result; | |
137 } | |
138 | |
139 sub _roman_mediaeval { | |
140 my ($number) = @_; | |
141 if ($number == 0) { | |
142 return "NIHIL"; | |
143 } | |
144 my $first = ''; | |
145 my $second = ''; | |
146 if ($number >= 500000000) { | |
147 my $val = uc(_m_numeral(int($number / 500000000) * 5)); | |
148 $first .= ' _ ' x length($val); | |
149 $val =~ s/(.)/||$1||/g; | |
150 $second .= $val; | |
151 $number %= 500000000; | |
152 } | |
153 if ($number >= 5000000) { | |
154 my $val = uc(_m_numeral(int($number / 5000000) * 5)); | |
155 $first .= ' _ ' x length($val); | |
156 $val =~ s/(.)/|$1|/g; | |
157 $second .= $val; | |
158 $number %= 5000000; | |
159 } | |
160 if ($number >= 5000) { | |
161 my $val = uc(_m_numeral(int($number / 5000) * 5)); | |
162 $first .= '_' x length($val); | |
163 $second .= $val; | |
164 $number %= 5000; | |
165 } | |
166 if ($number > 0) { | |
167 my $val = uc(_m_numeral($number)); | |
168 $first .= ' ' x length($val); | |
169 $second .= $val; | |
170 } | |
171 $first =~ s/\s+$//; | |
172 $first ne '' ? ($first, $second) : ($second); | |
173 } | |
174 | |
175 sub _roman_modern { | |
176 my ($number) = @_; | |
177 if ($number == 0) { | |
178 return "NIHIL"; | |
179 } | |
180 my $first = ''; | |
181 my $second = ''; | |
182 if ($number >= 100000000) { | |
183 my $val = uc(_numeral(int($number / 100000000) * 10)); | |
184 $first .= ' _ ' x length($val); | |
185 $val =~ s/(.)/||$1||/g; | |
186 $second .= $val; | |
187 $number %= 100000000; | |
188 } | |
189 if ($number >= 1000000) { | |
190 my $val = uc(_numeral(int($number / 1000000) * 10)); | |
191 $first .= ' _ ' x length($val); | |
192 $val =~ s/(.)/|$1|/g; | |
193 $second .= $val; | |
194 $number %= 1000000; | |
195 } | |
196 if ($number >= 1000) { | |
197 my $val = uc(_numeral(int($number / 1000))); | |
198 $first .= '_' x length($val); | |
199 $second .= $val; | |
200 $number %= 1000; | |
201 } | |
202 if ($number > 0) { | |
203 my $val = uc(_numeral($number)); | |
204 $first .= ' ' x length($val); | |
205 $second .= $val; | |
206 } | |
207 $first =~ s/\s+$//; | |
208 $first ne '' ? ($first, $second) : ($second); | |
209 } | |
210 | |
211 sub _roman_wimpmode { | |
212 my ($number) = @_; | |
213 $number + 0; | |
214 } | |
215 | |
216 sub _roman_archaic { | |
217 my ($number) = @_; | |
218 if ($number == 0) { | |
219 return "NIHIL"; | |
220 } | |
221 my $result = ''; | |
222 if ($number >= 1000000000) { | |
223 $result .= _a_numeral(7, int($number / 1000000000)); | |
224 $number %= 1000000000; | |
225 } | |
226 if ($number >= 100000000) { | |
227 $result .= _a_numeral(6, int($number / 100000000)); | |
228 $number %= 100000000; | |
229 } | |
230 if ($number >= 10000000) { | |
231 $result .= _a_numeral(5, int($number / 10000000)); | |
232 $number %= 10000000; | |
233 } | |
234 if ($number >= 1000000) { | |
235 $result .= _a_numeral(4, int($number / 1000000)); | |
236 $number %= 1000000; | |
237 } | |
238 if ($number >= 100000) { | |
239 $result .= _a_numeral(3, int($number / 100000)); | |
240 $number %= 100000; | |
241 } | |
242 if ($number >= 10000) { | |
243 $result .= _a_numeral(2, int($number / 10000)); | |
244 $number %= 10000; | |
245 } | |
246 if ($number >= 1000) { | |
247 $result .= _a_numeral(1, int($number / 1000)); | |
248 $number %= 1000; | |
249 } | |
250 if ($number >= 500) { | |
251 $result .= 'I)'; | |
252 $number -= 500; | |
253 } | |
254 if ($number >= 1) { | |
255 $result .= uc(_m_numeral($number)); | |
256 } | |
257 $result; | |
258 } | |
259 | |
260 sub _roman_1972 { | |
261 my ($number) = @_; | |
262 if ($number == 0) { | |
263 return "_", " "; | |
264 } | |
265 my $first = ''; | |
266 my $second = ''; | |
267 if ($number >= 4000000000) { | |
268 my $val = lc(_numeral(int($number / 1000000000))); | |
269 $first .= '_' x length($val); | |
270 $second .= $val; | |
271 $number %= 1000000000; | |
272 } | |
273 if ($number >= 4000000) { | |
274 my $val = lc(_numeral(int($number / 1000000))); | |
275 $first .= ' ' x length($val); | |
276 $second .= $val; | |
277 $number %= 1000000; | |
278 } | |
279 if ($number >= 4000) { | |
280 my $val = uc(_numeral(int($number / 1000))); | |
281 $first .= '_' x length($val); | |
282 $second .= $val; | |
283 $number %= 1000; | |
284 } | |
285 if ($number > 0) { | |
286 my $val = uc(_numeral($number)); | |
287 $first .= ' ' x length($val); | |
288 $second .= $val; | |
289 } | |
290 $first =~ s/\s+$//; | |
291 ($first, $second); | |
292 } | |
293 | |
294 sub _numeral { | |
295 my ($value) = @_; | |
296 my $result = ''; | |
297 if ($value >= 1000) { | |
298 $result .= 'M' x int($value / 1000); | |
299 $value %= 1000; | |
300 } | |
301 if ($value >= 900) { | |
302 $result .= 'CM'; | |
303 $value -= 900; | |
304 } | |
305 if ($value >= 500) { | |
306 $result .= 'D'; | |
307 $value -= 500; | |
308 } | |
309 if ($value >= 400) { | |
310 $result .= 'CD'; | |
311 $value -= 400; | |
312 } | |
313 if ($value >= 100) { | |
314 $result .= 'C' x int($value / 100); | |
315 $value %= 100; | |
316 } | |
317 if ($value >= 90) { | |
318 $result .= 'XC'; | |
319 $value -= 90; | |
320 } | |
321 if ($value >= 50) { | |
322 $result .= 'L'; | |
323 $value -= 50; | |
324 } | |
325 if ($value >= 40) { | |
326 $result .= 'XL'; | |
327 $value -= 40; | |
328 } | |
329 if ($value >= 10) { | |
330 $result .= 'X' x int($value / 10); | |
331 $value %= 10; | |
332 } | |
333 if ($value >= 9) { | |
334 $result .= 'IX'; | |
335 $value -= 9; | |
336 } | |
337 if ($value >= 5) { | |
338 $result .= 'V'; | |
339 $value -= 5; | |
340 } | |
341 if ($value >= 4) { | |
342 $result .= 'IV'; | |
343 $value -= 4; | |
344 } | |
345 if ($value >= 1) { | |
346 $result .= 'I' x $value; | |
347 $value %= 1; | |
348 } | |
349 $result; | |
350 } | |
351 | |
352 sub _m_numeral { | |
353 my ($value) = @_; | |
354 my $result = ''; | |
355 if ($value >= 1000) { | |
356 $result .= 'M' x int($value / 1000); | |
357 $value %= 1000; | |
358 } | |
359 if ($value >= 500) { | |
360 $result .= 'D'; | |
361 $value -= 500; | |
362 } | |
363 if ($value >= 100) { | |
364 $result .= 'C' x int($value / 100); | |
365 $value %= 100; | |
366 } | |
367 if ($value >= 50) { | |
368 $result .= 'L'; | |
369 $value -= 50; | |
370 } | |
371 if ($value >= 10) { | |
372 $result .= 'X' x int($value / 10); | |
373 $value %= 10; | |
374 } | |
375 if ($value >= 5) { | |
376 $result .= 'V'; | |
377 $value -= 5; | |
378 } | |
379 if ($value >= 1) { | |
380 $result .= 'I' x $value; | |
381 $value %= 1; | |
382 } | |
383 $result; | |
384 } | |
385 | |
386 sub _a_numeral { | |
387 my ($parens, $number) = @_; | |
388 my $result = ''; | |
389 if ($number >= 5) { | |
390 $result .= "I" . (")" x (1 + $parens)); | |
391 $number -= 5; | |
392 } | |
393 if ($number >= 1) { | |
394 $result .= (("(" x $parens) . "I" . (")" x $parens)) x $number; | |
395 } | |
396 $result; | |
397 } | |
398 | |
399 1; |