Iterate over uneven array - javascript

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) );

Related

find all possible combinations of two integers

Each time I can climb 1 or 2 steps to reach the top (3 steps for example)
1 + 1 + 1, 1 + 2, 2 + 1. There are three cases (scenarios). Here's my voodoo code (the thing is some numbers (missing) don't appear for n = 5 it's 1211. the solution would be to do the reverse string and store two versions of such strings in the hash, so duplicates will disappear and after the cycle sums them.
function setCharAt(str, index, chr) {
if (index > str.length - 1) return str;
return str.substring(0, index) + chr + str.substring(index + 1);
}
let n = 9;
find(n);
function find(n) {
let origin = n; //every loop n decreases by one when it 0 while returns false,
let sum = 1;
n -= 1; //because n once once of 1's (n = 5) 1+1+1+1+1 then 1111, 1112 etc.
if (n <= 1) return sum;
while (origin <= n * 2) { //if n = 10; only"22222" can give 10, we don't go deeper
let str = "1".repeat(n); //from "1" of n(4) to "1111"
let copyStr = str;
while (str.length === copyStr.length) { //at the end we get 2222 then 22221,
// therefore the length will change, we exit the loop
let s = str.split('').reduce((a, b) => Number(a) + Number(b), 0); //countinng elems
console.log(str, "=", s);
if (s === origin) ++sum; //if elems equals the target we increase the amount by one
let one = str.lastIndexOf("1");
let two = str.lastIndexOf("2");
if (str[one] === "1" && str[one + 1] === "2") {
str = setCharAt(str, one, "2");
str = setCharAt(str, one + 1, "1");
} else {
str = setCharAt(str, one, "2");
}
}
--n;
}
console.log(sum)
}
If i understood your question, you wanna for let say n = 5 get all combinations of 1 and 2 (when you sum it) that give a sum of 5 (11111, 1112, etc)?
It is most likely that you wanna use recursion in these kind of situations, because its much easier. If you have just two values (1 and 2) you can achieve this pretty easily:
getAllCombinations = (n = 1) => {
const combinations = [];
const recursion = (n, sum = 0, str = "") => {
if (sum > n) return;
if (sum === n) {
combinations.push(str);
return;
}
// Add 1 to sum
recursion(n, sum + 1, str + "1");
// Add 2 to sum
recursion(n, sum + 2, str + "2");
};
recursion(n);
return combinations;
};

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);

Finding the outlier number

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)

How to get 2 random numbers divisible by each other?

