From: Greg Hurrell Date: Sat, 1 Aug 2015 00:43:08 +0000 (-0700) Subject: Add multiplyDigits and friends X-Git-Url: https://git.wincent.com/hextrapolate.git/commitdiff_plain/e123f7cc825b33d1ecb20512d922107233666195?hp=b68717dc492a9abc8ca446579d955b8997c4d5b0 Add multiplyDigits and friends --- diff --git a/.babelrc b/.babelrc index ce840ab..019f402 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,8 @@ { - "stage": 0 -} \ No newline at end of file + "optional": [ + "es7.asyncFunctions", + "es7.classProperties", + "es7.decorators", + "es7.objectRestSpread" + ] +} diff --git a/src/__tests__/multiplyDigits-test.js b/src/__tests__/multiplyDigits-test.js new file mode 100644 index 0000000..b2de7e1 --- /dev/null +++ b/src/__tests__/multiplyDigits-test.js @@ -0,0 +1,38 @@ +/** + * Copyright 2015-present Greg Hurrell. All rights reserved. + * Licensed under the terms of the MIT license. + */ + +'use strict'; + +import multiplyDigits from '../multiplyDigits'; + +describe('multiplyDigits()', () => { + it('multiplies by 0', () => { + expect(multiplyDigits([1], 0, 2)).toEqual([0]); + expect(multiplyDigits([5], 0, 8)).toEqual([0]); + expect(multiplyDigits([4], 0, 10)).toEqual([0]); + expect(multiplyDigits([12], 0, 16)).toEqual([0]); + }); + + it('multiplies by 1', () => { + expect(multiplyDigits([1], 1, 2)).toEqual([1]); + expect(multiplyDigits([5], 1, 8)).toEqual([5]); + expect(multiplyDigits([4], 1, 10)).toEqual([4]); + expect(multiplyDigits([12], 1, 16)).toEqual([12]); + }); + + it('multiplies by 2', () => { + expect(multiplyDigits([1], 2, 2)).toEqual([0, 1]); + expect(multiplyDigits([5], 2, 8)).toEqual([2, 1]); + expect(multiplyDigits([4], 2, 10)).toEqual([8]); + expect(multiplyDigits([12], 2, 16)).toEqual([8, 1]); + }); + + it('multiplies by 100', () => { + expect(multiplyDigits([1], 100, 2)).toEqual([0, 0, 1, 0, 0, 1, 1]); + expect(multiplyDigits([5], 100, 8)).toEqual([4, 6, 7]); + expect(multiplyDigits([4], 100, 10)).toEqual([0, 0, 4]); + expect(multiplyDigits([12], 100, 16)).toEqual([0, 11, 4]); + }); +}); diff --git a/src/add.js b/src/add.js index fe31aa6..fbf49d6 100644 --- a/src/add.js +++ b/src/add.js @@ -7,41 +7,8 @@ 'use strict'; -/** - * Strips the leading prefix from `number` in `base` and returns the remaining - * part of the string. - * - * - "0x" (or "0X") for hexadecimal numbers. - * - "0" for octal numbers. - * - * For all bases, leading whitespace is stripped. - */ -function stripPrefix(number: string, base: number): string { - if (base === 16) { - return number.replace(/^\s*0x/i, ''); - } else if (base === 8) { - return number.replace(/^\s*0/, ''); - } else { - return number.replace(/^\s*/, ''); - } -} - -/** - * Breaks the string repsentation of `number` in `base` into an array of decimal - * digits (from least significant to most significant) for easier manipulation. - * - * For example, the hexadecimal representation `"40fa"` becomes `[10, 15, 0, - * 4]`. - */ -function getDigits(number: string, base: number): Array { - return stripPrefix(number, base).trim().split('').reverse().map(digit => { - const result = parseInt(digit, base); - if (isNaN(result)) { - throw new Error('Invalid digit `' + digit + '` for base `' + base + '`'); - } - return result; - }); -} +import addDigits from './addDigits'; +import getDigits from './getDigits'; /** * Adds two numbers `a` and `b`, both in `base` and returns the answer as a @@ -50,18 +17,8 @@ function getDigits(number: string, base: number): Array { export default function add(a: string, b: string, base: number): string { const aDigits = getDigits(a, base); const bDigits = getDigits(b, base); - let result = ''; - let carry = 0; - for ( - let i = 0, max = Math.max(aDigits.length, bDigits.length); - i < max || carry; - i++ - ) { - const aDigit = aDigits[i] || 0; - const bDigit = bDigits[i] || 0; - const sum = aDigit + bDigit + carry; - result = (sum % base).toString(base) + result; - carry = Math.floor(sum / base); - } - return result ? result : '0'; + return addDigits(aDigits, bDigits, base) + .reverse() + .map(number => number.toString(base)) + .join(''); } diff --git a/src/addDigits.js b/src/addDigits.js new file mode 100644 index 0000000..4a3de34 --- /dev/null +++ b/src/addDigits.js @@ -0,0 +1,29 @@ +/** + * Copyright 2015-present Greg Hurrell. All rights reserved. + * Licensed under the terms of the MIT license. + * + * @flow + */ + +'use strict'; + +export default function addDigits( + aDigits: Array, + bDigits: Array, + base: number +): Array { + let result = []; + let carry = 0; + for ( + let i = 0, max = Math.max(aDigits.length, bDigits.length); + i < max || carry; + i++ + ) { + const aDigit = aDigits[i] || 0; + const bDigit = bDigits[i] || 0; + const sum = aDigit + bDigit + carry; + result.push(sum % base); + carry = Math.floor(sum / base); + } + return result.length ? result : [0]; +} diff --git a/src/getDigits.js b/src/getDigits.js new file mode 100644 index 0000000..fc8888d --- /dev/null +++ b/src/getDigits.js @@ -0,0 +1,44 @@ +/** + * Copyright 2015-present Greg Hurrell. All rights reserved. + * Licensed under the terms of the MIT license. + * + * @flow + */ + +'use strict'; + +/** + * Strips the leading prefix from `number` in `base` and returns the remaining + * part of the string. + * + * - "0x" (or "0X") for hexadecimal numbers. + * - "0" for octal numbers. + * + * For all bases, leading whitespace is stripped. + */ +function stripPrefix(number: string, base: number): string { + if (base === 16) { + return number.replace(/^\s*0x/i, ''); + } else if (base === 8) { + return number.replace(/^\s*0/, ''); + } else { + return number.replace(/^\s*/, ''); + } +} + +/** + * Breaks the string repsentation of `number` in `base` into an array of decimal + * digits (from least significant to most significant) for easier manipulation. + * + * For example, the hexadecimal representation `"40fa"` becomes `[10, 15, 0, + * 4]`. + */ +export default function getDigits(number: string, base: number): Array { + return stripPrefix(number, base).trim().split('').reverse().map(digit => { + const result = parseInt(digit, base); + if (isNaN(result)) { + throw new Error('Invalid digit `' + digit + '` for base `' + base + '`'); + } + return result; + }); +} diff --git a/src/multiplyDigits.js b/src/multiplyDigits.js new file mode 100644 index 0000000..afd2146 --- /dev/null +++ b/src/multiplyDigits.js @@ -0,0 +1,25 @@ +/** + * Copyright 2015-present Greg Hurrell. All rights reserved. + * Licensed under the terms of the MIT license. + * + * @flow + */ + +'use strict'; + +import addDigits from './addDigits'; + +/** + * Multiplication is repeated addition. + */ +export default function multiplyDigits( + multiplicand: Array, + multiplier: number, + base: number +): Array { + let result = [0]; + for (let i = 0; i < multiplier; i++) { + result = addDigits(result, multiplicand, base); + } + return result; +}