Finding the outlier number - javascript

I'm trying to solve a coding challenge over on CodeWars.com and I was hoping to get a little nudge in the right direction. The following function is supposed to take a string of numbers (like "2 4 7 8 10", or "1 2 2" etc.) and output the position of the number that is different in evenness (even or odd) than the others. The CodeWars.com link to this is at: https://www.codewars.com/kata/iq-test/train/javascript)
My function seems to be failing on tests where the last number is the number that is different ("100 100 1" or "5 3 2"). Any ideas why my function is performing this way? I've been looking at it and I can't see why it would be doing this:
function iqTest(numbers){
let numArr = numbers.split(' ');
let obj = {};
obj.evenCount = 0;
obj.oddCount = 0;
console.log(numArr);
for (let i = 0; i < numArr.length; i++) {
if (numArr[i] % 2 === 0) {
obj.evenCount += 1;
obj.even = i + 1;
} else {
obj.oddCount += 1;
obj.odd = i + 1;
}
}
if (obj.even < obj.odd) {
return (obj.even);
} else {
return (obj.odd);
}
}
console.log(iqTest('5 3 2'));

You need to check the eventCount and oddCount at the end of your function, not the odd and event properties like so:
if (obj.evenCount < obj.oddCount) {
Before, you were checking which index is higher (ie the position), but really you want to check which count/frequency is higher.
See working example below:
function iqTest(numbers) {
let numArr = numbers.split(' ');
let obj = {};
obj.evenCount = 0;
obj.oddCount = 0;
console.log(numArr);
for (let i = 0; i < numArr.length; i++) {
if (numArr[i] % 2 === 0) {
obj.evenCount += 1;
obj.even = i + 1;
} else {
obj.oddCount += 1;
obj.odd = i + 1;
}
if(obj.oddCount > 0 && obj.evenCount > 0 && obj.oddCount !== obj.evenCount) { // early termination condition
break; // break out of the loop is the difference between odd and even already exists
}
}
if (obj.evenCount < obj.oddCount) { // change to check the counts
return (obj.even);
} else {
return (obj.odd);
}
}
console.log(iqTest("2 4 7 8 10")); // 3 (item: 7)
console.log(iqTest("1 2 2")); // 1 (item: 1)
console.log(iqTest("100 100 1")); // 3 (item: 1)
console.log(iqTest("5 3 2")); // 3 (item: 2)

As mentioned, the issue in your code is that you're trying to determine which is the majority (odd or even), but you do this by comparing the last occurrence position (obj.odd and obj.even) rather than the amount of occurrences (obj.evenCount and obj.oddCount).
Simply change it to this: if (obj.evenCount < obj.oddCount) { ... }
That said, your function will always look through the entire array, however you can determine whether the outlier is even or odd just by looking at the first three numbers. Whichever appears less, even or odd, is the outlier.
With that in mind, we can make this more efficient by breaking it into two steps:
Use the first three numbers to determine if the outlier is odd or even.
Exit when we find the first occurrence of that outlier, rather than searching the entire array.
function iqTest(stringOfNumbers) {
let arr = stringOfNumbers.split(' ');
let desiredRemainder = arr
.slice(0,3)
.reduce((evenCount, item) => item % 2 === 0 ? evenCount+1 : evenCount, 0)
> 1
? 1
: 0;
return arr.findIndex(i => i % 2 === desiredRemainder) + 1;
}
console.log(iqTest("3 4 7 9"));
console.log(iqTest("1 1 1 100"));
console.log(iqTest("5 2 3"));
Here's a slightly more verbose version to break-out the steps into meaningful variable names:
function iqTest(stringOfNumbers) {
let arr = stringOfNumbers.split(' ');
let firstThree = arr.slice(0,3);
let evenCount = firstThree.reduce((evenCount, item) => item % 2 === 0 ? evenCount+1 : evenCount, 0);
let desiredRemainder = evenCount > 1 ? 1 : 0;
let indexOfOutlier = arr.findIndex(i => i % 2 === desiredRemainder);
return indexOfOutlier+1;
}
console.log(iqTest("3 4 7 9"));
console.log(iqTest("1 1 1 100"));
console.log(iqTest("5 2 3"));
I use Array.reduce() to determine whether we have more odds or evens.
If the outlier is odd, we're looking for the first item where item % 2 === 1 (an odd number).
If the outlier is even, we're looking for the first item where item % 2 === 0 (an even number).
I then put that logic in Array.findIndex(), which will return the position of the first item in which the given test is true (and I add 1 to it to replicate your code).

Based on this condition of the data:
Find out which one of the given numbers differs from the others. Bob observed that one number usually differs from the others in evenness
I'm going to give an alternative approach using the built-in array methods, for a standard approach, refer to Nick Parsons answer:
function iqTest(numbers)
{
return 1 + numbers.split(" ").findIndex(
(x, idx, arr) => arr.filter(y => y % 2 === x % 2).length === 1
);
}
console.log(iqTest("2 4 7 8 10")); // 3 (item: 7)
console.log(iqTest("1 2 2")); // 1 (item: 1)
console.log(iqTest("100 100 1")); // 3 (item: 1)
console.log(iqTest("5 3 2")); // 3 (item: 2)

Related

Iterate over uneven array

So I have a dataset of 16 items, I want to loop through them every 5 items after the first set of 6 so the columns are 6 5 5.
Initially I tried something like this, but then I remembered I had that one orphaned item.
if(thisI <= 6) {
y = prevtitle.position[0];
} elseif(thisI % 5 == 0) {
y = prevtitle.position[0] + w + (p *3);
} else {
y = prevtitle.position[0];
}
Not sure if there is a simple way to do the first 6 and then the next ones in five without a bunch of nested if statements.
Using Array#splice:
const splitArr = (arr = []) => {
const array = [...arr];
const res = array.length ? [array.splice(0, 6)] : [];
while(array.length) res.push(array.splice(0, 5));
return res;
}
console.log( splitArr([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]) );
Would a simple ternary expression work for you?
let num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
num.forEach((n,i) => {
y = (i<=6 || i % 5 == 0) ? prevtitle.position[0] : prevtitle.position[0] + w + (p *3) ;
})
I presume that you're skipping the first position, and jumps directly to the 6th position.
Just use a normal for loop.
Calculate the remainder for the number of steps that you will make. 16 % 5 results in 1 remainder.
step - countForZero + remainder sets the start point in the for loop.
i += step replaces the typical i++ in the for loop.
The method below can make any kind of leap, and it doesn't matter how many items there are in the array.
let num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
function getEvery(step, arr) {
let newArr = [],
remainder = arr.length % step,
countForZero = 1;
for (let i = step - countForZero + remainder; i < arr.length; i += step) {
newArr.push(arr[i]);
}
return newArr;
}
console.log( getEvery(5, num) );

Persistent Bugger - Help to get rid of some 0

I need some help with a task which is about creating a function that only accepts integer numbers to then multiply each other until getting only one digit. The answer would be the times:
Example: function(39) - answer: 3
Because 3 * 9 = 27, 2 * 7 = 14, 1 * 4 = 4 and 4 has only one digit
Example2: function(999) - answer: 4
Because 9 * 9 * 9 = 729, 7 * 2 * 9 = 126, 1 * 2 * 6 = 12, and finally 1 * 2 = 2
Example3: function(4) - answer: 0
Because it has one digit already
So trying to figure out how to solve this after many failures, I ended up coding this:
function persistence(num) {
let div = parseInt(num.toString().split(""));
let t = 0;
if(Number.isInteger(num) == true){
if(div.length > 1){
for(let i=0; i<div.length; i++){
div = div.reduce((acc,number) => acc * number);
t += 1;
div = parseInt(div.toString().split(""))
if(div.length == 1){
return t } else {continue}
} return t
} else { return t }
} else { return false }
}
console.log(persistence(39),3);
console.log(persistence(4),0);
console.log(persistence(25),2);
console.log(persistence(999),4);
/*
output: 0 3
0 0
0 2
0 4
*/
It seems I could solve it, but the problem is I don't know why those 0s show up. Besides I'd like to receive some feedback and if it's possible to improve those codes or show another way to solve it.
Thanks for taking your time to read this.
///EDIT///
Thank you all for helping and teaching me new things, I could solve this problem with the following code:
function persistence(num){
let t = 0;
let div;
if(Number.isInteger(num) == true){
while(num >= 10){
div = (num + "").split("");
num = div.reduce((acc,val) => acc * val);
t+=1;
} return t
}
}
console.log(persistence(39));
console.log(persistence(4));
console.log(persistence(25));
console.log(persistence(999));
/*output: 3
0
2
4
*/
You've got a few issues here:
let div = parseInt(num.toString().split("")); You're casting an array to a number, assuming you're trying to extract the individual numbers into an array, you were close but no need for the parseInt.
function persistence(input, count = 0) {
var output = input;
while (output >= 10) {
var numbers = (output + '').split('');
output = numbers.reduce((acc, next) {
return Number(next) * acc;
}, 1);
count += 1;
}
​
return count;
};
For something that needs to continually check, you're better off using a recurssive function to check the conditions again and again, this way you won't need any sub loops.
Few es6 features you can utilise here to achieve the same result! Might be a little too far down the road for you to jump into es6 now but here's an example anyways using recursion!
function recursive(input, count = 0) {
// convert the number into an array for each number
const numbers = `${input}`.split('').map(n => Number(n));
// calculate the total of the values
const total = numbers.reduce((acc, next) => next * acc, 1);
// if there's more than 1 number left, total them up and send them back through
return numbers.length > 1 ? recursive(total, count += 1) : count;
};
console.log(recursive(39),3);
console.log(recursive(4),0);
console.log(recursive(25),2);
console.log(recursive(999),4);
function persistance (num) {
if (typeof num != 'number') throw 'isnt a number'
let persist = 0
while(num >= 10) {
let size = '' + num
size = size.length
// Get all number of num
const array = new Array(size).fill(0).map((x, i) => {
const a = num / Math.pow(10, i)
const b = parseInt(a, 10)
return b % 10
})
console.log('here', array)
// actualiser num
num = array.reduce((acc, current) => acc * current, 1)
persist++
}
return persist
}
console.log(persistance(39))
console.log(persistance(999))
console.log() can take many argument...
So for example, console.log("A", "B") will output "A" "B".
So all those zeros are the output of your persistence function... And the other number is just the number you provided as second argument.
So I guess you still have to "persist"... Because your function always returns 0.
A hint: You are making this comparison: div.length > 1...
But div is NOT an array... It is a number, stringified, splitted... And finally parsed as integer.
;) Good luck.
Side note, the calculation you are attempting is known as the Kaprekar's routine. So while learning JS with it... That history panel of the recreational mathematic wil not hurt you... And may be a good line in a job interview. ;)
My best hint
Use the console log within the function to help you degug it. Here is your unchanged code with just a couple of those.
function persistence(num) {
let div = parseInt(num.toString().split(""));
let t = 0;
console.log("div.length", div.length)
if (Number.isInteger(num) == true) {
if (div.length > 1) {
for (let i = 0; i < div.length; i++) {
div = div.reduce((acc, number) => acc * number);
t += 1;
div = parseInt(div.toString().split(""));
if (div.length == 1) {
console.log("return #1")
return t;
} else {
continue;
}
}
console.log("return #2")
return t;
} else {
console.log("return #3")
return t;
}
} else {
console.log("return #4")
return false;
}
}
console.log(persistence(39), 3);
console.log(persistence(4), 0);
console.log(persistence(25), 2);
console.log(persistence(999), 4);

