Tonumber功能(tonumber'(一二三) - > 123

时间:2014-03-27 22:52:24

标签: scheme racket

how to spell a number in racket? (spellNum)的解决方案之后,现在我正在尝试编写与此函数相反的函数。即

(tonumber ‘(one two three) --> 123

到目前为止,我已经编写了这个工作代码

(define (symbol->digit n)
  (case n
    ('zero 0)
    ('one 1)
    ('two 2)
    ('three 3)
    ('four 4)
    ('five 5)
    ('six 6)
    ('seven 7)
    ('eight 8)
    ('nine 9)
    (else (error "unknown symbol:" n))))



(define (numlist n)
  (map symbol->digit  n))



(numlist '(one two three))

从numlist,我得到'(1 2 3)。但是在下面的函数中存在一些问题,我希望将列表转换为数字

(define (list->number l)
  (set! multiplier (* 10 (lenght l)))
  (for/list [(c l)] 
    (* multiplier c))
  (set! multiplier (/ multiplier 10)))

(list->number '(1 2 3))

任何帮助将不胜感激。我在网上找不到各种循环的文档。在 http://docs.racket-lang.org/ts-reference/special-forms.html?q=loop#%28part._.Loops%29

我想熟悉Racket,所以我想避免使用内置转换功能。在list->数字中,我试图从列表中逐个取数字然后我想将它们与10,100,1000相乘,具体取决于列表的长度。这样它就可以返回一个数字。例如'(1 2 3)= 1 * 100 + 2 * 10 + 3 * 1

3 个答案:

答案 0 :(得分:1)

(define (symbol->digit n)
  (case n
    ('zero "0")
    ('one "1")
    ('two "2")
    ('three "3")
    ('four "4")
    ('five "5")
    ('six "6")
    ('seven "7")
    ('eight "8")
    ('nine "9")
    (else (error "unknown symbol:" n))))

(define (symbols->number symb)
  (string->number (string-join (map symbol->digit symb) "")))

(symbols->number '(one two three))

答案 1 :(得分:1)

这与previous solution完全相反,再次使用list->number过程的尾递归:

(define (symbol->digit n)
  (case n
    ('zero 0)
    ('one 1)
    ('two 2)
    ('three 3)
    ('four 4)
    ('five 5)
    ('six 6)
    ('seven 7)
    ('eight 8)
    ('nine 9)
    (else (error "unknown symbol:" n))))

(define (list->number lst)
  (let loop ((acc 0) (lst lst))
    (if (null? lst)
        acc
        (loop (+ (car lst) (* 10 acc)) (cdr lst)))))

(define (toNumber lst)
  (list->number (map symbol->digit lst)))

按预期工作:

(toNumber '(four six seven))
=> 467

为了好玩,在Racket中我们可以使用iteration and comprehensions编写类似list->number的函数。即便如此,请注意我们不在任何地方使用set!,变异状态是像Python这样的语言的常态,但在一般的Scheme中,特别是Racket我们试图避免在循环中修改变量 - 更优雅表达解决方案的方法:

(define (list->number lst)
  (for/fold ([acc 0]) ([e lst])
    (+ e (* 10 acc))))

答案 2 :(得分:0)

很多方法可以给猫皮肤。这是使用fold-left的版本。就像Óscar的解决方案一样,它使用数学而不是字符和字符串。

#!r6rs
(import (rnrs))

;; converts list with worded digits into
;; what number they represent.
;; (words->number '(one two zero)) ==> 120
(define (words->number lst)
  (fold-left (lambda (acc x)
               (+ x (* acc 10)))
             0
             (map symbol->digit lst)))

对于#!racket版本,只需将fold-left重命名为foldl并切换xacc的顺序。