Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

to get alphabets using number as input

Tags:

perl

I'm working with some alphabet coding where input is number which returns respective alphabet . Consider input is 3 it return C, for 5 its E and so on. If number is greater than 26 output changes to AA for 27, 28-AB, 29-AC

here is the code:

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?

}

for three letter combination any suggestions?

Update: input number can not be zero.

like image 602
waghso Avatar asked Mar 15 '26 03:03

waghso


1 Answers

I wrote a full test suite because I found this surprisingly hard to get right.

You're converting from base 10 to base 26, but since 1 is A instead of 0, everything is shifted over 1. Dealing with that as early in the process as possible (ie. $number--) eliminates a lot of downstream mistakes.

#!/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;
}

The constants might seem silly, but it's the 21st century and there's a very good chance other character encodings will be a consideration. Although I doubt chr( $CHAR_BASE + $shift) will work out as neatly.

like image 153
Schwern Avatar answered Mar 16 '26 15:03

Schwern



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!