File Coverage

blib/lib/Convert/Number/Armenian.pm
Criterion Covered Total %
statement 44 44 100.0
branch 16 16 100.0
condition 8 9 88.8
subroutine 7 7 100.0
pod 2 2 100.0
total 77 78 98.7


line stmt bran cond sub pod time code
1             package Convert::Number::Armenian;
2              
3 1     1   63219 use strict;
  1         2  
  1         37  
4 1     1   6 use warnings;
  1         1  
  1         29  
5 1     1   6 use Exporter 'import';
  1         3  
  1         40  
6 1     1   6 use vars qw/ $VERSION @EXPORT_OK /;
  1         2  
  1         2487  
7              
8             $VERSION = "0.1";
9             @EXPORT_OK = qw/ arm2int int2arm /;
10              
11             =encoding utf-8
12              
13             =head1 NAME
14              
15             Convert::Number::Armenian - convert between Armenian and Western numerals
16              
17             =head1 SYNOPSIS
18              
19             use Convert::Number::Armenian qw( arm2int int2arm );
20            
21             my $armenian_rep = int2arm( 1999 );
22             my $decimal_val = arm2int( 'ՌՋՂԹ' );
23              
24             =head1 DESCRIPTION
25              
26             This is a relatively simple module for converting between Armenian-style
27             numbers and their Western decimal representations. The module exports two
28             functions on request: C and C.
29              
30             =head1 FUNCTIONS
31              
32             =head2 arm2int
33              
34             Takes a string that contains an Armenian number and returns the decimal
35             value. The function tries to deal with common though non-canonical
36             representations such as ՃՌ for 100,000. The Armenian string may be upper-
37             or lowercase, or a mix of both.
38              
39             =cut
40              
41             my $BASE = 1328; # Armenian 'A' minus one
42             # 10^4 is 555-556
43             # 10^3 is 54C-553
44             # 10^2 is 543-54B
45             # 10^1 is 53A-542
46             # 10^0 is 531-539
47              
48             sub arm2int {
49 10     10 1 76 my $str = shift;
50             # Uppercase the string for convenience.
51 1     1   12 $str = uc( $str );
  1         3  
  1         17  
  10         83  
52 10         32143 my @codepoints = unpack( "U*", $str );
53 10         20 my $total;
54 10         20 foreach my $digit ( @codepoints ) {
55             # Error check.
56 20 100 66     94 unless( $digit > 1328 && $digit < 1367 ) {
57 1         13 warn "string $str appears not to be an Armenian number\n";
58 1         119 return 0;
59             }
60              
61             # Convert into a number.
62 19         18 my $val;
63 19 100       59 if( $digit < 1338 ) {
    100          
    100          
    100          
64 7         9 $val = $digit - 1328;
65             } elsif( $digit < 1347 ) {
66 5         8 $val = ( $digit - 1337 ) * 10;
67             } elsif( $digit < 1356 ) {
68 4         10 $val = ( $digit - 1346 ) * 100;
69             } elsif( $digit < 1365 ) {
70 2         4 $val = ( $digit - 1355 ) * 1000;
71             } else {
72 1         2 $val = ( $digit - 1364 ) * 10000;
73             }
74              
75             # Figure out if we are adding or multiplying.
76 19 100 100     64 if( $total && $total < $val ) {
77 2         5 $total = $total * $val;
78             } else {
79 17         37 $total += $val;
80             }
81             }
82              
83 9         68 return $total;
84             }
85              
86             =head2 int2arm
87              
88             Takes a number and returns its Armenian representation in canonical form, meaning
89             an uppercase string with digit values descending from left to right. At the moment
90             only values between 1 and 29999 can be converted.
91              
92             =cut
93              
94             ## TODO handle bigger numbers through multiplication,
95             ## e.g. 144,000 as 144-1000
96             sub int2arm {
97 11     11 1 111 my $int = shift;
98 11 100 100     66 if( $int < 1 || $int > 29999 ) {
99 2         24 warn "Can only convert numbers between 1 - 29999";
100 2         190 return;
101             }
102 9         14 my @parts;
103 9         24 foreach my $i ( 0 .. 4 ) {
104 45         77 my $digit = int( $int / ( 10 ** $i ) ) % 10;
105 45 100       115 if( $digit ) {
106 21         69 unshift( @parts, chr( $BASE + ( 9 * $i ) + $digit ) );
107             }
108             }
109            
110 9         66 return( join( '', @parts ) );
111             }
112            
113              
114             =head1 TODO
115              
116             The module as written depends on correct Perl Unicode behavior; that means
117             that on earlier versions of Perl this module may not work as expected. As
118             soon as I work out which is the minimum version, I will update the module
119             with the correct requirement.
120              
121             Armenian ligatures probably won't produce the correct result for arm2int.
122              
123             =head1 LICENSE
124              
125             This package is free software and is provided "as is" without express
126             or implied warranty. You can redistribute it and/or modify it under
127             the same terms as Perl itself.
128              
129             =head1 AUTHOR
130              
131             Tara L Andrews, L
132              
133             =cut
134              
135             1;