I read @ xuyun19840618's "Mutual conversion between Chinese numerals and Arabic numerals" and wrote my own implementation in the comments.
Anyway, wouldn't it be interesting if we could calculate with Chinese numerals? I thought it was a class.
It is made a subclass of int class so that it can be operated.
The int instance is immutable, so the value must be given in the __new__
method.
Since the operation result will not be displayed in Kanji unless it is made an instance of KanjiInt again, the operation method is overridden to KanjiInt. Since it is difficult to define the method one by one, the for loop overrides the methods of the unary operator and the binary operator.
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
class KanjiInt(int):
def __new__(cls, value=0):
arabic = kanji_to_int(value)
if isinstance(arabic, int):
value = arabic
return int.__new__(cls, value)
def __str__(self):
return int_to_kanji(self)
def __repr__(self):
return 'KanjiInt(%s)' % repr(str(self))
_unary = ('abs', 'inv', 'invert', 'neg', 'pos')
_binary = ('add', 'sub', 'mul', 'floordiv', 'mod', 'pow',
'and', 'or', 'xor', 'lshift', 'rshift')
for method in _unary:
exec('KanjiInt.__{0}__ = lambda self: KanjiInt(int.__{0}__(self))'.format(method))
for method in _binary:
exec('KanjiInt.__{0}__ = lambda self, value: KanjiInt(int.__{0}__(self, value))'.format(method))
unitlong = 'Tsunekawa Sha', 'A monk', 'Decillion and others', 'Mysterious', 'Immeasurable large number'
unit4 = ('',) + tuple('100 billion trillion kyoho') + unitlong
unit1 = ('',) + tuple('Ten thousand')
digits = tuple('〇 1 2 3 4 5 6 7 8 9')
arabic4 = {unit[:1]: 10000**i for i, unit in enumerate(unit4)}
arabic1 = {unit: 10**i for i, unit in enumerate(unit1)}
arabics = {digit: i for i, digit in enumerate(digits)}
def int_to_kanji(arabic):
arabic = int(arabic)
if arabic == 0:
return digits[0]
sign = '-' if arabic < 0 else ''
arabic = abs(arabic)
def convert():
for column, digit in enumerate(map(int, str(arabic)[::-1])):
if column % 4 == 0 and (arabic // (10 ** column)) % 10000 != 0:
yield unit4[column // 4]
if digit != 0:
yield unit1[column % 4]
if digit != 1 or column % 4 == 0: #One thousand,One hundred,Except for eleven
yield digits[digit]
return sign + ''.join(list(convert())[::-1])
def kanji_to_int(kanji):
if not isinstance(kanji, str):
return 'error'
for longname in unitlong:
kanji = kanji.replace(longname, longname[0])
a0 = a1 = a4 = 0
for j in kanji:
if j in arabics:
a0 = a0 * 10 + arabics[j]
elif j in arabic1:
a1 += (a0 or 1) * arabic1[j]
a0 = 0
elif j in arabic4:
a4 += (a0 + a1 or 1) * arabic4[j]
a0 = a1 = 0
else:
return 'error'
return a0 + a1 + a4
if __name__ == '__main__':
value = KanjiInt('Fifty-six')
print("value =", value)
print('repr(value) =', repr(value))
print('str(value) =', str(value))
print('int(value) =', int(value))
print('abs(value) =', abs(value))
print('+value =', +value)
print('-value =', -value)
print('~value =', ~value)
print('value + 3 =', value + 3)
print('3 + value =', 3 + value)
print('value - 3 =', value - 3)
print('value * 3 =', value * 3)
print('value / 3 =', value / 3)
print('value // 3 =', value // 3)
print('value % 3 =', value % 3)
print('value ** 3 =', value ** 3)
print('value & 3 =', value & 3)
print('value | 3 =', value | 3)
print('value ^ 3 =', value ^ 3)
print('value << 3 =', value << 3)
print('value >> 3 =', value >> 3)
Execution result
value =Fifty-six
repr(value) = KanjiInt('Fifty-six')
str(value) =Fifty-six
int(value) = 56
abs(value) =Fifty-six
+value =Fifty-six
-value = -Fifty-six
~value = -Fifty-seven
value + 3 =Fifty-nine
3 + value = 59
value - 3 =Fifty-three
value * 3 =168
value / 3 = 18.666666666666668
value // 3 =XVIII
value % 3 =two
value ** 3 =175,616
value & 3 = 〇
value | 3 =Fifty-nine
value ^ 3 =Fifty-nine
value << 3 =448
value >> 3 =Seven
Recommended Posts