count repeated number and replace elements from last index - javascript

If the count of number 1 is repeated more than or equal to 12: replace all elements with 2 after last index of number 1.
Original array contains 0,1,-1;
I tried using below it works, if there is any simpler solution please suggest and help with link to documentation for further reference.
var arr = [0, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 0, 1, 1, -1, 0, 1, 0];
var total = arr.reduce((t, i) => i == 1 ? t + i : t, 0);
if (total >= 12) {
var startingIndex = arr.lastIndexOf(1) + 1;
var arr = arr.map((e, i) => i >= startingIndex ? 2 : e);
}
console.log(arr);
If array is [0,1,1,1,1,-1,1,1,1,1,1,0,1,1,-1,0,1,0]
then resulting array should be [0,1,1,1,1,-1,1,1,1,1,1,0,1,1,-1,0,1, 2]
If given array is [-1,1,1,1,1,-1,1,1,1,1,1,1,1,1,-1,0,-1,-1]
then resulting array should be[-1,1,1,1,1,-1,1,1,1,1,1,1,1,1,2,2,2,2]
If given array is [1,1,1,1,1,-1,1,1,1,1,1,0,1,1,1,0,-1,0]
then resulting array should be [1,1,1,1,1,-1,1,1,1,1,1,0,1,1,1,2,2,2]

Use filter to find how many, use fill to fill index starting from last found 1
const oneFill = arr =>
arr.filter(x=>x===1).length >= 12 ? arr.fill(2,arr.lastIndexOf(1)+1) : arr
const array = [
[0,1,1,1,1,-1,1,1,1,1,1,0,1,1,-1,0,1,0],
[-1,1,1,1,1,-1,1,1,1,1,1,1,1,1,-1,0,-1,-1]
]
for(const arr of array)
console.log(JSON.stringify(
oneFill(arr)
))
optimized version using .some, breaks out immediately after finding 12th element
// fills from the 1 found at the 12th instance of 1
const oneFill = arr => {
let count = 0
// if equals 1 increment and check if counter reached 12, fill with 2s
arr.some((x,i)=>x===1 && ++count >= 12 && arr.fill(2,i+1))
return arr
}
const array = [
[0,1,1,1,1,-1,1,1,1,1,1,0,1,1,-1,0,1,0],
[-1,1,1,1,1,-1,1,1,1,1,1,1,1,1,-1,0,-1,-1]
]
for(const arr of array)
console.log(JSON.stringify(
oneFill(arr)
))
// I don't know if you want lastIndex, or just the 12th index
// Below is a version that finds the lastIndex
const oneFill2 = arr => {
let count = 0
arr.some((x,i)=>x===1 && ++count >= 12) && arr.fill(2,arr.lastIndexOf(1)+1)
return arr
}
for(const arr of array)
console.log(JSON.stringify(
oneFill2(arr)
))

This is an alternate approach for #user120242 answer. This is more imperative code but uses less amount of iterations.
Idea:
Create 2 variables:
count: to keep count of valid cases.
index_12: to hold index of 12th valid case.
Now loop over the passed array and return value as:
If count is less than 12 the no processing is required. Return same value/
If count is 12, check if current index is same as index_12. If yes, this is the 12th valid case and return item instead.
If count is greater than 12 or if its equal to 12 but index is not same as index_12, return processed value (in this case 2)
function doSomething(arr) {
let count = 0;
let index_12 = null;
return arr.map((item, index) => {
count = item === 1 ? count + 1 : count;
index_12 = !index_12 && count === 12 ? index : index_12;
return index === index_12 || count < 12 ? item : 2
})
}
console.log( doSomething([0,1,1,1,1,-1,1,1,1,1,1,0,1,1,-1,0,1,0]).join() );
console.log( doSomething([-1,1,1,1,1,-1,1,1,1,1,1,1,1,1,-1,0,-1,-1]).join() );

Related

How do I turn this recursion into tail recursion?

