fork(1) download
  1. <?php
  2.  
  3.  
  4.  
  5. // Staring deep into abyss... oh please, oh please
  6.  
  7.  
  8. //tools
  9. // tool 1, function to pick form
  10.  
  11. function doFormCheck($input,$i) {
  12. $form=NULL;
  13. $arrayOfForms=array
  14. (
  15. 0=>array('single'=>'рубль','plural'=>'рублей','special'=>'рубля'),
  16. 1=>array('single'=>'тысяча','plural'=>'тысяч','special'=>'тысячи'),
  17. 2=>array('single'=>'миллион','plural'=>'миллионов','special'=>'миллиона'),
  18. );
  19.  
  20. // ^this is also map for our numbers layout. 0 roubles 1 thousands 2 millions
  21.  
  22. //main code identifying form
  23.  
  24. if ( ($input-1) % 10 == 0 && ($input % 100) !== 11) {
  25.  
  26. //number ends with 1 except 11
  27.  
  28. $form= "single";
  29. }
  30.  
  31. elseif (!($input % 10)) {
  32.  
  33. //number ends with 0
  34.  
  35. $form="plural";
  36.  
  37. }
  38. elseif (round($input / 10) == floor ($input / 10) && !in_array($input % 100, [11,12,13,14])) {
  39.  
  40. //ends with 1-4 but 1 is omitted because of first condiition check (as is omitted 0)
  41.  
  42. $form="special";
  43.  
  44. }
  45.  
  46. else {
  47.  
  48. //number ends with 5-9
  49.  
  50. $form= "plural";
  51.  
  52. }
  53.  
  54. return $arrayOfForms[$i][$form];
  55. }
  56.  
  57.  
  58. // tool 2, function to lookup last 3 digits of any given number
  59.  
  60. function identifyLastThreeDigits($input) {
  61.  
  62. return $input % 1000;
  63. }
  64.  
  65. //tool 3, function to split complex numbers into array of triplets
  66.  
  67. function doTriplets($input) {
  68. $arrayOfTriplets=[];
  69.  
  70. while (identifyLastThreeDigits($input)!==$input) {
  71.  
  72. //number has > 3 digits
  73.  
  74. array_push($arrayOfTriplets,identifyLastThreeDigits($input));
  75. $input = intval(floor($input / 1000));
  76.  
  77. /*
  78.  
  79.   intval() is used here because floor from float produces float. Remainder of float / 1000 will be int. Thus the loop condition !==
  80.   in the head will be evaluated as int vs float comparison, thus falling to infinitive cycle
  81.  
  82.   this could be bypassed by either covert coercion in the head of loop != instead of strict !==
  83.   or by overt coercion with inval(). i chose the second
  84.  
  85.   */
  86. }
  87.  
  88. //now number has <= 3 digits
  89.  
  90. array_push($arrayOfTriplets, $input);
  91.  
  92. return $arrayOfTriplets;
  93. }
  94.  
  95.  
  96. //tool 4, function to convert arrayofnumbers into a string while picking form with tool1 in a process
  97.  
  98. function doStringify($arrayOfNumbers) {
  99.  
  100. $arrayOfStrings = [];
  101.  
  102.  
  103. $maleSpelling = array(
  104.  
  105. 0 => 'ноль', 10 => 'десять', 100 => 'сто',
  106. 1 => 'один', 11 => 'одиннадцать', 20 => 'двадцать', 200 => 'двести',
  107. 2 => 'два', 12 => 'двенадцать', 30 => 'тридцать', 300 => 'триста',
  108. 3 => 'три', 13 => 'тринадцать', 40 => 'сорок', 400 => 'четыреста',
  109. 4 => 'четыре', 14 => 'четырнадцать', 50 => 'пятьдесят', 500 => 'пятьсот',
  110. 5 => 'пять', 15 => 'пятнадцать', 60 => 'шестьдесят', 600 => 'шестьсот',
  111. 6 => 'шесть', 16 => 'шестнадцать', 70 => 'семьдесят', 700 => 'семьсот',
  112. 7 => 'семь', 17 => 'семнадцать', 80 => 'восемьдесят', 800 => 'восемьсот',
  113. 8 => 'восемь', 18 => 'восемнадцать', 90 => 'девяносто', 900 => 'девятьсот',
  114. 9 => 'девять', 19 => 'девятнадцать'
  115. );
  116.  
  117. $femSpelling = array(
  118.  
  119. 1 => 'одна',
  120. 2 => 'две',
  121.  
  122. );
  123.  
  124. for ($i=0;$i<count($arrayOfNumbers);$i++) {
  125.  
  126. // remember layout: 0 roubles 1 thousands 2 millions
  127.  
  128. $spelling = ($i == 1) ? ($femSpelling+$maleSpelling) : $maleSpelling;
  129.  
  130. // general check for blanks begins
  131.  
  132. // blanks will not be processed unless '0 roubles' (with 0 being omitted if not standalone)
  133.  
  134. if ($arrayOfNumbers[$i]==0) {
  135.  
  136. if ($i==0 && count($arrayOfNumbers) == 1) {
  137. $word = $spelling[$arrayOfNumbers[$i]];
  138. $word = $word . " " . doFormCheck($arrayOfNumbers[$i], $i);
  139. array_unshift($arrayOfStrings, $word);
  140. }
  141. elseif ($i==0 && count($arrayOfNumbers) > 1) {
  142. $word = " " . doFormCheck($arrayOfNumbers[$i], $i);
  143. array_unshift($arrayOfStrings, $word);
  144. }
  145.  
  146. continue;
  147.  
  148. }
  149.  
  150. //general check for blanks ends
  151.  
  152. //filling non-blanks begins
  153.  
  154.  
  155. if (isset($spelling[$arrayOfNumbers[$i]])) {
  156.  
  157. //if number is mapped case
  158.  
  159. $word = $spelling[$arrayOfNumbers[$i]];
  160.  
  161. $word = $word . " " . doFormCheck($arrayOfNumbers[$i], $i);
  162.  
  163. array_unshift($arrayOfStrings, $word);
  164.  
  165. }
  166.  
  167. else {
  168.  
  169. //if number is not a mapped case
  170.  
  171. $componentHundreds=NULL;
  172. $componentTens=NULL;
  173. $componentPrimes=NULL;
  174.  
  175. //cant use single word, need array of them
  176.  
  177. $arrayOfWords=[];
  178.  
  179.  
  180. //preparing arrayOfWords
  181.  
  182. if ($arrayOfNumbers[$i] < 100) {
  183.  
  184. // number will have 2 components. componentHundreds remains NULL.
  185.  
  186. $componentTens = floor($arrayOfNumbers[$i] / 10) * 10;
  187. $componentPrimes = $arrayOfNumbers[$i] - $componentTens;
  188. $arrayOfWords = [$spelling[$componentTens], $spelling[$componentPrimes]];
  189.  
  190. }
  191.  
  192. else {
  193.  
  194. //number will have either 2 (remnant is mapped case) or 3 components
  195.  
  196. $componentHundreds = floor($arrayOfNumbers[$i] / 100) * 100;
  197. $componentTens = $arrayOfNumbers[$i] - $componentHundreds;
  198.  
  199. //if remnant is mapped case
  200.  
  201. if (isset($spelling[$componentTens])) {
  202. $arrayOfWords=[$spelling[$componentHundreds], $spelling[$componentTens]];
  203.  
  204. }
  205.  
  206. // now if remnant is a mapped case having 2 components is enough. If not we must go deeper.
  207.  
  208. elseif (!isset($spelling[$componentTens])) {
  209.  
  210. //im using elseif for clarity
  211.  
  212. $componentTens = floor($componentTens / 10) * 10;
  213. $componentPrimes = $arrayOfNumbers[$i] - $componentHundreds - $componentTens;
  214. $arrayOfWords=[$spelling[$componentHundreds], $spelling[$componentTens], $spelling[$componentPrimes]];
  215.  
  216. }
  217.  
  218. }
  219.  
  220. // arrayOfWords prepared
  221.  
  222.  
  223. $word = implode(" ", $arrayOfWords) . " " . doFormCheck($arrayOfNumbers[$i],$i);
  224.  
  225. // ^our doFormCheck() function can parse number as is, components not needed for it
  226.  
  227. array_unshift($arrayOfStrings, $word);
  228. }
  229. }
  230.  
  231.  
  232. return "". implode(" ", $arrayOfStrings);
  233.  
  234. }
  235.  
  236.  
  237. //main function and launcher
  238.  
  239. function numberToText($input) {
  240.  
  241. $arrayOfNumbers=[];
  242.  
  243. //preparing array
  244.  
  245. if (identifyLastThreeDigits($input)==$input) {
  246.  
  247. // number is already of <=3 digits
  248.  
  249. array_push($arrayOfNumbers, $input);
  250.  
  251. }
  252.  
  253. elseif (identifyLastThreeDigits($input)!==$input) {
  254.  
  255. // number has >3 digits
  256.  
  257. $arrayOfNumbers = doTriplets($input);
  258. }
  259.  
  260. //array prepared
  261.  
  262. $string=doStringify($arrayOfNumbers);
  263.  
  264. // insert amount in parenthesis
  265.  
  266. $string=preg_replace('/\s(?=(рубл+))/u', " ({$input}) ", $string);
  267.  
  268. echo "На Вашем счете {$string}";
  269. }
  270.  
  271. $amount1 = mt_rand(1,99999999);
  272. numberToText($amount1);
  273.  
  274.  
  275.  
  276. ?>
Success #stdin #stdout 0.02s 82624KB
stdin
Standard input is empty
stdout
На Вашем счете пятьдесят два миллиона восемьсот семьдесят шесть тысяч триста девяносто (52876390) рублей