Skip to content

Commit 1b54ad9

Browse files
Merge pull request #261 from rchavarria/sync-luhn-canonical
Synchronize Luhn exercise with canonical specs
2 parents 9eafdc0 + cef16e9 commit 1b54ad9

File tree

2 files changed

+44
-92
lines changed

2 files changed

+44
-92
lines changed

exercises/luhn/example.js

Lines changed: 28 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,34 @@
1-
export default class Luhn {
2-
3-
constructor(number) {
4-
this.checkDigit = number % 10;
5-
this.addends = Luhn.calculateAddends(number);
6-
this.checksum = Luhn.calculateChecksum(this.addends);
7-
this.valid = Luhn.determineIfValid(this.checksum);
8-
}
9-
10-
static calculateAddends(number) {
11-
const numberAsString = '' + number + '',
12-
numbers = [...numberAsString],
13-
addends = [];
14-
15-
for (let i = 0; i < numbers.length; i++) {
16-
const index = numbers.length - 1 - i;
17-
let currentAddend = parseInt(numbers[index], 10);
18-
19-
if ((i + 1) % 2 === 0) {
20-
currentAddend = currentAddend * 2;
21-
if (currentAddend > 10) {
22-
currentAddend = currentAddend - 9;
23-
}
1+
function isValid(number) {
2+
number = number.replace(/\s/g, '');
3+
const digits = [...number];
4+
5+
const sum = digits
6+
// convert to integers
7+
.map(d => parseInt(d, 10))
8+
// double even positions (odd indexes)
9+
.map((d, i) => {
10+
if (i % 2 !== 0) {
11+
return d * 2;
2412
}
25-
addends.push(currentAddend);
26-
}
27-
return addends.reverse();
28-
}
29-
30-
static calculateChecksum(numbers) {
31-
let sum = 0;
32-
for (let i = 0; i < numbers.length; i++) {
33-
sum += numbers[i];
34-
}
35-
return sum;
36-
}
13+
return d;
14+
})
15+
// limit to digits less than 10
16+
.map(d => {
17+
if (d > 9) {
18+
return d - 9;
19+
}
20+
return d;
21+
})
22+
// sum all digits
23+
.reduce((d, acc) => d + acc, 0);
3724

38-
static determineIfValid(sum) {
39-
return sum % 10 === 0;
40-
}
25+
return sum > 0 && sum % 10 === 0;
26+
}
4127

42-
static create(number) {
43-
let finalNumber = number * 10,
44-
luhnNumber = new Luhn(finalNumber),
45-
index = 0;
28+
export default class Luhn {
4629

47-
while (!luhnNumber.valid) {
48-
finalNumber = number * 10 + index;
49-
luhnNumber = new Luhn(finalNumber);
50-
if (luhnNumber.valid) {
51-
break;
52-
}
53-
index += 1;
54-
}
55-
return finalNumber;
30+
constructor(number) {
31+
this.valid = isValid(number);
5632
}
33+
5734
}

exercises/luhn/luhn.spec.js

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,34 @@ import Luhn from './luhn';
22

33
describe('Luhn',() => {
44

5-
it('check digit',() => {
6-
const luhn = new Luhn(34567);
7-
expect(luhn.checkDigit).toEqual(7);
8-
});
9-
10-
xit('check digit again',() => {
11-
const luhn = new Luhn(91370);
12-
expect(luhn.checkDigit).toEqual(0);
13-
});
14-
15-
xit('addends',() => {
16-
const luhn = new Luhn(12121);
17-
expect(luhn.addends).toEqual([1, 4, 1, 4, 1]);
18-
});
19-
20-
xit('too large added',() => {
21-
const luhn = new Luhn(8631);
22-
expect(luhn.addends).toEqual([7, 6, 6, 1]);
23-
});
24-
25-
xit('checksum',() => {
26-
const luhn = new Luhn(4913);
27-
expect(luhn.checksum).toEqual(22);
28-
});
29-
30-
xit('checksum again',() => {
31-
const luhn = new Luhn(201773);
32-
expect(luhn.checksum).toEqual(21);
5+
it('single digit strings can not be valid', () => {
6+
const luhn = new Luhn('1');
7+
expect(luhn.valid).toEqual(false);
338
});
349

35-
xit('invalid number',() => {
36-
const luhn = new Luhn(738);
10+
xit('A single zero is invalid', () => {
11+
const luhn = new Luhn('0');
3712
expect(luhn.valid).toEqual(false);
3813
});
3914

40-
xit('invalid number',() => {
41-
const luhn = new Luhn(8739567);
15+
xit('valid Canadian SIN', () => {
16+
const luhn = new Luhn('046 454 286');
4217
expect(luhn.valid).toEqual(true);
4318
});
4419

45-
xit('create valid number',() => {
46-
const number = Luhn.create(123);
47-
expect(number).toEqual(1230);
20+
xit('invalid Canadian SIN', () => {
21+
const luhn = new Luhn('046 454 287');
22+
expect(luhn.valid).toEqual(false);
4823
});
4924

50-
xit('create other valid number',() => {
51-
const number = Luhn.create(873956);
52-
expect(number).toEqual(8739567);
25+
xit('invalid credit card', () => {
26+
const luhn = new Luhn('8273 1232 7352 0569');
27+
expect(luhn.valid).toEqual(false);
5328
});
5429

55-
xit('create yet another valid number',() => {
56-
const number = Luhn.create(837263756);
57-
expect(number).toEqual(8372637564);
30+
xit('valid strings with a non-digit added become invalid', () => {
31+
const luhn = new Luhn('046a 454 286');
32+
expect(luhn.valid).toEqual(false);
5833
});
5934

6035
});

0 commit comments

Comments
 (0)