With given array on unique numbers which are always greater than 0 I need to find all possible unique combinations of those numbers that are equal to a certain number when summed.
For example, getNumberComponents([7, 4, 3, 2, 5, 6, 8, 1], 8) should return
[ [ 7, 1 ], [ 4, 3, 1 ], [ 3, 5 ], [ 2, 5, 1 ], [ 2, 6 ], [ 8 ] ] because sum of all numbers in every subarray equals 8.
My solution:
function getNumberComponents(numArray, number) {
const arrayLength = numArray.length;
const allVariants = [];
function findComponents(currentIndex = 0, currentVariant = []) {
while (currentIndex < arrayLength) {
const currentElement = numArray[currentIndex];
const currentSum = currentVariant.reduce((acc, cur) => acc + cur, 0);
const sumWithCurrent = currentSum + currentElement;
if (sumWithCurrent === number) {
allVariants.push([...currentVariant, currentElement]);
}
currentIndex++;
if (sumWithCurrent < number) {
findComponents(currentIndex, [...currentVariant, currentElement]);
}
}
}
findComponents();
return allVariants;
}
But I wonder if it's possible to use tail recursion for that? I have no idea how to turn my solution into tail recursion.
To make this tail recursive, you could:
Keep track of all indices that were selected to arrive at the current sum. That way you can easily replace a selected index with the successor index.
In each execution of the function get the "next" combination of indices. This could be done as follows:
If the sum has not been achieved yet, add the index the follows immediately after the most recently selected index, and adjust the sum
If the sum has achieved or exceeded, remove the most recently selected index, and then add the successor index instead, and adjust the sum
If there is no successor index, then forget about this index and replace the previous one in the list, again adjusting the sum
If there are no more entries in the list of indices, then all is done.
Instead of accumulating a sum, you could also decrease the number that you pass to recursion -- saving one variable.
Make the function return the array with all variants, so there is no need for an inner function, nor any action that follows the function call.
Here is an impementation:
function getNumberComponents(numArray, number, selectedIndices=[], allVariants=[]) {
let i = selectedIndices.at(-1)??-1;
if (number < 0) { // Sum is too large. There's no use to adding more
i = numArray.length; // Force the while-condition to be true
} else if (number == 0) { // Bingo
allVariants.push(selectedIndices.map(idx => numArray[idx]));
}
while (++i >= numArray.length) { // No more successor index available
if (selectedIndices.length == 0) return allVariants; // All done
i = selectedIndices.pop(); // Undo a previous selection
number += numArray[i]; // Remove from sum
}
selectedIndices.push(i); // Select index and recur:
return getNumberComponents(numArray, number - numArray[i], selectedIndices, allVariants);
}
console.log(getNumberComponents([7, 4, 3, 2, 5, 6, 8, 1], 8));
Here is my version of your function, but using tail recursion. This is still a complex subject for me, check if there are no mistakes
function getNumberComponents(numArray, number, currentIndex = 0, currentVariant = [], allVariants = new Set()) {
if (currentIndex >= numArray.length) {
const currentSum = currentVariant.reduce((acc, cur) => acc + cur, 0);
if (currentSum === number) {
allVariants.add(currentVariant);
}
return Array.from(allVariants);
}
const currentElement = numArray[currentIndex];
const currentSum = currentVariant.reduce((acc, cur) => acc + cur, 0);
const sumWithCurrent = currentSum + currentElement;
if (sumWithCurrent <= number) {
allVariants = new Set([...allVariants, ...getNumberComponents(numArray, number, currentIndex + 1, [...currentVariant, currentElement], allVariants), ...getNumberComponents(numArray, number, currentIndex + 1, currentVariant, new Set())]);
} else {
allVariants = new Set([...allVariants, ...getNumberComponents(numArray, number, currentIndex + 1, currentVariant, new Set())]);
}
return Array.from(allVariants);
}
console.log(getNumberComponents([7, 4, 3, 2, 5, 6, 8, 1], 8));

reversing an array in javascript in function without method reverse()

