"漢数字からアラビア数字"をschemeで

やりたいのは単純で、一〜五十くらいまでで、十一とか三十一とかの表記となる。これを1〜50、11とか31とかに直す。

L'eclat des jours(2010-12-09)

なんとなくGaucheでチャレンジ。

(define (kj_to_ar kj-string)
  (define kj-number '((#\十 10) (#\一 1) (#\二 2) (#\三 3) (#\四 4) (#\五 5) (#\六 6) (#\七 7)(#\八 8) (#\九 9)))
  (define (kj-ref kj)
    (cadr (assoc kj kj-number)))
  (define base-char #\十)
  (define (base-char? kj)
    (char=? kj base-char))
  (let ((r-kj-lis (reverse (string->list kj-string))))
    (define (iter rest base result)
      (if (null? rest) result
          (if base
              (iter (cdr rest) base
                    (+ result (* (- (kj-ref (car rest)) 1) (kj-ref base-char))))
              (iter (cdr rest) (base-char? (car rest))
                    (+ result (kj-ref (car rest)))))))
    (iter r-kj-lis #f 0)))

実行

gosh> (kj_to_ar "一")
1
gosh> (kj_to_ar "五")
5
gosh> (kj_to_ar "十三")
13
gosh> (kj_to_ar "十")
10
gosh> (kj_to_ar "二十一")
21

Rubyで実装するとこんな感じかなぁ。って全然変わってるけど。

def kj_to_ar(s)
  kj_list = '零一二三四五六七八九十'
  s.reverse!
  base = 10
  base_ex = false
  result = 0
  s.each_char do |c|
    if base_ex
      result += (kj_list.index(c) - 1) * base
    elsif kj_list.index(c) == base
      result += base
      base_ex = true
    else
      result += kj_list.index(c)
    end
  end
  result
end

実行

irb(main):163:0> kj_to_ar('')
=> 10
irb(main):164:0> kj_to_ar('二十五')
=> 25
irb(main):165:0> kj_to_ar('十六')
=> 16
irb(main):166:0> kj_to_ar('六十')
=> 60
irb(main):167:0> kj_to_ar('')
=> 7
irb(main):168:0> kj_to_ar('')
=> 8

全然スマートにはならなかったな…。