Finding the first index of a sequence inside an array - javascript

In this function I count the number of consecutive zeros that should be at least of length zerosMin. Is there any way I could return the first index of the start of the sequences? For example, for arr = [1,0,0,0,0,0,1,0,0,0,0] it would be [1,7]
function SmallestBlockOfZeros(arr, zerosMin) {
let result = [];
let counter = 1;
for (let i = 0; i < arr.length; i++) {
if (arr[i] == 0) {
if (arr[i] === arr[i + 1]) {
counter++;
} else if (counter >= zerosMin) {
result.push(counter);
counter = 1;
} else {
counter = 1;
}
}
}
return result;
}
let arr = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0];
let zerosMin = 4;
console.log(SmallestBlockOfZeros(arr, zerosMin));
//Console output : [5,4]

You can iterate through the array, pushing an index into the result array whenever you encounter a block of 0 values that is at least zerosMin long, and then skipping all those 0 values until you find the next non-0 value or pass the point at which a zerosMin string of 0s could occur:
let arr = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0];
let zerosMin = 4;
let zeroStarts = [];
for (let i = 0; i <= arr.length - zerosMin; i++) {
if (arr.slice(i, i + zerosMin).filter(Boolean).length == 0) {
zeroStarts.push(i);
i += zerosMin;
while (i <= arr.length - zerosMin && arr[i] == 0) {
i++;
}
}
}
console.log(zeroStarts);
Note I've used filter(Boolean) because 0 is falsey; if you were searching for a run of non-zero values you would use something like filter(v => v != 0)

If you don't need to actually iterate elements, you can use a shortcut
function foo(arr, min)
{
let el = arr.join("").match(new RegExp('0{' + min + ',}'));
return [el.index, el.index + el[0].length];
}
console.log(foo([1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], 3));

For start of each chain of zeros:
function indexOfValue(arr, val) {
var indexes = [], i;
for(i = 0; i < arr.length; i++)
if (arr[i] === val)
indexes.push(i);
return indexes;
}
(see How to find index of all occurrences of element in array?)
The code you posted above appears to work for length of blocks of 0s.

While iterating the items, keep track of last non-zero index and push the index to output array when criteria matches.
const SmallestBlockOfZeros = (arr, zerosMin) => {
let index = 0;
const output = [];
for (let i = 0; i <= arr.length; i++) {
if (arr[i] !== 0 || !(i in arr)) {
i - index - 1 >= zerosMin && output.push(index + 1);
index = i;
}
}
return output;
};
const arr = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0];
const zerosMin = 4;
console.log(SmallestBlockOfZeros(arr, zerosMin));

Related

code check :i expect IndexPlus is 2 but it seems it becom 1+1=11,why?

description :
i expect the indexPlus 2 but it comes 11,what is wrong? and why?
see it in line 28 .
code:
var inputArr = [1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0]
console.log('before', inputArr)
var arr = []
//先遍历inputArr确定0的位置
for (key in inputArr) {
if (inputArr[key] === 0) {
arr.push(key)
}
}
//将0移到数组最后面,通过位置交换实现
for (value of arr) {
for (i = value; i < inputArr.length - 1; i++) {
swap(i, i + 1)
}
}
function swap(index, indexPlus) {
var temp = inputArr[index]
inputArr[index] = inputArr[indexPlus]
inputArr[indexPlus] = temp
}
console.log('after', inputArr)
When you do for (key in inputArr), the keys are strings, not integers. So later when you do swap(i, i + 1), i is a string, and i + 1 does string concatenation, not integer addition.
Change the first loop to loop over indexes, not keys.
var inputArr = [1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0]
console.log('before', inputArr)
var arr = []
//先遍历inputArr确定0的位置
for (let key = 0; key < inputArr.length; key++) {
if (inputArr[key] === 0) {
arr.push(key)
}
}
//将0移到数组最后面,通过位置交换实现
for (value of arr) {
for (i = value; i < inputArr.length - 1; i++) {
swap(i, i + 1)
}
}
function swap(index, indexPlus) {
var temp = inputArr[index]
inputArr[index] = inputArr[indexPlus]
inputArr[indexPlus] = temp
}
console.log('after', inputArr)
When you use for ( in ), in every single loop, you will get a key(position) as a string. So when you take it and + 1 you will get result as a string.

Function in Javascript that returns closest distance of two given array indices