here is my code:
const reverseArr = (...args) => {
let length = args.length - 1
let reversed = []
let i = 0
for (let a = length - i; i <= length; i++) {
args[a] = reversed[i]
}
return reversed
}
console.log( reverseArr(3, 5, 4, 1) )
What's the problem here? Does it about value of 'i' or lenght?
function reverse(arr){
// get length
var len = arr.length;
// create new array
var newArr = [];
// loop through array
for(var i = len - 1; i >= 0; i--){
// push to new array
newArr.push(arr[i]);
}
// return new array
return newArr;}
reverse([1,2,3,4,5]);
try this.
There are multiple issues :
for initialisation happens once, so if you do let a = lemgth - i, it doesn't update a any further, even though i changes.
You're reassigning values to your input array itself with reversed array, which is empty itself.
You're output-ing the input array (arr).
I tried to fix your snippet, and also adding better approach:
const reverseArr = (...args) => {
let length = args.length - 1
let reversed = []
let i = 0
// update 'a' as soon as you update 'i'
for(let a = length - i; i <= length; i++, a = length - i){
// update the standby array 'reveresed'
reversed[i] = args[a]
}
// print the reversed array instead of 'args'
console.log(reversed)
}
// Alternate approach (in-place reverse)
const reverseInput = (...args) => {
let left = 0, right = args.length - 1;
while(left <= right) {
// swap the left and right elements in array
[args[left], args[right]] = [args[right], args[left]] ;
left++;
right--;
}
console.log(args);
}
// Approach 1
console.log(reverseArr(3, 5, 4, 1))
// Approach 2
console.log(reverseInput(3,5,4,1));
simply...
const reverseArr = (...args) => Array.from({length:args.length},_=>args.pop())
console.log( reverseArr(3, 5, 4, 1) )
if you want to use an array as argument and let it untouched:
const reverseArr = arr => Array.from({length:arr.length},(_,i)=>arr[(arr.length-++i)])
let arrOrigin = [3,5,4,1]
let arrResult = reverseArr( arrOrigin )
console.log( arrOrigin )
console.log( arrResult )
.as-console-wrapper {max-height: 100%!important;top:0 }
const numbers = [1, 2, 3, 4, 5];
const reverse = (array) => {
const reversed = [];
for (const [index, element] of numbers.entries())
reversed[array.length - index - 1] = element;
return reversed;
}
console.log(reverse(numbers)); // [ 5, 4, 3, 2, 1 ]
We can use a for ... of loop on the entries of the array we want to reverse, and push the element into the desired position of the array.
To calculate the position we want, we can just do array length - index - 1.
This means that if we have an array of 5 items, [1, 2, 3, 4, 5] and we iterate through, we will be doing...
5 - 0 - 1 = 4 for the index of the first item.
5 - 1 - 1 = 3 for the index of the second item.
5 - 2 - 1 = 2 for the index of the third item.
5 - 3 - 1 = 1 for the index of the fourth item.
5 - 4 - 1 = 0 for the index of the fifth item.
In javascript you can reverse an array with sort function
function reverseArr(a){
return a.sort((a,b)=>b-a)
}
Try this:
function reversearr(...args) {
let reversed = args
args.forEach((x, y) => {reversed[-(y+1)]=x})
}

Appending new keys, and changing values in for/if loop

