2016-02-27 3 views
1

Хорошо. Поэтому мне интересно, как создать функцию, которая превратит случайное число в его компонент английского слова.(SCHEME) Номер -> Английский Список

Такие, как (1001 -> «(одна тысяча) или 0 ->» (ноль) и (имя-номер факториал 20 -> «(два нониллион четыреста тридцать два квадриллиона девятьсот два триллиона восемь миллиардов сто семьдесят шесть миллионов шестьсот сорок тысяч))

Я работал с предыдущим пользователем в stackoverflow, чтобы получить то, что превратилось в длинное число на 3 части (1 341 100 - один миллион, 341 тыс. 1 сто 0 десятков 0 единиц)

#lang r5rs 
(define (three-names n) 
    (if (zero? n) 
    "zero" 
    (let loop ((n n) 
      (units '((10 one) (10 ten) (10 hundred) (1000 thousand) (1000 million) (1000 billion) (1000 trillion) (1000 quadrillion) (1000 quintillion) 
          (1000 sextillion) (1000 septillion) (1000 octillion) (1000 nonillion) 
          (1000 decillion) (1000 undecillion) (1000 duodecillion) (1000 tredecillion) 
          (1000 quatturodecillion) (1000 sexdillion) (1000 septendecillion) (1000 octodecillion) 
          (1000 novemdecillion) (1000 vigintillion))) 
      (ARRAY '())) 

    (if 
    (or (zero? n) (null? units)) 
     ARRAY 
     (let* ((unit (car units)) (div (car unit)) (english (cadr unit))) 
      (let 
       ((q (quotient n div)) (r (remainder n div))) 
      (loop q 
        (cdr units) 
        (cons r (cons english ARRAY)))))))))  

Единственное, что я понимаю прямо сейчас, чтобы сделать это так, что есть ценности для 0-20:

(= x 0) zero 
(= x 1) one 
... 
(> x 1000) thousand 
(> x 1000000) million 

Но для того, они не будут выводиться в список и два, не знаю, что еще делать?

+0

И как это отличается от вашего предыдущего вопроса [] (http://stackoverflow.com/q/35530887/201359)? –

+0

Выход аналогичен, но очень отличается.Вместо того, чтобы иметь 3 числа, за которыми следует местозаполнитель (тысячи или десятки), возвращается вся строка – Anitun

ответ

1

Как Сильвестер объясняет вам нужно, чтобы иметь возможность

  1. правильно напечатать текст для каждого числа ниже 1000 (3 цифры)
  2. делит число в 3-х значных группах, печатать их с помощью выше коды и просто добавить «тысячи» достаточно

Вот пример реализации, который совместим с r5rs языка ракетку в:

(define (n2t n) 
    (define 1to19  '(one two three four five six seven eight nine ten eleven twelve 
          thirteen fourteen fifteen sixteen seventeen eighteen nineteen)) 
    (define multof10 '(twenty thirty forty fifty sixty seventy eighty ninety)) 
    (define thousands '(thousand million billion trillion quadrillion quintillion sextillion septillion octillion nonillion decillion undecillion)) 
    (cond 
    ((= n 0) '(zero)) ; zero is a special case since from now on all 0 will be suppressed 
    ((< n 0) (cons 'minus (n2t (- n)))) 
    (else 
    (let loop ((n n) (units thousands) (res '())) 
     (cond 
     ; --- below 1000 
     ((= n 0) res) 
     ((< 0 n 20) (cons (list-ref 1to19 (- n 1)) res)) 
     ((< n 100) (cons (list-ref multof10 (- (quotient n 10) 2)) 
          (loop (remainder n 10) '() res))) 
     ((< n 1000) (loop (quotient n 100) 
          '() 
          (cons 'hundred (loop (remainder n 100) '() res)))) 
     (else 
      ; --- 1000 and above 
      (let ((q (quotient n 1000)) 
       (res (loop (remainder n 1000) thousands res))) 
      (if (zero? q) 
       res 
       (loop q (cdr units) (cons (car units) res)))))))))) 

Тестирование:

> (n2t 0) 
'(zero) 
> (n2t 1001) 
'(one thousand one) 
> (n2t 132219) 
'(one hundred thirty two thousand two hundred nineteen) 
> (n2t -132219) 
'(minus one hundred thirty two thousand two hundred nineteen) 
> (n2t 2345678213) 
'(two billion three hundred forty five million six hundred seventy eight thousand two hundred thirteen) 
> (n2t 2432902008176640000) 
'(two quintillion four hundred thirty two quadrillion nine hundred two trillion eight billion one hundred seventy six million six hundred forty thousand) 
+0

Хм ... Я не могу заставить это работать. define: не разрешено в контексте выражения для первых функций «define». – Anitun

+0

О, я вижу, я потерял совместимость R5RS с моим последним правлением ... теперь это исправлено. – uselpa

+0

Удивительно, это очень помогает. @uselpa Я пытаюсь выяснить, как поставить факторную функцию. Поэтому я определил функцию в первой части. Насколько я знаю, он вычислит его, но не включит его в список. Так сказать, у меня есть (n2t (factorial 3)) -> (шесть). Как я могу добавить эту факториальную функцию в основной код и вернуть список? Просто нужно сначала вычислить значение, затем продолжить в этот цикл? – Anitun

1

Как вы, наверное, знаете, что вы должны быть в состоянии сделать что-то вроде:

(number->english 2345678213) 
; ==> "two billion three hundred and fourtyfive million six \ 
;  hundred and seventyeight tousand two hundred and thirteen" 

На первый glimse вы можете увидеть, что существует закономерность:

... 
<english number text below 1000> million 
<english number text below 1000> thousand 
<english number text below 1000> 

Таким образом .. процедура будет возможно выглядеть примерно так:

(define (number->english x) 
    (if (zero? x) 
     "zero" 
     (iterate-thousands x thousands '())) 

с thousands определяется как: '("" "thousand" "million" "billion" "trillion" ...) и iterate-tousands возможно выглядеть примерно так:

(define (iterate-thousands thousands x acc) 
    (if (zero? x) 
     (join acc " ") 
     (iterate-thousands (cdr thousands) 
         (quotient x 1000) 
         (list* (below-1000 (remainder x 1000)) 
           (car thousands) 
           acc)))) 

Где below-1000 возвращает правильную строку для каждого числа ниже 1000. Было бы, как правило, разделить работу в соответствии с соглашением об именах. Это что-то особенное для ниже 13, подростки до 19, объединяют ty + до 99 и, возможно, рекурсию по выше, которая берет + + 100% + рекурсию на остатке, так что 234 становится (string-append "two hundred and " (below-1000 34)). join просто используйте string-append с разделителем и правильно обработайте пустые строки.

+0

. Так мне придется проходить через каждый номер? Например, если я хочу миллионы, я должен перебирать миллионы, сотни тысяч, тысячи, десять, один. Что, если число больше 1000? – Anitun

+0

Извините, как бы плохой вопрос. У вас есть пример того, как это будет выглядеть? Мне нелегко визуализировать – Anitun

+0

@anitun весь код для этой итерации. Он делает это наоборот, начиная с 1000^0. Единственное, что я забыл, было «ниже-1000», что интересно сделать. – Sylwester

Смежные вопросы