Let's say I want a variable to contain numbers from 1 to 100.
I could do it like this:
var numbers = [1,2,3,4,...,98,99,100]
But it would take a bunch of time to write all those numbers down.
Is there any way to set a range to that variable? Something like:
var numbers = [from 1, to 100]
This might sound like a really nooby question but haven't been able to figure it out myself. Thanks in advance.
Store the minimum and maximum range in an object:
var a = {
from: 0,
to: 100
};
In addition to this answer, here are some ways to do it:
for loop:
var numbers = []
for (var i = 1; i <= 100; i++) {
numbers.push(i)
}
Array.prototype.fill + Array.prototype.map
var numbers = Array(100).fill().map(function(v, i) { return i + 1; })
Or, if you are allowed to use arrow functions:
var numbers = Array(100).fill().map((v, i) => i + 1)
Or, if you are allowed to use the spread operator:
var numbers = [...Array(100)].map((v, i) => i + 1)
However, note that using the for loop is the fastest.
You can easily create your own, and store only the limits:
function Range(begin, end) {
this.low = begin;
this.hi = end;
this.has = function(n) {
return this.low <= n <= this.hi;
}
}
// code example
var range = new Range(1,100);
var num = 5;
if (range.has(num)) {
alert("Number in range");
}
Supported in all modern browsers including IE9+.
var numbers = Array.apply(null,Array(100)).map(function(e,i){return i+1;});
For what it's worth, #MaxZoom had answer that worked for my situation. However, I did need to modify the return statement to evaluate with && comparison. Otherwise appeared to return true for any number.
function Range(begin, end) {
this.low = begin;
this.hi = end;
this.has = function(n) {
//return this.low <= n <= this.hi;
return ( n >= this.low && n <= this.hi );
};
}
// code example
var alertRange = new Range(0,100);
var warnRange = new Range(101, 200);
var num = 1000;
if (alertRange.has(num)) {
alert("Number in ALERT range");
//Add Alert Class
}
else if (warnRange.has(num)) {
alert("Number in WARN range");
//Add Warn Class
}
else{
alert("Number in GOOD range")
//Default Class
}
Python
# There can be two ways to generate a range in python
# 1)
a = [*range(5)]
print(a)
#[0, 1, 2, 3, 4]
# 2)
a = [*range(5,10)]
print(a)
#[5, 6, 7, 8, 9]
Javascript
// Similar pattern in Javascript can be achieved by
let a;
// 1)
a = [...Array(5).keys()]
console.log(a) //[0, 1, 2, 3, 4]
// 2)
a = [...Array(5).keys()].map(value => value + 5);
console.log(a) //[5,6,7,8,9]
Related
The question was to find the largest binary gap in a number, and while this worked in my IDE, Codility didn't accept it. Any thoughts?
const biGap = (number) => {
const binary = number.toString(2)
const re = /1(0+)1/g;
const found = binary.match(re)
let counter = 0
found.map((match) => {
if (match.length > counter) {
counter = match.length
}
})
return (counter - 2);
}
console.log(biGap(1041));
The main problem with your code is that binary.match(re) won't return overlapping matches. So if binary = "1010000001001", it will return ["101", "1001"], which is missing the long gap 10000001 between them.
You can solve this by changing the regexp to
const re = /0+1/g;
Then you should return counter - 1 instead of counter - 2.
You don't need to put 1 on both sides of the 0+ because number.toString(2) will never include leading zeroes, so there's always a 1 to the left of any string of zeroes, and it's not necessary to match it explicitly.
If you also want to include the binary gap in the low order bits of the number, you can change the regexp to simply:
const re = /0+/g;
Then you don't need to subtract anything from counter when returning.
const biGap = (number) => {
const binary = number.toString(2)
const re = /0+1/g;
const found = binary.match(re)
let counter = 0
found.map((match) => {
if (match.length > counter) {
counter = match.length
}
})
return (counter - 1);
}
console.log(biGap(1041));
console.log(biGap(parseInt("1010000001001", 2))); // Your code returns 2
function binGap(N) {
var max=0;
var count=0;
var binary = Number(N).toString(2);;
Array.prototype.forEach.call(binary,function(i) {
if(i == 0) {
count++;
} else {
if(count > max) {
max = count;
}
count = 0;
}
});
return max;
}
for starters make sure that the regex returns all the right candidates
map operator is used the wrong way. Reduce is the way to use in your case
you should not subtract 2 from the counter at return, instead do that in the reduce callback
don't console.log
And a final thought, why convert the number into string? why not use modulo 2? it's way simpler and efficient. (think of how much resources a regex requires)
a possible solution may be this
solution(N) {
while(N && N%2 === 0) {
N = N>>1
}
let counter = 0;
let tempCounter = 0;
let n=N;
while(n) {
if(n%2 === 1) {
counter = Math.max(counter, tempCounter);
tempCounter=0;
} else {
tempCounter = tempCounter + 1;
}
n = n>>1;
}
return counter;
}
I'm trying to get whatever number is the most frequently occuring number in an array, so for an array containing 1,2,10,5,1 the result should be 1. The code I wrote returns me the frequency for each number, so 1 occurs twice, 2 occurs once, 10 occurs once etc. Any suggestions how I can fix my result?
function mode(arr) {
var uniqNum = {};
var numCounter = function(num, counter) {
if(!uniqNum.hasOwnProperty(num)) {
uniqNum[num] = 1;
} else {
uniqNum[num] ++;
}
};
arr.forEach(numCounter);
return uniqNum;
}
I've kept your code unchanged and added some extra statements. Here is the demo: http://codepen.io/PiotrBerebecki/pen/rrdxRo
function mode(arr) {
var uniqNum = {};
var numCounter = function(num, counter) {
if(!uniqNum.hasOwnProperty(num)) {
uniqNum[num] = 1;
} else {
uniqNum[num] ++;
}
};
arr.forEach(numCounter);
return Object.keys(uniqNum)
.sort((a,b) => uniqNum[b] - uniqNum[a]) // sort by frequency
.filter((val,ind,array) => uniqNum[array[0]] == uniqNum[val]) // leave only most frequent
.map(val => Number(val)); // convert text to number
}
console.log( JSON.stringify(mode([3,3,2,4,4])) ) // [3,4]
console.log( JSON.stringify(mode([2,4,3,3])) ) // [3]
I think it could be done only with a little modification to your forEach loop and the assistance of another auxiliary data structure:
function mode(arr) {
var freq = [], uniqNum = {}, i;
arr.forEach(function (num) {
uniqNum[num] = i = (uniqNum[num] || 0) + 1;
freq[i] = (freq[i] || []).concat(num);
});
return freq[freq.length - 1];
}
console.log(mode([1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 6, 7, 1, 6]));
With only one iteration over all the elements of the array we can gather enough information to print out the result:
uniqNum is the set you created to gather info about the element's frequency.
freq will be an array which last element will contain an array with the elements of higher frequency.
Fiddle. Hope it helps.
First we want to make an array where we count the number of occurrences of a certain value up to that point.
Then we use the reduce function to return an array of values read from the original array for the indexes whose values have the current max appearances. We redefine max and empty the final output array of modes (if new max is established) as we go along. We want this to be a collection in case there is a tie for maximum appearances.
Additional advantage of the below is that it doesn't require sort which is more expensive o(nlog n) and keeps the time complexity down to just linear. I also wanted to keep the functions used down to only two (map and reduce) as it is all that is need in this case.
edit: fixed a major bug uniqNum[e] += 1 instead of uniqNum[e] + 1 which went unnoticed as my initial case array was still returning expected result. Also made the syntax more concise in favor of more comments.
var arr = [1,2,10,5,1,5,2,2,5,3,3];
//global max to keep track of which value has most appearances.
var max = -1;
var uniqNum = {};
var modeArray = arr.map(function(e) {
//create array that counts appearances of the value up to that point starting from beginning of the input arr array.
if(!uniqNum.hasOwnProperty(e)) {
uniqNum[e] = 1;
return 1;
} else {
return uniqNum[e] += 1;
}
//reduce the above appearance count array into an array that only contains values of the modes
}).reduce(function (modes, e1, i) {
//if max gets beaten then redefine the mode array to only include the new max appearance value.
if(e1 > max){
//redefining max
max = e1;
//returning only the new max element
return [arr[i]];
//if its a tie we still want to include the current value but we don't want to empty the array.
}else if(e1 == max){
//append onto the modes array the co-max value
return[...modes, arr[i]];
}
return modes;
},[]);
alert(modeArray);
Here is a test you can run of my solution against #acontell. In my browser (Chrome with V8) my solution was around three-four times faster for arrays with large number of repeating values and even bigger advantage with distributions with lower number of repeating values. #acontell 's is a cleaner looking solution for sure, but definitely not faster in execution.
var arr = [];
for(var i=0; i < 100000; i++){
arr.push(Math.floor(Math.random() * (100 - 1)) + 1);
}
console.time("test");
test();
function test(){
var max = -1;
var uniqNum = {};
var modeArray = arr.map(function(e) {
//create array that counts appearances of the value up to that point starting from beginning of the input arr array.
if(!uniqNum.hasOwnProperty(e)) {
uniqNum[e] = 1;
return 1;
} else {
return uniqNum[e] += 1;
}
//reduce the above appearance count array into an array that only contains values of the modes
}).reduce(function (modes, e1, i) {
//if max gets beaten then redefine the mode array to only include the new max appearance value.
if(e1 > max){
//redefining max
max = e1;
//returning only the new max element
return [arr[i]];
//if its a tie we still want to include the current value but we don't want to empty the array.
}else if(e1 == max){
//append onto the modes array the co-max value
modes.push(arr[i])
return modes;
}
return modes;
},[]);
}
console.timeEnd("test");
console.time("test1");
test1();
function test1 () {
var freq = [],
uniqNum = {},
i;
arr.forEach(function(num) {
uniqNum[num] = i = (uniqNum[num] || 0) + 1;
freq[i] = (freq[i] || []).concat(num);
});
return freq[freq.length - 1];
}
console.timeEnd("test1");
I've tried as an exercise to solve this with native js functions.
var arr = [1,2,10,5,1];
// groupBy number
var x = arr.reduce(
function(ac, cur){
ac[cur]?(ac[cur] = ac[cur] + 1):ac[cur] = 1;
return ac;
}, {}
);
// sort in order of frequencies
var res = Object.keys(x).sort(
function(a,b){ return x[a] < x[b]}
);
res[0] has the most frequent element
I wonder what's the most efficient way to write a function that takes two arrays of random integers and terminates when a pair of matching Integers is found.
In the following example there are two arrays, one larger then the other.
The larger array contains the potential dividents, the smaller array the divisors.
I'd like the function to calculate until it has found a pair of divident and divisor that are divisible without remainder.
EXAMPLE:
var listDivident = _.shuffle(_.range(1, 101));
var listDivisor = _.shufle(_.range(1, 11));
randomMatch = function (listDivident, listDivisor) {
/* until ((listDivident % listDivisor !== "undefined")
&& (listDivident % listDivisor === 0) {
...
}
*/
return {
matchDivident: matchDivident,
matchDivisor: matchDivisor
};
};
Is there something like an "until" function or construct in JS?
Thanks for your help!
Vin
Unless your arrays are very large, you can simply generate all valid pairs first and then pick a random one:
var pairs = [];
_.each(listDivident, function(a) {
_.each(listDivisor, function(b) {
if(!(a % b))
pairs.push([a, b])
})
});
result = _.shuffle(pairs)[0];
What you call "until" can be achieved by looping until you find what you need:
var listDivident = _.shuffle(_.range(1, 101));
var listDivisor = _.shufle(_.range(1, 11));
randomMatch = function (listDivident, listDivisor) {
var i = 0,
found = false,
dividentLength = listDivident.length,
divisorLength = listDivisor.length,
matchDivident = null,
matchDivisor = null;
while (!found && i < dividentLength && i < divisorLength) {
if (listDivident[i] % listDivisor[i] === 0) {
matchDivident = listDivident[i];
matchDivisor = listDivisor[i];
found = true;
} else {
i++;
}
}
return {
matchDivident: matchDivident,
matchDivisor: matchDivisor
};
};
EDIT: After that, just call the randomMatch() with the whole arrays:
alert(randomMatch(listDivident, listDivisor));
I've a problem that has been bugging me for a while now.
I have 14 divs each which must be assigned a random ID (between 1 and 14) each time the page loads.
Each of these divs have the class ".image-box" and the format of the ID I'm trying to assign is 'box14'
I have the JS code working to assign random IDs but I'm having trouble not getting the same ID to assign twice.
JavaScript
var used_id = new Array();
$( document ).ready(function() {
assign_id();
function assign_id()
{
$('.image-box').each(function (i, obj) {
random_number();
function random_number(){
number = 2 + Math.floor(Math.random() * 14);
var box_id = 'box' + number;
if((box_id.indexOf(used_id) !== -1) === -1)
{
$(this).attr('id',box_id);
used_id.push(box_id);
}
else
{
random_number();
}
}
});
}
});
Thanks for your help,
Cheers
Mmm, random...
Instead of using a randomly generated number (which, as your experiencing, may randomly repeat values) just use an incrementally-updated counter when assigning IDs.
function assign_id() {
var counter = 0;
$('.image-box').each(function (i, obj) {
$(this).attr('id','image-box-' + counter++); }
});
}
I think this is what you want and DEMO
$(document).ready(function() {
assign_id();
});
function assign_id() {
var numberOfDiv = $('.image-box').length;
var listOfRandomNumber = myFunction(numberOfDiv);
$('.image-box').each(function(i, obj) {
$(this).attr("id",listOfRandomNumber[i]);
});
};
//Getting List Of Number contains 1 to the number of Div which is
//14 in this case.
function myFunction(numberOfDiv ) {
for (var i = 1, ar = []; i < numberOfDiv +1 ; i++) {
ar[i] = i;
}
ar.sort(function() {
return Math.random() - 0.5;
});
return ar;
};
I would suggest to have a global array like u have for user_id and push assigned div ids into array. Then you can check before assigning random id to div. If it is assigned use different one.
Hope this helps.
Cheers.
First how you'd use my implementation:
var takeOne = makeDiminishingChoice(14);
In this case, takeOne is a function that you can call up to 14 times to get a unique random number between 1 and 14.
For example, this will output the numbers between 1 and 14 in random order:
for (var i = 0; i < 14; i++) {
console.log(takeOne());
}
And here is the implementation of makeDiminishingChoice itself:
var makeDiminishingChoice = function (howMany) {
// Generate the available choice "space" that we can select a random value from.
var pickFrom = [];
for (var i = 0; i < howMany; i++) {
pickFrom.push(i);
}
// Return a function that, when called, will return a value from the search space,
// until there are no more values left.
return function() {
if (pickFrom.length === 0) {
throw "You have requested too many values. " + howMany + " values have already been used."
}
var randomIndex = Math.floor(Math.random() * pickFrom.length);
return pickFrom.splice(randomIndex, 1)[0];
};
};
It's better to use incremental values(or something like (new Date).getTime()) if all you want to do is assign unique values. But if, for some reason, you must have randomly-picked values(only from 1-14) then use something like this to pick unique/random values
var arrayId = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
function getRandomId(array) {
var randomIndex = Math.floor(Math.random() * (array.length));
var randomId = array.splice(randomIndex, 1);
return randomId[0];
}
Now getRandomId(arrayId) would return a randomly picked value from your array and then remove that value so that it is not repeated.
This function is meant to find the highest variable in a list of variables, which have five id letters, and one number. It works fine with all the other slots, 2, 3, 4, 5, 6, 7, 8, 9, 10, but not 1. I need another set of eyes here.
The getVer function takes the number from the id; so ImpHt1 with getVer would be 1, while getShtNm gets ImpHt.
function find_max_feat(array_input,ShtNm) {
if (String(array_input[0]).length == 1) {
var max = 0;
}
else {
var max = getVer(array_input[0]);
}
var maxver = 0
var len = array_input.length;
for (var i = 0; i < len; i++) {
if (String(array_input[i]).length > 1) {
if (getShtNm(String(array_input[i])) == ShtNm) {
if (getVer(String(array_input[i])) > maxver) {
var max = array_input[i];
var maxver = getVer(String(array_input[i]));
}
}
}
}
return max;
}
0,DmnHt1_0,AltFm1_,0,0,0,0,0,0,0
An example of the array, which is why getVer is needed.
This is for a sheet generator, to be clear, but I've been working on the entire thing for at least a few days now, maybe even a week or weeks of on and off work.
The array above is generated any time a feat is selected, and the find_max_feat array is used to find the highest version in a group; it operates off of an infinite loop since nothing else I did could get it to work the way I wanted it to.
function checkFeats() {
updateFeatsel();
t=setTimeout("checkFeats()",1000);
}
function updateFeatsel() {
curselarray = new Array();
var selinc = 1;
while (selinc <= 10) {
var selincar = selinc - 1;
var selid = document.getElementById(String('ftlst' + selinc));
if (getVer(selid.options[selid.selectedIndex].title)) {
curselarray[selincar] = selid.options[selid.selectedIndex].title;
}
else {
curselarray[selincar] = 0;
}
selinc++;
}
document.getElementById('debug1').innerHTML = curselarray.valueOf();
featSelch('hlthm','ImpHt',healthom);
featSelch('strdmgm','ImpPd',Strpdom);
featSelch('strwhtm','ImpLi',Strwhtom);
featSelch('strsltm','EnhIt',StrSltom);
featSelch('endsurm','ImpEn',EndSurom);
featSelch('endsokm','ImpDf',EndSokom);
featSelch('intelmpm','ImpMg',Intelmom);
featSelch('willsokm','ImpMs',Willsokom);
featSelch('luckrllm','ImpLu',Lukrllom);
featSelch('luckpntm','EnhLu',Lukpntom);
featSelch('hlthbn','DmnHt',0);
featSelch('strbn','SupSt',0);
featSelch('luckbn','DmnLu',0);
featSelch('endbn','Armor',0)
document.getElementById('debug2').innerHTML = find_max_feat(curselarray,'DmnHt');
updateAmounts();
}
function featSelch(sid,fshtnm,defval) {
return document.getElementById(sid).innerHTML = getFeatvalue(fshtnm,defval);
}
That is because you are initialising max using getVer(array_input[0]) instead of array_input[0]. If the first item is the highest and has the version number zero, the initial value is used.
Change this:
var max = getVer(array_input[0]);
into:
var max = array_input[0];