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.

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!

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, '')
``````

Peter Lau

``````// 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))
``````

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(\$_)
}
}
``````