# Convert Chinese numbers

In Chinese, numbers are written as follows:

1 一 2 二 3 三 4 四 5 五 6 六 7 七 8 八 9 九 10 十

For numbers above 10, it is expressed as the number of tens and the number of ones. If there is only one ten, you do not need to explicitly say one, and if there are no ones, you don't need to put anything after:

11 十一
24 二十四
83 八十三
90 九十

For numbers above 100, you use the same logic, but with the character . This time though, if there is only one hundred, you still need to write it out, and if there are no tens, you need to say .

100 一百 231 二百三十一 803 八百零三 999 九百九十九

Your task is to convert these Chinese numerals into Arabic numerals. Given a number N in Chinese ( (1) <= N <= 九百九十九 (999)), convert it into an Arabic number.

Remember, this is , so the code with the smallest number of bytes wins.

• Can you add test cases 503 and 380? Oct 27, 2016 at 14:46
• ^ Good point. If I am following correctly, it should be 503 -> 五百三 and 380 -> 三百八十. Also, you say for tens that you do not need to explicitly say one. Does that mean it doesn't matter if we do?
Oct 27, 2016 at 15:03
• Related Oct 27, 2016 at 16:26
• Up to 999? You shuold give the upper limit Oct 28, 2016 at 8:50
• 503 should be 五百零三 as there are no tens (I think) Oct 28, 2016 at 8:53

## JavaScript (ES6), 112 bytes

s=>[...s].map(c=>d=(i="零一二三四五六七八九十百".search(c))>9?(n+=(d||1)*(i*90-890),0):i,n=d=0)&&n+d

Digits 一-九 are converted to decimal and saved in d, while 十 and 百 multiply the last digit by 10 or 100 respectively and accumulate it in n. is effectively ignored, since d is already zero when it is encountered.

## Perl, 110 bytes

98 bytes code + 12 for -plC -Mutf8.

Perl does hate unicode. Hopefully I haven't missed any edge cases, I had an issue with numbers like 二百十 but I've addressed that now!

s/十/*10+/;s/百/*100+/;y/一二三四五六七八九零/123456789 /;s/^\*|\+\*/+/g;$_=eval"$_-0"

### Usage

perl -plC -Mutf8 -e 's/十/*10+/;s/百/*100+/;y/一二三四五六七八九零/123456789 /;s/^\*|\+\*/+/g;$_=eval"$_-0"' <<< '一

1
2
3
4
5
6
7
8
9
10
11
24
83
90
100
231
803
999

