Implement a single iteration in Javascript - javascript

So I came into this online test question, something like this :
Write a function to check if the given value is a single digit. If it is not, add up all the numbers until it becomes a single digit. For example, the given value is 55555 resulting 25. When 2 and 5 added will get 7.
And here is my answer :
function createCheckDigit(membershipId) {
let sum = 0;
let array = membershipId.toString().split("")
if(array.length > 1){
for(let i = 0; i < array.length; i++){
sum = sum + parseInt(array[i]);
}
}
if(sum.toString().split("").length > 1){
return createCheckDigit(sum.toString())
} else {
return sum
}
}
console.log(createCheckDigit("55555"));
The goal for this question is:
test case answer = 7 (done)
single iteration required (required)
two iterations required (done)
multiple iterations required (done)
I managed to get 1, 3, 4 fulfilled but not 2. I don't understand which part should the single iteration takes place?

I think I have found a solution to the problem:
function checkDigit(v) {
let sum = 0;
const digits = v.toString().split("");
for (let i = 0; i < digits.length; ++i) {
sum += Number(digits[i]);
if (sum >= 10) {
sum -= 9; // same as (sum - 10) + 1; this works because we won't ever get a sum greater than 9+9=18 so the sum of those digits will be a single digit
}
}
return sum;
}
console.log(checkDigit('55555'));
console.log(checkDigit('2'));
console.log(checkDigit('12345'));
console.log(checkDigit('99999'));
console.log(checkDigit('775542'));

Related

Function for happy algorithm not recurring properly

I am having trouble with my happy algorithm. The algorithm takes an input which came from my html input box. It squares the digits and adds them up. If the sum is 1, then the number is happy but if not, it checks against all of the previous sums to see if it is the same as one of them. If so, the number is unhappy. If neither then the algorithm is repeated with the new number.
//takes input value and then receives the output
function start() {
var int = document.getElementById('inp').value;
numbersChecked = [];
var value = happy(int);
console.log(int.toString() + " is " + value);
}
//recurs the funtion it doesn't work with it in the function
function unhappy(n) {
happy(n)
}
//the main function. Takes the value, adds up the squares of their digits and then checks
//to see if it is equal to one (happy) or repeats a numbers (unhappy)
function happy(n) {
n.toString();
//create|reset variables
sum = 0;
//loop through digits in string
for (var i = 0; i < n.length; i++) {
num = parseInt(n[i]);
square = num**2;
sum+=square;
}
//check numbers for repeats or return "Happy"
if (sum == 1) {
return "Happy";
} else {
for (var i = 0; i < numbersChecked.length; i++) {
if (sum == numbersChecked[i]) {
return "Unhappy";
}
}
numbersChecked.push(sum);
console.log(numbersChecked);
unhappy(sum);
}
}

How to iterate over an array of numbers to find the first number that occurs 3 times in the array

