project-euler problem 17

これはキモい。

  • thirtyがthirityになっていることに気づくのに苦労しました><
  • パターンマッチがとても便利でした
(define (num->list n)
  (define (iter re n)
    (if (= n 0) re (iter (cons (remainder n 10) re) (floor (/ n 10)))))
  (iter '() n))

(define (string-length str) (length (string->list str)))

(define (f n)
  (let ((lst (num->list n)))
    (match lst
     ((a b c d) "onethousand")
     ((a b c) (100f a b c))
     ((b c) (10f b c))
     ((c) (1f c))
     (_ (error "invalid arguments is passed")))))

(define (1f c)
  (match c
         (0 "")
         (1 "one")
         (2 "two")
         (3 "three")
         (4 "four")
         (5 "five")
         (6 "six")
         (7 "seven")
         (8 "eight")
         (9 "nine")))

(define (10f b c)
  (cond  ((= b 1)
          (match c
                 (0 "ten")
                 (1 "eleven")
                 (2 "twelve")
                 (3 "thirteen")
                 (4 "fourteen")
                 (5 "fifteen")
                 (6 "sixteen")
                 (7 "seventeen")
                 (8 "eighteen")
                 (9 "nineteen")))
         (else
          (string-append (match b
                      (0 "")
                      (2 "twenty")
                      (3 "thirty")
                      (4 "forty")
                      (5 "fifty")
                      (6 "sixty")
                      (7 "seventy")
                      (8 "eighty")
                      (9 "ninety"))
               (1f c)))))

(define (100f a b c)
  (string-append (1f a) "hundred" (if (= c b 0) "" (string-append "and" (10f b c)))))
(f 20)

(let* ((n 1000)
       (word-list (map (cut f <>) (iota n 1))))
  (apply + (map (pa$ string-length) word-list)))