FInding out the Harshad number - javascript

I am being stuck in situation where the problem is defined as:
Harshad/Niven numbers are positive numbers that are divisible by the sum of their digits. All single-digit numbers are Harshad numbers.
For example, 27 is a Harshad number as 2 + 7 = 9, and 9 is a divisor
of 27.
Harshad numbers can occur in consecutive clusters. The numbers 1
through 10 are Harshad numbers. The numbers 132 and 133 are both
Harshad numbers. The numbers 1014, 1015, 1016, 1017 are Harshad
numbers.
Create a function that takes a number and returns an array of two
elements. The first element is the length of the Harshad cluster of
which the number is a part. The second is its order in the cluster.
Examples harshad(5) ➞ [10, 5] // cluster = [1, 2, 3, 4, 5, 6, 7, 8, 9,
10] // The second element should be the layman order in the //
cluster, not the programming index.
harshad(133) ➞ [2, 2] // cluster = [132, 133]
so i have figured out a way to find out all the harshed cluster greater than the number passed as arguement to function whose code is defined below
function track(num) {
let a = num.toString().split("");
let b = a.reduce((a, b) => +a + +b, 0);
if (num % b != 0) {return;}
console.log(num,num%b);
if (num % b == 0) {
num++;
track(num);
}
}
track(1015);
so console.log() gives me 1015,1016 and 1017
cluster as they are greater than 1015 which is passed to the function now how can i check for the numbers smaller than 1015 as 1014 should also be the answer but i just cant write another IF statement after the first IF statement and make it as
function track(num) {
let a = num.toString().split("");
let b = a.reduce((a, b) => +a + +b, 0);
if (num % b != 0) {return;}
console.log(num,num%b);
if (num % b == 0) {
num++;
track(num);
}
if(num%b==0){
num--
track(num)
}
}
track(1015);
as this makes no sense

You could separate the functions, one for checking if a number is a harshad value and another which collects these numbers by decrementing the value and incrementing and collecting valid numbers in an array.
function harshad(value) {
function isHarshad(value) {
return value % Array.from(value.toString(), Number).reduce((a, b) => a + b) === 0;
}
var cluster = [],
left = value,
right = value + 1;
while (isHarshad(left)) cluster.unshift(left--);
while (isHarshad(right)) cluster.push(right++);
return [cluster.length, cluster.indexOf(value) + 1];
}
console.log(harshad(5)); // [10, 5] cluster = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(harshad(133)); // [ 2, 2] cluster = [132, 133]
console.log(harshad(1015)); // [ 4, 2] cluster = [1014, 1015, 1016, 1017]
.as-console-wrapper { max-height: 100% !important; top: 0; }

Try this:
function track(num) {
const isHarshed = n => {
let a = n.toString().split("").reduce((a, b) => (+a) + (+b), 0);
return n % a === 0;
};
if (!isHarshed(num)) {return false;}
let index = 1;
let count = 1;
let n = num - 1;
while(isHarshed(n)) {
count++;
index++;
n--;
}
n = num + 1;
while(isHarshed(n)) {
count++;
n++;
}
return [count, index];
}
console.log(track(5));
console.log(track(133));

Related

Reduce numbers with a minimal cost without minheaps