How to display list of numbers based on condition in javascript

I would like to know how to get the list of numbers based on two condition
number should be divisible by 3
number should not end with 3
How to implement the list within 50 numbers in javascript
Expected Output
6,9,12,15...45
My attempt
function getNumbers() {
var result = [];
for (var i = 0; i < 50; i++) {
if (i % 2 == 0) {
return
} else {
result.push(i);
return result.toString()
}
}
}
console.log(getNumbers())
This seems to work to specs - your specs says it should start at 6 and not at 1
const numbers = [...Array(50).keys()].
filter(num => num !== 0 && num%3 === 0 && !String(num).endsWith("3"))
console.log(numbers)
NOTE: You can change [...Array(50).keys()] to [...Array(50).keys()].slice(1) if you want to avoid the test for 0
You can do that with a check if the modulo of 3 is 0 and the modulo of 10 is not 3. If you want to beautify the code you can combine this answer with mplungjan answer, but i wanted to show a mathematical alternative of the !String(num).endsWith("3") method provided by mplungjan.
I started your iteration at 1 instead of 0 to avoid 0 being put into the array. I also corrected your return statements.
function getNumbers() {
var result = [];
for (var i = 1; i < 50; i++) {
if (i % 3 === 0 && i % 10 !== 3) {
result.push(i);
}
}
return result;
}
console.log(getNumbers())