My current goal is to take items in array integers and create a key pair value based on how many times the key appeared in integers. My logic is: for i in integers, if i is in integers 2 already, increment that key's value by 1. if it doesn't exist, create the key and pair it with a value of 1. It's been a few hours now and after heavy googling I can't seem to find where im messing my logic up.
//require realdine-sync module
var readlineSync = require('readline-sync');
//initialize variable and list
var integer;
integers2 = {};
var integers = [];
//user input
integer = readlineSync.question('Integer?: ')
//check user input and append any integer besides 0
while (integer != 0 && integer >= 1 && integer <= 100){
console.log("not 0!")
integers.push(integer)
integer = readlineSync.question('Integer?: ')
}
console.log(integers);
for(i in integers){if (i in integers2){integers2[i] += 1}else{integers2[i] = 1}
}
console.log(integers2)
let integers2 = {}
integers = [5, 4, 5, 2, 4, 7, 5];
// you were using 'in' instead 'of', 'in': gives you index , 'of'?: gives you value of array
for (let i of integers) {
if (integers2[i]) { // if key exist increment value by one
integers2[i] += 1
} else { // else add 1 as the first value
integers2[i] = 1
}
}
console.log(integers2);
This is a solution that you can try which works. It uses the same logic as you described in the question. This solution uses Array.prototype.reduce() with a Map().
const howMany = arr => arr
.reduce(
(map, n) => map.set(n, (map.get(n) ?? 0) + 1),
new Map()
)
console.log([...howMany([3, 4, 6, 4, 5, 5, 5])])

Given an array index, how to get the n neighbors before and after index while wrapping?

Given an array and an index, I'd like to return n values surrounding the value at index.
For instance:
Array: [0,1,2,3,4,5,6]
index: 1
values: 2
Result:
[6,0,1,2,3]
slice comes in handy but I can't get the wrapping requirement working. Is the simplest solution to concat the array and work from that? ([...array, ...array])
You could take the double array and an offset with adjustment for slicing.
const
getValues = (array, index, values) => {
let offset = index - values;
if (offset < 0) offset += array.length;
return [...array, ...array].slice(offset, offset + 2 * values + 1);
},
array = [0, 1, 2, 3, 4, 5, 6],
result = getValues(array, 1, 2);
console.log(...result);
I'm not sure this adds much to the answers here already unless it might need to wrap over a size greater than the array length:
const circle_number_for_size = (circle_size) => (number) => {
const rem = number % circle_size;
return rem + (rem < 0 ? circle_size : 0);
};
const circle_slice = (array, start, end) => {
const circle_number = circle_number_for_size(array.length);
let new_array = [];
for(let i = start; i <= end; i++)
new_array.push(array[circle_number(i)]);
return new_array;
};
const neighbours = (array, centre_index, offset) =>
circle_slice(array, centre_index - offset, centre_index + offset);
console.log( ...neighbours([0,1,2,3,4,5,6], 1, 2) );
console.log( ...neighbours([0,1,2,3,4,5,6,7,8,9], 0, 21) );

Check array in JS - is list sorted? [duplicate]

