After the solution of how to spell a number in racket? (spellNum) ,now I am trying to write a function which is opposite of this function. i.e
(tonumber ‘(one two three) --> 123
so far I have written this working code
(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))
From numlist, I got '(1 2 3). But to there is some problem in the function below in which I want to convert list to number
(define (list->number l)
(set! multiplier (* 10 (lenght l)))
(for/list [(c l)]
(* multiplier c))
(set! multiplier (/ multiplier 10)))
(list->number '(1 2 3))
any help will be appreciated. I can't find documentation of all kind of loops online. at
http://docs.racket-lang.org/ts-reference/special-forms.html?q=loop#%28part._.Loops%29
I want to become familiar with Racket so I want to avoid builtin conversion functions. In list->number,I am trying to take digits one by one from list and then i want to multiply them with 10,100,1000 so on depending on the length of list. so that it can return a number. For example '(1 2 3) = 1*100+2*10+3*1
Here's the exact opposite of my previous solution, once again using tail recursion for the list->number
procedure:
(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)))
It works as expected:
(toNumber '(four six seven))
=> 467
Just for fun, in Racket we can write a function like list->number
using iteration and comprehensions. Even so, notice that we don't use set!
anywhere, mutating state is the norm in a language like Python but in Scheme in general and Racket in particular we try to avoid modifying variables inside a loop - there are more elegant ways to express a solution:
(define (list->number lst)
(for/fold ([acc 0]) ([e lst])
(+ e (* 10 acc))))
(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))
Lots of ways to skin a cat. Here is version that uses fold-left
. Like Óscar's solution it uses math rather than chars and strings.
#!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)))
For a #!racket
version just rename fold-left
to foldl
and switch the order of x
and acc
.