I have n numbers and an operation to add two numbers to produce a new number. The cost of such an operation is equal to sum of numbers.
The final cost is the sum of all intermediate costs.
The question is what is a minimal final cost to reduce numbers to one number.
example:
[5, 3, 3, 4, 20] -> minimum cost = 6 + 9 + 15 + 35 = 65
3 + 3 = 6 // after the operation I have an array: [5, 6, 4, 20]
4 + 5 = 9 // [9, 6, 20]
6 + 9 = 15 // [15, 20]
15 + 20 = 35 // [35]
I am wondering if there is any simple solution for this faster than O(n**2) without introducing non-standard JS data structures (i.e. min-max heaps).
I know that additional structures can be implemented but such a solution is not 'simple' as requires a lot of extra code (but maybe they can be reduced to solve only this particular problem?).
You could sort the elements descending, then pop two elements, insert their sum, and add up the sums:
input.sort((a, b) => b - a); // O(n log n)
let cost = 0;
while(input.length > 1) { // O(n²) :(
const op = input.pop() + input.pop();
cost += op;
input.splice( // O(n) ?
binarySearch(input, op), // O(log n)
0,
op
);
}
function binarySearch(arr, value, min = 0, max = arr.length - 1) {
const middle = Math.floor((min + max) / 2);
if(value === arr[middle] || min === max)
return middle;
if(value < arr[middle])
return binarySearch(arr, value, min, middle - 1);
return binarySearch(arr, value, middle + 1, max);
}
You could take one index for the unseen values and another to splice the array for adding a sum at the right place.
At the end add all values.
var data = [5, 3, 3, 4, 20],
result,
i = 0;
data.sort((a, b) => a - b);
while (data.length - i > 2) {
let sum = data[i++] + data[i++],
j = i;
while (data[j] < sum) j++;
data.splice(j, 0, sum);
}
result = data.reduce((a, b) => a + b);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Why is my for loop not registering the first line in its block?

I have recently started learning the basics of coding from codeacademy and was given a project involving applying something called the "Luhn Algorithm" for validating credit card numbers. I think I understand the algorithm, but I seem to be getting something wrong in my JavaScript code.
// I'm using this as a sample to test if it works
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
// I used that Array for this piece of code:
const validateCred = arr => {
for (let i = arr.length - 1; i >= 0; i-=2) {
for (let j = arr.length - 2; j >= 0; j-=2) {
arr[j] *= 2;
if (arr[j] > 9) {
arr[j] -= 9;
}
const redFunc = (tot,num) => {
return tot + num;
}
return total = arr.reduce(redFunc,0);
}
}
}
console.log(validateCred(invalid1));
And the answer that logs is 82. I checked the math manually and found out that it should be 85.
I figured out that the problem is that this code isn't registering
arr[j] *= 2;
I've been at it for hours but can't, for the life of me, figure out how to fix it. Please help.
arr[j] *= 2; is registering.
Your logic have to be wrong. As you are a beginner, I recommend to try the Quokka.js extension for VS Code to troubleshoot your code and test it...
Like I did here:
// Source for logic: https://en.wikipedia.org/wiki/Luhn_algorithm
const validCreditCard1 = [4, 5, 3, 9, 1, 4, 8, 8, 0, 3, 4, 3, 6, 4, 6, 7];
const invalidCreditCard1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const validAccountNumber1 = [7, 9, 9, 2, 7, 3, 9, 8, 7, 1, 3];
const invalidAccountNumber1 = [7, 9, 9, 2, 7, 3, 9, 8, 7, 1, 1];
/*
1. From the rightmost digit (excluding the check digit) and moving left,
double the value of every second digit. The check digit is neither doubled nor included in this calculation;
the first digit doubled is the digit located immediately left of the check digit. If the result of this doubling
operation is greater than 9 (e.g., 8 × 2 = 16), then add the digits of the result (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9) or,
alternatively, the same final result can be found by subtracting 9 from that result (e.g., 16: 16 − 9 = 7, 18: 18 − 9 = 9).
2. Take the sum of all the digits.
3. If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid
according to the Luhn formula; otherwise it is not valid.
*** Example: ***
The sum of all the digits in the third row is 67+x.
The check digit (x) is obtained by computing the sum of the non-check digits then computing 9 times
that value modulo 10 (in equation form, ((67 × 9) mod 10)). In algorithm form:
Compute the sum of the non-check digits (67).
Multiply by 9 (603).
The units digit (3) is the check digit. Thus, x=3.
*/
const checkLuhnIsValid = async (arrayDigits, isAccountNumberCheck) => {
const arrayDigitsReversed = arrayDigits.slice().reverse();
let totalSum = 0;
// let checkDigitAccountNumber = null;
await new Promise(resolve => {
arrayDigitsReversed.map((digit, index, array) => {
digit = Number(digit);
if (digit) {
// Check if digit needs to be subtracted with 9
if (index % 2 === 1) { digit *= 2; if (digit > 9) { digit -= 9; } }
// Add to the total sum
totalSum += digit;
}
if ((index + 1) === array.length) {
// Get the true check number of the total sum... (if 10 number account number + check number)
// if (isAccountNumberCheck) { checkDigitAccountNumber = ((totalSum * 9) % 10); }
resolve();
}
});
});
if (totalSum % 10 === 0) { return true; } else {
return false;
}
};
(async () => {
console.log('validCreditCard1 isValid =>', await checkLuhnIsValid(validCreditCard1));
console.log('invalidCreditCard1 isValid =>', await checkLuhnIsValid(invalidCreditCard1));
console.log('validAccountNumber1 isValid =>', await checkLuhnIsValid(validAccountNumber1, true));
console.log('invalidAccountNumber1 isValid =>', await checkLuhnIsValid(invalidAccountNumber1, true));
})();
<p>
Also tested on account number, VISA and MasterCard.
</p>
I looked at the implementations of the Luhn Algorithm online and I found a blog post that implements it: Medium Post
It looks like your logic is little bit off, here is the implementation in the post:
const isValid = card => {
const arr = []
for (let i = 0; i < card.length; i++) {
if (i % 2 == 0) {
if (card[i]*2 < 10) {
arr.push(card[i]*2);
} else {
arr.push(card[i]*2-9);
}
} else {
arr.push(parseInt(card[i],10))
}
}
return arr.reduce( (prv, cur) => prv + cur) % 10 === 0;
}
There seems to be only one for-loop. When I ran this code with your input with removing the last %10 ===0 part(I wanted it to return number instead of boolean) , I received 85, which is your expected result.