This question already has answers here:
Check if an array is descending, ascending or not sorted?
(10 answers)
Check if array values are ascending or descending
(1 answer)
Closed 4 years ago.
I need to create a program that checks the list in the array is sorted. I have three input data:
1,2,3,4,5
1,2,8,9,9
1,2,2,3,2
So here is my code:
let sorts = +gets(); // 3
let list = [];
for (let i = 0; i < sorts; i++) {
list[i] = gets().split(',').map(Number); // The Array will be: [ [ 1, 2, 3, 4, 5 ], [ 1, 2, 8, 9, 9 ], [ 1, 2, 2, 3, 2 ] ]
}
for (let i = 0; i < list[i][i].length; i++){
if (list[i][i] < list[i][i +1]) {
print('true');
} else {
print('false');
}
}
I need to print for all lists on new line true or false. For this example my output needs to be:
true
true
false
I have no idea how to resolve this.
You can use array#every to check if each value is greater than the previous value.
const isSorted = arr => arr.every((v,i,a) => !i || a[i-1] <= v);
console.log(isSorted([1,2,3,4,5]));
console.log(isSorted([1,2,8,9,9]));
console.log(isSorted([1,2,2,3,2]));
How about something like this:
!![1,2,3,4,5].reduce((n, item) => n !== false && item >= n && item)
// true
!![1,2,8,9,9].reduce((n, item) => n !== false && item >= n && item)
// true
!![1,2,2,3,2].reduce((n, item) => n !== false && item >= n && item)
// false
Reduce will literally reduce the array down to a single value - a boolean in our case.
Here, we are calling a function per iteration, the (n, item) is our function signature, it's body being n !== false && item >- n && item - we are making sure that n exists (n is our accumulator - read up!), testing if item is greater than n, and making sure item exists.
This happens for every element in your array. We then use !! to force the result into a tru boolean.
Simply try this way by using slice method : It will check if previous element is less than the next element.If the condition is true for every element then it will return true else false
arr.slice(1).every((item, i) => arr[i] <= item);
Checkout this below sample as Demo
var arr = [[1,2,3,4,5],[1,2,8,9,9],[1,2,2,3,2],[0,1,2,3,4,5]];
function isArrayIsSorted (arr) {
return arr.slice(1).every((item, i) => arr[i] <= item)
}
var result= [];
for (var i = 0; i < arr.length; i++){
result.push(isArrayIsSorted(arr[i]))
}
console.log(result);
Sorted Number Lists
Including Negative Numbers, Zeros, and Adjacent Duplicates
Use every() method which will return true should all of the numbers be in order otherwise it will return false. The conditions are as follows:
(num <= arr[idx + 1]) || (idx === arr.length - 1)
if the current number is less than or equal to the next number...
OR...
if the current index is equal to the last index...
return 1 (truthy)
Demo
var arr0 = [1, 2, 3, 4, 5];
var arr1 = [1, 2, 8, 9, 9];
var arr2 = [1, 2, 2, 3, 2];
var arr3 = [0, 0, 0, 1, 3];
var arr4 = [-3, 0, 1, 3, 3];
var arr5 = [-4, -2, 0, 0, -4];
function sorted(array) {
return array.every(function(num, idx, arr) {
return (num <= arr[idx + 1]) || (idx === arr.length - 1) ? 1 : 0;
});
}
console.log(arr0 +' | '+sorted(arr0));
console.log(arr1 +' | '+sorted(arr1));
console.log(arr2 +' | '+sorted(arr2));
console.log(arr3 +' | '+sorted(arr3));
console.log(arr4 +' | '+sorted(arr4));
console.log(arr5 +' | '+sorted(arr5));
var str = ["1,2,3,4,5", "1,2,8,9,9", "1,2,2,3,2"];
for (var i in str){
var list = str[i].split(',').map(Number);
console.log(list);
var isSorted = true;
for(var j = 0 ; j < list.length - 1 ; j++){
if(list[j] > list[j+1]) {
isSorted = false;
break;
}
}
console.log(isSorted);
}
Maybe you can use this helping method that checks if is sorted correctly:
var arr1 = [1, 2, 3, 4, 4];
var arr2 = [3, 2, 1];
console.log(checkList(arr1));
console.log(checkList(arr2));
function checkList(arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i + 1]) {
if (arr[i] > arr[i + 1]) {
return false;
}
}
}
return true;
}
There are plenty of ways how to do that. Here is mine
const isArraySorted = array =>
array
.slice(0) // clone array
.sort((a, b) => a - b) // sort it
.every((el, i) => el === array[i]) // compare with initial value)
You can check if stringified sorted copy of original array has same value as the original one. Might not be the most cool or performant one, but I like it's simplicity and clarity.
const arraysToCheck = [
[1, 2, 3, 4, 5],
[1, 2, 8, 9, 9],
[1, 2, 2, 3, 2]
]
const isSorted = arraysToCheck.map(
item => JSON.stringify([...item].sort((a, b) => a - b)) === JSON.stringify(item)
);
console.log(isSorted);
If i get what you mean, you want to know if an array is sorted or not. This is an example of such a solution, try it. I pasted some codes below.
var myArray=[1,4,3,6];
if(isSorted(myArray)){
console.log("List is sorted");
}else{
console.log("List is not sorted");
}
function isSorted(X){
var sorted=false;
for(var i=0;i<X.length;i++){
var next=i+1;
if (next<=X.length-1){
if(X[i]>X[next]){
sorted=false;
break;
}else{
sorted=true;
}
}
}
return sorted;
}

Categories