expect(multiplyDigits([4], 100, 10)).toEqual([0, 0, 4]);
expect(multiplyDigits([12], 100, 16)).toEqual([0, 11, 4]);
});
+
+ it('multiplies by 1000', () => {
+ expect(multiplyDigits([1], 1000, 2)).toEqual([0, 0, 0, 1, 0, 1, 1, 1, 1, 1]);
+ expect(multiplyDigits([5], 1000, 8)).toEqual([0, 1, 6, 1, 1]);
+ expect(multiplyDigits([4], 1000, 10)).toEqual([0, 0, 0, 4]);
+ expect(multiplyDigits([12], 1000, 16)).toEqual([0, 14, 14, 2]);
+ });
});
multiplier: number,
base: number
): Array<number> {
+ // Partial result being built up.
let result = [0];
+
+ // Running total of additions performed so far.
let count = 0;
+ // We memoize partial subresults in a stack so they can be re-used.
+ const memo = [];
+
while (multiplier) {
if (count && count * 2 < multiplier) {
+ // We can double the current result without exceeding the target.
+ result = addDigits(result, result, base);
multiplier -= count;
count *= 2;
- result = addDigits(result, result, base);
+ memo.push({count, result});
} else {
- result = addDigits(result, multiplicand, base);
- count++;
- multiplier--;
+ const last = memo.pop();
+ if (last && last.count < multiplier) {
+ // We can use a previous result on the stack to leap ahead.
+ result = addDigits(result, last.result, base);
+ multiplier -= last.count;
+ count += last.count;
+ } else if (!memo.length) {
+ // Stack is empty, so fall back to base case (single addition).
+ result = addDigits(result, multiplicand, base);
+ multiplier--;
+ count++;
+ memo.push({count, result});
+ }
}
}