I have the following code
let range = [1,2,3];
let multiples = [1,2,3,4,5,6,2,4,6,3,6];
I want to find the first number in the multiples array that occurs range.lenght times (3);
I want to start with multiples[0] check how many times it occurs in multiples, if it occurs 3 times I want to return multiples[0], if it is less than 3 times, I want to check how many times multiples[1] occurs in the multiples array. If multiples[1] occurs 3 times I want to return multiples[1], else I move on to check multiples[2], etc. until I find a number that occurs 3 times. In the code above I should return 6.
I've looked at
How to count the number of certain element in an array?
and
Idiomatically find the number of occurrences a given value has in an array
and
get closest number out of array
among other research but have not figured it out yet.
I tried to simplify the question as much as possible. But if more info is needed it relates to this challenge on freeCodeCamp. Where I am at with my code is
function smallestCommons(arr) {
let sortArr = arr.sort((a, b) => a - b);
console.log(sortArr);
let range = [];
for (let i = sortArr[0]; i <= sortArr[1]; i++) {
range.push(i);
}
console.log("range = " + range);
let maxNum = range.reduce( (a, b) => a * b);
console.log("maxNum = " + maxNum);
let multiples = [];
for (let i = 0; i < maxNum; i++) {
let j = 0;
do {
multiples.push(j + range[i]);
j += range[i];
} while (j < maxNum);
//j = 0;
}
for (let i = 0; i < multiples.length; i++) {
let numberToFind = multiples[i];
/*stuck here hence my question, maybe I shouldn't even start with a for loop*/
//tried reduce, forEach, filter, while loop, do while loop
}
console.log("multiples = " + multiples);
}
console.log(smallestCommons([1,3]));
The logs are
1,3
range = 1,2,3
maxNum = 6
multiples = 1,2,3,4,5,6,2,4,6,3,6,NaN,NaN,NaN
What you can do is, first split your string with , and then using below function loop for check.
function countLength(arr, checkNumber) {
var count = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === checkNumber) {
count++;
}
}
return count;
}
countLength(list, NUMBER YOU WANT TO CHECK);
And if you want to check first number occur for 3 time then you need to make change in function and introduce .map or .filter in action to count number.
Example
const multiples = [1,2,3,4,5,6,2,4,6,3,6];
let occurance_arr=[];
const aCount = [...new Set(multiples)].map(x => {
if(multiples.filter(y=> y==x).length == 3) {
occurance_arr.push(x);
}
});
console.log(occurance_arr);
Above code will give you 6 in console, if you have multiple value then 0th element is the answer you are looking for which is first three time occurrence of item.
You can loop through your list keeping an object that maps each number to the number of times you've seen it. You can check the counts object as you loop, so if you see a number and the count is one less than your target, you can return it. If you make it through the loop without returning you didn't find what you're looking for — return something sensible :
let range = [1,2,3]
let multiples = [1,2,3,4,5,6,2,4,6,3,6]
function findFirstMult(arr, len){
let counts = {} // to keep track of how many times you've seen something
for (let n of arr){ // loop throught the array
if (!counts[n]) counts[n] = 0 // if it's then first time you've seen n, defined that key
if (counts[n] == len - 1) return n // found it
counts[n] +=1 // otherwise increase the count
}
return undefined
}
console.log(findFirstMult(multiples, range.length))
This will require only one loop through the array in the worse case and will return early if if finds something.

Multiplicative Persistence Codewars Challenge

