// Convert a signed long integer to English text. (2.01)
// @see dwYRr9
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <time.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_lower( 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"
} ;
int hundred = n / 100 % 10 ;
int ten = n / 10 % 10 ;
int one = n % 10 ;
if ( hundred)
{
astring_append( result, ones[ hundred] ) ;
astring_append( result, " hundred" ) ;
if ( ten || one)
astring_append( result, " and " ) ;
}
if ( ten == 0 )
{
astring_append( result, ones[ one] ) ;
}
else if ( ten == 1 )
{
astring_append( result, teens[ one] ) ;
}
else
{
astring_append( result, tens[ ten] ) ;
if ( one)
{
astring_append( result, "-" ) ;
astring_append( result, ones[ one] ) ;
}
}
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;
if ( n == 0 )
{
astring_append( result, "zero" ) ;
return result-> first;
}
if ( n < 0 )
{
astring_append( result, "minus " ) ;
n = - n;
}
const long int k = 1000 ;
long int k_to_j = 1 ;
int j = 0 ;
for ( long int i = n; i >= k; i /= k)
{
k_to_j *= k;
j += 1 ;
}
for ( ; j >= 0 ; j-- )
{
long int m = n / k_to_j % k;
if ( m != 0 )
{
astring_append( textnumber_lower( m, result) , base[ j] ) ;
if ( n % k_to_j != 0 )
astring_append( result, ", " ) ;
else break ;
}
k_to_j /= k;
}
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 ;
}
Ly8gQ29udmVydCBhIHNpZ25lZCBsb25nIGludGVnZXIgdG8gRW5nbGlzaCB0ZXh0LiAoMi4wMSkKLy8gQHNlZSBkd1lScjkKCiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPGxpbWl0cy5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxhc3NlcnQuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDx0aW1lLmg+CgovLwovLyBVdGlsaXR5LgovLwoKc3RydWN0IGFzdHJpbmcgewogICAgY2hhciBmaXJzdFsyODhdLCAqIGxhc3Q7Cn07CgpjaGFyKiBzdHBjcHlfKGNoYXIqIHMsIGNvbnN0IGNoYXIqIHQpCnsKICAgIHNpemVfdCBuID0gc3RybGVuKHQpOwogICAgbWVtY3B5KHMsIHQsIG4gKyAxKTsKICAgIHJldHVybiBzICsgbjsKfQoKc3RydWN0IGFzdHJpbmcqIGFzdHJpbmdfYXBwZW5kKHN0cnVjdCBhc3RyaW5nKiBzLCBjb25zdCBjaGFyKiB0KQp7CiAgICBzLT5sYXN0ID0gc3RwY3B5XyhzLT5sYXN0LCB0KTsKICAgIHJldHVybiBzOwp9CgovLwovLyBDb252ZXJ0LgovLwoKc3RydWN0IGFzdHJpbmcqIHRleHRudW1iZXJfbG93ZXIoaW50IG4sIHN0cnVjdCBhc3RyaW5nKiByZXN1bHQpCnsKICAgIGFzc2VydCgxIDw9IG4gJiYgbiA8PSA5OTkpOwoKICAgIHN0YXRpYyBjb25zdCBjaGFyKiBvbmVzW10gPSB7CiAgICAgICAgIiIsCiAgICAgICAgIm9uZSIsCiAgICAgICAgInR3byIsCiAgICAgICAgInRocmVlIiwKICAgICAgICAiZm91ciIsCiAgICAgICAgImZpdmUiLAogICAgICAgICJzaXgiLAogICAgICAgICJzZXZlbiIsCiAgICAgICAgImVpZ2h0IiwKICAgICAgICAibmluZSIKICAgIH07CgogICAgc3RhdGljIGNvbnN0IGNoYXIqIHRlZW5zW10gPSB7CiAgICAgICAgInRlbiIsCiAgICAgICAgImVsZXZlbiIsCiAgICAgICAgInR3ZWx2ZSIsCiAgICAgICAgInRoaXJ0ZWVuIiwKICAgICAgICAiZm91cnRlZW4iLAogICAgICAgICJmaWZ0ZWVuIiwKICAgICAgICAic2l4dGVlbiIsCiAgICAgICAgInNldmVudGVlbiIsCiAgICAgICAgImVpZ2h0ZWVuIiwKICAgICAgICAibmluZXRlZW4iCiAgICB9OwoKICAgIHN0YXRpYyBjb25zdCBjaGFyKiB0ZW5zW10gPSB7CiAgICAgICAgIiIsCiAgICAgICAgIiIsCiAgICAgICAgInR3ZW50eSIsCiAgICAgICAgInRoaXJ0eSIsCiAgICAgICAgImZvcnR5IiwKICAgICAgICAiZmlmdHkiLAogICAgICAgICJzaXh0eSIsCiAgICAgICAgInNldmVudHkiLAogICAgICAgICJlaWdodHkiLAogICAgICAgICJuaW5ldHkiCiAgICB9OwoKICAgIGludCBodW5kcmVkID0gbiAvIDEwMCAlIDEwOwogICAgaW50IHRlbiA9IG4gLyAxMCAlIDEwOwogICAgaW50IG9uZSA9IG4gJSAxMDsKCiAgICBpZiAoaHVuZHJlZCkKICAgIHsKICAgICAgICBhc3RyaW5nX2FwcGVuZChyZXN1bHQsIG9uZXNbaHVuZHJlZF0pOwogICAgICAgIGFzdHJpbmdfYXBwZW5kKHJlc3VsdCwgIiBodW5kcmVkIik7CiAgICAgICAgaWYgKHRlbiB8fCBvbmUpCiAgICAgICAgICAgIGFzdHJpbmdfYXBwZW5kKHJlc3VsdCwgIiBhbmQgIik7CiAgICB9CgogICAgaWYgKHRlbiA9PSAwKQogICAgewogICAgICAgIGFzdHJpbmdfYXBwZW5kKHJlc3VsdCwgb25lc1tvbmVdKTsKICAgIH0KICAgIGVsc2UgaWYgKHRlbiA9PSAxKQogICAgewogICAgICAgIGFzdHJpbmdfYXBwZW5kKHJlc3VsdCwgdGVlbnNbb25lXSk7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgYXN0cmluZ19hcHBlbmQocmVzdWx0LCB0ZW5zW3Rlbl0pOwogICAgICAgIGlmIChvbmUpCiAgICAgICAgewogICAgICAgICAgICBhc3RyaW5nX2FwcGVuZChyZXN1bHQsICItIik7CiAgICAgICAgICAgIGFzdHJpbmdfYXBwZW5kKHJlc3VsdCwgb25lc1tvbmVdKTsKICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gcmVzdWx0Owp9Cgpjb25zdCBjaGFyKiB0ZXh0bnVtYmVyKGxvbmcgaW50IG4pCnsKICAgIGFzc2VydChuID4gTE9OR19NSU4gfHwgTE9OR19NSU4gKyBMT05HX01BWCA9PSAwKTsKCiAgICBzdGF0aWMgY29uc3QgY2hhciogYmFzZVtdID0gewogICAgICAgICIiLAogICAgICAgICIgdGhvdXNhbmQiLAogICAgICAgICIgbWlsbGlvbiIsCiAgICAgICAgIiBiaWxsaW9uIiwKICAgICAgICAiIHRyaWxsaW9uIiwKICAgICAgICAiIHF1YWRyaWxsaW9uIiwKICAgICAgICAiIHF1aW50aWxsaW9uIgogICAgfTsKCiAgICBzdGF0aWMgX1RocmVhZF9sb2NhbCBzdHJ1Y3QgYXN0cmluZyByZXN1bHRbMV07CiAgICByZXN1bHQtPmxhc3QgPSByZXN1bHQtPmZpcnN0OwoKICAgIGlmIChuID09IDApCiAgICB7CiAgICAgICAgYXN0cmluZ19hcHBlbmQocmVzdWx0LCAiemVybyIpOwogICAgICAgIHJldHVybiByZXN1bHQtPmZpcnN0OwogICAgfQoKICAgIGlmIChuIDwgMCkKICAgIHsKICAgICAgICBhc3RyaW5nX2FwcGVuZChyZXN1bHQsICJtaW51cyAiKTsKICAgICAgICBuID0gLW47CiAgICB9CgogICAgY29uc3QgbG9uZyBpbnQgayA9IDEwMDA7CiAgICBsb25nIGludCBrX3RvX2ogPSAxOwogICAgaW50IGogPSAwOwoKICAgIGZvciAobG9uZyBpbnQgaSA9IG47IGkgPj0gazsgaSAvPSBrKQogICAgewogICAgICAgIGtfdG9faiAqPSBrOwogICAgICAgIGogKz0gMTsKICAgIH0KCiAgICBmb3IgKDsgaiA+PSAwOyBqLS0pCiAgICB7CiAgICAgICAgbG9uZyBpbnQgbSA9IG4gLyBrX3RvX2ogJSBrOwogICAgICAgIGlmIChtICE9IDApCiAgICAgICAgewogICAgICAgICAgICBhc3RyaW5nX2FwcGVuZCh0ZXh0bnVtYmVyX2xvd2VyKG0sIHJlc3VsdCksIGJhc2Vbal0pOwogICAgICAgICAgICBpZiAobiAlIGtfdG9faiAhPSAwKQogICAgICAgICAgICAgICAgYXN0cmluZ19hcHBlbmQocmVzdWx0LCAiLCAiKTsKICAgICAgICAgICAgZWxzZSBicmVhazsKICAgICAgICB9CiAgICAgICAga190b19qIC89IGs7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0LT5maXJzdDsKfQoKLy8KLy8gU2hvdy4KLy8KCmludCBtYWluKGludCBhcmdjLCBjaGFyKiBhcmd2W10pCnsKICAgIHByaW50ZigiJWRcbiVzXG5cbiIsIDAsIHRleHRudW1iZXIoMCkpOwogICAgcHJpbnRmKCIlZFxuJXNcblxuIiwgLTEsIHRleHRudW1iZXIoLTEpKTsKICAgIHByaW50ZigiJWRcbiVzXG5cbiIsIDEwMDAwMDAsIHRleHRudW1iZXIoMTAwMDAwMCkpOwogICAgcHJpbnRmKCIlZFxuJXNcblxuIiwgMTAwMDAwMywgdGV4dG51bWJlcigxMDAwMDAzKSk7CiAgICBwcmludGYoIiVkXG4lc1xuXG4iLCAxMDAyMDAzLCB0ZXh0bnVtYmVyKDEwMDIwMDMpKTsKICAgIHByaW50ZigiJWxkXG4lc1xuXG4iLCBMT05HX01BWCwgdGV4dG51bWJlcihMT05HX01BWCkpOwoKICAgIHNyYW5kKHRpbWUoMCkpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCA1OyBpKyspCiAgICB7CiAgICAgICAgaW50IHggPSByYW5kKCkgJSAyMSAtIDEwOwogICAgICAgIHByaW50ZigiJWRcbiVzXG5cbiIsIHgsIHRleHRudW1iZXIoeCkpOwogICAgfQogICAgZm9yIChpbnQgaSA9IDA7IGkgPCA1OyBpKyspCiAgICB7CiAgICAgICAgaW50IHggPSByYW5kKCkgJSAyMDEgLSAxMDA7CiAgICAgICAgcHJpbnRmKCIlZFxuJXNcblxuIiwgeCwgdGV4dG51bWJlcih4KSk7CiAgICB9CiAgICBmb3IgKGludCBpID0gMDsgaSA8IDU7IGkrKykKICAgIHsKICAgICAgICBpbnQgeCA9IHJhbmQoKSAlIDIwMDEgLSAxMDAwOwogICAgICAgIHByaW50ZigiJWRcbiVzXG5cbiIsIHgsIHRleHRudW1iZXIoeCkpOwogICAgfQogICAgZm9yIChpbnQgaSA9IDA7IGkgPCA1OyBpKyspCiAgICB7CiAgICAgICAgaW50IHggPSByYW5kKCkgLSByYW5kKCk7CiAgICAgICAgcHJpbnRmKCIlZFxuJXNcblxuIiwgeCwgdGV4dG51bWJlcih4KSk7CiAgICB9CiAgICByZXR1cm4gMDsKfQ==