Display number series with modulo in JavaScript

I'm currently trying to display number series (for 2, 3, 4, 5, 6 and 7) in JavaScript. I was looking for the smallest number (x), which results in modulo = 1, if divided by 2, 3, 4, 5 and 6. If the same number (x) is divided by 7, id should result in modulo = 0. I'm not quite sure, if I'm explaining it correct. It should be like this: x % 2 = 1, x % 3 = 1, x % 4 = 1, x % 5 = 1, x % 6 = 1, x % 7 = 0.
The result is 301. My code looks like this and it works fine:
var seven = 7;
var six;
var five;
var four;
var three;
var two;
while (six != 1 || five != 1|| four != 1|| three != 1|| two != 1)
{six = seven % 6;
five = seven % 5;
four = seven % 4;
three = seven % 3;
two = seven % 2;
console.log(seven);
seven += 7;}
It displays all the numbers in the seven-series, until 301. Now, I wanted some more while-loops for the other numbers (2-6), that work the same why and show all the different numbers/steps in each series, until 301. I'm new to JavaScript and I just don't get it. I tried to modify my code, so that it should work with the other number series, but it doesn't. Or is there any other (maybe a better) way to do this? With some nested loops/functions? It only should be possible to display every number in each number series, but not all at the same time (in the end, there should be buttons, which show (by clicking them) the different number series with all the numbers/steps until 301). Thank you soso much!
When doing this you should probably use a loop to simplify your life.
Start x at 0 and iterate to (for example) 100.000.
For every iteration, check to see if x % 2 / 3 / 4 / 5 / 6 is equal to 0. Then check to see if x % 7 === 1. If both these conditions are true, log the value and break the for loop.
The smallest value that answers this seems to be 120.
const numbers = [2,3,4,5,6]
const special = 7;
for(let x = 0; x < 100000; x++){
const isModulo0ForAllNumbers = numbers.every(n => (x % n) === 0);
const isModulo1ForSpecial = (x % special) === 1;
if(isModulo0ForAllNumbers && isModulo1ForSpecial){
console.log(`Smallest number found: ${x}`);
break;
}
}
Sometimes this is not possible to find such a number and you'll get infinite loop with unexpected behavior. This is a possible approach (see the comments inside):
// first define the greatest common divisor
// for two numbers - we'll need that later
let gcd = function(a, b) {
// classic 'Euclidean' method with recursion
if(a == 0) {
return b;
}
if(a > b) {
return gcd(b, a);
}
return gcd(b % a, a);
}
// define your series
let series = [2,3,4,5,6,7];
// now you need least common multiple for all numbers
// except for the last one
lcm = series[0];
for (let i = 1; i < series.length - 1; i++) {
lcm *= series[i] / gcd(lcm, series[i])
}
// the last number from series
let last = series[series.length - 1];
// exercise: you can research or think for smarter solution
// I will just loop until we get the result
if(gcd(lcm, last) == 1) {
let r = lcm + 1;
while(r % last) {
r += lcm;
}
console.log('number found: ', r);
} else {
// not possible
console.log('impossible to find the number');
}
You could take an array of values for the modulo calculation and use a function for getting a check of a value.
const f = x => [2, 3, 4, 5, 6].every(v => x % v === 1) && x % 7 === 0;
var value = 0;
while (!f(value)) value += 7;
console.log(value);

