forked from exercism/javascript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add exercise perfect-numbers (exercism#266)
* Perfect numbers exercise implementation. * Implementation of the perfect-numbers exercise. * Updated JSDoc. * Fixed typo and removed unneeded line.
- Loading branch information
1 parent
bccc1fa
commit 9b8efa0
Showing
5 changed files
with
267 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
|
||
export default class PerfectNumbers { | ||
|
||
/** | ||
* Calculate all the divisors for a given number. | ||
* @param {number} number - natural number. | ||
* @returns {array} array that contains the divisors for a given number NOT including the number itself. | ||
*/ | ||
getDivisors(number) { | ||
|
||
let i; | ||
let divs = new Array(); | ||
|
||
// Accepts only natural numbers greater than 1. | ||
if (number <= 1) { | ||
return divs; | ||
} | ||
|
||
// 1 always divides everyone! | ||
divs.push(1); | ||
|
||
// Calculate the divisors up the the half of the number + 1 | ||
for (i = 2; i <= number / 2; i++) { | ||
|
||
if (number % i === 0) { | ||
divs.push(i); | ||
} | ||
} | ||
|
||
return divs; | ||
} | ||
|
||
/** | ||
* Classify a given number as perfect, abundant or deficient. | ||
* @param {number} number - number to be classified. Note: if the number is equal or smaller than 0, | ||
* then returns an error: Classification is only possible for natural numbers. | ||
* @returns {string} - string that contains the number classification (perfect, abundant or deficient). | ||
*/ | ||
classify(number) { | ||
|
||
let i, sum, result; | ||
|
||
// Check if the input is valid | ||
if (number <= 0) { | ||
return 'Classification is only possible for natural numbers.'; | ||
} | ||
|
||
// Factorize the current number. | ||
const divsArray = this.getDivisors(number); | ||
|
||
// Sum the factors. | ||
sum = divsArray.reduce((sum, div) => sum += div, 0); | ||
|
||
// Check if the number is perfect. | ||
if (sum === number) { | ||
result = 'perfect'; | ||
} | ||
else if (sum > number) { | ||
result = 'abundant'; | ||
} | ||
else { | ||
result = 'deficient'; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
function getInputDirectory(argv) { | ||
if (argv.input) { | ||
return argv.input; | ||
} | ||
return '.'; | ||
} | ||
|
||
function getOutputDirectory(argv) { | ||
if (argv.output) { | ||
return argv.output; | ||
} | ||
return 'babel-output'; | ||
} | ||
|
||
const gulp = require('gulp'), | ||
eslint = require('gulp-eslint'), | ||
jasmine = require('gulp-jasmine'), | ||
babel = require('gulp-babel'), | ||
polyfill = require('babel/polyfill'), | ||
del = require('del'), | ||
argv = require('yargs').argv, | ||
inputDir = getInputDirectory(argv), | ||
outputDir = getOutputDirectory(argv); | ||
|
||
// Gulp tasks definition | ||
|
||
gulp.task('default', [ 'test' ]); | ||
|
||
gulp.task('test', [ 'babel' ], function () { | ||
return gulp.src([ outputDir + '/*.spec.js' ]) | ||
.pipe(jasmine()); | ||
}); | ||
|
||
gulp.task('babel', function () { | ||
return gulp.src([ inputDir + '/*.js', inputDir + '/lib/*.js' ]) | ||
.pipe(babel()) | ||
.pipe(gulp.dest(outputDir)); | ||
}); | ||
|
||
gulp.task('lint', function () { | ||
return gulp.src([ inputDir + '/*.js' ]) | ||
.pipe(eslint({ | ||
envs: [ | ||
'es6' //turns on all es6 features except modules | ||
], | ||
rules: { | ||
// full documentation here : http://eslint.org/docs/rules | ||
|
||
// Possible errors | ||
'comma-dangle': [2, 'never'], // don't let a comma at the end of object properties or array element | ||
'no-cond-assign': [2, 'always'], // no assignments in conditional statements | ||
'no-console': 2, // no console.log() statements in production code | ||
'no-constant-condition': 2, // no constants in conditional statements | ||
'no-control-regex': 2, // no control characters in regex's | ||
'no-debugger': 2, // no debugger in productin code | ||
'no-dupe-args': 2, // no duplicated arguments in functions | ||
'no-dupe-keys': 2, // no duplicated keys when creating object literals | ||
'no-duplicate-case': 2, // no duplicated `case` in `switch` statements | ||
'no-empty-character-class': 2, // disallow the use of empty character classes in regular expressions | ||
'no-empty': 2, // no empty blocks | ||
'no-ex-assign': 2, // do not assign any value to an Exception raised | ||
'no-extra-boolean-cast': 2, // do not use !!falseExpression to cast to boolean | ||
'no-extra-parens': 2, // do not use extra parenthesis | ||
'no-extra-semi': 2, // do not use extra semicolons | ||
'no-func-assign': 2, // do not overwrite variables declared as functions | ||
'no-inner-declarations': [2, 'both'], // only declare var's and funct's on function scope | ||
'no-invalid-regexp': 2, // validates string arguments passed to RegExp constructor | ||
'no-irregular-whitespace': 2, // detects special characters used as spaces | ||
'no-negated-in-lhs': 2, // do not use negation in the left operand in an `in` expression | ||
'no-obj-calls': 2, // prevent calling global objects as if they were functions | ||
'no-regex-spaces': 2, // do not use multiple spaces in regex's | ||
'no-sparse-arrays': 2, // do not use sparse arrays (empty elements) | ||
'no-unexpected-multiline': 2, // Avoid code that looks like two expressions but is actually one | ||
'no-unreachable': 2, // detects unreachable statements (after return, throw,...) | ||
'use-isnan': 2, // do not compare with `NaN` value, use isNan() instead | ||
'valid-jsdoc': 2, // ensure JSDoc comments are valid | ||
'valid-typeof': 2 // ensure that the results of typeof are compared against a valid string | ||
}, | ||
ecmaFeatures: { | ||
'modules': true //this gives us modules :) | ||
} | ||
})) | ||
.pipe(eslint.format()) | ||
.pipe(eslint.failAfterError()); | ||
}); | ||
|
||
gulp.task('clean', function (cb) { | ||
del([ outputDir ], cb); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "xecmascript", | ||
"version": "0.0.0", | ||
"description": "Exercism exercises in ECMAScript 6.", | ||
"author": "Katrina Owen", | ||
"private": true, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/exercism/xecmascript" | ||
}, | ||
"devDependencies": { | ||
"babel": "~5.8.29", | ||
"del": "~2.0.2", | ||
"gulp": "~3.9.0", | ||
"gulp-babel": "~5.3.0", | ||
"gulp-eslint": "^1.1.0", | ||
"gulp-jasmine": "~2.4.2", | ||
"yargs": "~3.27.0" | ||
}, | ||
"scripts": { | ||
"test": "gulp test", | ||
"lint-test": "gulp lint test" | ||
}, | ||
"licenses": [ | ||
"MIT" | ||
], | ||
"dependencies": {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import PerfectNumbers from './perfect-numbers'; | ||
|
||
describe('Exercise - Perfect Numbers', () => { | ||
|
||
const perfectNumbers = new PerfectNumbers(); | ||
|
||
describe('Perfect Numbers', () => { | ||
|
||
it('Smallest perfect number is classified correctly', () => { | ||
expect(perfectNumbers.classify(6)).toEqual('perfect'); | ||
}); | ||
|
||
it('Medium perfect number is classified correctly', () => { | ||
expect(perfectNumbers.classify(28)).toEqual('perfect'); | ||
}); | ||
|
||
it('Large perfect number is classified correctly', () => { | ||
expect(perfectNumbers.classify(33550336)).toEqual('perfect'); | ||
}); | ||
|
||
}); | ||
|
||
describe('Abundant Numbers', () => { | ||
|
||
it('Smallest abundant number is classified correctly', () => { | ||
expect(perfectNumbers.classify(12)).toEqual('abundant'); | ||
}); | ||
|
||
it('Medium abundant number is classified correctly', () => { | ||
expect(perfectNumbers.classify(30)).toEqual('abundant'); | ||
}); | ||
|
||
it('Large abundant number is classified correctly', () => { | ||
expect(perfectNumbers.classify(33550335)).toEqual('abundant'); | ||
}); | ||
|
||
}); | ||
|
||
describe('Deficient Numbers', () => { | ||
|
||
it('Smallest prime deficient number is classified correctly', () => { | ||
expect(perfectNumbers.classify(2)).toEqual('deficient'); | ||
}); | ||
|
||
it('Smallest non-prime deficient number is classified correctly', () => { | ||
expect(perfectNumbers.classify(4)).toEqual('deficient'); | ||
}); | ||
|
||
it('Medium deficient number is classified correctly', () => { | ||
expect(perfectNumbers.classify(32)).toEqual('deficient'); | ||
}); | ||
|
||
it('Large deficient number is classified correctly', () => { | ||
expect(perfectNumbers.classify(33550337)).toEqual('deficient'); | ||
}); | ||
|
||
it('Edge case (no factors other than itself) is classified correctly', () => { | ||
expect(perfectNumbers.classify(1)).toEqual('deficient'); | ||
}); | ||
|
||
}); | ||
|
||
describe('Invalid Inputs', () => { | ||
|
||
it('Zero is rejected (not a natural number)', () => { | ||
expect(perfectNumbers.classify(0)).toEqual('Classification is only possible for natural numbers.'); | ||
}); | ||
|
||
it('Negative integer is rejected (not a natural number)', () => { | ||
expect(perfectNumbers.classify(-1)).toEqual('Classification is only possible for natural numbers.'); | ||
}); | ||
|
||
}); | ||
|
||
}); |