diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interps/clc-intercal/inst/lib/perl5/Language/INTERCAL/ReadNumbers.pm	Sun Dec 09 19:30:08 2012 +0000
@@ -0,0 +1,399 @@
+package Language::INTERCAL::ReadNumbers;
+
+# Convert numbers to Roman numerals
+
+# This file is part of CLC-INTERCAL
+
+# Copyright (c) 2006-2008 Claudio Calvelli, all rights reserved.
+
+# CLC-INTERCAL is copyrighted software. However, permission to use, modify,
+# and distribute it is granted provided that the conditions set out in the
+# licence agreement are met. See files README and COPYING in the distribution.
+
+use strict;
+use vars qw($VERSION $PERVERSION);
+($VERSION) = ($PERVERSION = "CLC-INTERCAL/Base INTERCAL/ReadNumbers.pm 1.-94.-2") =~ /\s(\S+)$/;
+
+use Carp;
+use Language::INTERCAL::Exporter '1.-94.-2';
+use Language::INTERCAL::Splats '1.-94.-2', qw(SP_ROMAN faint);
+use vars qw(@EXPORT @EXPORT_OK);
+@EXPORT = ();
+@EXPORT_OK = qw(roman_type roman_name roman_type_default read_number roman);
+
+my (@roman_types, %roman_types);
+
+BEGIN {
+    @roman_types = (
+	['CLC'         => \&_roman_clc],         # CLC-INTERCAL's "roman"
+	['UNDERLINE'   => \&_roman_underline],   # alternative CLC-INTERCAL's
+	['ARCHAIC'     => \&_roman_archaic],     # as used when Rome was new
+	['MEDIAEVAL'   => \&_roman_mediaeval],   # as used in the middle ages
+	['MODERN'      => \&_roman_modern],      # as used today
+	['TRADITIONAL' => \&_roman_1972],        # INTERCAL-1972
+	['WIMPMODE'    => \&_roman_wimpmode],    # not Roman at all
+    );
+
+    %roman_types =
+	map { ( $roman_types[$_][0] => $_ + 1 ) } (0..@roman_types - 1);
+
+    my $d = $roman_types{'CLC'};
+    use vars '*roman_type_default';
+    *roman_type_default = sub () { $d };
+}
+
+sub roman_type {
+    @_ == 1 or croak "Usage: roman_type(TYPE)";
+    my ($type) = @_;
+    $type =~ s/\s+//g;
+    if ($type =~ /^\d+$/) {
+	return roman_type_default if $type == 0;
+	return $type < 1 || $type > @roman_types ? undef : $type;
+    } else {
+	return exists $roman_types{$type} ? $roman_types{$type} : undef;
+    }
+}
+
+sub roman_name {
+    @_ == 1 or croak "Usage: roman_name(TYPE)";
+    my ($type) = @_;
+    $type = roman_type_default if $type == 0;
+    return undef if $type < 1 || $type > @roman_types;
+    return $roman_types[$type - 1][0];
+}
+
+sub read_number {
+    @_ == 3 or croak "Usage: read_number(NUMBER, TYPE, FILEHANDLE)";
+    my ($number, $type, $fh) = @_;
+    my $rtype = roman_type($type);
+    defined $rtype or faint(SP_ROMAN, $type);
+    for my $line (&{$roman_types[$rtype - 1][1]}($number)) {
+	$fh->read_text($line . "\n");
+    }
+}
+
+sub roman {
+    @_ == 2 or croak "Usage: read_number(NUMBER, TYPE)";
+    my ($number, $type, $fh) = @_;
+    my $rtype = roman_type($type);
+    defined $rtype or faint(SP_ROMAN, $type);
+    return &{$roman_types[$rtype - 1][1]}($number);
+}
+
+sub _roman_clc {
+    my ($number) = @_;
+    if ($number == 0) {
+	return "NIHIL";
+    }
+    my $result = '';
+    if ($number >= 4000000000) {
+	my $val = lc(_numeral(int($number / 1000000000)));
+	$val =~ s/(.)/\\$1/g;
+	$result .= $val;
+	$number %= 1000000000;
+    }
+    if ($number >= 4000000) {
+	my $val = uc(_numeral(int($number / 1000000)));
+	$val =~ s/(.)/\\$1/g;
+	$result .= $val;
+	$number %= 1000000;
+    }
+    if ($number >= 4000) {
+	$result .= lc(_numeral(int($number / 1000)));
+	$number %= 1000;
+    }
+    if ($number > 0) {
+	$result .= uc(_numeral($number));
+    }
+    $result;
+}
+
+sub _roman_underline {
+    my ($number) = @_;
+    if ($number == 0) {
+	return "NIHIL";
+    }
+    my $result = '';
+    if ($number >= 4000000000) {
+	my $val = lc(_numeral(int($number / 1000000000)));
+	$val =~ s/(.)/_\b$1/g;
+	$result .= $val;
+	$number %= 1000000000;
+    }
+    if ($number >= 4000000) {
+	my $val = uc(_numeral(int($number / 1000000)));
+	$val =~ s/(.)/_\b$1/g;
+	$result .= $val;
+	$number %= 1000000;
+    }
+    if ($number >= 4000) {
+	$result .= lc(_numeral(int($number / 1000)));
+	$number %= 1000;
+    }
+    if ($number > 0) {
+	$result .= uc(_numeral($number));
+    }
+    $result;
+}
+
+sub _roman_mediaeval {
+    my ($number) = @_;
+    if ($number == 0) {
+	return "NIHIL";
+    }
+    my $first = '';
+    my $second = '';
+    if ($number >= 500000000) {
+	my $val = uc(_m_numeral(int($number / 500000000) * 5));
+	$first .= '  _  ' x length($val);
+	$val =~ s/(.)/||$1||/g;
+	$second .= $val;
+	$number %= 500000000;
+    }
+    if ($number >= 5000000) {
+	my $val = uc(_m_numeral(int($number / 5000000) * 5));
+	$first .= ' _ ' x length($val);
+	$val =~ s/(.)/|$1|/g;
+	$second .= $val;
+	$number %= 5000000;
+    }
+    if ($number >= 5000) {
+	my $val = uc(_m_numeral(int($number / 5000) * 5));
+	$first .= '_' x length($val);
+	$second .= $val;
+	$number %= 5000;
+    }
+    if ($number > 0) {
+	my $val = uc(_m_numeral($number));
+	$first .= ' ' x length($val);
+	$second .= $val;
+    }
+    $first =~ s/\s+$//;
+    $first ne '' ? ($first, $second) : ($second);
+}
+
+sub _roman_modern {
+    my ($number) = @_;
+    if ($number == 0) {
+	return "NIHIL";
+    }
+    my $first = '';
+    my $second = '';
+    if ($number >= 100000000) {
+	my $val = uc(_numeral(int($number / 100000000) * 10));
+	$first .= '  _  ' x length($val);
+	$val =~ s/(.)/||$1||/g;
+	$second .= $val;
+	$number %= 100000000;
+    }
+    if ($number >= 1000000) {
+	my $val = uc(_numeral(int($number / 1000000) * 10));
+	$first .= ' _ ' x length($val);
+	$val =~ s/(.)/|$1|/g;
+	$second .= $val;
+	$number %= 1000000;
+    }
+    if ($number >= 1000) {
+	my $val = uc(_numeral(int($number / 1000)));
+	$first .= '_' x length($val);
+	$second .= $val;
+	$number %= 1000;
+    }
+    if ($number > 0) {
+	my $val = uc(_numeral($number));
+	$first .= ' ' x length($val);
+	$second .= $val;
+    }
+    $first =~ s/\s+$//;
+    $first ne '' ? ($first, $second) : ($second);
+}
+
+sub _roman_wimpmode {
+    my ($number) = @_;
+    $number + 0;
+}
+
+sub _roman_archaic {
+    my ($number) = @_;
+    if ($number == 0) {
+	return "NIHIL";
+    }
+    my $result = '';
+    if ($number >= 1000000000) {
+	$result .= _a_numeral(7, int($number / 1000000000));
+	$number %= 1000000000;
+    }
+    if ($number >= 100000000) {
+	$result .= _a_numeral(6, int($number / 100000000));
+	$number %= 100000000;
+    }
+    if ($number >= 10000000) {
+	$result .= _a_numeral(5, int($number / 10000000));
+	$number %= 10000000;
+    }
+    if ($number >= 1000000) {
+	$result .= _a_numeral(4, int($number / 1000000));
+	$number %= 1000000;
+    }
+    if ($number >= 100000) {
+	$result .= _a_numeral(3, int($number / 100000));
+	$number %= 100000;
+    }
+    if ($number >= 10000) {
+	$result .= _a_numeral(2, int($number / 10000));
+	$number %= 10000;
+    }
+    if ($number >= 1000) {
+	$result .= _a_numeral(1, int($number / 1000));
+	$number %= 1000;
+    }
+    if ($number >= 500) {
+	$result .= 'I)';
+	$number -= 500;
+    }
+    if ($number >= 1) {
+	$result .= uc(_m_numeral($number));
+    }
+    $result;
+}
+
+sub _roman_1972 {
+    my ($number) = @_;
+    if ($number == 0) {
+	return "_", " ";
+    }
+    my $first = '';
+    my $second = '';
+    if ($number >= 4000000000) {
+	my $val = lc(_numeral(int($number / 1000000000)));
+	$first .= '_' x length($val);
+	$second .= $val;
+	$number %= 1000000000;
+    }
+    if ($number >= 4000000) {
+	my $val = lc(_numeral(int($number / 1000000)));
+	$first .= ' ' x length($val);
+	$second .= $val;
+	$number %= 1000000;
+    }
+    if ($number >= 4000) {
+	my $val = uc(_numeral(int($number / 1000)));
+	$first .= '_' x length($val);
+	$second .= $val;
+	$number %= 1000;
+    }
+    if ($number > 0) {
+	my $val = uc(_numeral($number));
+	$first .= ' ' x length($val);
+	$second .= $val;
+    }
+    $first =~ s/\s+$//;
+    ($first, $second);
+}
+
+sub _numeral {
+    my ($value) = @_;
+    my $result = '';
+    if ($value >= 1000) {
+	$result .= 'M' x int($value / 1000);
+	$value %= 1000;
+    }
+    if ($value >= 900) {
+	$result .= 'CM';
+	$value -= 900;
+    }
+    if ($value >= 500) {
+	$result .= 'D';
+	$value -= 500;
+    }
+    if ($value >= 400) {
+	$result .= 'CD';
+	$value -= 400;
+    }
+    if ($value >= 100) {
+	$result .= 'C' x int($value / 100);
+	$value %= 100;
+    }
+    if ($value >= 90) {
+	$result .= 'XC';
+	$value -= 90;
+    }
+    if ($value >= 50) {
+	$result .= 'L';
+	$value -= 50;
+    }
+    if ($value >= 40) {
+	$result .= 'XL';
+	$value -= 40;
+    }
+    if ($value >= 10) {
+	$result .= 'X' x int($value / 10);
+	$value %= 10;
+    }
+    if ($value >= 9) {
+	$result .= 'IX';
+	$value -= 9;
+    }
+    if ($value >= 5) {
+	$result .= 'V';
+	$value -= 5;
+    }
+    if ($value >= 4) {
+	$result .= 'IV';
+	$value -= 4;
+    }
+    if ($value >= 1) {
+	$result .= 'I' x $value;
+	$value %= 1;
+    }
+    $result;
+}
+
+sub _m_numeral {
+    my ($value) = @_;
+    my $result = '';
+    if ($value >= 1000) {
+	$result .= 'M' x int($value / 1000);
+	$value %= 1000;
+    }
+    if ($value >= 500) {
+	$result .= 'D';
+	$value -= 500;
+    }
+    if ($value >= 100) {
+	$result .= 'C' x int($value / 100);
+	$value %= 100;
+    }
+    if ($value >= 50) {
+	$result .= 'L';
+	$value -= 50;
+    }
+    if ($value >= 10) {
+	$result .= 'X' x int($value / 10);
+	$value %= 10;
+    }
+    if ($value >= 5) {
+	$result .= 'V';
+	$value -= 5;
+    }
+    if ($value >= 1) {
+	$result .= 'I' x $value;
+	$value %= 1;
+    }
+    $result;
+}
+
+sub _a_numeral {
+    my ($parens, $number) = @_;
+    my $result = '';
+    if ($number >= 5) {
+	$result .= "I" . (")" x (1 + $parens));
+	$number -= 5;
+    }
+    if ($number >= 1) {
+	$result .= (("(" x $parens) . "I" . (")" x $parens)) x $number;
+    }
+    $result;
+}
+
+1;