Javascript + return PrimeNumbers

I am trying to write a function that returns the PrimeNumber. for testing purposes i am just doing a console.log for stages of this function, to try and understand it better.
so this line(line:18) in my total function will just return i; as opposed to do a console.log
So Basically, 30 will be passed to the function and the function will return every prime number <=30.
It is based on this from wiki:
This routine consists of dividing n by each integer m that is greater than 1
and less than or equal to the square root of n.
If the result of any of these divisions is an integer,
then n is not a prime, otherwise it is a prime.
(Question here: 25/Math.sqrt(25) = 0, therefore NotPrime
BUT 25/2=12.5, 25/3=8.3333 25/4=6.25 => IsPrime as 12.5 is not an integer Or am I mising something here???)
there is also the problem of duplication: 13 is printed twice because 13/2 and 13/3 is executed. Question here: I would like to fix this duplication also?
function isInt(n) {
return n % 1 === 0;
}
var test = 25
console.log(Math.sqrt(test));
function prime(n) {
for(var i = 1; i <= n; i++)
{ if(i%2 !==0 && i%3 !==0){ // if i/2 does not have a remainder it might be a prime so go to next line else jump
to next number and i%3 the same
var a = Math.floor(Math.sqrt(i));
for(j = 2; j<=a; j++){
console.log(i + "/" + j); //print j//it prints 9 twice and 10 twice
console.log("==" + i/j); //because the sqrt of 9 = 3 =>
for j= 2 and j=3
if(isInt(i/j)) {}
else{console.log("----" + i + "is Prime");}
}
}
}
};
prime(test);
Another example here using aslightly different method: but again I have the same problem as the above 25 and duplication
var test = 25
console.log(Math.sqrt(test));
for(var i = 1; i <= test; i++)
{ if(i%2 !==0 && i%3 !==0){ // if i/2 does not have a remainder it might be a prime so go to next line else jump to next number and i%3 the same
var a = Math.floor(Math.sqrt(i));
for(j = 2; j<=a; j++){
console.log(i + "%" + j); //print j//it prints 9 twice and 10 twice
console.log("==" + i%j); //because the sqrt of 9 = 3 => for j= 2 and j=3
if(i%j !==0) {
console.log("----" + i + "is Prime");
}
}
}
}
[EDIT]Thank you all very much for pointing out my flaws/mistakes
here is my working example. Thank you all again!!
function isInt(n) {
return n % 1 === 0;
}
var test = 100
console.log(Math.sqrt(test));
function prime(n) {
for (var i = 1; i <= n; i++) {
var a = Math.floor(Math.sqrt(i));
var bool = true;
for(j = 2; j<=a; j++) {
if(!isInt(i/j)) {
//console.log(i+"/"+j+"=="+i/j+", therefore "+i+" is Prime");
} else {bool = false;}
}
if(bool) {console.log(i+"/"+j+"=="+i/j+", therefore "+i+" is Prime");}
}
}
prime(test);
25/Math.sqrt(25) = 0, therefore NotPrime
BUT 25/2=12.5, 25/3=8.3333 25/4=6.25 => IsPrime
No. Only because it neither is divisible by 2, 3, and 4, it does not mean that 25 is a prime number. It must be divisible by nothing (except 1 and itself) - but 25 is divisible by 5 as you noticed. You will have to check against that as well.
13 is printed twice because 13/2 and 13/3 is executed.
Question here: I would like to fix this duplication also?
Your logic is flawed. As above, just because a number is not divisible by an other number that does not mean it was prime - but your code prints results based on that condition. Instead, is has to be not divisible by all other numbers.
You just have an extra condition that nothing that is divisible by 2 or 3 enters the loop, but everything that is divisible by 5, 7, 11 etc (and not divisible by 2 or 3) is yielded. 25 is just the first number to occur in that series, the next ones will be 35 and 49.
Actually you're already testing 2 and 3 in the loop from 2 to a already, so you should just omit that condition. You would've noticed your actual problem much faster then if you had tried:
function prime(n) {
for (var i = 1; i <= n; i++) {
var a = Math.floor(Math.sqrt(i));
for(j = 2; j<=a; j++) {
if(!isInt(i/j)) {
console.log(i+"/"+j+"=="+i/j+", therefore "+i+" is Prime");
}
}
}
}
prime(25);
The logic should be: Test all divisors from 2 to sqrt(i), and if i is divisible by any of them you know that it's not a prime. Only if it has passed the loop with none of them being a factor of i, you know in the end that it's a prime. I'll leave that as an exercise to you :-)

Categories

Resources