DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #248 - Chinese Numerals

Create a function that takes a Number as its argument and returns a Chinese numeral string. You don't need to validate the input argument, it will always be a Number in the range [0, 99999] with no decimals.

Simplified Chinese numerals have characters representing each number from 0 to 9 and additional numbers representing larger numbers like 10, 100, 1000, and 10000.

0 líng 零
1 yī 一
2 èr 二
3 sān 三
4 sì 四
5 wǔ 五
6 liù 六
7 qī 七
8 bā 八
9 jiǔ 九
10 shí 十
100 bǎi 百
1000 qiān 千
10000 wàn 万

Multiple-digit numbers are constructed by first the digit value (1 to 9) and then the place multiplier (such as 10, 100, 1000), starting with the most significant digit. A special case is made for 10 - 19 where the leading digit value (yī 一) is dropped. Note that this special case is only made for the actual values 10 - 19, not any larger values. Trailing zeros are omitted, but interior zeros are grouped together and indicated by a single 零 character without giving the place multiplier.

Examples

10 十
11 十一
18 十八
21 二十一
110 一百一十
123 一百二十三
24681 二万四千六百八十一

Tests

to_chinese_numeral(9)
to_chinese_numeral(10)
to_chinese_numeral(110)
to_chinese_numeral(111)
to_chinese_numeral(1000)
to_chinese_numeral(10000)

Good luck!


This challenge comes from ConstableBrew on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Top comments (4)

Collapse
 
savagepixie profile image
SavagePixie • Edited

I didn't quite get what the deal was with the zero, and since there were no examples to show how it worked, I decided to do Japanese numerals, which are basically the same but without the zero. Here's my JavaScript implementation. It could probably be a lot simpler, but oh well.

const numerals = {
    0: '0',
    1: '',
    2: '',
    3: '',
    4: '',
    5: '',
    6: '',
    7: '',
    8: '',
    9: '',
}

const units = {
    0: '',
    1: '',
    2: '',
    3: '',
    4: '',
}

const toJapaneseNumeral = n => n
    .toString()
    .split('')
    .reverse()
    .map((x, i) => numerals[x] + units[i])
    .reverse()
    .join('')
    .replace('一十', '')
    .replace(/0.?/g, '')
Collapse
 
peterlau profile image
Peter Lau

Add more test cases.

// 28901 二万八千九百零一
// 28911 二万八千九百一十一
// 20911 二万零九百一十一
// 20901 二万零九百零一
// 20001 二万零一
// 29000 二万九

let numberArray = [
  '',
  '',
  '',
  '',
  '',
  '',
  '',
  '',
  '',
  '',
]

let unitArray = ['', '', '', '', '']

const toChineseNumeral = input => {
  return input.toString().split('').map(
    (number, idx) => {
      return numberArray[parseInt(number)]
    }
  ).reduce(
    (acc, current) => {
      let last = acc[acc.length - 1]
      if (last == '' && current == '')
        acc[acc.length - 1] = ' '
      if (acc.length == (input.length - 1) && current == '')
        current = ''
      acc.push(current)
      return acc
    },
    []
  ).map(
    (elem, idx) => {
      if (elem == ' ' || elem == '')
        return elem.trim()
      return elem + unitArray[input.length-1 - idx]
    }
  ).join('').replace(/^一十/, '')
}

console.log(toChineseNumeral(29389))
console.log(toChineseNumeral(29000))
console.log(toChineseNumeral(20001))
console.log(toChineseNumeral(20901))

console.log([
    10,
    11,
    18,
    21,
    110,
    123,
    24681
].map(toChineseNumeral))
Collapse
 
raymperry profile image
Ray M. Perry

First time doing one of these. Figured I'd throw out one of those weird languages (Raku):

use v6;

sub toChineseNumeral(Int $number = 0) {
    my $numerals = <         >;
    my $places = $number.polymod(10, 10, 10, 10).reverse;
    my Str $numbers = join "", do for ^4 {
        my Int $number = $places[$_];
        next if $number == 0;
        $numerals[$number] ~ <   >[$_];
    }

    given $number {
        when 0..9 { $numerals[$places.tail] }
        when 10 { $numbers.substr(1) }
        when 11..19 { $numbers.substr(1) ~ $numerals[$places.tail] }
        default { $numbers ~ $numerals[$places.tail] }
    }
}

sub MAIN() {
    for [9, 10, 11, 18, 21, 110, 111, 123, 1000, 10000, 24681] {
        say $_ ~ ": " ~ toChineseNumeral($_)
    }
}