I want to write a function with for-loops that finds the index of the number 1 in an array and returns the difference to the index of the number 2 that is closest to number 1 (number 1 only appears once). For instance:
Input: [1, 0, 0, 0, 2, 2, 2]
Output: 4
Input: [2, 0, 0, 0, 2, 2, 1, 0, 0 ,2]
Output: 1
My try
function closest (array) {
let elem=array.findIndex(index=>index === 1)
let numberplus=0;
let numberminus=0;
for (let i=elem; i<array.length; i++){
if (array[elem+1] === 2)
{numberplus+=array[elem+1]-elem;}
break;
}
for (let i=elem; i>=0; i--) {
if (array[elem-1] ===2)
{numberminus+=array[elem-1]-elem;}
break;
}
if (numberplus < numberminus) {
return numberplus
} else {
return numberminus}
}
When invoked, the function just returns '0'. Thanks for reading!
Take the position of 1 as starting point and loop up and (if necessary) down the array:
const log = (arr, d) => console.log(`mimimal distance [${arr.join()}]: ${d}`);
const arr = [2, 0, 0, 0, 2, 2, 1, 0, 0, 2];
const arr2 = [1, 0, 0, 0, 2, 2, 2];
const arr3 = [2, 0, 1, 0, 2, 2, 2];
const arr4 = [2, 1, 0, 0, 2, 2, 2];
log(arr, clostes(arr));
log(arr2, clostes(arr2));
log(arr3, clostes(arr3));
log(arr4, clostes(arr4));
function clostes(arr) {
// determine position of 1
const indxOf1 = arr.indexOf(1);
// create array of distances
const distances = [0, 0];
// forward search
for (let i = indxOf1; i < arr.length; i += 1) {
if (arr[i] === 2) {
break;
}
distances[0] += arr[i] !== 2 ? 1 : 0;
}
// if 1 is # position 0 backwards search
// is not necessary and minimum equals the
// already found maximum
if (indxOf1 < 1) {
distances[1] = distances[0];
return Math.min.apply(null, distances);
}
// backwards search
for (let i = indxOf1; i >= 0; i -= 1) {
if (arr[i] === 2) {
break;
}
distances[1] += arr[i] !== 2 ? 1 : 0;
}
return Math.min.apply(null, distances);
}
Something like this will do the job. You could make the code shorter but I've tried to make it clear. Once we find 1, start at that index and keep checking adjacent indices. We also do bounds checking to ensure we don't overflow either end.
function closest(arr) {
const index = arr.findIndex(n => n === 1);
const len = arr.length;
let offset = 1;
while (true) {
const before = index - offset;
const after = index + offset;
const beforeBad = before < 0;
const afterBad = after >= len;
// It's necessary to check both, we could exceed the bounds on one side but not the other.
if (beforeBad && afterBad) {
break;
}
if ((!beforeBad && arr[before] === 2) || (!afterBad && arr[after] === 2)) {
return offset;
}
++offset;
}
return -1;
}
You could approach this using entries and reduce.
const arr = [2, 0, 0, 0, 2, 2, 1, 0, 0 ,2];
const goal = arr.indexOf(1);
const indices = [];
// Find all the indices of 2 in the array
for (let x of arr.entries()) {
if (x[1] === 2) indices.push(x[0]) ;
}
// Find the index that is closest to your goal
const nearestIndex = indices.reduce((prev, curr) => {
return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
}); // 5
console.log(Math.abs(goal - nearestIndex)); // 1
How about this:
Output = Input.map((cur,idx,arr)=>cur==2?Math.abs(idx-arr.indexOf(1)):Infinity).sort()[0]
You could avoid for loops here in favor of a more functional style. The function minDist takes m, n, and array as arguments, and returns the minimum distance between the first occurrence of m and any occurrence of n in an array.
First, map is used to create an array with pairs for each element containing the distance to the target m element and the value of the current element. Then filter is used to keep only the pairs representing n elements. Then sort is used so that the pairs representing the closest elements are at the beginning of the array. Finally, the [0] pair of the sorted array represents the closest element, and the [0] element of this closest pair is the minimum distance.
function minDist(m, n, array) {
let index = array.indexOf(m);
return array
.map((x, i) => [Math.abs(i - index), x])
.filter(p => p[1] === n)
.sort()[0][0];
}
console.log(minDist(1, 2, [1, 0, 0, 0, 2, 2, 2]));
console.log(minDist(1, 2, [2, 0, 0, 0, 2, 2, 1, 0, 0, 2]));

How can i calculate the modes of an array and ignore a data

