aboutsummaryrefslogtreecommitdiff
path: root/challenge-133/iangoodnight/javascript/ch-2.js
diff options
context:
space:
mode:
authorIan Goodnight <goodnight.ian@gmail.com>2021-10-09 14:55:44 -0400
committerIan Goodnight <goodnight.ian@gmail.com>2021-10-09 14:55:44 -0400
commitc0428c3468203840d5cd0948d298fa86a72f1c9c (patch)
treec1b13cc2490ebf075763b5730b97f752a945445e /challenge-133/iangoodnight/javascript/ch-2.js
parent7e31b242f4012d100b2949c29f00a3597a9bb80f (diff)
downloadperlweeklychallenge-club-c0428c3468203840d5cd0948d298fa86a72f1c9c.tar.gz
perlweeklychallenge-club-c0428c3468203840d5cd0948d298fa86a72f1c9c.tar.bz2
perlweeklychallenge-club-c0428c3468203840d5cd0948d298fa86a72f1c9c.zip
solutions 133
Diffstat (limited to 'challenge-133/iangoodnight/javascript/ch-2.js')
-rwxr-xr-xchallenge-133/iangoodnight/javascript/ch-2.js105
1 files changed, 105 insertions, 0 deletions
diff --git a/challenge-133/iangoodnight/javascript/ch-2.js b/challenge-133/iangoodnight/javascript/ch-2.js
new file mode 100755
index 0000000000..5f229008ec
--- /dev/null
+++ b/challenge-133/iangoodnight/javascript/ch-2.js
@@ -0,0 +1,105 @@
+#!/usr/bin/env node
+// ch-2.js
+
+/**
+ * https://theweeklychallenge.org/blog/perl-weekly-challenge-133/
+ *
+ * Task 2 > Smith Numbers
+ * ======================
+ *
+ * Write a script to generate the first 10 `Smith Numbers` in base 10.
+ *
+ * According to Wikipedia:
+ *
+ * > In number theory, a Smith number is a composite number for which, in a
+ * > given number base, the sum of its digits is equal to the sum of the digits
+ * > in its prime factorization in the given number base.
+ *
+ **/
+
+'use strict';
+
+/**
+ * Our PWC solution and some helper functions
+ **/
+
+// First, we need a utility function to return our prime factors
+function primeFactors(number) {
+ let n = parseInt(number, 10); // Input validation
+ if (number === 'NaN') {
+ // Fail fast if arg is not a positive integer
+ throw new Error(
+ 'function `primeFactors` expects a positive integer as an argument.',
+ );
+ }
+ const factors = [];
+
+ let divisor = 2; // Starting with 2, check for remainder
+ while (n >= 2) {
+ if (n % divisor === 0) {
+ // If modulo is 0, push to factors
+ factors.push(divisor);
+ n /= divisor;
+ } else {
+ divisor += 1; // Else, increment the divisor and try again
+ }
+ }
+ return factors;
+}
+
+// Reduce numbers to the sum of their digits
+function sumDigits(number) {
+ return number
+ .toString()
+ .split('')
+ .reduce((sum, digit) => sum + parseInt(digit, 10), 0);
+}
+
+// Find our actual smith numbers with the help of `primeFactors` and `sumDigits`
+function identifySmithNumbers(limit = 10) {
+ const smithNumbers = [];
+
+ let test = 4; // Smith numbers are composite numbers, so skip the primes
+ while (smithNumbers.length < limit) {
+ const primeFactorsArr = primeFactors(test);
+
+ const factorSum = primeFactorsArr.reduce(
+ (sum, factor) => sum + sumDigits(factor),
+ 0,
+ );
+
+ const digitSum = sumDigits(test);
+
+ if (factorSum === digitSum && primeFactorsArr.length !== 1) {
+ smithNumbers.push(test);
+ }
+ test += 1;
+ }
+ return smithNumbers;
+}
+
+/**
+ * General utilities
+ **/
+
+// Takes an array and returns it as human-readable comma separated list
+function stringWithOxfordComma(arr = []) {
+ const reversed = [...arr].reverse();
+
+ const [last, ...rest] = reversed;
+
+ const first = [...rest].reverse().join(', ');
+
+ return `${first}, and ${last}`;
+}
+
+// IIFE to handle args and print results
+(function main() {
+ const limit = process.argv[2] || 10;
+
+ const smithNumbers = identifySmithNumbers(limit);
+
+ const stringified = stringWithOxfordComma(smithNumbers);
+
+ console.log(`The first ${limit} Smith Numbers are ${stringified}.`);
+})();