使用数字作为输入获取字母表
to get alphabets using number as input
我正在使用一些字母编码,其中输入是 return 各自字母的数字。考虑输入是 3 it return C,对于 5 it E 等等。如果数字大于 26,输出更改为 AA for 27, 28-AB, 29-AC
代码如下:
my $input = <>;
my @a = ("A".."B");
if($input <=26){
my $num1 = $input-1;
say $a[$num1];
}
elsif( $input <= 702 ){
#702 for ZZ
my $mod = $input % 26;
my $div = $input / 26;
my ($letter) = $div =~ /^(\d+)\./;
my $num1 = $div - 1;
my $num2 = $letter - 1;
say $a[$num1]$a[$num2];
}else{
# Here I stuck
# how to code for three or more letter combination?
}
对于三个字母的组合有什么建议吗?
更新:输入的数字不能为零。
我想你需要一个 while 循环。虽然不确定你从哪里得到 351 - 我得到的是 "NN"。 26 * 26 = 676.
例如类似于:
use warnings;
use strict;
my $number = 17577;
my @letters;
while ( $number > 0 ) {
my $part = $number % 26;
#print "$part, $number\n";
$number -= $part;
if ( $number == 26 ) { $number = 0; }
$number /= 26;
#print "$number $part\n";
push @letters,chr(65+$part);
}
print reverse @letters;
我不太了解 Perl,无法在其中写出答案,但这里有一个适用于任何长度的算法:
verify the input value is valid for your purpose
set Number to the input value (for clarity in this answer, or if you need the input value later)
set Output to an empty string
while Number > 25
set Remainder to Number modulo 26 plus 1
set Number to the integer part of Number divided by 26
prepend the character represented by Remainder to Output
end while
if Number is not zero prepend the character represented by Number plus 1 to the Output
我写了一个完整的测试套件,因为我发现这出奇地难以正确。
您正在从 10 进制转换为 26 进制,但由于 1 是 A 而不是 0,所以所有内容都移到 1 之上。尽早处理这个过程(即。$number--
)消除了很多下游错误。
#!/usr/bin/env perl
use v5.12;
use strict;
use warnings;
use Test::More;
my %tests = (
1 => "A",
1.0 => "A",
2 => "B",
25 => "Y",
26 => "Z",
27 => "AA",
52 => "AZ",
54 => "BB",
78 => "BZ",
(26**2 + 26) => "ZZ",
(26**2 + 26 + 1) => "AAA",
(26**3 + 26**2 + 26) => "ZZZ",
(26**3 + 26**2 + 26 + 1) => "AAAA",
);
for my $have (keys %tests) {
my $want = $tests{$have};
is to_letters($have), $want, "to_letters($have) -> $want";
}
for my $negative (0, -1, -100) {
ok !eval { to_letters($negative) }, "negative input $negative";
like $@, qr{^0 and less cannot be converted to letters};
}
for my $decimal (1.1, 2.001) {
ok !eval { to_letters($decimal) }, "decimal input $decimal";
like $@, qr{^Decimals cannot be converted to letters};
}
done_testing;
use Carp;
sub to_letters {
my $number = shift;
croak "0 and less cannot be converted to letters" if $number <= 0;
croak "Decimals cannot be converted to letters" if int $number != $number;
state $BASE = 26;
state $CHAR_BASE = 65;
my @letters;
while( $number > 0 ) {
$number--; # A is 1, not 0
my $shift = $number % $BASE;
unshift @letters, chr( $CHAR_BASE + $shift );
$number = int($number / $BASE);
}
return join '', @letters;
}
常量可能看起来很愚蠢,但现在是 21 世纪,很有可能会考虑其他字符编码。虽然我怀疑 chr( $CHAR_BASE + $shift)
是否会如此整齐。
Perl 已经按字母顺序自动递增,所以实现你想要的最短方法是在循环中利用它。
my $a = 'A';
my $n = $ARGV[0];
for (my $i = 1; $i < $n; $i++) { $a++ }
print $a;
当然,数字越大,循环次数越多,所以对于非常大的数字可能效率不高。
我正在使用一些字母编码,其中输入是 return 各自字母的数字。考虑输入是 3 it return C,对于 5 it E 等等。如果数字大于 26,输出更改为 AA for 27, 28-AB, 29-AC
代码如下:
my $input = <>;
my @a = ("A".."B");
if($input <=26){
my $num1 = $input-1;
say $a[$num1];
}
elsif( $input <= 702 ){
#702 for ZZ
my $mod = $input % 26;
my $div = $input / 26;
my ($letter) = $div =~ /^(\d+)\./;
my $num1 = $div - 1;
my $num2 = $letter - 1;
say $a[$num1]$a[$num2];
}else{
# Here I stuck
# how to code for three or more letter combination?
}
对于三个字母的组合有什么建议吗?
更新:输入的数字不能为零。
我想你需要一个 while 循环。虽然不确定你从哪里得到 351 - 我得到的是 "NN"。 26 * 26 = 676.
例如类似于:
use warnings;
use strict;
my $number = 17577;
my @letters;
while ( $number > 0 ) {
my $part = $number % 26;
#print "$part, $number\n";
$number -= $part;
if ( $number == 26 ) { $number = 0; }
$number /= 26;
#print "$number $part\n";
push @letters,chr(65+$part);
}
print reverse @letters;
我不太了解 Perl,无法在其中写出答案,但这里有一个适用于任何长度的算法:
verify the input value is valid for your purpose
set Number to the input value (for clarity in this answer, or if you need the input value later)
set Output to an empty string
while Number > 25
set Remainder to Number modulo 26 plus 1
set Number to the integer part of Number divided by 26
prepend the character represented by Remainder to Output
end while
if Number is not zero prepend the character represented by Number plus 1 to the Output
我写了一个完整的测试套件,因为我发现这出奇地难以正确。
您正在从 10 进制转换为 26 进制,但由于 1 是 A 而不是 0,所以所有内容都移到 1 之上。尽早处理这个过程(即。$number--
)消除了很多下游错误。
#!/usr/bin/env perl
use v5.12;
use strict;
use warnings;
use Test::More;
my %tests = (
1 => "A",
1.0 => "A",
2 => "B",
25 => "Y",
26 => "Z",
27 => "AA",
52 => "AZ",
54 => "BB",
78 => "BZ",
(26**2 + 26) => "ZZ",
(26**2 + 26 + 1) => "AAA",
(26**3 + 26**2 + 26) => "ZZZ",
(26**3 + 26**2 + 26 + 1) => "AAAA",
);
for my $have (keys %tests) {
my $want = $tests{$have};
is to_letters($have), $want, "to_letters($have) -> $want";
}
for my $negative (0, -1, -100) {
ok !eval { to_letters($negative) }, "negative input $negative";
like $@, qr{^0 and less cannot be converted to letters};
}
for my $decimal (1.1, 2.001) {
ok !eval { to_letters($decimal) }, "decimal input $decimal";
like $@, qr{^Decimals cannot be converted to letters};
}
done_testing;
use Carp;
sub to_letters {
my $number = shift;
croak "0 and less cannot be converted to letters" if $number <= 0;
croak "Decimals cannot be converted to letters" if int $number != $number;
state $BASE = 26;
state $CHAR_BASE = 65;
my @letters;
while( $number > 0 ) {
$number--; # A is 1, not 0
my $shift = $number % $BASE;
unshift @letters, chr( $CHAR_BASE + $shift );
$number = int($number / $BASE);
}
return join '', @letters;
}
常量可能看起来很愚蠢,但现在是 21 世纪,很有可能会考虑其他字符编码。虽然我怀疑 chr( $CHAR_BASE + $shift)
是否会如此整齐。
Perl 已经按字母顺序自动递增,所以实现你想要的最短方法是在循环中利用它。
my $a = 'A';
my $n = $ARGV[0];
for (my $i = 1; $i < $n; $i++) { $a++ }
print $a;
当然,数字越大,循环次数越多,所以对于非常大的数字可能效率不高。