I'm trying to calculate the mode of an array which I can do, but I want to exclude the 0
This is my code :
const datas = [0, 0, 0, 4, 4, 2, 3, 2, 0];
function mode(numbers) {
var modes = [],
count = [],
i,
number,
maxIndex = 0;
for (i = 0; i < numbers.length; i += 1) {
number = numbers[i];
count[number] = (count[number] || 0) + 1;
if (count[number] > maxIndex) {
maxIndex = count[number];
}
}
for (i in count)
if (count.hasOwnProperty(i)) {
if (count[i] === maxIndex) {
modes.push(Number(i));
}
}
return modes;
}
mode(datas); // output : [0] and I want [4] [2]
Thanks for you time.
You can simply filter out zeroes:
datas = [0, 0, 0, 4, 4, 2, 3, 2, 0];
function mode(numbers) {
// we don't want to consider zeros
// so filter them out
numbers = numbers.filter(function(n) { return n !== 0 });
var modes = [],
count = [],
i, number, maxIndex = 0;
for (i = 0; i < numbers.length; i += 1) {
number = numbers[i];
count[number] = (count[number] || 0) + 1;
if (count[number] > maxIndex) {
maxIndex = count[number];
}
}
for (i in count)
if (count.hasOwnProperty(i)) {
if (count[i] === maxIndex) {
modes.push(Number(i));
}
}
return modes;
}
console.log(mode(datas)) // output : [4] [2]
If you're using ES6, you can use the arrow function syntax:
numbers = numbers.filter(n => n !== 0);
I just wanted to share a way to calculate the mode without for/forEach loops.
Relevant docs:
filter
reduce
Object.keys
Object.values
spread syntax (...)
arrow functions
Math.max
const counted = [0, 0, 0, 4, 4, 2, 3, 2, 0]
.filter(element => element)
.reduce(
(accumulator, currentValue) =>
({
...accumulator,
[currentValue]: (accumulator[currentValue] || 0) + 1
}),
{}
);
const maxCount = Math.max(...Object.values(counted));
const mode = Object.keys(counted).filter(key => counted[key] === maxCount);
console.log(mode);

Javascript: Check to see if multiple array values are the same (order matters)

If I have two arrays, lets say
[0, 0, 1, 1, 1, 0]
[0, 1, 0, 1, 0, 1]
I would like to check if to see if the number 1 appears three times in order so that the first array would return true and the second would return false.
I'm not really sure how to accomplish this (since order matters).
You can use a counter to see if values of 1 are sequential.
function containsSequence(arr, val, max) {
var count = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === val) {
counter++; // increment the counter by 1
}
else {
counter = 0; // reset counter
}
// our counter met our maximum
if (counter >= max) {
return true;
}
}
// if we get this far, there was no sequence
return false;
}
console.log(containsSequence([0,0,1,1,1,0], 1, 3)); // true
console.log(containsSequence([0,1,0,1,0,1], 1, 3)); // false
A solution using Array.prototype.some - tracks the count and index to test the array for consecutive numbers:
var test1 = [0, 0, 1, 1, 1, 0];
var test2 = [0, 1, 0, 1, 0, 1];
function test(arr, num, max) {
return arr.some(function(element, index) {
if(element == num) {
this.prevIndex = (this.prevIndex + 1) || index;
this.count = this.count || 0;
if(this.prevIndex == index)
this.count++;
else
this.count = 1;
if(this.count == max) return true;
}
}, Object.create(null));
}
console.log(test(test1, 1, 3));
console.log(test(test2, 1, 3));
Loop through the array,
each time take three elements from the array -if possible- starting from the element i
Check if those three elements equals one
function check(arr){
for(var i=0;i<arr.length;i++)
if(arr[i] && arr[i+1] && arr[i+2])
if(arr[i] == arr[i+1] == arr[i+2] == 1)
return true;
return false;
}
console.log(check([0, 0, 1, 1, 1, 0]));
console.log(check([0, 1, 0, 1, 0, 1]));
You can use a counter to check if the desired value val is repeated sequentially a limit of times:
function checkLimit(arr, val, limit) {
var counter = 0;
for (var i = 0, l = arr.length; i < l; i++) {
counter = (arr[i] === val) ? ++counter : 0;
if (counter === limit) {
return true;
}
}
return false;
}
console.log(checkLimit([0, 0, 1, 1, 1, 0], 1, 3)); // true
console.log(checkLimit([0, 0, 1, 1, 0, 0], 1, 3)); // false
Check this code snippet
var arr1=[0,0,1,1,1,0]
var arr2=[0,1,0,1,0,1]
console.log(checkThreeOnes(arr1));
console.log(checkThreeOnes(arr2));
function checkThreeOnes(numbers){
var i=0;
var j=numbers.length;
var oneCount=1;
for(var i=0;i<j;){
if(numbers[i]==numbers[i+1]){
oneCount++;
if(oneCount==3)
return true;
}
else
oneCount=1;
i++;
}
return false;
}
Hope this helps

Javascript - Creating pyramid array from number values

