整数の漢数字表記
Posted feedbacks - Nested
Flatten Hidden初の1番乗り? きれいなコードではないですが... > perl suuzi.pl 1732050807568877 千七百三十二兆五百八億七百五十六万八千八百七十七
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/usr/bin/perl
my $num = $ARGV[0];
my @name0 = ('', qw(一 二 三 四 五 六 七 八 九));
my @name1 = ('', qw(十 百 千));
my @name2 = ('', qw(万 億 兆));
my $i = 0;
my $j = 0;
my $res = '';
while($num =~ s/(\d)$//) {
my $d = $1;
if($d > 1) {
$res = $name0[$d] . $name1[$i] . $res;
}
elsif($d == 1 and $i != 0) {
$res = $name1[$i] . $res;
}
$i++;
if($i % 4 == 0) {
$j++;
$i = 0;
$res = $name2[$j] . $res if($num ne '');
}
}
print $res, "\n";
|
バグがありました(汗 1の位の1の処理条件が抜けていました. シャワー浴びていたときにふと気づきましたが,手遅れ. というわけで一番乗りは無かったことにしていただけないでしょうか...(恥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #!/usr/bin/perl
my $num = $ARGV[0];
my @name0 = ('', qw(一 二 三 四 五 六 七 八 九));
my @name1 = ('', qw(十 百 千));
my @name2 = ('', qw(万 億 兆));
my $i = 0;
my $j = 0;
my $res = '';
while($num =~ s/(\d)$//) {
my $d = $1;
if($d > 1) {
$res = $name0[$d] . $name1[$i] . $res;
}
elsif($d == 1 and $i != 0) {
$res = $name1[$i] . $res;
}
elsif($d == 1 and $i == 0) {
$res = $name0[$d] . $res;
}
$i++;
if($i % 4 == 0) {
$j++;
$i = 0;
$res = $name2[$j] . $res if($num ne '');
}
}
print $res, "\n";
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | def num2K(num):
if num == 0: return u"零"
s = []
for i,v in enumerate(map(int, reversed(str(num)))):
if i in num2K.table:
s.append(num2K.table2[v]+num2K.table[i]+(i > 3 and u" " or u""))
elif v > 1:
s.append(num2K.table2[int(v)]+num2K.table[i%4])
elif v != 0:
s.append(num2K.table[i%4])
return "".join(reversed(s))
num2K.table = {0:u"", 1:u"十",2:u"百",3:u"千",4:u"万",8:u"億",12:u"兆",16:u"京"}
num2K.table2 = {0:u"",1:u"一",2:u"二",3:u"三",4:u"四", 5:u"五", 6:u"六", 7:u"七", 8:u"八", 9:u"九"}
print num2K(input(u">>"))
|
>>10001 一万 千百十一 と表示されます。
うわーすみません。これで大丈夫かな?
あと、1000と100は千、百、でいいんですよね、これ。でも一千はありなのかな。とりあえず、10000からは一万とかにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | def num2K(num):
if num == 0: return u"零"
s = []
for i,v in enumerate(map(int, reversed(str(num)))):
if v == 0:
continue
if i in num2K.table:
if v > 1 or i > 3:
s.append(num2K.table2[v]+num2K.table[i]+(i > 3 and u" " or u""))
else:
s.append(num2K.table[i] or num2K.table2[v]+(i > 3 and u" " or u""))
elif v > 1:
s.append(num2K.table2[int(v)]+num2K.table[i%4])
elif v != 0:
s.append(num2K.table[i%4])
return "".join(reversed(s))
num2K.table = {0:u"", 1:u"十",2:u"百",3:u"千",4:u"万",8:u"億",12:u"兆",16:u"京"}
num2K.table2 = {0:u"",1:u"一",2:u"二",3:u"三",4:u"四", 5:u"五", 6:u"六", 7:u"七", 8:u"八", 9:u"九"}
print num2K(input(u">>"))
|
さらに突き詰めてみました。たぶんいけているハズ。
この方法だと、どれだけ単位が増えても単純にテーブルに追加するだけでいけます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def num2kanji(num):
if num == 0: return u"零"
num_str = str(num)[::-1]
s = []
for n,v in enumerate(map(int, num_str)):
i = n if n in num2kanji.table else n%4
sep = i>3 and u" "or""
if v == 0 and i > 3 and num_str[n:n+4]!=u"0000":
s.append(num2kanji.table[i]+sep)
elif v > 1 or (i > 3 and v == 1):
s.append(num2kanji.table2[v]+num2kanji.table[i]+sep)
elif v > 0:
s.append(num2kanji.table[i] or num2kanji.table2[v]+sep)
return "".join(reversed(s)).rstrip()
num2kanji.table = {0:u"", 1:u"十",2:u"百",3:u"千",4:u"万",8:u"億",12:u"兆",16:u"京", 20:u"垓",24:u"予", 28:u"穣", 32:u"溝", 36:u"潤", 40:u"正", 44:u"載", 48:u"極", 52:u"恒河沙", 56:u"阿僧祇", 60:u"那由多", 64:u"不可思議", 68:u"無量大数"}
num2kanji.table2 = {0:u"",1:u"一",2:u"二",3:u"三",4:u"四", 5:u"五", 6:u"六", 7:u"七", 8:u"八", 9:u"九"}
print num2kanji(input(u">>"))
|
「恒河沙」以降が10^8ステップになる流儀があるので、もうちょっと面倒では?
ありゃそうなんですか・・・日本の単位も奥深いですねえ。
日本語コケるのでエスケープしてます。こういうときのためにソースコードのASCII以外をエスケープするスクリプトを作ってあるのですが、役に立ちました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | object num2K {
val table = Map(0->"", 1->"\u5341",2->"\u767e",3->"\u5343",4->"\u4e07",8->"\u5104",12->"\u5146",16->"\u4eac")
val table2 = Map(0->"",1->"\u4e00",2->"\u4e8c",3->"\u4e09",4->"\u56db", 5->"\u4e94", 6->"\u516d", 7->"\u4e03", 8->"\u516b", 9->"\u4e5d")
def apply(num:long):String = {
if(num == 0) return "\u96f6"
val lst = num.toString.reverse.map(x=>Integer.parseInt(x+""))
(0 to lst.length-1).foldLeft(List("")){(r, i) =>
if(table.contains(i)) {
table2(lst(i))+table(i)+(if(i>3){" "}else{""})::r
}else if(lst(i) > 1){
table2(lst(i))+table(i%4)::r
}else if(lst(i) != 0){
table(i%4)::r
}else{
r
}
}.mkString("")
}
}
print(">>")
println(num2K(readLong))
|
ミスってたので修正。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | object num2K {
val table = Map(0->"", 1->"\u5341",2->"\u767e",3->"\u5343",4->"\u4e07",8->"\u5104",12->"\u5146",16->"\u4eac")
val table2 = Map(0->"",1->"\u4e00",2->"\u4e8c",3->"\u4e09",4->"\u56db", 5->"\u4e94", 6->"\u516d", 7->"\u4e03", 8->"\u516b", 9->"\u4e5d")
def apply(num:long):String = {
if(num == 0) return "\u96f6"
val numStr = num.toString.reverse.mkString("")
val lst = numStr.map(x=>Integer.parseInt(x+""))
(0 to lst.length-1).foldLeft(List("")){(r, n) =>
val i = (if(table.contains(n)){n}else{n%4})
val sep = (if(i>3){" "}else{""})
val v = lst(n)
if(v==0 && i>3 && !numStr.substring(n).startsWith("0000"))
table(i)::sep::r
else if(v > 1 || (i > 3 && v == 1))
table2(v)+table(i)::sep::r
else if(v > 0)
(if(table(i) == ""){table2(v)}else{table(i)})::sep::r
else
r
}.mkString("").trim
}
}
while(true) {
print(">>")
println(num2K(readLong))
}
|
途中からわけがわからなくなりましたが、多分できました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | public class Test {
public static void main(String[] args) {
System.out.println("args[0] = " + args[0]);
String res = num2K(args[0]);
System.out.println(res);
}
static String[] unitStr = new String[] { "", "万", "億", "兆", /*"京", "垓",
"穰", "溝", "澗", "正", "載", "極",
"恒河沙", "阿僧祇", "那由他", "不可思議", "無量大数",*/ };
static String[] unitStr2 = new String[] { "千", "百", "十", };
static String numStr = "零一ニ三四五六七八九";
public static String num2K(long num) {
String s = Long.toString(num);
return num2K(s);
}
public static String num2K(String s) {
if (s.length() == 1) {
return Character.toString(numStr.charAt(s.charAt(0) - '0'));
}
StringBuffer sb = new StringBuffer();
boolean flag = false;
for (int i = 0; i < s.length(); i++) {
int mod = 3 - (s.length() - i - 1) % 4;
int div = (s.length() - i - 1) / 4;
if (div >= unitStr.length) {
return null;
}
int num = s.charAt(i) - '0';
flag |= num != 0;
if (num == 0 && (mod != 3 || div != 0) && (!flag || mod != 3)) {
continue;
}
if (num == 0 || num == 1 && mod != 3 && !(mod == 0 && div != 0)) {
} else {
sb.append(numStr.charAt(num));
}
if (mod == 3) {
sb.append(unitStr[div]);
flag = false;
} else {
sb.append(unitStr2[mod]);
}
}
return sb.toString();
}
}
|
多分できました。終了するときは、CTRL+Zを押してリターンキーを押します。(Windows以外ではもしかしたら違うキーかも)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | # coding: shift_jis
class SolveError(RuntimeError):
pass
def split(n, m):
while n:
yield n % m
n //= m
def solve(s):
try:
n = int(s)
except ValueError:
raise SolveError("not an integer")
if not(0 < n < 10000000000000000):
raise SolveError("not in range")
large = [u"", u"万", u"億", u"兆"]
small = [u"", u"十", u"百", u"千"]
digit = [u"", u"一", u"二", u"三", u"四", u"五", u"六", u"七", u"八", u"九"]
def convert():
for i_large, n_large in enumerate(split(n, 10000)):
if n_large:
if i_large:
yield u" "
yield large[i_large]
for i_small, n_small in enumerate(split(n_large, 10)):
if n_small:
yield small[i_small]
if not(n_small == 1 and i_small):
yield digit[n_small]
return "".join(reversed(list(convert())))
def main():
while 1:
try:
s = raw_input("> ")
except EOFError:
break
try:
print solve(s)
except SolveError, e:
print "error:", e
if __name__ == '__main__':
main()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | function num2K(num){
table = {0=>"", 1=>"十",2=>"百",3=>"千",4=>"万",8=>"億",12=>"兆",16=>"京"}
table2 = ["","一","二","三","四","五","六","七","八","九"]
if (num == 0) return "零"
i = 0
s = {}
for (v : project(reverse(string(num)), {a->a-'0'})){
if (table.containsKey(i)){
s.add(table2[v] + table[i] + (i > 3 ? " " : "" ))
} else if (v > 1){
s.add(table2[v] + table[i%4])
} else if (v != 0){
s.add(table[i%4])
}
i++
}
join("", reverse(s))
}
print(">>"); flush(); println(num2K(readLine(System.in)))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | (use text.tree)
(use util.list)
(define (positive->kansuji n)
(define (keta-split n keta)
(receive (q r) (quotient&remainder n keta)
(if (< q keta)
(if (zero? q)
(list r)
(list r q))
(cons r (keta-split q keta)))))
(define (add-tanni lst tanni)
(fold
(lambda (x t l)
(cons (list (cond ((and (equal? 1 x) (not (equal? t ""))) "")
((integer? x)
(list-ref '("" "一" "二" "三" "四" "五" "六" "七" "八" "九") x))
(else x))
(if (and (equal? 0 x) (not (equal? t "")))
""
t))
l))
'() lst tanni))
(tree->string
(intersperse " " (add-tanni (map (lambda (n)
(add-tanni (keta-split n 10)
'("" "十" "百" "千")))
(keta-split n 10000))
'("" "万" "億" "兆")))))
|
寝る前にのぞいたらまた増えてる…ペースはやいですね。とりあえずぐっちゃぐっちゃと回答。うごいてるっぽい。
DOUKAKU-38> (number-to-kanji 1732050807568877)
"千七百三十二兆五百八億七百五十六万八千八百七十七"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | (defun number-to-kanji (num)
(let ((digit #("零" "一" "二" "三" "四" "五" "六" "七" "八" "九"))
(subunit #("" "十" "百" "千"))
(unit #("" "万" "億" "兆")))
(loop for i from 0
initially (if (= num 0) (return (aref digit 0)))
for (n m) = (multiple-value-list (floor num 10000)) ; 4 桁ずつ区切る
until (and (= n 0) (= m 0))
for value = (loop for j from 0 to 3 ; 位
for x = (mod (floor m (expt 10 j)) 10) ; 数字
when (/= x 0) ; 零千 零百 零十 対策
collect (format nil "~A~A"
; 一千 一百 一十 対策
(if (and (= x 1) (> j 0)) "" (aref digit x))
(aref subunit j)))
when value appending (cons (aref unit i) value) into result
do (setf num n)
finally (return (apply #'concatenate (cons 'string (reverse result)))))))
|
昔のコード、漢数字名があるかぎり表示可能
123456789012345678901234567890
=>十二穣三千四百五十六禾予七千八百九十外千二百三十四京五千六百七十八兆九千十二億三千四百五十六万七千八百九十
Data.UTF8 は手製のライブラリ
http://www.sampou.org/cgi-bin/haskell.cgi?nobsun%3autf8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | module Main where
import System.Environment
import Data.List
import qualified Data.UTF8 as U
main = do { a:_ <- getArgs
; U.putStrLn $ toKanSuuji a
}
toKan,toKan' :: String -> String
toKan = concat . reverse .zipWith mkname base10000
. map (concat . reverse . conv4) . slices 4
toKan' = concat . reverse . zipWith mkname baseBig
. map toKan . slices 8
toKanSuuji str
= case splitAt 52 $ reverse str of
(s,"") -> toKan $ padding 4 s
(s,b) -> if length b > 40
then "こんな大きな数の漢字数字名は知りません"
else (toKan' $ padding 8 b) ++ toKan s
where
padding n s = s ++ replicate ((n - (length s `mod` n)) `mod` n) '0'
slices :: Int -> [a] -> [[a]]
slices n = unfoldr phi
where phi [] = Nothing
phi xs = Just $ splitAt n xs
base1 = ["","一","二","三","四","五","六","七","八","九"]
base10 = ["","十","百","千"]
base10000 = ["","万","億","兆","京","外","禾予","穣","溝","澗","正","載","極"]
baseBig = ["恒河沙","阿僧祇","那由多","不可思議","無量大数"]
conv4 = zipWith mkname' base10 . map ((base1 !!) . read . (:[]))
mkname "" "" = ""
mkname "" d = d
mkname p "" = ""
mkname p d = d++p
mkname' "" "" = ""
mkname' "" d = d
mkname' p "" = ""
mkname' p "一" = p
mkname' p d = d++p
|
うへぇ 外じゃなくて 垓 ですね。タトしちゃった。
(n - (length s `mod` n)) `mod` n は (- length s) `mod n でよい?
1 2 3 4 5 | -- 「なんとなくlength使いたくない Maybe大好き のオレが来ましたよ」的には
-- foo s = slices 4 $ padding 4 s
-- は
foo s = map (map (fromMaybe '0')) $ takeWhile (isJust.head)
$ slices 4 $ map Just s ++ repeat Nothing
|
たぶん同じ時に書いたScheme版を発掘。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | (use text.tree)
(define (漢数字 整数)
(define 桁 '("" "" "弐" "参" "四" "伍" "六" "七" "八" "九"))
(define 小位列 '("千" "百" "拾" ""))
(define 大位列 '("" "万" "億" "兆" "京" "垓" "(禾予)" "穰" "溝" "澗" "正"
"載" "極"))
(define 特位列 '("恒河砂" "阿僧祇" "那由多" "不可思議" "無量大数"))
(define 壱恒河砂 (expt 10 52))
(define 限界 (expt 10 92))
(define (小再帰 数 単位 位列)
(cond ((zero? 数) '())
((= 数 1) '("壱"))
((>= 数 単位)
`(,(list-ref 桁 (quotient 数 単位)) ,(car 位列)
,@(小再帰 (modulo 数 単位) (/ 単位 10) (cdr 位列))))
(else (小再帰 数 (/ 単位 10) (cdr 位列)))))
(define (大再帰 数 位列)
`(,@(if (>= 数 10000)
(大再帰 (quotient 数 10000) (cdr 位列))
'())
,@(if (zero? (modulo 数 10000))
'()
`(,(小再帰 (modulo 数 10000) 1000 小位列) ,(car 位列)))))
(define (特大再帰 数 位列)
`(,@(if (>= 数 100000000)
(特大再帰 (quotient 数 100000000) (cdr 位列))
'())
,@(if (zero? (modulo 数 100000000))
'()
`(,(大再帰 (modulo 数 100000000) 大位列) ,(car 位列)))))
(tree->string
(cond ((>= 整数 限界) "限界突破")
((>= 整数 壱恒河砂)
(list (特大再帰 (quotient 整数 壱恒河砂) 特位列)
(大再帰 (modulo 整数 壱恒河砂) 大位列)))
(else (大再帰 整数 大位列))))
)
|
Squeak Smalltalk で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | | 数 漢数字 |
数 := 1732050807568877.
漢数字 := ''.
#('' 万 億 兆 京) do: [:大位 |
| 大位の数 |
大位の数 := ''.
#('' 十 百 千) do: [:小位 |
| 小位の数 |
小位の数 := #('' 一 二 三 四 五 六 七 八 九) at: 数 \\ 10 + 1.
数 := 数 // 10.
小位の数 ifNotEmpty: [
(小位 notEmpty and: [小位の数 = '一']) ifTrue: [小位の数 := ''].
大位の数 := 小位の数, 小位, 大位の数]].
大位の数 ifNotEmpty: [漢数字 := 大位の数, 大位, 漢数字]].
^漢数字 "=> '千七百三十二兆五百八億七百五十六万八千八百七十七' "
|
M-x number-to-kanji <RET> 1732050807568877 <RET> =>千七百三十二兆五百八億七百五十六万八千八百七十七
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | (require 'cl)
(defun number-to-kanji (str)
(interactive "sNumber: ")
(and (> (length str) 52) (error "52桁まで"))
(labels ((nsplit (str)
(labels ((rev (s) (concat (nreverse (mapcar #'identity s)))))
(setq str (rev str))
(let ((start 0) r)
(while (string-match ".\\{1,4\\}" str start)
(push (match-string 0 str) r)
(setq start (match-end 0)))
(mapcar #'rev r))))
(kanji (str)
(apply #'concat
(nreverse
(mapcar*
#'(lambda (i n)
(let ((s (nth (string-to-number n)
'("〇" "一" "二" "三" "四" "五" "六" "七" "八" "九"))))
(and (> i 0) (string= s "一") (setq s ""))
(if (string= s "〇") ""
(concat s (nth i '("" "十" "百" "千"))))))
'(0 1 2 3) (nreverse (mapcar #'string str)))))))
(let ((l (nreverse (mapcar #'kanji (nsplit str)))))
(funcall
(if current-prefix-arg #'insert #'message)
(apply #'concat
(nreverse
(mapcar* #'(lambda (i s)
(concat s (if (string= s "") ""
(nth i '("" "万" "億" "兆" "京" "垓" "(禾予)" "穣" "溝" "澗" "正" "載" "極")))))
(number-sequence 0 (- (length l) 1)) l)))))))
|




にしお
#3394()
Rating0/0=0.00
このお題は匿名での投稿です。 与えられる整数の範囲は一京未満(10000000000000000未満)としたいと思います。 ご投稿ありがとうございます。
2年前のLL Day&Nightの「キミならどう書く」で、 これ専用のCPANモジュールが作られていたような記憶があるので 勝手にPerlからの挑戦状とみなしておきます(笑)
[ reply ]