// Convert a signed long integer to English text. (2.00)
// @see dwYRr9
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>
//
// Utility.
//
struct astring {
char first[ 288 ] , * last;
} ;
char * stpcpy_( char * s, const char * t)
{
return s + n;
}
struct astring* astring_append( struct astring* s, const char * t)
{
s-> last = stpcpy_( s-> last, t) ;
return s;
}
//
// Convert.
//
struct astring* textnumber_detail( int n, struct astring* result)
{
static const char * ones[ ] = {
"" ,
"one" ,
"two" ,
"three" ,
"four" ,
"five" ,
"six" ,
"seven" ,
"eight" ,
"nine"
} ;
static const char * teens[ ] = {
"ten" ,
"eleven" ,
"twelve" ,
"thirteen" ,
"fourteen" ,
"fifteen" ,
"sixteen" ,
"seventeen" ,
"eighteen" ,
"nineteen"
} ;
static const char * tens[ ] = {
"" ,
"" ,
"twenty" ,
"thirty" ,
"forty" ,
"fifty" ,
"sixty" ,
"seventy" ,
"eighty" ,
"ninety"
} ;
// Hundreds.
if ( n >= 100 )
{
astring_append( result, ones[ n / 100 % 10 ] ) ;
astring_append( result, " hundred" ) ;
n %= 100 ;
if ( n != 0 )
astring_append( result, " and " ) ;
}
// Tens and ones.
if ( n < 10 )
{
astring_append( result, ones[ n] ) ;
}
else if ( n < 20 )
{
astring_append( result, teens[ n % 10 ] ) ;
}
else
{
astring_append( result, tens[ n / 10 ] ) ;
if ( n % 10 )
{
astring_append( result, "-" ) ;
astring_append( result, ones[ n % 10 ] ) ;
}
}
return result;
}
const char * textnumber( long int n)
{
assert ( n
> LONG_MIN
|| LONG_MIN
+ LONG_MAX
== 0 ) ;
static const char * base[ ] = {
"" ,
" thousand" ,
" million" ,
" billion" ,
" trillion" ,
" quadrillion" ,
" quintillion"
} ;
static _Thread_local struct astring result[ 1 ] ;
result-> last = result-> first;
// Zero.
if ( n == 0 )
{
astring_append( result, "zero" ) ;
return result-> first;
}
// Negative.
if ( n < 0 )
{
astring_append( result, "minus " ) ;
n = - n;
}
// Log base 1000.
long int k = 1 ;
int j = 0 ;
for ( long int i = n; i >= 1000 ; i /= 1000 )
{
j += 1 ;
k *= 1000 ;
}
// Powers of 1000.
for ( int i = j; i >= 0 ; i-- )
{
long int m = n / k % 1000 ;
if ( m != 0 )
{
astring_append( textnumber_detail( m, result) , base[ i] ) ;
if ( n % k != 0 )
astring_append( result, ", " ) ;
else break ;
}
k /= 1000 ;
}
return result-> first;
}
//
// Show.
//
int main( int argc, char * argv[ ] )
{
printf ( "%d\n %s\n \n " , 0 , textnumber
( 0 ) ) ; printf ( "%d\n %s\n \n " , - 1 , textnumber
( - 1 ) ) ; printf ( "%d\n %s\n \n " , 1000000 , textnumber
( 1000000 ) ) ; printf ( "%d\n %s\n \n " , 1000003 , textnumber
( 1000003 ) ) ; printf ( "%d\n %s\n \n " , 1002003 , textnumber
( 1002003 ) ) ; printf ( "%ld\n %s\n \n " , LONG_MAX
, textnumber
( LONG_MAX
) ) ;
for ( int i = 0 ; i < 5 ; i++ )
{
int x
= rand ( ) % 21 - 10 ; printf ( "%d\n %s\n \n " , x
, textnumber
( x
) ) ; }
for ( int i = 0 ; i < 5 ; i++ )
{
int x
= rand ( ) % 201 - 100 ; printf ( "%d\n %s\n \n " , x
, textnumber
( x
) ) ; }
for ( int i = 0 ; i < 5 ; i++ )
{
int x
= rand ( ) % 2001 - 1000 ; printf ( "%d\n %s\n \n " , x
, textnumber
( x
) ) ; }
for ( int i = 0 ; i < 5 ; i++ )
{
printf ( "%d\n %s\n \n " , x
, textnumber
( x
) ) ; }
return 0 ;
}
Ly8gQ29udmVydCBhIHNpZ25lZCBsb25nIGludGVnZXIgdG8gRW5nbGlzaCB0ZXh0LiAoMi4wMCkKLy8gQHNlZSBkd1lScjkKCiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPGxpbWl0cy5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8dGltZS5oPgojaW5jbHVkZSA8YXNzZXJ0Lmg+CgovLwovLyBVdGlsaXR5LgovLwoKc3RydWN0IGFzdHJpbmcgewogICAgY2hhciBmaXJzdFsyODhdLCAqIGxhc3Q7Cn07CgpjaGFyKiBzdHBjcHlfKGNoYXIqIHMsIGNvbnN0IGNoYXIqIHQpCnsKICAgIHNpemVfdCBuID0gc3RybGVuKHQpOwogICAgbWVtY3B5KHMsIHQsIG4gKyAxKTsKICAgIHJldHVybiBzICsgbjsKfQoKc3RydWN0IGFzdHJpbmcqIGFzdHJpbmdfYXBwZW5kKHN0cnVjdCBhc3RyaW5nKiBzLCBjb25zdCBjaGFyKiB0KQp7CiAgICBzLT5sYXN0ID0gc3RwY3B5XyhzLT5sYXN0LCB0KTsKICAgIHJldHVybiBzOwp9CgovLwovLyBDb252ZXJ0LgovLwoKc3RydWN0IGFzdHJpbmcqIHRleHRudW1iZXJfZGV0YWlsKGludCBuLCBzdHJ1Y3QgYXN0cmluZyogcmVzdWx0KQp7CiAgICBhc3NlcnQoMSA8PSBuICYmIG4gPD0gOTk5KTsKCiAgICBzdGF0aWMgY29uc3QgY2hhciogb25lc1tdID0gewogICAgICAgICIiLAogICAgICAgICJvbmUiLAogICAgICAgICJ0d28iLAogICAgICAgICJ0aHJlZSIsCiAgICAgICAgImZvdXIiLAogICAgICAgICJmaXZlIiwKICAgICAgICAic2l4IiwKICAgICAgICAic2V2ZW4iLAogICAgICAgICJlaWdodCIsCiAgICAgICAgIm5pbmUiCiAgICB9OwoKICAgIHN0YXRpYyBjb25zdCBjaGFyKiB0ZWVuc1tdID0gewogICAgICAgICJ0ZW4iLAogICAgICAgICJlbGV2ZW4iLAogICAgICAgICJ0d2VsdmUiLAogICAgICAgICJ0aGlydGVlbiIsCiAgICAgICAgImZvdXJ0ZWVuIiwKICAgICAgICAiZmlmdGVlbiIsCiAgICAgICAgInNpeHRlZW4iLAogICAgICAgICJzZXZlbnRlZW4iLAogICAgICAgICJlaWdodGVlbiIsCiAgICAgICAgIm5pbmV0ZWVuIgogICAgfTsKCiAgICBzdGF0aWMgY29uc3QgY2hhciogdGVuc1tdID0gewogICAgICAgICIiLAogICAgICAgICIiLAogICAgICAgICJ0d2VudHkiLAogICAgICAgICJ0aGlydHkiLAogICAgICAgICJmb3J0eSIsCiAgICAgICAgImZpZnR5IiwKICAgICAgICAic2l4dHkiLAogICAgICAgICJzZXZlbnR5IiwKICAgICAgICAiZWlnaHR5IiwKICAgICAgICAibmluZXR5IgogICAgfTsKCiAgICAvLyBIdW5kcmVkcy4KCiAgICBpZiAobiA+PSAxMDApCiAgICB7CiAgICAgICAgYXN0cmluZ19hcHBlbmQocmVzdWx0LCBvbmVzW24gLyAxMDAgJSAxMF0pOwogICAgICAgIGFzdHJpbmdfYXBwZW5kKHJlc3VsdCwgIiBodW5kcmVkIik7CiAgICAgICAgbiAlPSAxMDA7CiAgICAgICAgaWYgKG4gIT0gMCkKICAgICAgICAgICAgYXN0cmluZ19hcHBlbmQocmVzdWx0LCAiIGFuZCAiKTsKICAgIH0KCiAgICAvLyBUZW5zIGFuZCBvbmVzLgoKICAgIGlmIChuIDwgMTApCiAgICB7CiAgICAgICAgYXN0cmluZ19hcHBlbmQocmVzdWx0LCBvbmVzW25dKTsKICAgIH0KICAgIGVsc2UgaWYgKG4gPCAyMCkKICAgIHsKICAgICAgICBhc3RyaW5nX2FwcGVuZChyZXN1bHQsIHRlZW5zW24gJSAxMF0pOwogICAgfQogICAgZWxzZQogICAgewogICAgICAgIGFzdHJpbmdfYXBwZW5kKHJlc3VsdCwgdGVuc1tuIC8gMTBdKTsKICAgICAgICBpZiAobiAlIDEwKQogICAgICAgIHsKICAgICAgICAgICAgYXN0cmluZ19hcHBlbmQocmVzdWx0LCAiLSIpOwogICAgICAgICAgICBhc3RyaW5nX2FwcGVuZChyZXN1bHQsIG9uZXNbbiAlIDEwXSk7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKfQoKY29uc3QgY2hhciogdGV4dG51bWJlcihsb25nIGludCBuKQp7CiAgICBhc3NlcnQobiA+IExPTkdfTUlOIHx8IExPTkdfTUlOICsgTE9OR19NQVggPT0gMCk7CgogICAgc3RhdGljIGNvbnN0IGNoYXIqIGJhc2VbXSA9IHsKICAgICAgICAiIiwKICAgICAgICAiIHRob3VzYW5kIiwKICAgICAgICAiIG1pbGxpb24iLAogICAgICAgICIgYmlsbGlvbiIsCiAgICAgICAgIiB0cmlsbGlvbiIsCiAgICAgICAgIiBxdWFkcmlsbGlvbiIsCiAgICAgICAgIiBxdWludGlsbGlvbiIKICAgIH07CgogICAgc3RhdGljIF9UaHJlYWRfbG9jYWwgc3RydWN0IGFzdHJpbmcgcmVzdWx0WzFdOwogICAgcmVzdWx0LT5sYXN0ID0gcmVzdWx0LT5maXJzdDsKCiAgICAvLyBaZXJvLgoKICAgIGlmIChuID09IDApCiAgICB7CiAgICAgICAgYXN0cmluZ19hcHBlbmQocmVzdWx0LCAiemVybyIpOwogICAgICAgIHJldHVybiByZXN1bHQtPmZpcnN0OwogICAgfQoKICAgIC8vIE5lZ2F0aXZlLgoKICAgIGlmIChuIDwgMCkKICAgIHsKICAgICAgICBhc3RyaW5nX2FwcGVuZChyZXN1bHQsICJtaW51cyAiKTsKICAgICAgICBuID0gLW47CiAgICB9CgogICAgLy8gTG9nIGJhc2UgMTAwMC4KCiAgICBsb25nIGludCBrID0gMTsKICAgIGludCBqID0gMDsKICAgIGZvciAobG9uZyBpbnQgaSA9IG47IGkgPj0gMTAwMDsgaSAvPSAxMDAwKQogICAgewogICAgICAgIGogKz0gMTsKICAgICAgICBrICo9IDEwMDA7CiAgICB9CgogICAgLy8gUG93ZXJzIG9mIDEwMDAuCgogICAgZm9yIChpbnQgaSA9IGo7IGkgPj0gMDsgaS0tKQogICAgewogICAgICAgIGxvbmcgaW50IG0gPSBuIC8gayAlIDEwMDA7CiAgICAgICAgaWYgKG0gIT0gMCkKICAgICAgICB7CiAgICAgICAgICAgIGFzdHJpbmdfYXBwZW5kKHRleHRudW1iZXJfZGV0YWlsKG0sIHJlc3VsdCksIGJhc2VbaV0pOwogICAgICAgICAgICBpZiAobiAlIGsgIT0gMCkKICAgICAgICAgICAgICAgIGFzdHJpbmdfYXBwZW5kKHJlc3VsdCwgIiwgIik7CiAgICAgICAgICAgIGVsc2UgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGsgLz0gMTAwMDsKICAgIH0KICAgIHJldHVybiByZXN1bHQtPmZpcnN0Owp9CgovLwovLyBTaG93LgovLwoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqIGFyZ3ZbXSkKewogICAgcHJpbnRmKCIlZFxuJXNcblxuIiwgMCwgdGV4dG51bWJlcigwKSk7CiAgICBwcmludGYoIiVkXG4lc1xuXG4iLCAtMSwgdGV4dG51bWJlcigtMSkpOwogICAgcHJpbnRmKCIlZFxuJXNcblxuIiwgMTAwMDAwMCwgdGV4dG51bWJlcigxMDAwMDAwKSk7CiAgICBwcmludGYoIiVkXG4lc1xuXG4iLCAxMDAwMDAzLCB0ZXh0bnVtYmVyKDEwMDAwMDMpKTsKICAgIHByaW50ZigiJWRcbiVzXG5cbiIsIDEwMDIwMDMsIHRleHRudW1iZXIoMTAwMjAwMykpOwogICAgcHJpbnRmKCIlbGRcbiVzXG5cbiIsIExPTkdfTUFYLCB0ZXh0bnVtYmVyKExPTkdfTUFYKSk7CgogICAgc3JhbmQodGltZSgwKSk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDU7IGkrKykKICAgIHsKICAgICAgICBpbnQgeCA9IHJhbmQoKSAlIDIxIC0gMTA7CiAgICAgICAgcHJpbnRmKCIlZFxuJXNcblxuIiwgeCwgdGV4dG51bWJlcih4KSk7CiAgICB9CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDU7IGkrKykKICAgIHsKICAgICAgICBpbnQgeCA9IHJhbmQoKSAlIDIwMSAtIDEwMDsKICAgICAgICBwcmludGYoIiVkXG4lc1xuXG4iLCB4LCB0ZXh0bnVtYmVyKHgpKTsKICAgIH0KICAgIGZvciAoaW50IGkgPSAwOyBpIDwgNTsgaSsrKQogICAgewogICAgICAgIGludCB4ID0gcmFuZCgpICUgMjAwMSAtIDEwMDA7CiAgICAgICAgcHJpbnRmKCIlZFxuJXNcblxuIiwgeCwgdGV4dG51bWJlcih4KSk7CiAgICB9CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDU7IGkrKykKICAgIHsKICAgICAgICBpbnQgeCA9IHJhbmQoKSAtIHJhbmQoKTsKICAgICAgICBwcmludGYoIiVkXG4lc1xuXG4iLCB4LCB0ZXh0bnVtYmVyKHgpKTsKICAgIH0KICAgIHJldHVybiAwOwp9