Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

play with phone numbers & w perl :)

by dominix (Deacon)
on Dec 27, 2003 at 02:18 UTC ( #317151=CUFP: print w/ replies, xml ) Need Help??

I've played around with perl when it was time for me to find a phone number for my company. I know there is plenty|some modules that do such thing, but it was fun and instructive for me to do it whith no module.
you can use it to discover the numbers needed if you want your phone # to be like
1 800 MEATHOME 
just type
 ./script.pl MEATHOME 
and it gives you the right number !
or discover the possible words of your existing number(s) with
 ./script.pl -d=456123 

or completely usefulless guess how to type SMS
 ./script.pl -s=hello_dolly 

readmore to get the code

I know there is some bugs, for instance, it doesn't handle Digits in "SMS message typer" (so please don't mix), because handling digit depend on cellular phone brand. BTW improvement are on the way ...
#!/usr/bin/perl -l use strict; my @telear = ( ["+"], [" "], [ "A", "B", "C" ], [ "D", "E", "F" ], [ "G", "H", "I" ], [ "J", "K", "L" ], [ "M", "N", "O" ], [ "P", "Q", "R", "S" ], [ "T", "U", "V" ], [ "W", "X", "Y", "Z" ] ); my %telealph = ( ( map { $_ => $_ } ( 0 .. 9 ) ), ( map { my $d = $_; map { $_ => $d } @{ $telear[$d] } } ( 0 .. $#telear ) ) ); # big improvement by simonm my @tab = (); sub telecode { my $tocode = uc($_[0]); my $telecode = ""; foreach my $byte ( split //, $tocode ) { $telecode .= $telealph{$byte}; } return $telecode; } sub teledecode { my $tocode = $_[0]; my @telecode = (); my $i = 0; foreach my $byte ( split //, $tocode ) { $telecode[$i] = $telear[$byte]; $i++; } @tab = (); return arrangecode( "", 0, @telecode ); } sub arrangecode { my ( $first, $i, @dat ) = @_; foreach my $j ( @{ $dat[$i] } ) { if ( $i < ( @dat - 1 ) ) { @tab = arrangecode( $first . $j, $i + 1, @dat ); } else { $tab[@tab] = $first . $j; } } return @tab; } sub smstype { my $first = uc($_[0]); # uc() improvement by b10m $first =~ s/_/ /g; my $sms = ""; foreach my $j ( split //, $first ) { my $tou = $telealph{$j}; my $k = scalar( @{ $telear[$tou] } ); for my $i ( 0 .. $k ) { $sms = $sms . "$tou"; if ( $j eq $telear[$tou][$i] ) { $sms = $sms . ", "; last; } } } return $sms; } foreach my $toto (@ARGV) { if ( $toto =~ /-d=(\d+)/ ) { foreach my $tata ( teledecode($1) ) { print $tata} } elsif ( $toto =~ /-s=([a-zA-Z_]+)/ ) { print smstype($1); # typo fixed by b10m (thanks) } else { print telecode($toto); } }
--
dominix