I'm generating 2 random numbers:
1) The first number must be random from 1 to 30
2) The second number must be random from 1 to 10
I'm simply trying to have the first number divisible by the second number or vice-versa, and finally, alert the result. My question is how to get the result of the division of 2 random numbers? Can anyone point me in the right direction? Thanks a lot in advance!.
Note: the first number must be divisible by the second number.
Here's my code:
var arr = [];
for (var i = 0; i < 2; i++) {
do {
var firstRandomNumber = Math.floor(Math.random()*30) + 1;
var secondRandomNumber = Math.floor(Math.random()*10) + 1;
if(firstRandomNumber % secondRandomNumber === 0){
correctResult = result;
arr.push(correctResult);
}
} while ((firstRandomNumber % secondRandomNumber === 0));
}
console.log(arr);
I would suggest a more functional approach: create a function that creates two random numbers, and returns them if one is divisible by the other. Then, just call that function until you get a truthy result:
function tryGetDivisible() {
var firstRandomNumber = Math.floor(Math.random() * 30) + 1;
var secondRandomNumber = Math.floor(Math.random() * 10) + 1;
if (firstRandomNumber % secondRandomNumber === 0) {
console.log(firstRandomNumber, secondRandomNumber);
return firstRandomNumber / secondRandomNumber;
}
}
let result;
while (!result) result = tryGetDivisible();
const arr = [result];
console.log(arr);
Few things:
Your while loop should be looping until firstRandomNumber % secondRandomNumber === 0, so you want to just keep looping while it's not true.
result isn't set anywhere, so I added the result in the array
The if(firstRandomNumber % secondRandomNumber === 0){ is redundant. When the do/while loop completes, it will have the do numbers that matched. Simply move the arr.push() outside that loop.
var arr = [];
for (var i = 0; i < 2; i++) {
do {
var firstRandomNumber = Math.floor(Math.random()*30) + 1;
var secondRandomNumber = Math.floor(Math.random()*10) + 1;
} while ((firstRandomNumber % secondRandomNumber !== 0));
console.log('first', firstRandomNumber, 'second', secondRandomNumber);
arr.push(firstRandomNumber / secondRandomNumber);
}
console.log(arr);
A much simpler approach is to get the first random number, and then try getting the second random number until they are divisible. So here will be the code:
var firstRandomNumber = Math.floor(Math.random()*30) + 1;
while (firstRandomNumber % secondRandomNumber !== 0) {
var secondRandomNumber = Math.floor(Math.random()*10) + 1;
}
console.log(firstRandomNumber + "," + secondRandomNumber);
Since the first must be divisible by the second, my approach would be:
Generate the second number.
Determine the maximum multiple of the second number that is no more than 30 (e.g., Math.floor(30/firstNumber)).
Select a multiple at random and use that as the first number. You simply need to select a random number between 1 and the largest allowed multiplier (inclusive).
This way, there's no need to do a generate-and-test loop, which could go on an unbounded number of times before a successful pair is generated.
If you want to avoid the while loop, you can pick the first number, then assemble the possible second numbers in an array. Then randomly pick one of these:
let first = Math.floor(Math.random() * 10) + 1
// all possible divisible numbers
let factors = Array.from({length: 30}, (_, i) => i + 1)
.filter(i => first % i === 0 || i % first === 0)
//pick one
let second = factors[Math.floor(Math.random() * factors.length)]
console.log(first, second)

Javascript How to return an array with odd numbers

I'm trying to return an array of numbers
function numbers(l, r) {
// l and r are any given numbers
var x=[];
var i=l;
while(x.push(i++)<r){};
return x;
}
console.log(numbers(10, 19));
So far so good. Now I want to get the odd numbers. How can I achieve that?
x.filter(n => n%2) will keep only odd numbers.
if n is even, n%2 will return 0 and the item will be removed by the filter.
let arr = [1,2,3,4,5,6,7,8,9,10,11,12]
let odds = arr.filter(n => n%2)
console.log(odds)
function* numbers(start, end) {
let i = start%2 ? start : ++start;
while(i <= end) {
yield i;
i += 2
}
}
console.log([...numbers(2, 10)])
or
class Odd {
constructor(l, r) {
this.l = l;
this.r = r;
}
*[Symbol.iterator]() {
let i = this.l % 2 ? this.l : ++(this.l);
while (i <= this.r) {
yield i;
i += 2
}
}
}
const odd = new Odd(2,10);
console.log([...odd])
Provided two values l (starting point) and r (ending point) you would create your array from l to r in increments of +1. Use that array to filter the desired values that meet the mod 2 or % 2 criteria. FYI mod 2 returns 0 if the value is an even number or 1 if the value is an odd number. The filter() method creates a new array with all elements that pass the test implemented by the provided function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter). Do note that in JavaScript 0 is a falsy value so only positive integer values like 1 are returned thus the array is formed with all values that resulted in n % 2 equal to 1.
function oddNumbers(l, r) {
let arr = [];
while (l <= r) {
arr.push(l);
l += 1;
};
return arr.filter(n => n % 2);
}
You could use an appropriate start value and increment by 2 for each pushing.
function numbers(l, r) {
var x = [],
i = Math.floor(l / 2) * 2 + 1; // start with an odd number
while(i <= r) {
x.push(i);
i += 2;
};
return x;
}
console.log(numbers(10, 19));
console.log(numbers(3, 5));
.as-console-wrapper { max-height: 100% !important; top: 0; }
At first, make i odd:
i = i+1-i%2;
Then iterate over every second:
while(x.push(i+=2)<r){};
Note that this returns r-1 numbers and not numbers up to r-1
Shorter
var EverySecond = (start,length) => Array.from({length}).map((el,i)=>start+i*2);
var even = (start,length) => EverySecond(start+start%2,length);
var odd = (start,length) => EverySecond(start+1-start%2,length);
Try this for pairs:
[0,1,2,3,4].filter(function(n){ return n%2 === 0; });
Try this for odds:
[0,1,2,3,4].filter(function(n){ return n%2 !== 0; });

Categories

Resources