Admittedly, "Phonobulize" is a word I created, but I think it's cooler than saying "numerize". And appropriate too.

My Inspiration:My phone number sucks. No mathematical reason or rhyme to it... but what if I could tell people to call me at: how-cool rather than 469-2665. (It's not my real phone number)

The challenge:A script that takes up to 10 digits as input, and outputs to a file containing all possible "phonobulized" conversions.

The Rules:0 and 1 on the phone keypad are to equal 0 and 1, respectively. For all the other digits, there are three possible letter values as defined by your phone's keypad. All possible combinations must be outputted: That's the main reason I limited input to 10 digits. To much more than that and the output flows in astounding quantity.

I want a full report on how that rediculously efficient code works, because I understand about 10 percent of it. And I want to know how long it took you to figure that out. Then if I don't like the answers you give me, I'm going to cry like a little baby until my wife bars me from visiting this website.

After running your code, and wonderful code it is, I realized that you have made a fatal mistake! You have yet to pass the Phonobulizer quiz, because your code returns letters that are missing from an actual phone key pad. Atleast from my keypad... is the "Q" on phones in Germany? Also: where is the "Y" when I use the number 9? I disovered this while useing the number 7448 as input, and it didn't return one of my favorite dirty words that start with an "s". Now, you will more than likely fix this w/ minor modification. But then you will truly be phonobulizing.

Next, I'm going to give the subroutine a cool name (although I personally find the underscore is really cool as a subroutine name) and replace the ?: section by an if/else section, just to make it even more readable:

Now, one can almost immediately see that this is a recursive algorithm. It's started in the last line by calling phone() with an empty string and all digits entered by the user. <> reads in one line and the regular expression transforms that line into a list containing all digits. The heart of that algorithm is obviously the phone() subroutine. In that subroutine, $a is always the string that is assembled to contain the phonobulized version of the phone number. In the first call, $a will be the empty string and $_ will be the first of the digits:

Depending on whether the first digit is less than 2 or not, two different blocks need to be executed. In case of a 0 or 1, we only need to add the digit to the string and enter the next recursion level by calling the phone() subroutine again with the new string and all remaining digits. (Remember we shifted the string and the first digit off @_, so it holds all remaining digits.) But if the first digit is 2 or greater, we need to replace it by three consecutive letters. Fortunately enough, the characters are sorted in the ASCII set, and since the lowercase letters start at 97 (a) and our digit ($_) is at least 2, the three letters of interest start at (91+3*$_). We now call phone() again recursively from within a loop over the ASCII values of the three letters. The new string passed to the next recursion level is a concatenation of the old string and the character that corresponds to the current ASCII code stored in $_, which is the default argument to the chr function. Now, when does the recursion stop? As we've seen, with each level of recursion there's one digit shifted off the list. So at a certain level, there's no more digits and thus $_ will become undef. That's when the following line becomes interesting:

Code

defined || return print "$a\n";

Since $_ is also the default argument to defined, the return statement will be executed when we've run out of digits. But before returning from the subroutine, we have to print out the string we've assembled, and this string is still stored in $a. As we don't call phone(), the recursion has reached its end.

If you're familiar with recursion, this shouln't be too hard to understand. If you're not it may be, uh, quite hard.

To answer your other questions: I read your post shortly after I got up. Then I went shopping with my mom and that's where I made up most of the algorithm. It was clear to me from the beginning that it had to be recursive. I also had the idea of using $_=3*$_+91 to get the letters corresponding to a digit while being in town. Back home, coding those ideas took about 15 minutes and compressing the code took another 15 minutes. So, considering that I spent a total of 30 minutes thinking about the solution, you can say that it took me about an hour to come up with the above code.

I'm pretty sure there's still room for improvements. I'd guess about 120 characters should be possible. However, I hope you find the above explanations helpful and I also hope you won't be crying to much as you'll see that there's really nothing special about the code.

Hey Marcus, I didn't really mean it when I said you suck. I feel bad now...

Thanks for breaking it all down for me, I really like learning the stuff that boggles me. And your stuff does boggle me. What a wonderful thing: I'm learning so much from this forum. I'm putting it on my Resume.

As far as forgetting the "Q" and "Y" thing, it's really not the point of the challenge anyway... just a small technicality. You figured out the recursion and that was (for me) the real challenge.

Well, I don't know that there is an ANSI standard supplied to phone manufacturers on what letters go on what numbers in America, but on the phone I was sitting next too when I coded mine, the mapping was what you saw in my HoA attachment on the first post.

Personally I think the German phones make more sense... why exclude a letter if you don't really have too?

I don't know if all US phones omit those two letters: Q and Z I'll do a little survey to find out...