File Coverage

blib/lib/Math/NumSeq/AlphabeticalLength.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             # Copyright 2012, 2015 Kevin Ryde
2              
3             # This file is part of Math-NumSeq-Alpha.
4             #
5             # Math-NumSeq-Alpha is free software; you can redistribute it and/or modify
6             # it under the terms of the GNU General Public License as published by the
7             # Free Software Foundation; either version 3, or (at your option) any later
8             # version.
9             #
10             # Math-NumSeq-Alpha is distributed in the hope that it will be useful, but
11             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13             # for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Math-NumSeq-Alpha. If not, see .
17              
18             package Math::NumSeq::AlphabeticalLength;
19 2     2   2688 use 5.004;
  2         5  
  2         66  
20 2     2   8 use strict;
  2         2  
  2         70  
21 2     2   13 use List::Util 'min';
  2         2  
  2         152  
22              
23 2     2   9 use vars '$VERSION', '@ISA';
  2         2  
  2         126  
24             $VERSION = 3;
25 2     2   394 use Math::NumSeq;
  0            
  0            
26             use Math::NumSeq::Base::IterateIth;
27             @ISA = ('Math::NumSeq::Base::IterateIth',
28             'Math::NumSeq');
29             *_is_infinite = \&Math::NumSeq::_is_infinite;
30              
31             use Lingua::Any::Numbers;
32              
33             # uncomment this to run the ### lines
34             #use Smart::Comments;
35              
36              
37             # use constant name => Math::NumSeq::__('...');
38             use constant description => Math::NumSeq::__('Length of i written out in words.');
39             use constant default_i_start => 1;
40             use constant characteristic_count => 1;
41             use constant characteristic_smaller => 1;
42             use constant characteristic_integer => 1;
43              
44             use constant::defer parameter_info_array => sub {
45             require Lingua::Any::Numbers;
46              
47             # Lingua::Any::Numbers version 0.44 excludes Lingua::Conlang::Numbers
48             # which is a front-end to various Esperanto etc, no need to do that here.
49             my @choices = sort(Lingua::Any::Numbers::available());
50             ### @choices
51              
52             # move 'EN' to the start, if it exists (which it should)
53             foreach my $i (0 .. $#choices) {
54             if ($choices[$i] eq 'EN') {
55             unshift @choices, splice(@choices, $i, 1);
56             last;
57             }
58             }
59             ### @choices
60              
61             return [
62             {
63             name => 'lang',
64             display => ('Language'),
65             type => 'string',
66             default => 'EN',
67             choices => \@choices,
68             width => 8,
69             # description => Math::NumSeq::__('...'),
70             },
71             {
72             name => 'number_type',
73             type => 'enum',
74             default => 'cardinal',
75             choices => ['cardinal','ordinal'],
76             choices_display => [Math::NumSeq::__('Cardinal'),
77             Math::NumSeq::__('Ordinal')],
78             # description => Math::NumSeq::__('...'),
79             },
80             {
81             name => 'conjunctions',
82             display => ('Conjunctions'),
83             type => 'boolean',
84             default => 1,
85             description => ('Whether to include conjunctions "and" or "et" in the words of the sequence.'),
86             },
87              
88             # Not through Lingua::Any::Numbers interface
89             # {
90             # name => 'gender',
91             # type => 'enum',
92             # default => 'M',
93             # choices => ['M','F','N'],
94             # # description => Math::NumSeq::__('...'),
95             # },
96             # {
97             # name => 'declension',
98             # type => 'enum',
99             # default => 'nominative',
100             # choices => ['nominative','genitive','dative','accusative','ablative'],
101             # # description => Math::NumSeq::__('...'),
102             # },
103             ];
104             };
105              
106             sub values_min {
107             my ($self) = @_;
108             ### values_min(): $self
109             my $i_start = $self->i_start;
110             return ($self->{'values_min'}
111             = min (map {$self->ith($_)||0}
112             $i_start .. $i_start + 20));
113             }
114              
115             #------------------------------------------------------------------------------
116             # cf A052360 en cardinal including spaces and hyphens
117             # A052363 new longest alpha
118             # A134629 first requiring n letters
119             # A006968 or A092196 Roman numerals, up to 4000
120             # A037193 num consonants in French
121             #
122             # A164058 Number of curves in n-th letter of capitalized English alphabet (A being first).
123             # A164059 Number of straight plus curved segments in the capitalized English name of n.
124             #
125             # A003078 (Danish) DK
126             # A001050 (Finnish) FI
127             # A001368 (Irish Gaelic) GA
128             # A051785 (Catalan) CA
129             # A056597 (Serbian or Croatian) SR
130             # A132984 (Latin) LA
131             # A140395 (Hindi) HI
132             # A053306 (Galego)
133             # A140396 (Welsh) CY
134             # A140438 (Tamil) TA
135             # A014656 (Bokmal) NB, was NO Lingua::NO::Num2Word
136             # A028292 (Nynorsk) NN
137              
138             # catalogued in Alpha.pm
139             my %oeis_anum
140             = ('en,cardinal,0,noand' => 'A005589',
141             'en,ordinal,1,noand' => 'A006944',
142              
143             # Lingua::CS::Num2Word doubtful ...
144             'cs,cardinal,1' => 'A010038', # Czech, Lingua::CS::Num2Word
145              
146             # Lingua::DE::Num2Word doubtful ...
147             # 'de,cardinal,1' => 'A007208', # German, Lingua::DE::Num2Word
148              
149             'eo,cardinal,0' => 'A057853', # Esperanto, Lingua::EO::Numbers
150              
151             'es,cardinal,0' => 'A011762', # Spanish, Lingua::ES::Numeros
152              
153             'fr,ordinal,1' => 'A006969', # French, Lingua::FR::Numbers
154             'fr,cardinal,0,incspaces' => 'A007005',
155              
156             'hu,cardinal,1' => 'A007292', # Hungarian, Lingua::HU::Numbers
157              
158             # Not quite, centottanta in A026858 vs centoottanta in Lingua
159             # 'it,cardinal,0' => 'A026858', # Italian, Lingua::IT::Numbers
160              
161             'ja,cardinal,0' => 'A030166', # Japanese Kanji, Lingua::JA::Numbers
162              
163             'nl,cardinal,1' => 'A090589', # Dutch, Lingua::NL::Numbers
164             # cf A007485 ij as one letter
165              
166             # Not sure about 11=ellve cf A014656(11)=6
167             # # Bokmal NO, lately code change to NB
168             # 'no,cardinal,1' => 'A014656', # Lingua::NO::Num2Word
169             #
170             # cf A028292 Nynorsk A028292(1)=3
171             # 'nn,cardinal,1' => 'A028292',
172              
173             'pl,cardinal,0' => 'A008962', # Polish, Lingua::PL::Numbers
174              
175             # Not quite, A057696 Brazilian Portuguese "catorze"
176             # whereas "quatorze" in Lingua::PT::Nums2Words
177             # 'pt,cardinal,1' => 'A057696', # Lingua::PT::Nums2Words
178             # cf A057697 including spaces
179              
180             # No, Lingua::RU::Number 0.05 is money amounts only.
181             # 'ru,cardinal,1' => 'A006994', # Russian, Lingua::RU::Number
182              
183             'sv,cardinal,0' => 'A059124', # Swedish, Lingua::SV::Numbers
184              
185             'tr,cardinal,1' => 'A057435', # Turkish, Lingua::TR::Numbers
186             );
187             sub oeis_anum {
188             my ($self) = @_;
189             ### oeis_anum: $self
190              
191             my $key = join(',',
192             $self->{lang},
193             $self->{number_type},
194             $self->i_start);
195             if (! $self->{'conjunctions'}) {
196             $key .= ',noand';
197             }
198             ### $key
199             return $oeis_anum{$key};
200             }
201              
202             #------------------------------------------------------------------------------
203              
204             my %conjunctions_word = (en => 'and',
205             fr => 'et',
206             );
207             sub new {
208             my $self = shift->SUPER::new(@_);
209              
210             my $lang = $self->{'lang'} = lc($self->{'lang'});
211              
212             if ($lang eq 'sv') {
213             my $str = Lingua::Any::Numbers::to_string (2, 'sv');
214             ### $str
215             if (length($str) == 4) {
216             # Lingua::SV::Numbers gives utf-8 bytes, mangle it down to chars
217             ### decode_chars mangle out utf8 ...
218             $self->{'decode_chars'} = sub {
219             $_[0] =~ s/\303./X/g;
220             };
221             }
222             }
223              
224             if (! $self->{'conjunctions'}) {
225             if (! defined $self->{'conjunctions_word'}) {
226             $self->{'conjunctions_word'} = $conjunctions_word{$lang}
227             }
228             }
229              
230             return $self;
231             }
232              
233             sub ith {
234             my ($self, $i) = @_;
235             ### AlphabeticalLength ith(): "$i"
236              
237             if (_is_infinite($i)) {
238             return undef;
239             }
240              
241             my $lang = $self->{'lang'};
242             my $str;
243             if ($self->{'number_type'} eq 'ordinal') {
244             $str = Lingua::Any::Numbers::to_ordinal ($i, $lang);
245             if ($str eq $i) {
246             # some modules without ordinal support return $i as numerals unchanged
247             return undef;
248             }
249              
250             } else {
251             if ($lang eq 'eo' && $i == 1) {
252             # HACK: avoid warn() from num2eo(1) in Lingua::EO::Numbers 0.03
253             $str = 'unu';
254             } else {
255             $str = Lingua::Any::Numbers::to_string ($i, $lang);
256             }
257             }
258             if (my $decode_chars = $self->{'decode_chars'}) {
259             $decode_chars->($str);
260             }
261             ### language: $self->{'lang'}
262             ### $str
263              
264             if (! $self->{'conjunctions'}) {
265             if ($self->{'lang'} eq 'en') {
266             $str =~ s/\b$self->{'conjunctions_word'}\b//ig;
267             }
268             }
269              
270             my $count = 0;
271             while ($str =~ /(\w|[^[:ascii:]])/g) {
272             $count += length($1);
273             }
274             ### $count
275             return $count;
276              
277             # ### letters only: $str
278             # counting whitespace ...
279             # $str =~ s/[^[:word:][:space:]]//g;
280             # return length($str);
281             }
282              
283             1;
284             __END__