I am looking to create a pyramid array from number values. The requirement is that I am to work from an array that which in my case has 3 rows with 5 columns. I need to create a pyramid that looks like the example below.
Here is what I want to achieve exactly..
[0, 0, 1, 0, 0]
[0, 1, 1, 1, 0]
[1, 1, 1, 1, 1]
So far my code looks something like this..
var a = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]];
function array_pyramid( array ){
for (i = 0; i < array.length; i++){
for (j = 0; j <= Math.floor(array[i].length / 2); j++){
var tmp = array[i].length / 2;
console.log (Math.floor(tmp));
if ( i < j ) {
array[i][j] = 1;
}
}
}
return array;
}
function print_array(array) {
for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}
}
//console.log(a);
//print_array(a);
print_array(array_pyramid(a));
Try example below. I purposely kept variable names long and descriptive and kept operations in multiple steps rather than inline for the ease of analyzing.
var a = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]];
function array_pyramid(array){
var pBlocksCount = 1;
var currentRow, rowIndex, columnIndex, columnsCount, rowsCount = array.length;
for(rowIndex=0; rowIndex<rowsCount; rowIndex++){
currentRow = array[rowIndex];
columnsCount = currentRow.length;
var piramidDrawIndex = parseInt(columnsCount/2);
var piramidDrawOffset = parseInt(pBlocksCount/2);
var piramidDrawTrigger = piramidDrawIndex-piramidDrawOffset;
var blocksToDraw = pBlocksCount;
for(columnIndex=0; columnIndex<columnsCount; columnIndex++){
if(columnIndex>=piramidDrawTrigger){
if(blocksToDraw){
currentRow[columnIndex]=1;
blocksToDraw--;
}
}
}
pBlocksCount+=2;
}
return array;
}
function print_array(array) {
for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}
}
print_array(array_pyramid(a));
This will probably fail for most other cases you could come up with, but works in this specific instance:
function array_pyramid( array ){
var mid = Math.floor(array[0].length/2);
for(var i=0;i<array.length;i++){
for(var j=0;j<array[i].length;j++){
var boundsLower = mid-i;
var boundsUpper = mid+i;
if(j>=boundsLower && j<=boundsUpper){
array[i][j] = 1;
}
}
}
return array;
}
Live example: https://jsfiddle.net/o6t1cbdu/
Try this ...
function array_pyramid(array){
var limit = [0,0];
for (var i = array.length - 1, limit = [0, (array[0] || []).length - 1]; i >= 0; i--) {
for (var j = limit[0]; j <= limit[1]; j++) {
array[i][j] = 1;
}
limit[0]++; limit[1]--;
}
return array;
}
I hope it helps
You were starting down the right track with an inner and an outer loop, as well as your use of division to try to account for the midpoint.
Here is a verbose and heavily commented modification of your code that accounts for any number of columns (odd or even) and uses a range that widens during row progression to determine which columns should be 1 or 0. I've included a second array, b, to show it works for even column counts as well.
var a = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]
],
b = [
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]
];
function array_pyramid (a) {
// Use first row to determine row length, assume all others are the same
var base_length = a[0].length,
// Get a modulus to account for odd or even row length
mod = base_length % 2,
// Find the middle point
mid_point = Math.floor(base_length / 2) + mod,
// Account for zero-index of arrays
zero_indexed = mid_point - 1,
// Produce an initial set of boundaries
marker_range = {
lower: zero_indexed,
upper: (mod === 1) ? zero_indexed : (zero_indexed + 1)
};
// Iterate the array's rows
a.forEach(function (row) {
// Iterate the row's cols
row.forEach(function (col, i) {
// Compare index to boundaries to determine if we're outputting a 1 or a 0
row[i] = (i >= marker_range.lower && i <= marker_range.upper) ? 1 : 0;
});
// If we still have room to expand, widen the range in each direction
if (marker_range.lower > 0) {
marker_range.lower -= 1;
marker_range.upper += 1;
}
});
return a;
}
function print_array(a) {
var i;
console.log('-- Start output');
for (i = 0; i < a.length; i++) {
console.log(' ', a[i]);
}
console.log('-- End output');
console.log(' ');
}
console.log('a (odd col count):');
print_array(array_pyramid(a));
console.log('b: (even col count)');
print_array(array_pyramid(b));
So here is my code, it works fine.
The idea is that you find the main vertical center of the matrix and the sideA and sideB variables represent the left and the right side of the pyramid. Once you've found the sides, you make them equal to one as well as everything between them ( if (j <= sideA && j >= sideB) ). I hope that helps. :)
function array_pyramid ( array ) {
var item, sideA, sideB;
if (array instanceof Array) {
for (var i = 0; i < array.length; i++) {
item = array[i];
centerIndex = Math.floor(item.length / 2);
sideA = centerIndex + i;
sideB = centerIndex - i;
for (var j = 0; j < item.length; j++) {
if (j <= sideA && j >= sideB) {
item[j] = 1;
}
}
}
return array;
} else {
return 'Invalid array';
}
}
array_pyramid ([
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
]);
When you run that code in the console it will return this:
[0, 0, 1, 0, 0]
[0, 1, 1, 1, 0]
[1, 1, 1, 1, 1]
And that's it.

Categories