8
\$\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\$
  • 3
    \$\begingroup\$ Can you add test cases 503 and 380? \$\endgroup\$ – Martin Ender Oct 27 '16 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 '16 at 15:03
  • \$\begingroup\$ Related \$\endgroup\$ – NoOneIsHere Oct 27 '16 at 16:26
  • \$\begingroup\$ Up to 999? You shuold give the upper limit \$\endgroup\$ – edc65 Oct 28 '16 at 8:50
  • \$\begingroup\$ 503 should be 五百零三 as there are no tens (I think) \$\endgroup\$ – edc65 Oct 28 '16 at 8:53
3
\$\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\$
  • \$\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 '16 at 8:30
  • \$\begingroup\$ @Titus your way with a can not work in the range 10-19 \$\endgroup\$ – Jörg Hülsermann Oct 28 '16 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\$
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\$
  • \$\begingroup\$ The spec has changed. \$\endgroup\$ – Kade Oct 27 '16 at 15:12
  • \$\begingroup\$ @Shebang Luckily it does not matter, 803 still works. \$\endgroup\$ – Karl Napf Oct 27 '16 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 '16 at 15:24
  • 1
    \$\begingroup\$ [1,a][a>0]*10 -> 10*a**(a>0) saves two bytes :) \$\endgroup\$ – Kade Oct 27 '16 at 15:28
  • 1
    \$\begingroup\$ [0,d][d<=9] -> d*(d<10) saves three bytes too! \$\endgroup\$ – Kade Oct 27 '16 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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