http://www.perlmonks.org?node_id=142766


in reply to The Perl Review

Looks like a great contender to replace the downtrodden TPJ. Anyone interested in the golf-master position detailed below?
Perl Golf

We have not figured out the rules, chosen the judges, or calculated what your chances of winning really are, but we do have the prizes – Perl Mongers hats or tshirts along with a chance for fame and glory in the next issue of The Perl Review.

Solve the following problem with a ridiculously low number of keystrokes, uses Perl in some clever or devious way, or is otherwise interesting and send it to comdog@panix.com.

    Convert a base 36 number, with the digits [0-9A-Z], to its base 10 representation
If you would like to be a judge, or the maintainer of this column, or have an interesting golf problem, let us know. We can send you a hat or a t-shirt too.
Update: To get it started, here is my first attempt.... 61 chars
#!/usr/bin/perl -wT use strict; my $base36 = shift; $base36 = 10 if !defined $base36; die "invalid input, only 0-9 and A-Z allowed\n" if $base36 !~ /^[0-9A-Z]+\z/; my $dec = base36($base36); print "$base36 => $dec\n"; sub base36 { # 1 2 3 4 5 6 #234567890123456789012345678901234567890123456789012345678901 $%+=$_*36**$?++for reverse map/\d/?$_:ord($_)-55,pop=~/./g;$% }

-Blake

Replies are listed 'Best First'.
Re (tilly) 2: Fore!!! (was The Perl Review)
by tilly (Archbishop) on Feb 01, 2002 at 22:30 UTC
    How about 48?
    sub h{ # 1 2 3 4 #23456789_123456789_123456789_123456789_12345678 ($_,$s)=@_;y/A-Z/:-T/;$s=36*$s-48+ord for/./g;$s }
    PS If you read the problem statement carefully, there is a 1 character answer:
    sub convert_0 { 0 }
    tilly ducks
      The y/// is very sneaky, but why play games with that $s? If you want a 0, see if one of $% $- $? or $[ work for you. Here it is shortened to 43 chars and as an added bonus, its now strict compatible.
      # 1 2 3 4 #23456789_123456789_123456789_123456789_1234 $_=pop;y/A-Z/:-T/;$?=36*$?-48+ord for/./g;$?

      -Blake

        I wrote it as a function.

        The function should be usefully callable multiple times.

        Since you're well past my meagre 59 (from the use.perl thread), I might as well show it:
        $_=shift;y/0-9A-Z/\0-#/;(s/.//,($a*=36)+=ord)while length
        
        Yes, no output-- the game rules were unclear that way, too. Using your tricks I can get down to -- 43.
        $_=pop;y/0-9A-Z/\0-#/;($a*=46)+=ord for/./g
        
        If only the null byte were legal in y///, then the above could become 42...
        -- jhi
        
      Could someone brief me on the y/// syntax? I took a look in man perlre, and tried stepping through it in the debugger - both were futile.

      -jackdied

        y is a function which is explained in perlop. What it does is substitutes for any character in one list, the corresponding charater on another list.

        What I did was use ord and chr to figure out what the ASCII representation of 9 was, and what came right after that. Then I used tr to move the range A-Z so that they came right after the range 0-9, so that I could convert any digit into a number just by taking ord and subtracting off the ord of 0.

Re: Fore!!! (was The Perl Review)
by jynx (Priest) on Feb 02, 2002 at 01:35 UTC

    ok,

    i'm not even a contender for this one, but in the spirit of TMTOWTDI i submit the following 2:

    # 1 (57 characters) $a+=($_-($_|0?0:55))*36**$b++while$_=chop$ARGV[0];print$a # 2 (63 characters) print[map$a+=($_-($_|0?0:55))*36**$b++,reverse pop=~/./g]->[-1]
    jynx

    update: bad jynx! bad, evil, naughty jynx! not testing thoroughly! not golfing thoroughly! *sigh* neither of the above work correctly, i'm currently working on fixing them. *sigh* sorry 'bout that.

    update2: here's both of them:

    # 1 (still 57 characters, with props to petral for the idea) $a+=(-55+/\d/*7+ord)*36**$b++while$_=chop$ARGV[0];print$a # 2 (now 64 characters, with props to blakem for the idea) print[map$a+=(/\d/?$_:-55+ord)*36**$b++,reverse pop=~/./g]->[-1]