Advertisement
Guest User

Untitled

a guest
Oct 19th, 2019
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.32 KB | None | 0 0
  1. #!/usr/bin/env node
  2.  
  3. function getDigitFromRight(numberString, indexFromRight) {
  4. if (indexFromRight < 0) {
  5. throw new Error('you should not be here')
  6. }
  7. if (indexFromRight >= numberString.length) {
  8. return 0
  9. }
  10. return parseInt(numberString[numberString.length - 1 - indexFromRight])
  11. }
  12.  
  13. // test('getDigitFromRight', () => {
  14. // expect(getDigitFromRight('649', 0)).toBe(9)
  15. // expect(getDigitFromRight('649', 1)).toBe(4)
  16. // expect(getDigitFromRight('649', 2)).toBe(6)
  17. // })
  18. // test('return 0 when out of range', () => {
  19. // expect(getDigitFromRight('649', 3)).toBe(0)
  20. // })
  21.  
  22. function add(a = '' /*string*/, b = '' /*string*/) {
  23. let longNumberString = a
  24. let shortNumberString = b
  25. if (b.length > a.length) {
  26. longNumberString = b
  27. shortNumberString = a
  28. }
  29.  
  30. let carry = 0
  31. let answer = ''
  32.  
  33. for (let index = 0; index < longNumberString.length; index++) {
  34. const upDigit = getDigitFromRight(longNumberString, index)
  35. const downDigit = getDigitFromRight(shortNumberString, index)
  36.  
  37. const digitSum = upDigit + downDigit + carry
  38. answer = (digitSum % 10).toString() + answer
  39. carry = Math.floor(digitSum / 10)
  40. }
  41.  
  42. if (carry !== 0) {
  43. answer = carry.toString() + answer
  44. }
  45.  
  46. return answer
  47. }
  48.  
  49. // test('add', () => {
  50. // expect(add('0', '0')).toBe('0')
  51. // expect(add('0', '2')).toBe('2')
  52. // expect(add('1', '2')).toBe('3')
  53. // expect(add('10', '2')).toBe('12')
  54. // expect(add('10', '200')).toBe('210')
  55. // expect(add('96', '4')).toBe('100')
  56. // expect(add('960700081327001', '43520069100001')).toBe('1004220150427002')
  57. // })
  58. // test('add big int', () => {
  59. // expect(add('9007199254740991', '9007199254740991')).toBe('18014398509481982')
  60. // expect(add('9007199254740991', '9007199')).toBe('9007199263748190')
  61. // expect(add('9007199254740991', '90071992547409919007199254740991')).toBe('90071992547409928014398509481982')
  62. // })
  63.  
  64. const DIGITS_IN_KOREAN = '일이삼사오육칠팔구'
  65. const MAGNITUDES = {
  66. 십: 1, // 10^1 = 10
  67. 백: 2,
  68. 천: 3,
  69. 만: 4,
  70. 억: 8,
  71. 조: 12,
  72. }
  73.  
  74. function koreanToNumberString(koreanString) {
  75. const KOREAN_TO_DIGIT = {}
  76. DIGITS_IN_KOREAN.split('').forEach((char, index) => {
  77. KOREAN_TO_DIGIT[char] = index + 1
  78. })
  79.  
  80. let numString = ''
  81.  
  82. for (let indexFromRight = koreanString.length - 1; indexFromRight >= 0; indexFromRight--) {
  83. const char = koreanString[indexFromRight]
  84. if (typeof KOREAN_TO_DIGIT[char] !== 'undefined') {
  85. numString = KOREAN_TO_DIGIT[char].toString() + numString
  86. } else if (typeof MAGNITUDES[char] !== 'undefined') {
  87. if (MAGNITUDES[char] < 4) {
  88. numString = numString.padStart(Math.floor(numString.length / 4) * 4 + MAGNITUDES[char], '0')
  89. } else {
  90. numString = numString.padStart(MAGNITUDES[char], '0')
  91. }
  92.  
  93. if (
  94. indexFromRight !== 0 &&
  95. typeof MAGNITUDES[koreanString[indexFromRight - 1]] !== 'undefined' &&
  96. MAGNITUDES[koreanString[indexFromRight - 1]] > MAGNITUDES[char]
  97. ) {
  98. numString = '1' + numString
  99. }
  100. } else {
  101. throw new Error(`unknown character ${char}`)
  102. }
  103. }
  104.  
  105. if (typeof MAGNITUDES[koreanString[0]] !== 'undefined') {
  106. numString = '1' + numString
  107. }
  108.  
  109. return numString
  110. }
  111.  
  112. const TEST_CASES = {
  113. 일: '1',
  114. 구: '9',
  115. 십: '10',
  116. 이십: '20',
  117. 십일: '11',
  118. 십일: '11',
  119. 천백십일: '1111',
  120. 십: '10',
  121. 일조: '1000000000000',
  122. 일억: '100000000',
  123. 십만: '100000',
  124. 천십만: '10100000',
  125. 백십만: '1100000',
  126. 천백십만: '11100000',
  127. 일조일억일만: '1000100010000',
  128. 오백삼십조칠천팔백구십만천오백삼십구: '530000078901539',
  129. 삼조사천이만삼천구: '3000040023009',
  130. 육십사억삼천십팔만칠천육백구: '6430187609',
  131. 사십삼: '43',
  132.  
  133. // big int
  134. 구천칠조천구백구십이억오천사백칠십사만구백구십일: '9007199254740991',
  135. 구천칠조천구백구십이억오천사백칠십사만구백구십칠: '9007199254740997',
  136. 구천칠조천구백구십이억오천사백칠십사만구백구십구: '9007199254740999',
  137. 구천구백구십구조구천구백구십구억구천구백구십구만구천구백구십구: '9999999999999999',
  138. }
  139.  
  140. // test.each(Object.entries(TEST_CASES))('%s -> %s', (korean, expected) => {
  141. // expect(koreanToNumberString(korean)).toBe(expected)
  142. // })
  143.  
  144. function numberStringToKorean(numberString) {
  145. if (numberString.length > 16) {
  146. throw new Error('Cannot express. 일경 미만의 숫자만 표현 가능합니다.')
  147. }
  148.  
  149. const DIGIT_TO_KOREAN = {}
  150. DIGITS_IN_KOREAN.split('').forEach((char, index) => {
  151. DIGIT_TO_KOREAN[index + 1] = char
  152. })
  153.  
  154. const EVERY_FOURTH = ['만', '억', '조']
  155. const INSIDE_FOURTH = ['십', '백', '천']
  156.  
  157. let answer = ''
  158.  
  159. for (let index = 0; index < numberString.length; index++) {
  160. const numChar = numberString[index]
  161.  
  162. if (numChar !== '0') {
  163. if (numChar !== '1' || (numberString.length - 1 - index) % 4 === 0) {
  164. answer += DIGIT_TO_KOREAN[numChar]
  165. }
  166. if ((numberString.length - 1 - index) % 4 !== 0) {
  167. answer += INSIDE_FOURTH[((numberString.length - 1 - index) % 4) - 1]
  168. }
  169. }
  170. if (numberString.length - index - 1 !== 0 && (numberString.length - index - 1) % 4 === 0) {
  171. if (answer.length > 0 && !(answer[answer.length - 1] === '조' || answer[answer.length - 1] === '억')) {
  172. answer += EVERY_FOURTH[(numberString.length - index - 1) / 4 - 1]
  173. }
  174. }
  175. }
  176.  
  177. if (answer.length !== 2 && answer.slice(0, 2) === '일만') {
  178. return answer.slice(1)
  179. }
  180.  
  181. return answer
  182. }
  183.  
  184. // test('numberStringToKorean', () => {
  185. // expect(numberStringToKorean('1')).toBe('일')
  186. // expect(numberStringToKorean('9')).toBe('구')
  187. // expect(numberStringToKorean('39')).toBe('삼십구')
  188. // expect(numberStringToKorean('109')).toBe('백구')
  189. // expect(numberStringToKorean('1701')).toBe('천칠백일')
  190. // expect(numberStringToKorean('10000')).toBe('일만')
  191. // expect(numberStringToKorean('100000')).toBe('십만')
  192. // expect(numberStringToKorean('110000')).toBe('십일만')
  193. // expect(numberStringToKorean('110011')).toBe('십일만십일')
  194. // expect(numberStringToKorean('1000000000000')).toBe('일조')
  195. // expect(numberStringToKorean('1004')).toBe('천사')
  196. // expect(numberStringToKorean('10040000')).toBe('천사만')
  197. // expect(numberStringToKorean('100400000000')).toBe('천사억')
  198. // expect(numberStringToKorean('1004000000000000')).toBe('천사조')
  199. // })
  200.  
  201. // test.each(Object.entries(TEST_CASES).map(a => a.reverse()))('%s -> %s', (numString, expected) => {
  202. // expect(numberStringToKorean(numString)).toBe(expected)
  203. // })
  204.  
  205. function addKorean(a, b) {
  206. return numberStringToKorean(add(koreanToNumberString(a), koreanToNumberString(b)))
  207. }
  208.  
  209. // test('addKorean', () => {
  210. // expect(addKorean('구백육십조칠천억팔천백삼십이만칠천일', '사십삼조오천이백억육천구백십만일')).toBe(
  211. // '천사조이천이백일억오천사십이만칠천이',
  212. // )
  213. // expect(addKorean('일', '이')).toBe('삼')
  214. // })
  215.  
  216. // test('problem test case', () => {
  217. // expect(addKorean('오백삼십조칠천팔백구십만천오백삼십구', '삼조사천이만삼천구')).toBe(
  218. // '오백삼십삼조일억천팔백구십이만사천오백사십팔',
  219. // )
  220. // expect(addKorean('육십사억삼천십팔만칠천육백구', '사십삼')).toBe('육십사억삼천십팔만칠천육백오십이')
  221. // expect(addKorean('이천구백육십조천오백칠십만삼천구백구십', '삼천사백오십조일억이천만육백사십삼')).toBe(
  222. // '육천사백십조일억삼천오백칠십만사천육백삼십삼',
  223. // )
  224. // expect(addKorean('사십오억삼천육십만오백구십', '칠십억천이백삼십오만칠천구십이')).toBe(
  225. // '백십오억사천이백구십오만칠천육백팔십이',
  226. // )
  227. // expect(addKorean('오억사천', '백십일')).toBe('오억사천백십일')
  228. // expect(addKorean('만오천사백삼십', '십구만삼천오백')).toBe('이십만팔천구백삼십')
  229. // expect(addKorean('일조', '삼')).toBe('일조삼')
  230. // expect(addKorean('일억', '만')).toBe('일억일만')
  231.  
  232. // expect(addKorean('구백육십조칠천억팔천백삼십이만칠천일', '사십삼조오천이백억육천구백십만일')).toBe(
  233. // '천사조이천이백일억오천사십이만칠천이',
  234. // )
  235. // expect(addKorean('천백십일', '구천오백구십구')).toBe('만칠백십')
  236. // })
  237.  
  238. const args = process.argv.slice(2)
  239. console.log(addKorean(args[0], args[1]))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement