#!/usr/bin/perl
########################################################################
#
# $Id$
#
# Copyright (c) 2002 Okunev Igor <gosha@prv.mts-nn.ru>
#
########################################################################
use strict;

$^W = 1;

if ( defined ( my $i = shift ) ) {
	print digit_to_money_string( $i ), "\n";
} else {
	print "Число: " if -t STDIN;
	while ( defined ( $i = <STDIN> ) ) {
		chomp $i;
		print digit_to_money_string( $i ), "\n";
		print "Число: " if -t STDIN;
	}
}

sub digit_to_money_string {
	my $digit = shift;
	local $_;

	#
	# Проверка на отрицательность числа
	#
	my $sign = 1 if $digit =~ s/^-+//;

	#
	# Удаляем нули из начала числа
	#
	$digit =~ s#^0+##;

	my ( $b_dig, $s_dig ) = ( split( m/[,.]/, $digit, 2 ) );

	#
	# Очищаем числа от `лишних' символов ( 100_000,43 )
	#
	if ( defined $b_dig and length $b_dig ) {
		$b_dig =~ s#[^\d]##sg;
	} else {
		$b_dig = 0;
	}
	if ( defined $s_dig and length $s_dig ) {
		$s_dig =~ s#[^\d]##sg;
	} else {
		$s_dig = 0;
	}
	
	#
	# Округляем копейки в большую сторону, если в результате округления
	# получаем рубль, то приплюсовываем его к b_dig ( рублям )
	#
	if ( sprintf('%0.2f', "0.$s_dig" ) == 1 ) {
		$b_dig ++;
		$s_dig = '00';
	} else {
		$s_dig = substr( sprintf('%0.2f', "0.$s_dig" ), 2 );
	}

	my @array = split( //, ( $b_dig || 0 ) );

	#
	# Определяем разрядность числа.
	#
	my $class_id = int( scalar ( @array ) / 3);
	$class_id++ if ( scalar ( @array ) % 3 );

	#
	# Неподдерживаемая разрядность.
	#
	return $digit if $class_id > 12;

	my $digits_name = {
			0	=> ['ноль',			'',				''			],
			1	=> [['один','одна'],	'десять',		'сто'		],
			2	=> [['два','две'],		'двадцать',		'двести'	],
			3	=> ['три',		'тридцать',		'триста'	],
			4	=> ['четыре',	'сорок',		'четыреста'	],
			5	=> ['пять',		'пятьдесят',	'пятьсот'	],
			6	=> ['шесть',	'шестьдесят',	'шестьсот'	],
			7	=> ['семь',		'семьдесят',	'семьсот'	],
			8	=> ['восемь',	'восемьдесят',	'восемьсот'	],
			9	=> ['девять',	'девяносто',	'девятьсот'	],
		};

	my $dec_digits = {
				11	=> 'одинадцать',
				12	=> 'двенадцать',
				13	=> 'тринадцать',
				14	=> 'четырнадцать',
				15	=> 'пятнадцать',
				16	=> 'шестнадцать',
				17	=> 'семнадцать',
				18	=> 'восемнадцать',
				19	=> 'девятнадцать'
			};

	my $digits_class = {
			'-1'=>	[ 1,	'копейка',		'копеек',		'копейки'	],
			0	=>	[ 0,	'рубль',		'рублей',		'рубля'		],
			1	=>	[ 1,	'тысяча',		'тысяч',		'тысячи'	],
			2	=>	[ 0,	'миллион',		'миллионов',	'миллиона'	],
			3	=>	[ 0,	'миллиард',		'миллиардов',	'миллиарда'	],
			4	=>	[ 0,	'триллион',		'триллионов',	'триллиона'	],
			5	=>	[ 0,	'квадриллион',	'квадриллионов',	'квадриллиона' ],
			6	=>	[ 0,	'квинтиллиан',	'квинтиллианов','квинтиллиана'],
			7	=>	[ 0,	'секстиллион',	'секстиллионов','секстиллиона'],
			8	=>	[ 0,	'септиллион',	'септиллионов',	'септиллиона'],
			9	=>	[ 0,	'октилион',		'октлионов',	'октилиона'	],
			10	=>	[ 0,	'нониллион',	'нониллионов',	'ноннилиона'],
			11	=>	[ 0,	'дециллион',	'дециллионов',	'дециллиона' ]
		};
	
	#
	# Определяем длину левой `тройки'...
	#
	my $id = 0;
	unless ( ( scalar @array ) % 3 ) {
		$id = 2;
	} else {
		$id = ( ( scalar @array ) % 3 ) - 1;
	}

	my $str		= '';
	my $sub_str	= 0;
	my $tvar	= 0;

	if ( $array[0] == 0 ) {
		#
		# Если рублей таки ноль, то так и пишем 'ноль рублей',
		# если не надо то просто закомнтировать следующую строку...
		#
		$str .= $digits_name->{'0'}->[0] . ' ' . $digits_class->{'0'}->[2] . ' ';
	} else {
		while ( defined ( $_ = shift @array ) ) {
			if ( $_ > 0 ) {
				if ( $_ == 1 and $id == 1 ) {
					#
					# Считаем сумму для использования в sub num()
					#
					$sub_str += $_ * 10;
					if ( defined ( $tvar = shift @array ) and $tvar > 0 ) {
						$str .= $dec_digits->{ $_ . $tvar };
						$sub_str += $tvar;
						$id--;
					} else {
						unshift @array, $tvar;
						if ( ref $digits_name->{$_}->[$id] eq 'ARRAY' ) {
							$str .= $digits_name->{$_}->[$id]->[$digits_class->{$class_id-1}->[0]];
						} else {
							$str .= $digits_name->{$_}->[$id];
						}
					}
				} else {
					#
					# Считаем сумму для использования в sub num()
					#
					$sub_str += ( $_ * ( 10 ** $id ) );
					if ( ref $digits_name->{$_}->[$id]  eq 'ARRAY' ) {
						$str .= $digits_name->{$_}->[$id]->[$digits_class->{$class_id-1}->[0]];
					} else {
						$str .= $digits_name->{$_}->[$id];
					}
				}
				$str .= ' ';
			}
			if ( --$id == -1 ) {
				$id = 2;
				$class_id--;
				if ( $sub_str > 0 ) {
					$str .= num( $sub_str, ( @{ $digits_class->{$class_id} } )[ 1 .. 3 ] ) . ' ';
				} elsif ( $class_id == 0 ) {
					$str .= $digits_class->{$class_id}->[2] . ' ';
				}
				$sub_str = 0;
			}
		}
	}

	$str .= $s_dig . ' ' . num( $s_dig, ( @{ $digits_class->{ '-1' } } )[ 1 .. 3 ] );

	if ( defined $sign ) {
		$str = 'минус ' . $str;
	}

	$s_dig = substr( $str, 0, 1 );
	#
	# В том случае где оно пользовалось оказалось проще
	# так, чем через use locale & ucfirst...
	#
	if ( $s_dig =~ tr/абвгдеёжзийклмнопрстуфхцчшщъыьэюя/АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ/ ) {
		substr( $str, 0, 1, $s_dig );
	}

	return $str;
}

#
# Используется при переводе денежного числа в строку прописью..
#

sub num {
	my $d1 = $_[0] % 10;
	my $d2 = int( ( $_[0] % 100 ) / 10 );
	return $_[2] if ( ( $d2 == 1 ) or ( $d1 =~ /[05-9]/ ) );
	return $_[1] if ( $d1==1 );
	return $_[3];
}

