Skip to content

Commit ad7cb55

Browse files
committed
update example solution
1 parent a42befa commit ad7cb55

File tree

2 files changed

+159
-69
lines changed

2 files changed

+159
-69
lines changed
+65-31
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,72 @@
1-
const isPalindrome = num => num.toString().split('').reverse().join('') === num.toString();
1+
const reverseString = str => str.split('').reverse().join('');
22

3-
export class Palindrome {
4-
static generate(params) {
5-
let maxFactor,
6-
minFactor,
7-
maxProduct,
8-
minProduct,
9-
data;
10-
maxFactor = params.maxFactor;
11-
minFactor = params.minFactor || 1;
12-
maxProduct = 1;
13-
minProduct = Infinity;
14-
data = [];
15-
16-
for (let ii = minFactor; ii < maxFactor; ii++) {
17-
for (let jj = ii; jj <= maxFactor; jj++) {
18-
const product = ii * jj;
19-
if (isPalindrome(product)) {
20-
data[product] = [ii, jj];
21-
maxProduct = Math.max(maxProduct, product);
22-
minProduct = Math.min(minProduct, product);
3+
class Palindrome {
4+
constructor(factor1, factor2) {
5+
this.value = factor1 * factor2;
6+
this.factors = [[factor1, factor2].sort()];
7+
}
8+
9+
withFactors(factors) {
10+
this.factors.push(factors.sort());
11+
this.factors = this.factors.sort();
12+
return this;
13+
}
14+
15+
valid() {
16+
const s = `${this.value}`;
17+
return s === reverseString(s);
18+
}
19+
20+
merge(other) {
21+
other.factors.forEach(f => this.factors.push(f));
22+
this.factors = this.factors.sort();
23+
return this;
24+
}
25+
}
26+
27+
export class Palindromes {
28+
constructor(maxFactor, minFactor = 1) {
29+
this.maxFactor = maxFactor;
30+
this.minFactor = minFactor;
31+
}
32+
33+
get largest() {
34+
let best = new Palindrome(this.minFactor, this.minFactor);
35+
for (let m = this.maxFactor; m >= this.minFactor; m -= 1) {
36+
let p = null;
37+
for (let n = m; n >= this.minFactor && (!p || !p.valid()); n -= 1) {
38+
p = new Palindrome(m, n);
39+
if (p.valid()) {
40+
if (best.value < p.value) {
41+
best = p;
42+
} else if (best.value === p.value) {
43+
best = p.merge(best);
44+
}
45+
}
46+
}
47+
}
48+
if (best.valid()) {
49+
return best;
50+
}
51+
return { value: null, factors: [] };
52+
}
53+
54+
get smallest() {
55+
for (let m = this.minFactor; m <= this.maxFactor; m += 1) {
56+
for (let n = this.minFactor; n <= this.maxFactor; n += 1) {
57+
const p = new Palindrome(m, n);
58+
if (p.valid()) {
59+
return p;
2360
}
2461
}
2562
}
63+
return { value: null, factors: [] };
64+
}
2665

27-
return {
28-
largest: {
29-
value: maxProduct,
30-
factors: data[maxProduct],
31-
},
32-
smallest: {
33-
value: minProduct,
34-
factors: data[minProduct],
35-
},
36-
};
66+
static generate(params) {
67+
if ((params.minFactor || 1) > params.maxFactor) {
68+
throw new Error('min must be <= max');
69+
}
70+
return new Palindromes(params.maxFactor, params.minFactor || 1);
3771
}
3872
}
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,125 @@
1-
import { Palindrome } from './palindrome-products';
1+
import { Palindromes } from './palindrome-products';
22

3-
describe('Palindrome', () => {
4-
test('largest palindrome from single digit factors', () => {
5-
const palindromes = Palindrome.generate({ maxFactor: 9 });
3+
describe('Palindromes', () => {
4+
test('smallest palindrome from single digit factors', () => {
5+
const palindromes = Palindromes.generate({ maxFactor: 9, minFactor: 1 });
6+
const smallest = palindromes.smallest;
7+
const expected = {value: 1, factors: [[1, 1]]};
8+
9+
expect(smallest.value).toEqual(expected.value);
10+
expect(sortFactors(smallest.factors)).toEqual(expected.factors);
11+
});
12+
13+
xtest('largest palindrome from single digit factors', () => {
14+
const palindromes = Palindromes.generate({ maxFactor: 9, minFactor: 1 });
615
const largest = palindromes.largest;
16+
const expected = {value: 9, factors: [[1, 9], [3, 3]]};
717

8-
expect(largest.value).toEqual(9);
9-
const containsMatch = [[3, 3], [1, 9]].filter(el => numericalArraysMatch(el, largest.factors)).length > 0;
10-
expect(containsMatch).toBe(true);
18+
expect(largest.value).toEqual(expected.value);
19+
expect(sortFactors(largest.factors)).toEqual(expected.factors);
20+
});
21+
22+
xtest('smallest palindrome from double digit factors', () => {
23+
const palindromes = Palindromes.generate({ maxFactor: 99, minFactor: 10 });
24+
const smallest = palindromes.smallest;
25+
const expected = {value: 121, factors: [[11, 11]]};
26+
27+
expect(smallest.value).toEqual(expected.value);
28+
expect(sortFactors(smallest.factors)).toEqual(expected.factors);
1129
});
1230

1331
xtest('largest palindrome from double digit factors', () => {
14-
const palindromes = Palindrome.generate({ maxFactor: 99, minFactor: 10 });
32+
const palindromes = Palindromes.generate({ maxFactor: 99, minFactor: 10 });
1533
const largest = palindromes.largest;
34+
const expected = {value: 9009, factors: [[91, 99]]};
1635

17-
expect(largest.value).toEqual(9009);
18-
expect(largest.factors).toEqual([91, 99]);
36+
expect(largest.value).toEqual(expected.value);
37+
expect(sortFactors(largest.factors)).toEqual(expected.factors);
1938
});
2039

21-
xtest('smallest palindrome from double digit factors', () => {
22-
const palindromes = Palindrome.generate({ maxFactor: 99, minFactor: 10 });
40+
xtest('smallest palindrome from triple digit factors', () => {
41+
const palindromes = Palindromes.generate({ maxFactor: 999, minFactor: 100 });
2342
const smallest = palindromes.smallest;
43+
const expected = {value: 10201, factors: [[101, 101]]};
2444

25-
expect(smallest.value).toEqual(121);
26-
expect(smallest.factors).toEqual([11, 11]);
45+
expect(smallest.value).toEqual(expected.value);
46+
expect(sortFactors(smallest.factors)).toEqual(expected.factors);
2747
});
2848

2949
xtest('largest palindrome from triple digit factors', () => {
30-
const palindromes = Palindrome.generate({ maxFactor: 999, minFactor: 100 });
50+
const palindromes = Palindromes.generate({ maxFactor: 999, minFactor: 100 });
3151
const largest = palindromes.largest;
52+
const expected = {value: 906609, factors: [[913, 993]]};
3253

33-
expect(largest.value).toEqual(906609);
34-
expect(largest.factors).toEqual([913, 993]);
54+
expect(largest.value).toEqual(expected.value);
55+
expect(sortFactors(largest.factors)).toEqual(expected.factors);
3556
});
3657

37-
xtest('smallest palindrome from triple digit factors', () => {
38-
const palindromes = Palindrome.generate({ maxFactor: 999, minFactor: 100 });
58+
xtest('smallest palindrome from four digit factors', () => {
59+
const palindromes = Palindromes.generate({ maxFactor: 9999, minFactor: 1000 });
60+
const smallest = palindromes.smallest;
61+
const expected = {value: 1002001, factors: [[1001, 1001]]};
62+
63+
expect(smallest.value).toEqual(expected.value);
64+
expect(sortFactors(smallest.factors)).toEqual(expected.factors);
65+
});
66+
67+
xtest('largest palindrome from four digit factors', () => {
68+
const palindromes = Palindromes.generate({ maxFactor: 9999, minFactor: 1000 });
69+
const largest = palindromes.largest;
70+
const expected = {value: 99000099, factors: [[9901, 9999]]};
71+
72+
expect(largest.value).toEqual(expected.value);
73+
expect(sortFactors(largest.factors)).toEqual(expected.factors);
74+
});
75+
76+
xtest('empty result for smallest if no palindrome in range', () => {
77+
const palindromes = Palindromes.generate({ maxFactor: 1003, minFactor: 1002 });
3978
const smallest = palindromes.smallest;
4079

41-
expect(smallest.value).toEqual(10201);
42-
expect(smallest.factors).toEqual([101, 101]);
80+
expect(smallest.value).toBe(null);
81+
expect(smallest.factors).toEqual([]);
82+
});
83+
84+
xtest('empty result for largest if no palindrome in range', () => {
85+
const palindromes = Palindromes.generate({ maxFactor: 15, minFactor: 15 });
86+
const largest = palindromes.largest;
87+
88+
expect(largest.value).toBe(null);
89+
expect(largest.factors).toEqual([]);
90+
});
91+
92+
xtest('error for smallest if min is more than max', () => {
93+
expect(() => {
94+
const palindromes = Palindromes.generate({ maxFactor: 1, minFactor: 10000 });
95+
palindromes.smallest;
96+
}).toThrow(new Error('min must be <= max'));
97+
});
98+
99+
xtest('error for largest if min is more than max', () => {
100+
expect(() => {
101+
const palindromes = Palindromes.generate({ maxFactor: 1, minFactor: 2 });
102+
palindromes.largest;
103+
}).toThrow(new Error('min must be <= max'));
43104
});
44105
});
45106

46-
function numericalArraysMatch(a, b) {
107+
function factorsMatch(a, b) {
47108
if (a.length !== b.length) {
48109
return false;
49110
}
50-
const one = [...a].sort(numericalSort);
51-
const two = [...b].sort(numericalSort);
52-
let result = true;
53-
let index = 0;
54-
while (index < one.length) {
55-
result = result && one[index] === two[index];
56-
index++;
111+
const one = a.map(f => f.sort()).sort();
112+
const two = b.map(f => f.sort()).sort();
113+
for (let i = 0; i < one.length; i += 1) {
114+
for (let j = 0; j < one[i].length; j += 1) {
115+
if (one[i][j] !== two[i][j]) {
116+
return false;
117+
}
118+
}
57119
}
58-
return result;
120+
return true;
59121
}
60122

61-
function numericalSort(x, y) {
62-
if (x < y) {
63-
return -1;
64-
}
65-
if (x > y) {
66-
return 1;
67-
}
68-
return 0;
123+
function sortFactors(factors) {
124+
return factors.map(f => f.sort()).sort();
69125
}

0 commit comments

Comments
 (0)