15
\$\begingroup\$

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.

\$\endgroup\$
5
  • 3
    \$\begingroup\$ Can you add test cases 503 and 380? \$\endgroup\$ Oct 27, 2016 at 14:46
  • 1
    \$\begingroup\$ ^ 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? \$\endgroup\$
    – Kade
    Oct 27, 2016 at 15:03
  • \$\begingroup\$ Related \$\endgroup\$ Oct 27, 2016 at 16:26
  • \$\begingroup\$ Up to 999? You shuold give the upper limit \$\endgroup\$
    – edc65
    Oct 28, 2016 at 8:50
  • 2
    \$\begingroup\$ 503 should be 五百零三 as there are no tens (I think) \$\endgroup\$
    – edc65
    Oct 28, 2016 at 8:53

8 Answers 8

4
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

PHP, 225 Bytes

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;
\$\endgroup\$
2
  • \$\begingroup\$ 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). \$\endgroup\$
    – Titus
    Oct 28, 2016 at 8:30
  • \$\begingroup\$ @Titus your way with a can not work in the range 10-19 \$\endgroup\$ Oct 28, 2016 at 8:46
2
\$\begingroup\$

Java 7, 236 233 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
\$\endgroup\$
1
\$\begingroup\$

PowerShell, 107 bytes

switch -r($args){百{$s+=100*$d}十{$s+=10*($d+!$d)}.{$d='一二三四五六七八九'.IndexOf($_)+1}}$d+$s

Try it online!

\$\endgroup\$
1
1
\$\begingroup\$

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!

\$\endgroup\$
1
0
\$\begingroup\$

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
}
\$\endgroup\$
0
\$\begingroup\$

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)

Initial answer

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.

\$\endgroup\$
7
  • \$\begingroup\$ The spec has changed. \$\endgroup\$
    – Kade
    Oct 27, 2016 at 15:12
  • \$\begingroup\$ @Shebang Luckily it does not matter, 803 still works. \$\endgroup\$
    – Karl Napf
    Oct 27, 2016 at 15:18
  • 1
    \$\begingroup\$ @TimmyD It is ignored. find returns -1 and that is smaller than 9 so n and a are untouched. \$\endgroup\$
    – Karl Napf
    Oct 27, 2016 at 15:24
  • 1
    \$\begingroup\$ [1,a][a>0]*10 -> 10*a**(a>0) saves two bytes :) \$\endgroup\$
    – Kade
    Oct 27, 2016 at 15:28
  • 1
    \$\begingroup\$ [0,d][d<=9] -> d*(d<10) saves three bytes too! \$\endgroup\$
    – Kade
    Oct 27, 2016 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.