Comment on play with phone numbers & w perl :)
Download Code
Re: play with phone numbers & w perl :)
by simonm (Vicar) on Dec 27, 2003 at 06:31 UTC
    It looks like %telealph and @telear are two different views of the same data. For cases like this, I'd suggest maintaining whichever one is more obvious, and building the other from it:
    my %telealph = ( ( map { $_ => $_ } ( 0 .. 9 ) ), ( map { my $d = $_; map { $_ => $d } @{ $telear[$d] } } ( 0 .. $#t +elear ) );
      that a very cool improvement, thanks, I add it right now to original code so the script become :
      Updates : I've decided to put all enhancement typo-fix and recommendation in the main post, so it is ready to use for new readers
      --
      dominix
Re: play with phone numbers & w perl :)
by b10m (Vicar) on Dec 27, 2003 at 11:48 UTC
    elsif ( $toto =~ /-s=(\w+)/ ) { print smstype($toto); }

    I'm puzzled by the smstype call. Couple of things:

    • Why do you only allow \w chars, when -especially with SMS- digits are used. Think of "l8er" instead of later".
    • You possibly have a typo in "print smstype($toto);". I think you mean "print smstype($1);"?

    Just my € 0.02

    update: /me should remember not to post when just woke up (<strike> added ...)

    update: Mmm, although I'm barely awake (see above), I'd still like to rewrite the smstype sub a lil':

    sub smstype { # Using uc() will allow the user to enter lowercase letters too my $first = uc($_[0]); my $sms; my $i = 0; foreach my $j ( split //, $first ) { $sms .= $telealph{$j}; # Make sure we get a comma between digits, but not at the end $sms .= ", " if (++$i < length($first)); } return $sms; }

    Now the output of "./script.pl -s=B10M" will look like "2, 1, 0, 6", rather than "22, 11006,"

    update: I just realize that you probably do want "22" for a "B", for you have to punch the 2 button twice on your phone. Nevermind, I'll go back to sleep and come back when awake ...

    --
    b10m
      thanks, you're right for the typo ($toto instead of $1) and you were clever for the use of uc() to allow lowercase to be used, but the purpose of smstype is to tell us how do we have to type digit on cellular keypad to produce words (as SMS), and for instance it dont handle digit (as mentioned) because every brand of celular phone I've seen here have different view of the alphabet :-(
      --
      dominix
Re: play with phone numbers & w perl :)
by CharlesClarkson (Curate) on Dec 28, 2003 at 03:56 UTC

    First, bravo on the code. I really suck at writing recursive subs. I didn't intend to rewrite your code. I was just trying to rid it of global variables. Please don't take offense.

    I don't like the idea of using @tab as a global. IMO, it would be better to use it as a private variable instead.

    { my @tab; sub teledecode { my $tocode = $_[0]; my @telecode = (); my $i = 0; foreach my $byte ( split //, $tocode ) { $telecode[$i] = $telear[$byte]; $i++; } @tab = (); return arrangecode( "", 0, @telecode ); } sub arrangecode { my ( $first, $i, @dat ) = @_; foreach my $j ( @{ $dat[$i] } ) { if ( $i < ( @dat - 1 ) ) { @tab = arrangecode( $first . $j, $i + 1, @dat ); } # I thnk it is faster written as # push @tab, $first . $j; else { $tab[@tab] = $first . $j; } } return @tab; } }

    Now teledecode() is not using @tab globally, but @telear is still a global. We could suck it into this scope, but it is used to make %telealph. It would be nicer if we could condence teledecode() to one line. What if we use an array slice ...

    sub teledecode { @tab = (); return arrangecode( '', 0, @telear[ split //, $_[0] ] ); }

    Now we could move this array slice outside the sub.

    foreach my $toto (@ARGV) { if ( $toto =~ /-d=(\d+)/ ) { # Perhaps a description of what that slice # is doing would help the code maintainer :) print foreach teledecode( @telear[ split //, $1 ] ); } elsif ( $toto =~ /-s=([a-zA-Z_]+)/ ) { print smstype($1); # typo fixed by b10m (thanks) } else { print telecode($toto); } } { my @tab; sub teledecode { @tab = (); return arrangecode( '', 0, @_ ); } sub arrangecode { my ( $first, $i, @dat ) = @_; foreach my $j ( @{ $dat[$i] } ) { if ( $i < ( @dat - 1 ) ) { @tab = arrangecode( $first . $j, $i + 1, @dat ); } else { push @tab, $first . $j; } } return @tab; } }

    We could use a hash slice in place of telecode() as well. Removing the last global variable.

    else { # This slice should probably explained. print join '', @telealph{ split //, uc( $toto ) }; }
    HTH,
    Charles

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://317151]
Approved by Mr. Muskrat
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (8)
As of 2014-11-26 20:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (173 votes), past polls