7

I am solving a problem in which a positive integer is given and i have to display it in words.

For example if a number is 2134 the output should be "two one three four" . If i use the modulus operator and use the recursion technique, i get the digits starting from the least significant digit i.e "four three one two"

I can also reverse the number and then use modulus operator but i am looking for a better method.

What can be a better approach of solving this problem?.What concept am i missing?

poorvank
  • 7,524
  • 19
  • 60
  • 102
  • manipulating an integer using its base 10 representation is roughly equivalent to treating it as a character string, so using itoa or an equivalent function might be a good starting point. – SirDarius Jun 06 '13 at 16:15
  • No, you're not missing anything. There's no such thing as the "first" digit of a number, because there are an infinite number of 0 digits on the left. The only way to convert a number to digits is right-to-left, just like atoi() does it. You just have to reverse them afterward. – Lee Daniel Crocker Jun 06 '13 at 16:34
  • 3
    If you have a working recursive solution, the only thing left to do is move your print statement to after the recursion. – AShelly Jun 06 '13 at 16:34
  • 1
    Check out the answer by abelenky, it's a clean example of how to do it with recursion. There's a very important lesson hidden in this problem. Recursion can be used to do things in "stack" or "queue" order depending on their precise ordering. In lay terms, "stack" usually means, "things happen backwards" and "queue" usually comes out as "things happen forwards." – Kennet Belenky Jun 06 '13 at 17:27
  • @LeeDanielCrocker: "The only way to convert a number to digits is right-to-left," Flat out **wrong**. See my answer. – abelenky Jun 06 '13 at 18:24
  • You ARE doing it right-to-left! You recurse before the printf(), so the digits get built with your mod operation from right to left as the stack unwinds. You're just using the stack to do the reversing instead of an array. – Lee Daniel Crocker Jun 06 '13 at 18:41
  • But in the big picture you're right that there IS a way to do it left-to-right, but it requires calculating base-10 logarithms, which is overkill. – Lee Daniel Crocker Jun 06 '13 at 18:46

5 Answers5

5

My simple answer:

void printNum(int x)
{
    static const char * const num[] = {
        "zero ", "one ", "two "  , "three ", "four ",
        "five ", "six ", "seven ", "eight ", "nine "
    };

    if (x < 10) {
        printf(num[x]);
        return;
    }
    printNum(x / 10);
    printNum(x % 10);
}

edit

After some more experimenting and tweaking, I came up with this version. I think this is the about the most "pure" recursive function I can make.

void printNum(int x)
{
    static const char * const num[] = {"zero ",  "one ", "two ", "three ",
                                       "four ",  "five ", "six ", "seven ",
                                       "eight ", "nine "};
    (x < 10)? printf(num[x]) : (printNum(x / 10), printNum(x % 10));
}
abelenky
  • 63,815
  • 23
  • 109
  • 159
  • 2
    Nice recursion, but it prints nothing with x as 0 input. If you want to print "zero" when x is 0, recommend 2 lines change to `if (x == 0) { printf(num[0]); return; }` `if (x >= 10) printNum(x / 10);` (Maybe type `unsigned` to avoid x < 0 problems.) – chux - Reinstate Monica Jun 06 '13 at 18:39
  • @chux: Updated to properly print zero. Slightly different than how you suggested. – abelenky Jun 06 '13 at 21:50
  • 1
    Why do you need the modulo? if `x<10`, can't you just print `num[x]`? (If `x<0`, you already are in a problem...) – asaelr Jun 06 '13 at 21:55
  • Your edit `if (x < 10) { printf(num[x%10]);...` is a clearer improvement than my suggestion. – chux - Reinstate Monica Jun 06 '13 at 22:07
2

In case you're looking for recursive solution:

void num2word(int n) {
    if (n / 10 == 0) {
        // print the word for n
    }
    else {
        num2word(n / 10);
        // print the word for n % 10
    }
}
Ye Liu
  • 8,946
  • 1
  • 38
  • 34
2

Going for a pure math answer, because I think that's what you're looking for:

#include <math.h>
#include <stdio.h>

main() {
    long long mynum = 2987612345;
    long long firstDigitValue;
    int       firstDigit;
    char *names[] = { "zero", "one", "two", "three", "four", "five",
                      "six", "seven", "eight", "nine" };

    while (mynum > 0) {
        firstDigit = (int) (mynum/pow(10,(int)log10(mynum)));
        firstDigitValue = firstDigit * pow(10,(int)log10(mynum));
        mynum -= firstDigitValue;
        printf("%s ", names[firstDigit]); 
    }
    printf("\n");
}

And then running it produces:

two nine eight seven six one two three four five 

It should work with any size number that a long long can handle (in other languages, or with a big number library in C, it can handle something arbitrarily large).

Now... I'm not sure the use of log10 and pow is the fastest. But it's the most fun :-)

Wes Hardaker
  • 21,735
  • 2
  • 38
  • 69
1

If it is a null terminated char *, then why not just do this:

int i = 0;
while(char[i] != null){
    switch(char[i]):

         case '1': printf("One "); break;
         ....
         i++;

}

if its not a char *, turn it into one with char * temp = itoa(number);

KrisSodroski
  • 2,796
  • 3
  • 24
  • 39
  • I dont think he is given a char[], I think he is given an int. – David says Reinstate Monica Jun 06 '13 at 16:14
  • 1
    You are correct! But is it necessary to convert it into an array i was basically looking for a method of extracting digits from the int value without converting it into an array! – poorvank Jun 06 '13 at 16:17
  • 1
    @poorvankbhatia just look at open-source implementations of itoa, they detect each digit, all you will have to modify is the mapping between each digit and its representation. – SirDarius Jun 06 '13 at 16:19
1
1234 / 1000 => 1
1234 % 1000 => 234     234 / 100 => 2
1234 % 100  => 34      34  / 10  => 3
1234 % 10   => 4

You can pretty easely build a loop around that, but you may go even easer with itoa, sprintf, and std::to_string.

oblitum
  • 11,380
  • 6
  • 54
  • 120