preg_match_all("#[1-9]?10+|[1-9]#",str_replace(["一","二","三","四","五","六","七","八","九","十","百"],[1,2,3,4,5,6,7,8,9,10,100],$argv[1]),$z);foreach($z[0]as$p)$s+=($b=substr_count($p,0))?$p[0]*10**$b:$p;echo$s; • Too bad that strtr is not multibyte safe. It could save you 23 bytes. But you can use 0+ instead of 00?, saving one byte or you can a) replace with a and aa instead of 10 and 100, b) use a+ instead of 100? in the regex and c) a instead of 0 for substr_count (-4). Oct 28, 2016 at 8:30 • @Titus your way with a can not work in the range 10-19 Oct 28, 2016 at 8:46 # Java 7, 236233 229 bytes int c(String s){String x=" 一二三四五六七八九十百";int l=s.length(),i=x.indexOf(s.charAt(l-1)),j=x.indexOf(s.charAt(0)),q=j*100;return l<2?i:l<3?i==10?j*10:i>10?q:10+i:l<4?j*10+i:l<5?q+i:q+i+x.indexOf(s.charAt(2))*10;} Ungolfed & test code: Try it here. class M{ static int c(String s){ String x = " 一二三四五六七八九十百"; int l = s.length(), i = x.indexOf(s.charAt(l-1)), j = x.indexOf(s.charAt(0)); if(l<2) return i; // 1-10 if(l<3){ if(i==10) return j*10; // 20,30,40,50,60,70,80,90 if(i>10) return j*100; // 100,200,300,400,500,600,700,800,900 return 10+i; // 11-19 } if(l<4) return j*10+i; // 21-29,31-39,41-49,51-59,61-69,71-79,81-89,91-99 if(l<5) return j*100+i; // 101-109,201-209,301-309,401-409,501-509,601-609,701-709,801-809,901-909 return j*100+i+x.indexOf(s.charAt(2))*10; // 111-119,121-129,131-139,...,971-979,981-989,991-999 } public static void main(String[] a){ System.out.println(c("一")); System.out.println(c("二")); System.out.println(c("三")); System.out.println(c("四")); System.out.println(c("五")); System.out.println(c("六")); System.out.println(c("七")); System.out.println(c("八")); System.out.println(c("九")); System.out.println(c("十")); System.out.println(c("十一")); System.out.println(c("二十四")); System.out.println(c("八十三")); System.out.println(c("九十")); System.out.println(c("一百")); System.out.println(c("二百三十一")); System.out.println(c("八百零三")); System.out.println(c("九百九十九")); } } Output: 1 2 3 4 5 6 7 8 9 10 11 24 83 90 100 231 803 999 # PowerShell, 107 bytes switch -r($args){百{$s+=100*$d}十{$s+=10*($d+!$d)}.{$d='一二三四五六七八九'.IndexOf($_)+1}}$d+$s Try it online! • 106 bytes! Sep 14, 2021 at 12:07 # PowerShell Core, 131 bytes$args|%{if($i=("一二三四五六七八九"|% I*f$_)+1){$b=$i}if($_-eq"十"){$t+=(!$b+$b)*10
$b=0}if(!$i){$t+=$b*100
$b=0}}$t+\$b

Try it online!

-10 bytes thanks to Zaelin Goodman!

• -10 bytes Sep 13, 2021 at 20:34

# C#, 197 210 bytes

int x(string s){if(s=="")return 0;if(s[0]=='零')s=s.Substring(1);if(s[0]=='十')s="一"+s;string t=" 一二三四五六七八九";return s.Length<2?t.IndexOf(s[0]):(t.IndexOf(s[0])*(s[1]=='百'?100:10)+x(s.Substring(2)));}

Wrong byte count previously due to encoding ignored...

Big5 Encoding

A recursive solution which pads the input if it's 10-19 for easier processing, then process from left 2 characters at a time.

Ungolfed

public int x(string s)
{
if (s == "")
return 0;   // Recursion termination when input is divisible by 10 (no unit digit character)
if (s[0] == '零')
s = s.Substring(1);   // Ignore '零'
if (s[0 ]== '十')
s = "一" + s;   // Normalize 10-19 by padding with "一"
string t = " 一二三四五六七八九";   // Index lookup
return s.Length < 2
? t.IndexOf(s[0])   // 0-9
: (t.IndexOf(s[0]) * (s[1] == '百' ? 100 : 10) + x(s.Substring(2)));
// Get the first character's digit, multiply by 100 or 10 depends on 2nd character, and recursively process from 3rd character onwards
}

# Python 3, 128 bytes

Saving 2+3 bytes thanks to Shebang and 2 for replacing (d>9)+(d>10) with max(d-9,0)

n=a=0
for c in input():d=" 一二三四五六七八九十百".find(c);n+=[0,10*a**(a>0),a*100][max(d-9,0)];a=d*(d<10)
print(n+a)

Ungolfed:

n=a=0
for c in input():
d=" 一二三四五六七八九十百".find(c)
n+=[0, 10*a**(a>0), a*100][max(d-9,0)]
a=d*(d<10)
print(n+a)

n=a=0
for c in input():
d=" 一二三四五六七八九十百".find(c)
if d<=9:a=d
elif d==10:n+=[1,a][a>0]*10;a=0
elif d==11:n+=a*100;a=0
print(n+a)

n will be the final number and a is the previous digit.

• The spec has changed.