The last element of recursive function returns undefined

I wrote a recursive function to find the biggest number path in the matrix. Only move for down and right allowed. (if you can move to down you have to go)
My question is not about the algorithm, I really confiused why I get undefined the end of the recursion. I can see the last element and it is not undefined. Thanks for any help! :)
function solution(A = []) {
let c = A[0].length; // m
let r = A.length; // n
let pathLength = c + r - 1;
console.log(A[0][0]);
if (pathLength === 1) return A;
if (0 < c && A[0][0 + 1] > A[0 + 1][0]) {
//go right
A.forEach(element => {
element.shift();
});
solution(A, A[0][0]);
} else if (0 < r - 1) {
// go down
A.shift();
solution(A, A[0][0]);
}
}
const testcase = [
[9, 9, 7],
[9, 7, 2],
[6, 9, 5],
[9, 1, 2]
];
output:
9
9
7
9
5
2
undefined
I think length needs -1 on the end of it, as arrays are indexed from 0, but length counts from 1.

Generate valid combinations of numbers in array of digits

I’m trying to generate all valid combinations of numbers from an array of digits. Let’s assume we have the following:
let arr = [1, 2, 9, 4, 7];
We need to output something like this:
1 2 9 4 7
1 2 9 47
1 2 94 7
1 2 947
1 29 4 7
1 29 47
1 294 7
1 2947
12 9 4 7
12 9 47
12 94 7
12 947
129 4 7
129 47
1294 7
12947
An invalid number would be 91, 497, 72 and so on.
I tried this but I’m not satisfied with the result:
const combination = (arr) => {
let i, j, temp;
let result = [];
let arrLen = arr.length;
let power = Math.pow;
let combinations = power(2, arrLen);
for (i = 0; i < combinations; i += 1) {
temp = '';
for (j = 0; j < arrLen; j++) {
if ((i & power(2, j))) {
temp += arr[j];
}
}
result.push(temp);
}
return result;
}
const result = combination([1, 2, 9, 4, 7]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Any ideas?
This code does what you want:
const arr = [1, 2, 9, 4, 7],
result = Array.from({length: 2 ** (arr.length - 1)}, (_, index) => index.toString(2).padStart(arr.length - 1, "0"))
.map((binary) => JSON.parse("[" + arr.map((num, position) => num + (Number(binary[position]) ? "," : "")).join("") + "]"));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
It results in:
[
[12947],
[1294, 7],
[129, 47],
[129, 4, 7],
[12, 947],
[12, 94, 7],
[12, 9, 47],
[12, 9, 4, 7],
[1, 2947],
[1, 294, 7],
[1, 29, 47],
[1, 29, 4, 7],
[1, 2, 947],
[1, 2, 94, 7],
[1, 2, 9, 47],
[1, 2, 9, 4, 7]
]
Assuming, the expected result does not depend on order, the spaces represent a binary pattern:
12947 => 0000
1294 7 => 0001
129 47 => 0010
…
1 29 47 => 1010
…
1 2 9 4 7 => 1111
We can utilize this pattern with a counter that we convert to a binary string. We also pad that string with 0 so it always remains 4 digits long:
index.toString(2).padStart(arr.length - 1, "0")
For n digits in arr, there are exactly 2n - 1 combinations, so we use:
{length: 2 ** (arr.length - 1)}
This is an object that has a length property of 2arr.length - 1.
We combine both those things into an Array.from call which accepts two arguments:
an object to turn into an array
a function for mapping each slot
Turning an object with a length property into an array means that we create an array with length many slots.
The mapping function accepts the index of a slot as the second parameter. We only use the index — as a counter for our binary number.
So, finally this whole expression:
Array.from({length: 2 ** (arr.length - 1)}, (_, index) => index.toString(2).padStart(arr.length - 1, "0"))
evaluates to the following array:
[
"0000",
"0001",
"0010",
"0011",
"0100",
"0101",
"0110",
"0111",
"1000",
"1001",
"1010",
"1011",
"1100",
"1101",
"1110",
"1111"
]
We need to further map this to the final result:
.map((binary) => …)
For each array element, binary is one of the binary strings from the array above.
In order to turn e.g. "0110" into something like "12,9,47", we need to map over arr as well. Every digit num from arr should be followed by , at position, iff binary is 1 at position:
arr.map((num, position) => num + (Number(binary[position]) ? "," : "")).join("")
The expression (Number(binary[position]) ? "," : "") evaluates binary at the specified position as a number. If it’s truthy, i.e. anything but 0, it evaluates to ",", if it’s falsy, i.e. 0, it evaluates to "".
So an intermediate array would look like ["1", "2,", "9,", "4", "7"]. All of this is joined together to "12,9,47".
Then, with JSON.parse("[" + … + "]") it’s being treated and parsed as an array, so it turns into [12, 9, 47]. Since these steps are applied for each binary string, you’ll end up with the final result.
2 ** (arr.length - 1) can be replaced by Math.pow(2, arr.length - 1) if ECMAScript 7 is not supported.
{length: 2 ** (arr.length - 1)} can be replaced by new Array(2 ** (arr.length - 1)).
(Number(binary[position]) ? "," : "") can be replaced by ["", ","][Number(binary[position])]. In this case the evaluated number will be used as an index for a temporary array.
So you need to iterate over all the combinations of "space" and "not space" between all the numbers. With n items, there will be n - 1 spaces, and 2 ** (n - 1) different lists.
So you could do something like this to get all the possible lists:
const combination = arr => {
const len = arr.length;
const n = Math.pow(2, len - 1);
const combinations = [];
for (let i = 0; i < n; i++) {
let this_combination = [arr[0]];
for (let j = 1; j < len; j++) {
if (i & Math.pow(2, j - 1)) {
// If the jth bit is on, no space. Append to the last element.
const last_index = this_combination.length - 1;
this_combination[last_index] = +(this_combination[last_index] + '' + arr[j]);
} else {
// Otherwise create a new list item.
this_combination.push(arr[j]);
}
}
// Consider making this function a generator and making this a yield.
combinations.push(this_combination);
}
return combinations;
}
const result = combination([1, 2, 9, 4, 7]);
console.log(result.map(line => line.join(' ')).join('\n'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you wanted each individual item seperately, for each item in the array, combine it with no other item, then just the next item, then the next 2 items, etc. untill the end:
const combination = arr => {
const len = arr.length;
const combinations = [];
for (let i = 0; i < len; i++) {
let item = arr[i];
combinations.push(item);
for (let j = i + 1; j < len; j++) {
item = +(item + '' + arr[j]);
combinations.push(item);
}
}
return combinations;
}
const result = combination([1, 2, 9, 4, 7]);
console.log(result.join('\n'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could take a recursive approach by iterating the array and insert a space or not and fork the calling of the same function with an incremented index.
function combine(array) {
function fork(i, p) {
if (i === array.length) {
result.push(p);
return;
}
fork(i + 1, p + ' ' + array[i]);
fork(i + 1, p + array[i]);
}
var result = [];
fork(1, array[0].toString());
return result;
}
console.log(combine([1, 2, 9, 4, 7]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could do this by using below code where 3 pointer is used,
1st pointer print 0th position to cursor position.
2nd pointer print cursor to diffidence position in each iteration .
3rd pointer print cursor position to last position.
let arr = [1, 2, 9, 4, 7];
console.log(arr.join(','));
for(let diff=2;diff<=arr.length;diff++){
for(i=0,j=diff;arr.length>=i+diff;j++,i++){
var temp = [];
if(i>0)
temp.push(arr.slice(0,i).join(','));
temp.push(arr.slice(i,j).join(''));
if(j<arr.length)
temp.push(arr.slice(j,arr.length).join(','));
console.log(temp.join(','));
}
}

Break array into multiple arrays based on threshold

I have the following graph, which is a representation of an array [2,8,12,5,3,...]. X axis is in seconds. I want to break this array into multiple parts when y values stays 0 for longer than 2 seconds. So the array in this example would break into 3 parts: x = 0 to 8, x = 8 to 13 and x = 13 to 20 because y stays = 0 for more than 2 seconds from 8 to 13. In practice this array could be huge. What would be fastest method to do this in pure javascript (or if needed lodash/underscore)? Currently I am looping through this array to mark 2 second stop times. Is there a better way of doing this?
You could use an iterative approach with one loop while checking the expected zero value and decide if the threshold is reached or not. of not, then delete the last interval and append the length to the array before.
This proposal yields
with threshold = 2:
[
[ 1, 7],
[ 8, 13],
[14, 20]
]
with threshold = 7:
[
[ 1, 20]
]
var y = [2, 8, 12, 5, 3, 2, 0, 0, 3, 4, 8, 10, 8, 10],
x = [1, 2, 4, 5, 6, 7, 8, 13, 14, 15, 16, 18, 19, 20],
threshold = 2,
isZero = false;
result = [];
y.forEach(function (a, i) {
var last = result[result.length - 1];
if ((a === 0) !== isZero) {
if (last) {
last[1] = x[i];
}
return;
}
isZero = !isZero;
if (last && isZero && x[i] - last[0] < threshold) {
result.pop();
if (result[result.length - 1]) {
result[result.length - 1][1] = x[i];
}
return;
}
result.push([x[i]]);
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You'll always need to look at the values of the array, so you won't be able to get further than an O(n) solution. The most efficient would probably be to run through the array with a variable containing the amount of zeros you've passed through at a certain point.
The function below is a hastily made implementation of this. I've also used a variable to store the previous index. This could also be calculated from the split array, but that would be rather inefficient if you're really talking about huge arrays.
function splitArray(array, treshold) {
var zeros = 0,
previousIdx = 0,
splitArrays = [];
array.forEach(function(point, idx) {
if (point === 0) {
zeros++;
if (zeros == treshold && previousIdx != idx - treshold + 1) {
splitArrays.push(array.slice(previousIdx, idx - treshold + 1));
previousIdx = idx - treshold + 1;
}
} else if (zeros >= treshold) {
splitArrays.push(array.slice(previousIdx, idx));
previousIdx = idx;
zeros = 0;
}
});
if (previousIdx != array.length -1) {
splitArrays.push(array.slice(previousIdx));
}
return splitArrays;
}
I've created a JSFiddle that shows this function in action with some test data: https://jsfiddle.net/Glodenox/La8m3du4/2/
I don't doubt this code can still be improved though.
If you just want to get the indices of the sections instead of an array with all data in separate arrays, you can replace the three array.slice(a, b) statements with [a, b-1].

Categories