вторник, 20 декември 2011 г.

Задача 17 - Изписване на числа с думи

Следната задача беше изпратена от mariqfentuzi:

Въведено число от клавиятурата в интервала от 1 до 1000, числото да се изведе словом.
Например: 123, се извежда като : сто, двадесет и три.

Задачата за преобразуването на число в думи не е тривиална, заради многото изключения в правилата за образуване на названията: Решението ми е грозно и може и да бърка на моменти, но е някакво начало:

<?php
function edinici($n) {
switch($n) {
case 1: return 'едно';
case 2: return 'две';
case 3: return 'три';
case 4: return 'четири';
case 5: return 'пет';
case 6: return 'шест';
case 7: return 'седем';
case 8: return 'осем';
case 9: return 'девет';
}
}
function teen($n) {
switch($n) {
case 10: return 'десет';
case 11: return 'единадесет';
case 12: return 'дванадесет';
default: return edinici($n-10).'надесет';
}
}
function desetici($n){
switch($n) {
case 1: return 'десет';
case 2: return 'двадесет';
default: return edinici($n).'десет';
}
}
function stotici($n) {
switch ($n){
case 1: return 'сто';
case 2: return 'двеста';
case 3: return 'триста';
default: return edinici($n).'стотин';
}
}
function slovom ($num) {
$num_str = strrev((string)(int)$num);
$name = array();
if ($num == 1000) return 'хиляда';
if ($num == 0) return 'нула';
if ($num && $num % 100 == 0) return stotici($num_str[2]);
if ($num > 9 && $num < 20) {
return teen($num);
}
if (isset($num_str[0])){
$name[] = edinici($num_str[0]);
if ($num_str[0] != '0' && strlen($num_str) > 1) {
$name[] = 'и';
}
}
if (isset($num_str[1])){
$name[] = desetici($num_str[1]);
if ($num_str[0] == '0' && strlen($num_str) > 2) {
$name[] = 'и';
}
}
if (isset($num_str[2])){
$name[] = stotici($num_str[2]);
}
return implode (' ', array_reverse($name));
}
$test = array(0, 1, 2, 3, 10, 11, 12, 15, 23, 400, 567, 120, 121, 123, 999, 1000);
foreach ($test as $num) {
echo $num.': '.slovom($num).PHP_EOL;
}
?>
view raw slovom.php hosted with ❤ by GitHub


$php slovom.php 
0: нула
1: едно                                             
2: две                                                            
3: три                                                             
10: десет                                                          
11: единадесет                                                     
12: дванадесет                                                     
15: петнадесет                                                     
23: двадесет и три                                                
400: четиристотин                                                  
567: петстотин шестдесет и седем                                   
120: сто и двадесет                                                
121: сто двадесет и едно                                           
123: сто двадесет и три
999: деветстотин деветдесет и девет
1000: хиляда

4 коментара:

  1. Този коментар бе премахнат от автора.

    ОтговорИзтриване
  2. class NumMapper {
    private static $nums = array(
    0 => '',
    1 => 'one',
    2 => 'two',
    3 => 'three',
    4 => 'four',
    5 => 'five',
    6 => 'six',
    7 => 'seven',
    8 => 'eight',
    9 => 'nine',
    10 => 'ten',
    11 => 'eleven',
    12 => 'twelve',
    13 => 'thirteen',
    15 => 'fifteen',
    18 => 'eighteen',
    20 => 'twenty',
    30 => 'thirty',
    50 => 'fifty',
    80 => 'eighty',
    1000 => 'one thousand'
    );

    private $num;

    public function __construct($num) {
    if ($num == 0) {
    $this->num = 'zero';
    return;
    }

    if (array_key_exists($num, self::$nums)) {
    $this->num = self::$nums[$num];
    return;
    }

    if ($num > 13 && $num < 20) {
    $this->num = self::$nums[($num % 10)] . 'teen';
    return;
    }

    if ($num < 100) {
    if ($num % 10 == 0) {
    $this->num = self::$nums[$num/10] . 'ty';;
    return;
    }

    $tens = (int) ($num/10);
    $tens = array_key_exists($tens . '0', self::$nums) ? self::$nums[$tens . '0'] . ' ' : self::$nums[(int)$num/10] . 'ty ';
    $this->num = $tens . self::$nums[$num%10];
    return;
    }

    if ($num % 100 == 0) {
    $this->num = self::$nums[$num/100] . ' hundread';
    return;
    }

    $hundreads = self::$nums[$num/100] . ' hundread and ';
    $reminder = substr($num,1);

    if (isset(self::$nums[$reminder])) {
    $this->num = $hundreads . self::$nums[$reminder];
    return;
    }

    if ($reminder > 13 && $reminder < 20) {
    $this->num = $hundreads . self::$nums[($reminder % 10)] . 'teen';
    return;
    }

    if ($reminder % 10 == 0) {
    $this->num = $hundreads . self::$nums[$reminder/10] . 'ty';
    return;
    }

    if ($reminder[0] == '0') {
    $this->num = $hundreads . self::$nums[$reminder%10];
    return;
    }

    $tens = (int) ($reminder/10);
    $tens = array_key_exists($tens . '0', self::$nums) ? self::$nums[$tens . '0'] . ' ' : self::$nums[(int)$reminder/10] . 'ty ';
    $this->num = $hundreads . $tens . self::$nums[$reminder%10];
    }

    public function __toString() {
    return $this->num;
    }
    }

    // test
    $nums = array();

    for ($i = 0; $i < 100; $i++) {
    $nums[] = rand(0, 1000);
    }

    foreach ($nums as $n) {
    echo $n . ': ' . new NumMapper($n) . '
    ';
    }

    ОтговорИзтриване