alphanumeric counter - howto?

Discussion in 'Perl Misc' started by Oliver Bleckmann, Nov 11, 2005.

  1. Hi,
    I need an alphanumeric counter, which counts from 000000 to ZZZZZZ.
    Is there an easy way to do this?

    Thanks.

    PS: Can perl calculate with alphanumeric numbers?
    Oliver Bleckmann, Nov 11, 2005
    #1
    1. Advertising

  2. Oliver Bleckmann

    Brian Wakem Guest

    Brian Wakem, Nov 11, 2005
    #2
    1. Advertising

  3. Oliver Bleckmann

    Paul Lalli Guest

    Oliver Bleckmann wrote:
    > Hi,
    > I need an alphanumeric counter, which counts from 000000 to ZZZZZZ.
    > Is there an easy way to do this?


    I found this module on CPAN:
    http://search.cpan.org/src/RHENSSEL/Math-Base36-0.02/Base36.pm

    However, it seems to have a very odd bug, in that it strips off the
    first 'digit' from the encoded string. If you view the source, and
    change decode_base36's last line from:
    return(substr($t,1));
    to:
    return $t;

    The module seems to start working correctly (it still fails its fifth
    and final test, but I haven't analyzed why yet. After that change, the
    following program should do what you want:

    #!/usr/bin/perl
    use strict;
    use warnings;
    use Math::Base36 qw/:all/;

    for my $i (0..decode_base36('ZZZZZZ')){
    print encode_base36($i), "\n";
    }

    __END__

    (After further analysis, I will be attempting to contact the author and
    submit a patch for this module...)
    Paul Lalli, Nov 11, 2005
    #3
  4. Oliver Bleckmann

    Brian Wakem Guest

    Paul Lalli wrote:

    > Oliver Bleckmann wrote:
    >> Hi,
    >> I need an alphanumeric counter, which counts from 000000 to ZZZZZZ.
    >> Is there an easy way to do this?

    >
    > I found this module on CPAN:
    > http://search.cpan.org/src/RHENSSEL/Math-Base36-0.02/Base36.pm
    >
    > However, it seems to have a very odd bug, in that it strips off the
    > first 'digit' from the encoded string. If you view the source, and
    > change decode_base36's last line from:
    > return(substr($t,1));
    > to:
    > return $t;



    Quite bizarre. You've got to think he did that for a reason, you can't
    accidentally type (substr($t,1)) instead if $t, but as you say, it appears
    to be a bug.



    --
    Brian Wakem
    Email: http://homepage.ntlworld.com/b.wakem/myemail.png
    Brian Wakem, Nov 11, 2005
    #4
  5. Oliver Bleckmann

    Paul Lalli Guest

    Brian Wakem wrote:
    > Paul Lalli wrote:
    >
    > > I found this module on CPAN:
    > > http://search.cpan.org/src/RHENSSEL/Math-Base36-0.02/Base36.pm
    > >
    > > However, it seems to have a very odd bug, in that it strips off the
    > > first 'digit' from the encoded string. If you view the source, and
    > > change decode_base36's last line from:
    > > return(substr($t,1));
    > > to:
    > > return $t;

    >
    >
    > Quite bizarre. You've got to think he did that for a reason, you can't
    > accidentally type (substr($t,1)) instead if $t, but as you say, it appears
    > to be a bug.
    >


    Agreed. I wish the author had included more comments in the code to
    explain his/her line of thought. What confuses me more, however is
    this: http://testers.cpan.org/show/Math-Base36.html#Math-Base36-0.02
    Very few of the testers actually recorded failures. Now, when I
    installed the package, although `make test` did show "not ok" for
    tests 3-5, this did not hault the installation process (I don't
    understand enough about the inner workings of CPAN.pm or the Test
    suites to understand why). I wonder if the testers simply saw the end
    result that the module installed, without noticing that 3 of the 5
    tests failed.

    Paul Lalli
    Paul Lalli, Nov 11, 2005
    #5
  6. Oliver Bleckmann

    Guest

    > Oliver Bleckmann wrote:
    > >
    > > I need an alphanumeric counter, which counts from 000000 to ZZZZZZ.
    > > Is there an easy way to do this?


    Paul Lalli replied:
    >
    > I found this module on CPAN:
    > http://search.cpan.org/src/RHENSSEL/Math-Base36-0.02/Base36.pm
    >
    > However, it seems to have a very odd bug, in that it strips off the
    > first 'digit' from the encoded string.



    Maybe I'm missing something obvious here, but when I look in the
    code, I see the line:

    my $_digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWZYX';

    Is there any reason why the letters 'X' and 'Z' are swapped? The way
    the letters are arranged now would make YYYYYY and XXXXXX bigger than
    ZZZZZZ, which is not what the original poster wanted.

    -- Jean-Luc
    , Nov 11, 2005
    #6
  7. Oliver Bleckmann wrote:

    > I need an alphanumeric counter, which counts from 000000 to ZZZZZZ.
    > Is there an easy way to do this?


    There is no built-in way to get a base 36 counter. Perl's builtin
    string counter mechanism will count from 000000 to 999999 or from
    AAAAAA to ZZZZZZ. (i.e. base 10 or 26).

    > PS: Can perl calculate with alphanumeric numbers?


    You mean numbers in base 36?

    Numbers are conceptually just numbers (or if you prefer numbers base
    2). It's only when you come to convert them to/from strings that they
    can be said have some other base (typically 8,10 or 16).

    AFAIK there's no built-in way for perl to convert a number to string
    representation in base 2,8,10 or 16.

    Perhaps you should look on CPAN for modules with "Base36" in their name.
    Brian McCauley, Nov 11, 2005
    #7
  8. Oliver Bleckmann

    Paul Lalli Guest

    wrote:
    > Paul Lalli replied:
    > >
    > > I found this module on CPAN:
    > > http://search.cpan.org/src/RHENSSEL/Math-Base36-0.02/Base36.pm
    > >
    > > However, it seems to have a very odd bug, in that it strips off the
    > > first 'digit' from the encoded string.

    >
    >
    > Maybe I'm missing something obvious here, but when I look in the
    > code, I see the line:
    >
    > my $_digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWZYX';
    >
    > Is there any reason why the letters 'X' and 'Z' are swapped? The way
    > the letters are arranged now would make YYYYYY and XXXXXX bigger than
    > ZZZZZZ, which is not what the original poster wanted.


    I have no idea why they're swapped either, but this oddness does not
    affect the functionality of the module. the $_digits string is used
    soley to determine whether or not the characters in the to-be-encoded
    string are valid base-36 digits. The ordering is irrelevant. The
    actual values of the base-36 digits are computed by subtracting 55 from
    the ordinal value of the character in question.

    Paul Lalli
    Paul Lalli, Nov 11, 2005
    #8
  9. Brian McCauley wrote:
    > Oliver Bleckmann wrote:
    >
    > > I need an alphanumeric counter, which counts from 000000 to ZZZZZZ.
    > > Is there an easy way to do this?

    >
    > There is no built-in way to get a base 36 counter. Perl's builtin
    > string counter mechanism will count from 000000 to 999999 or from
    > AAAAAA to ZZZZZZ. (i.e. base 10 or 26).
    >
    > > PS: Can perl calculate with alphanumeric numbers?

    >
    > You mean numbers in base 36?
    >
    > Numbers are conceptually just numbers (or if you prefer numbers base
    > 2). It's only when you come to convert them to/from strings that they
    > can be said have some other base (typically 8,10 or 16).
    >
    > AFAIK there's no built-in way for perl to convert a number to string
    > representation in base 2,


    sprintf("%b",$_)

    > 8,


    sprintf("%o",$_)

    > 10,


    sprintf("%d",$_) # $_ + 0 would do the same thing.

    > or 16


    sprintf("%x",$_)

    > Perhaps you should look on CPAN for modules with "Base36" in their name.
    Chris Johnson, Nov 11, 2005
    #9
  10. Brian McCauley wrote:

    > AFAIK there's no built-in way for perl to convert a number to string
    > representation in base 2,8,10 or 16.


    That should, of course, read "...other than in base...".
    Brian McCauley, Nov 11, 2005
    #10
  11. Oliver Bleckmann

    Jeff Guest

    Paul Lalli wrote:
    > Agreed. I wish the author had included more comments in the code to
    > explain his/her line of thought.


    I thought it was mandatory that authors remove any useful comments from code before
    publishing to CPAN. I've had my head in a few CPAN modules recently, and I can't find a
    useful comment anywhere!

    ~Jeff
    Jeff, Nov 12, 2005
    #11
  12. Oliver Bleckmann

    Dr.Ruud Guest

    Brian McCauley:

    > Perl's builtin
    > string counter mechanism will count from 000000 to 999999 or from
    > AAAAAA to ZZZZZZ. (i.e. base 10 or 26).


    Or from A00000 to ZZZZZZ?

    BTW that also explains the substr(1,

    --
    Affijn, Ruud

    "Gewoon is een tijger."
    Dr.Ruud, Nov 12, 2005
    #12
  13. Oliver Bleckmann

    Dr.Ruud Guest

    Dr.Ruud:
    > Brian McCauley:


    >> Perl's builtin
    >> string counter mechanism will count from 000000 to 999999 or from
    >> AAAAAA to ZZZZZZ. (i.e. base 10 or 26).

    >
    > Or from A00000 to ZZZZZZ?
    >
    > BTW that also explains the substr(1,


    Oops:

    $ perl -e '$a = "A99"; $a++; print "$a\n"'
    B00

    (so not AA0)

    --
    Affijn, Ruud

    "Gewoon is een tijger."
    Dr.Ruud, Nov 12, 2005
    #13
  14. "Dr.Ruud" <> schrieb im Newsbeitrag
    news:...
    > $ perl -e '$a = "A99"; $a++; print "$a\n"'
    > B00


    This ist strange, but I cannot use it for a counter...
    Oliver Bleckmann, Nov 12, 2005
    #14
  15. ok, i did it myself.
    now this is my solution...

    sub base36
    {
    my ($num) = @_;
    use integer;
    my @chars = ('0'..'9', 'A'..'Z');
    my $result = "";
    for(my $b=@chars; $num; $num/=$b)
    {
    $result .= $chars[$num % $b];
    }
    return scalar reverse $result;
    }

    for ($i = 0; $i <= 2000; $i++ )
    {
    $tmp = base36($i);
    for ( $c = length($tmp); $c < 6; $c++ )
    {
    $tmp = "0" . "$tmp";
    }
    print "$tmp\n";
    }
    Oliver Bleckmann, Nov 12, 2005
    #15
  16. Oliver Bleckmann

    Dr.Ruud Guest

    Oliver Bleckmann:

    > sub base36
    > {
    > my ($num) = @_;
    > use integer;
    > my @chars = ('0'..'9', 'A'..'Z');
    > my $result = "";
    > for(my $b=@chars; $num; $num/=$b)
    > {
    > $result .= $chars[$num % $b];
    > }
    > return scalar reverse $result;
    > }



    Variant:

    #!/usr/bin/perl
    use strict; use warnings;

    use constant Chars => ('0'..'9', 'A'..'Z', 'a'..'z');
    use constant MaxBase => scalar Chars;

    { local ($,, $\) = ("\t", "\n");

    for (my $i = 0; $i != 30; $i++) {
    print $i, int2base($i, 16, 4);
    }
    }

    sub int2base {
    use integer;

    my ($ret, $num, $base, $minlen) = ('', @_);
    return undef if $num < 0
    || ($base ||= 10) < 2
    || MaxBase < $base
    || ($minlen ||= 1) < 1;

    for (; $num; $num /= $base) {
    $ret .= (Chars)[$num % $base];
    }
    return scalar reverse $ret . '0'x($minlen - length($ret));
    }

    --
    Affijn, Ruud

    "Gewoon is een tijger."
    Dr.Ruud, Nov 13, 2005
    #16
  17. "Dr.Ruud" <> wrote in news:dl7o6h.1h4.1
    @news.isolution.nl:

    > return undef if $num < 0
    > || ($base ||= 10) < 2
    > || MaxBase < $base
    > || ($minlen ||= 1) < 1;


    You should use a plain return here rather than returning undef. Otherwise,
    in list context, the sub will return a non-empty list with one element,
    foiling conditionals.

    Sinan

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
    A. Sinan Unur, Nov 13, 2005
    #17
  18. Oliver Bleckmann

    Dr.Ruud Guest

    A. Sinan Unur schreef:
    > Dr.Ruud:


    >> return undef if $num < 0
    >> || ($base ||= 10) < 2
    >> || MaxBase < $base
    >> || ($minlen ||= 1) < 1;

    >
    > You should use a plain return here rather than returning undef.
    > Otherwise, in list context, the sub will return a non-empty list with
    > one element, foiling conditionals.


    Yes, thanks. I actually had read about it not too long ago...

    --
    Affijn, Ruud

    "Gewoon is een tijger."
    Dr.Ruud, Nov 13, 2005
    #18
  19. Oliver Bleckmann

    Brad Baxter Guest

    Dr.Ruud wrote:
    > #!/usr/bin/perl
    > use strict; use warnings;
    >
    > use constant Chars => ('0'..'9', 'A'..'Z', 'a'..'z');
    > use constant MaxBase => scalar Chars;
    >
    > { local ($,, $\) = ("\t", "\n");
    >
    > for (my $i = 0; $i != 30; $i++) {
    > print $i, int2base($i, 16, 4);
    > }
    > }
    >
    > sub int2base {
    > use integer;
    >
    > my ($ret, $num, $base, $minlen) = ('', @_);
    > return undef if $num < 0
    > || ($base ||= 10) < 2
    > || MaxBase < $base
    > || ($minlen ||= 1) < 1;
    >
    > for (; $num; $num /= $base) {
    > $ret .= (Chars)[$num % $base];
    > }
    > return scalar reverse $ret . '0'x($minlen - length($ret));
    > }


    I assume you left this as an excercise for the reader?

    use constant Charstr => join '', Chars;
    sub base2int {
    use integer;

    my ($ret, $num, $base) = (0, @_);
    return if $num !~ /^[${\Charstr}]+$/o
    || ($base ||= 10) < 2
    || MaxBase < $base;

    for( my $i = length($num)-1, my $c = 0; $i >= 0; --$i ) {
    $ret += index(Charstr, substr($num, $i, 1)) * $base**$c++;
    }
    return $ret;
    }

    --
    Brad
    ps: If you care, please pardon the use of google groups.
    I'm still exploring options since my employer dropped
    most newsgroups.
    Brad Baxter, Nov 15, 2005
    #19
  20. Brad Baxter wrote:
    > Dr.Ruud wrote:
    >>#!/usr/bin/perl
    >>use strict; use warnings;
    >>
    >>use constant Chars => ('0'..'9', 'A'..'Z', 'a'..'z');
    >>use constant MaxBase => scalar Chars;
    >>
    >>{ local ($,, $\) = ("\t", "\n");
    >>
    >> for (my $i = 0; $i != 30; $i++) {
    >> print $i, int2base($i, 16, 4);
    >> }
    >>}
    >>
    >>sub int2base {
    >> use integer;
    >>
    >> my ($ret, $num, $base, $minlen) = ('', @_);
    >> return undef if $num < 0
    >> || ($base ||= 10) < 2
    >> || MaxBase < $base
    >> || ($minlen ||= 1) < 1;
    >>
    >> for (; $num; $num /= $base) {
    >> $ret .= (Chars)[$num % $base];
    >> }
    >> return scalar reverse $ret . '0'x($minlen - length($ret));
    >>}

    >
    > I assume you left this as an excercise for the reader?
    >
    > use constant Charstr => join '', Chars;
    > sub base2int {
    > use integer;
    >
    > my ($ret, $num, $base) = (0, @_);
    > return if $num !~ /^[${\Charstr}]+$/o
    > || ($base ||= 10) < 2
    > || MaxBase < $base;
    >
    > for( my $i = length($num)-1, my $c = 0; $i >= 0; --$i ) {
    > $ret += index(Charstr, substr($num, $i, 1)) * $base**$c++;
    > }
    > return $ret;
    > }


    And don't forget POSIX::strtol and POSIX::strtoul.

    $ perl -MPOSIX -le'print strtoul "ZZ", 36'
    12950



    John
    --
    use Perl;
    program
    fulfillment
    John W. Krahn, Nov 15, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. VB Programmer

    Check if var is alphanumeric?

    VB Programmer, Nov 16, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    566
    bruce barker
    Nov 16, 2004
  2. The Eeediot
    Replies:
    3
    Views:
    2,213
    =?Utf-8?B?UnVsaW4gSG9uZw==?=
    Dec 22, 2004
  3. Steven J Sobol
    Replies:
    8
    Views:
    5,647
    Thomas Weidenfeller
    Apr 30, 2004
  4. Paul
    Replies:
    1
    Views:
    13,160
    Rogan Dawes
    Sep 14, 2004
  5. George2
    Replies:
    1
    Views:
    781
    Alf P. Steinbach
    Jan 31, 2008
Loading...

Share This Page