I've been working on a kata from Codewars, the challenge is to write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit.
Example:
persistence(39) === 3 // because 3*9 = 27, 2*7 = 14, 1*4=4
// and 4 has only one digit
persistence(999) === 4 // because 9*9*9 = 729, 7*2*9 = 126,
// 1*2*6 = 12, and finally 1*2 = 2
persistence(4) === 0 // because 4 is already a one-digit number
While trying to figure this out I came across a solution online (shown below) and after trying to understand its logic, I couldn't see why the code didn't work
var count = 0;
function persistence(num) {
if (num.toString().length === 1) {
return count;
}
count++;
var mult = 1;
var splitStr = num.toString().split("");
for (var i = 0; i <= splitStr; i++) {
mult *= parseFloat(splitStr[i])
}
return persistence(parseFloat(mult));
}
The output for any single digit number will be 0 which is correct however for any number that is multiple digits, the persistence always logs as 1 and I can't seem to figure out why, any help would be greatly appreciated.
The posted code has quite a few problems.
for (var i = 0; i <= splitStr; i++) {
But splitStr is an array, not a number; i <= splitStr doesn't make sense. It should check against splitStr.length instead of splitStr.
Another problem is that it should use i <, not i <=, else the final splitStr[i] will be undefined.
Another problem is that the count variable is global, so more than one call of persistence will result in inaccurate results. There's no need for a count variable at all. To fix it:
function persistence(num) {
if (num.toString().length === 1) {
return 0;
}
var mult = 1;
var splitStr = num.toString().split("");
for (var i = 0; i < splitStr.length; i++) {
mult *= parseFloat(splitStr[i])
}
return 1 + persistence(parseFloat(mult));
}
console.log(
persistence(999),
persistence(39),
persistence(4)
);
Or, one could avoid the for loop entirely, and use more appropriate array methods:
function persistence(num) {
const str = num.toString();
if (str.length === 1) {
return 0;
}
const nextNum = str.split('').reduce((a, b) => a * b, 1);
return 1 + persistence(nextNum);
}
console.log(
persistence(999),
persistence(39),
persistence(4)
);
or we can use while loop with reduce array method
const persistence=(num)=>{
let splitNumArr=num.toString().split('')
let newList
let count=0
while(splitNumArr.length>1){
newList=splitNumArr.reduce((acc,curr)=>{
return acc*=curr
})
splitNumArr=newList.toString().split('')
count++
}
return count
}
console.log(persistence(39))===3
console.log(persistence(999))===4
console.log(persistence(9))===0

Factorializing a number by creating an array and multiplying it

I am going through one of the FreeCodeCamp challenges.
" Return the factorial of the provided integer.
If the integer is represented with the letter n, a factorial is the
product of all positive integers less than or equal to n.
Factorials are often represented with the shorthand notation n!
For example: 5! = 1 * 2 * 3 * 4 * 5 = 120 "
I already know that the easiest way is to use recursion but by the moment I've discovered this fact I was already trying to solve the problem by creating an array, pushing numbers in it and multiplying them. However I got stuck on this step. I have created an array with the number of digits depending on the function factorialize argument, but I can't get the product of those digits. What did I do wrong:
function factorialize(num) {
var array = [];
var product;
for(i = 0; i<=num;i++) {
array.push(i);
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
}
factorialize(5);
I think the easiest way would be to create a range and reduce that:
var n = 5;
function factorize(max) {
return [...Array(max).keys()].reduce((a,b) => a * (b + 1), 1);
}
console.log(factorize(n));
It looks like you missed a close parenthesis
function factorialize(num) {
var array = [];
var product = 1;
for(i = 0; i<=num;i++) {
array.push(i);
} //right here!!! <----
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
factorialize(5);
but as stated in the comments, you should change i = 0 to i = 1 not just because it would change the final result(which it does for all num ) but because it also doesn't follow the factorial algorithm.
1) You need initial value 'product' variable
2) You should change i = 0 to 1. You multiply by 0 in the loop
3) You don't need nested loop
function factorialize(num) {
var array = [];
var product = 1;
for(var i = 1; i <= num; i++) {
array.push(i);
}
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
You only need one loop for that,
from 1 to the maximum number, then you multiply them up,
just a little clean up from your code
fact variable will contain the string version of the individual numbers making up the sum
if m is 5 you'll fact will be 1*2*3*4*5
function factorialize(num) {
var product = 1;
var fact = ""
for (i = 1; i <= num; i++) {
product *= i;
fact += i + "*"
}
fact = fact.substring(0, fact.length - 1)
console.log(fact)
return product;
}
console.log(factorialize(5));

Validation for numeric data Javascript

I'm writing a program in Javascript that separates even and odd numbers, puts them into an array, adds the sum of numbers, and finds the average.
I'm having an issue not allowing zeros not to count. Because its adding to the array, and when the user types in 6+6, sum is 12, average is calculating to 4 because of the extra 0 in the array.
Is there anyway to not allow the zeros to count? Here is what I have so far..
var evenarray = [];
var oddarray = [];
var avgEven = 0;
var avgOdd = 0;
var isValid;
function numberFunction(){
do
{
var numbers = prompt("Please enter numbers. Enter empty string to exit.");
if(numbers % 2 == 0)
{
evenarray.push(numbers);
var sumEven = 0;
for (var i=0; i < evenarray.length; i++)
{
sumEven = sumEven + Number(evenarray[i]);
}
var avgEven = sumEven/evenarray.length;
//alert("even");
}
if(numbers % 2 !== 0)
{
oddarray.push(numbers);
var sumOdd = 0;
for (var i=0; i < oddarray.length; i++)
{
sumOdd = sumOdd + Number(oddarray[i]);
}
var avgOdd = sumOdd/oddarray.length;
//alert("odd");
}
//if(isNaN(numbers)){
//alert("Only numeric data only");
//}
}
while(numbers !== "");
Just do nothing when the number is actually 0:
if (numbers == 0)
{
}
else if(numbers % 2 == 0)
{
evenarray.push(numbers);
var sumEven = 0;
for (var i=0; i < evenarray.length; i++)
{
sumEven = sumEven + Number(evenarray[i]);
}
var avgEven = sumEven/evenarray.length;
}
else // only odds remain
{
oddarray.push(numbers);
var sumOdd = 0;
for (var i=0; i < oddarray.length; i++)
{
sumOdd = sumOdd + Number(oddarray[i]);
}
var avgOdd = sumOdd/oddarray.length;
}
You can do :
if(numbers % 2 == 0 && numbers !=0) ...
if(numbers % 2 != 0 && numbers !=0) ...
so that you don't do anything when numbers == 0;
It's a little strange to call your variable numbers instead of number.
your function should be,
function numberFunction(){
do
{
var numbers = prompt("Please enter numbers. Enter empty string to exit.");
if(numbers !=0 && !isNaN(numbers))
(numbers %2 == 0)? (evenarray.push(parseInt(numbers))) : (oddarray.push(parseInt(numbers)));
}while(numbers !== "");
for(var i = 0; i < evenarray.length; i++)
sumEven += evenarray[i];
for(var i = 0; i < oddarray.length; i++)
sumOdd += oddarray[i];
avgEven = sumEven / evenarray.length;
avgOdd = sumOdd / oddarray.length;
document.getElementById("even").innerHTML = evenarray.toString();
document.getElementById("sumEvenTotal").innerHTML = sumEven.toString(); //displays sum of even numbers.
document.getElementById("averageOdd").innerHTML = avgOdd; //displays average of odd numbers.
document.getElementById("averageEven").innerHTML = avgEven; //diplays average of even numbers.
document.getElementById("odd").innerHTML = oddarray.toString(); //displays all odd numbers that were entered.
document.getElementById("sumOddTotal").innerHTML = sumOdd.toString();
}
As you already have other answers with solutions to your particular issue, I would suggest a different approach. Think of the data you're manipulating: an array. Try to solve the issue only with data, no user input, no DOM manipulation; just data. This helps to separate concerns, and make your code easier to understand.
Since we're working with arrays, we can make use of some of the built-in JavaScript methods that are present in modern browsers, such as filter and reduce. These methods are in a way, alternatives to for loops, with some pre-defined behavior, and a callback function.
Now, let's think of the steps involved in solving your problem.
Get numbers from the user. We can represent this data as an array, as you were already doing.
We want all odd numbers, their sum and average.
We want all even numbers, their sum and average.
We display the data to the user.
In this solution I'm assuming you already have an array with the data, and will be focusing on points 2 and 3. Remember, think of data, user interaction shouldn't be mixed with your data logic. Instead of asking the user for a number on each loop, you could ask the user for a list of numbers directly; you avoid multiple prompts this way, and it lets you separate data and interaction nicely. Ideally you'd validate all user input to match your requirements.
// Helpers to work with numbers
var odd = function(x) {
return x % 2 === 0;
};
var even = function(x) {
return x % 2 !== 0;
};
var add = function(x, y) {
return x + y;
};
function solve(ns) {
// Solve the problem
// with odd or even numbers
var result = function(fn) {
var xs = ns.filter(fn); // odd or even
var sum = xs.reduce(add);
return {
numbers: xs,
sum: sum,
average: sum / xs.length
};
};
// Return an object
// with odd and even results
return {
odd: result(odd),
even: result(even)
};
}
var numbers = [1,2,3,4]; // from user input
var result = solve(numbers);
console.log(result.odd);
//^ {numbers: [2,4], sum: 6, average: 3}
console.log(result.even);
//^ {numbers: [1,2], sum: 4, average: 2}

Categories

Resources