Find the biggest number using javascript - javascript

I need to find the biggest number in a webpage (it is not my webpage).
Do I need javascript?
First I need to get the values from all the SPAN.f elements. Then, I must to compare the numbers into them to find out the biggest value.
How?
Let's say I've got 220 - 340 - 480 × 360 - 25/7/2012 from all the SPAN.f elements.
I need 480 to be highlighted, but I don't want /2012 to be highlighted because is part of the date. I mean, I want to highlight the 480, not the /2012.
I use GreaseMonkey with Firefox Nightly 22
THIS IS THE SCRIPT, but it does not work for me:
// ==UserScript==
// #name MAX NUMBER in page
// #include https://www.google.com/search*
// #version 1
// #grant none
// ==/UserScript==
var spans = document.querySelectorAll("SPAN.f");
var max = -Infinity;
var maxSpan;
Array.prototype.forEach.call(spans, function(span) {
var val = Number(span.textContent);
if (max < val)
{
max = val;
maxSpan = span;
}
});
if (maxSpan) maxSpan.style.backgroundColor = "yellow";
Try the code in the page into this link:
https://www.google.com/search?hl=es&tbs=sbi%3AAMhZZitcQmshs1XQVAv0-EH8Ix_18bqev3_1smHm0uRMYGzjaSYpDr6KHQ_1tWEwNyvZGPus4-VWnfO9P9071ZllBMIC3amGAveNcz_1uYWteP9OKZ1Si1Yz0urBuyIWQbBTQIue4Gntn5J8FIxaLI1kEHMdI2BIh6mrM6YGiMBT6DJyLlW4K-1kE0n_1d2fnXoNxKDd4jM034f9ctLfUYb4WvSaptVZknw_1jhHBFu9HeINrN15ha7k9Kzz1Ifm_1P5y7Vxws_1Qjr48P-rXcoqneksiRnfQyXwTGJeuMAD0wtgNnXubqYgzrPkxbZ-BonJ9Hgxvy5pv6lfEsGIuNzrtxd6QFdDKAP5keREmQ&ei=vTkuU87gBKay2wWU0IHoBg&ved=0CAgQiBw&biw=1024&bih=624&dpr=1

24/Dec/1789 is not a valid number, but should be a string, the others are numbers, and you can do
var biggest = Math.max(100, 220, 340);
If what you've got is a string, you could do
var str = '100 - 220 - 340 - 24/Dec/1789';
var biggest = Math.max.apply(null, str.split('-').filter(function(x) {
return !isNaN(x);
}));
FIDDLE;

I imagine you mean finding the largest number contained in SPAN elements having the class f (this is what the syntax SPAN.f stands for).
If so you don't need a regular expression and you don't even need to sort the values. Just iterate once over each value to find the smallest one.
Something like this:
var spans = document.querySelectorAll("SPAN.f");
var max = -Infinity;
var maxSpan;
Array.prototype.forEach.call(spans, function(span) {
var val = Number(span.textContent);
if (max < val)
{
max = val;
maxSpan = span;
}
});
if (maxSpan) maxSpan.style.backgroundColor = "yellow";
Fiddle: http://jsfiddle.net/C35W6/

Related

Circular Queue in Javascript

I was going through a book on Data Structures and Algorithm with JavaScript when I found this piece of codes.
I need someone to help me explain the logic behind the code here, also the logic behind the value of var i in each method.
var i = (this._front + length) & (this._size - 1); //explain this in push()
var i = (this._front + length - 1) & (this._size - 1); // explain this in pop()
var i = (((( this._front - 1 ) & ( size - 1) ) ^ size ) - size );// explain this in unshift()
Please explain the general logic for each method, I have an issue with the use of & operator in the above statements, please why the use of & instead of %
var CircularDequeue = (()=> {
class CircularDequeue {
constructor() {
// pseudo realistic 2^x value
this._size = 1024;
this._length = 0;
this._front = 0;
this._data = [];
}
push (item) {
// get the length of the array
var length = this._length;
// calculate the end
var i = (this._front + length) & (this._size - 1);
// assign value to the current end of the data
this._data[i] = item;
// increment length for quick look up
this._length = length + 1;
// return new length
return this._length;
}
pop () {
// get the length of the array
var length = this._length;
// calculate the end
var i = (this._front + length - 1) & (this._size - 1);
// copy the value to return
var ret = this._data[i];
// remove the value from data
this._data[i] = undefined;
// reduce length for look up
this._length = length - 1;
// return value
return ret;
}
shift () {
// get the current front of queue
var front = this._front;
// capture return value
var ret = this._data[front];
// reset value in the data
this._data[front] = undefined;
// calculate the new front of the queue
this._front = (front + 1) & (this._size - 1);
// reduce the size
this._length = this._length - 1;
// return the value
return ret;
}
unshift (item) {
// get the size
var size = this._size;
// calculate the new front
var i = (((( this._front - 1 ) & ( size - 1) ) ^ size ) -
size );
// add the item
this._data[i] = item;
// increment the length
this._length = this._length + 1;
// update the new front
this._front = i;
// return the acknowledgement of the addition of the new
item
return this._length;
}
}
return CircularDequeue;
})();
module.exports = CircularDequeue;
I have tried to understand this logic but the use of bitwise & in calculating the values of var i instead of modulo operator(%) keeps confusing me
In this code something & (size - 1) is equivalent to something % size because size is a power of 2, and seeing the comment in the constructor, it is supposed to be a power of 2.
I don't see a good reason why the following has been done:
(((( this._front - 1 ) & ( size - 1) ) ^ size ) - size )
The first part ( this._front - 1 ) & ( size - 1) is always going to be a non-negative number that is less than size.
^ size will set a bit that is 0 (because the intermediate value is less than size) and then - size will clear that same bit again. So that ^ size ) - size part is a non-operation. It can be left out.
It is unclear why the author of this code preferred to work with the & operator than the %, as the latter one would also work if the size would not have been a power of two, while the & operator will only work as intended when size is a power of 2.
To see how & works, take for example that the left side is 1025, which means it is out of range. In binary 1025 is 10000000001. On the other hand we have size which is 1024. size - 1 in binary is 1111111111.
So we have this & operation:
10000000001
1111111111
----------- &
0000000001
So this operation effectively removes any excess bits from the left side operand, whether they come from a negative value or from a value that is not less than size.

prevent rendering to page of duplicate random number generated when min and max are user defined [duplicate]

I ran into the challenge where I need a function that returns a random number within a given range from 0 - X. Not only that, but I require the number returned to be unique; not duplicating numbers that have already been returned on previous calls to the function.
Optionally, when this is done (e.g. the range has been 'exhausted'), just return a random number within the range.
How would one go about doing this?
This should do it:
function makeRandomRange(x) {
var used = new Array(x),
exhausted = false;
return function getRandom() {
var random = Math.floor(Math.random() * x);
if (exhausted) {
return random;
} else {
for (var i=0; i<x; i++) {
random = (random + 1) % x;
if (random in used)
continue;
used[random] = true;
return random;
}
// no free place found
exhausted = true;
used = null; // free memory
return random;
}
};
}
Usage:
var generate = makeRandomRange(20);
var x1 = generate(),
x2 = generate(),
...
Although it works, it has no good performance when the x-th random is generated - it searches the whole list for a free place. This algorithm, a step-by-step Fisher–Yates shuffle, from the question Unique (non-repeating) random numbers in O(1)?, will perform better:
function makeRandomRange(x) {
var range = new Array(x),
pointer = x;
return function getRandom() {
pointer = (pointer-1+x) % x;
var random = Math.floor(Math.random() * pointer);
var num = (random in range) ? range[random] : random;
range[random] = (pointer in range) ? range[pointer] : pointer;
return range[pointer] = num;
};
}
(Demo at jsfiddle.net)
Extended version which does only generate one "group" of unique numbers:
function makeRandomRange(x) {
var range = new Array(x),
pointer = x;
return function getRandom() {
if (range) {
pointer--;
var random = Math.floor(Math.random() * pointer);
var num = (random in range) ? range[random] : random;
range[random] = (pointer in range) ? range[pointer] : pointer;
range[pointer] = num;
if (pointer <= 0) { // first x numbers had been unique
range = null; // free memory;
}
return num;
} else {
return Math.floor(Math.random() * x);
}
};
}
(Demo)
You got some great programming answer. Here's one with a more theoretical flavor to complete your panorama :-)
Your problem is called "sampling" or "subset sampling" and there are several ways you could do this. Let N be the range you are sampling frame (i.e., N=X+1) and M be the size of your sample (the number of elements you want to pick).
if N is much larger than M, you'll want to use an algorithm such as the one suggested by Bentley and Floyd in his column "Programming Pearls: a sample of brilliance" (temporarily available without ACM's lock screen here), I really recommend this as they explicitly give code and discuss in terms of hash tables, etc.; there a few neat tricks in there
if N is within the same range as M, then you might want to use the Fisher-Yates shuffle but stop after only M steps (instead of N)
if you don't really know then the algorithm on page 647 of Devroye's book on random generation is pretty fast.
I wrote this function. It keeps its own array with a history of generated numbers, preventing initial duplicates, continuing to output a random number if all numbers in the range have been outputted once:
// Generates a unique number from a range
// keeps track of generated numbers in a history array
// if all numbers in the range have been returned once, keep outputting random numbers within the range
var UniqueRandom = { NumHistory: new Array(), generate: function(maxNum) {
var current = Math.round(Math.random()*(maxNum-1));
if (maxNum > 1 && this.NumHistory.length > 0) {
if (this.NumHistory.length != maxNum) {
while($.inArray(current, this.NumHistory) != -1) { current = Math.round(Math.random()*(maxNum-1)); }
this.NumHistory.push(current);
return current;
} else {
//unique numbers done, continue outputting random numbers, or we could reset the history array (NumHistory = [];)
return current;
}
} else {
//first time only
this.NumHistory.push(current);
return current;
}
}
};
Here's a working Fiddle
I hope this is of use to someone!
Edit: as pointed out by Pointy below, it might get slow with a large range (here is a
fiddle, going over a range from 0-1000, which seems to run fine). However; I didn't require a very large range, so perhaps this function is indeed not suited if you look to generate and keep track of an enormous range.
You may try generating the number using the current date and time value which would make it unique. To make it within the range, you may have to use some mathematical function.

Calculate Ratios in JS like Humble Bundle

Do you know the sliders that you have on humblebundle.com when selecting where you want the money to go? Well when you adjust any one ratio it will automatically adjust the rest.
So say you're paying $20 no matter what but you want to adjust your tip to HB from $2 to $5, the ratios that were on the other stuff should automatically lowered to match but I have no idea what I'm doing.
This is as close as I get mathematically:
var settip = 50;
var tip = 5;
var devs = 75;
var donation = 20;
tip = settip;
var newAvail = 100 - tip;
var rCalc = 100 - (devs + donation);
devs = ((devs + rCalc) * newAvail) * .01;
donation = ((donation + rCalc) * newAvail) * .01;
console.log("New Ratio Calculation: " + rCalc);
console.log("New available space: " + newAvail);
console.log(tip);
console.log(devs);
console.log(donation);
The console logs are just so I can try and put it together in my head where things are going wrong. The numbers are also whole numbers first: 50 instead of .5 because Javascript is not accurate and I don't want to do the fix code every time, I'd rather figure out how to make the code work first and then think about optimizing.
So if anyone could guide me on a method or where I am going wrong here, then that'd be great. Thanks.
Tip is tip to the bundle maker.
Devs is tip to the devs.
Donation is tip to the donation box.
Each number is the ratio. Settip is the new ratio, I should be able to change any one value and have it automatically change all others but I can't even figure out how to do the first part so I couldn't begin to try for the second part of making it actually functional.
I think this problem is not as easy as it might seem if you want to cover different edge cases. Here I assume that you distribute money so you need following properties:
Each amount must be whole integer in cents
Sum of all amounts must be equal to the total sum
The simplest way to deal with it in JS is to make all calculations using whole numbers (e.g. sum in cents instead of dollars) and format them in more human-readable way on UI. Still even with this simplification it requires some non-trivial code:
function updateRates(rates, newValue, index) {
var i, len = rates.length;
var sum = 0;
for (i = 0; i < len; i++)
sum += rates[i];
var oldValue = rates[index];
var newRest = sum - newValue;
var curRest = sum - rates[index];
rates[index] = newValue;
var remainders = new Array(len);
var fraction, value, subsum = 0;
for (i = 0; i < len; i++) {
if (i === index) continue;
// special case, all other sliders were at 0 - split value equally
if (curRest === 0) {
fraction = 1.0 / (len - 1)
}
else {
fraction = rates[i] / curRest
}
value = newRest * fraction;
rates[i] = Math.floor(value); // always round down and then distribute rest according to the Largest remainder method
subsum += rates[i];
remainders[i] = {
index: i,
value: value - rates[i]
};
}
// sort remainders and distribute rest (fractions) accordingly
remainders.sort(function (a, b) {
var av = a.value;
var bv = b.value;
if (av === bv)
return 0;
if (av < bv)
return 1;
else
return -1;
});
for (i = 0; subsum < newRest; i++) {
rates[remainders[i].index] += 1;
subsum += 1;
}
return rates;
}
Some non-trivial tests:
1. updateRates([85,10,5], 82, 0) => [82, 12, 6]
2. updateRates([85,10,5], 83, 0) => [83, 11, 6]
3. updateRates([85,10,5], 84, 0) => [84, 11, 5]
4. updateRates([100,0,0], 95, 0) => [95, 2, 3]
5. updateRates([4,3,3,1], 0, 0) => [0, 5, 5, 1]
Pay attention to the example #5. If one used some naive rounding, sum will not be preserved. Effectively you need to distribute +4 in proportion 3:3:1. It means you should add +12/7, +12/7 and +4/7. Since 12/7 = 1 5/7, according to standard mathematical rules all three should be rounded up resulting in +2, +2, +1 but we only got +4 cents to distribute. To fix this issue the largest remainder method is used to distribute fractional cents among categories. Simply speaking the idea is that we first distribute only whole number of cents (i.e. always round down), calculate how many cents are actually left and then distribute them one by one. The biggest possible drawback of this method is that some rates that started with equal values might have different values after update. On the other hand this can't be avoided as example #4 shows: you can't split 5 cents equally between two categories.
To restate what I think you want: the three variables tip, devs and donation should always sum to 100. When one variable is updated, the other two should be updated to compensate. The automatic updates should keep the same ratios to each other (for example, if donation is double devs, and tips is updated, then the updated donation value should still be double the devs value).
If I've got that right, then this should work for you:
var tips = 5;
var devs = 20;
var donation = 75;
var setTips = function(newValue) {
tips = newValue;
var sum = devs + donation;
var devShare = devs / sum; // the share devs gets between devs and donation
var donationShare = 1 - devShare; // or could calculate as donation / sum
devs = (100 - tips) * devShare; // the remaining times it's share ratio
donation = (100 - tips) * donationShare; // the remaining times it's share ratio
};
// test it out
setTips(50);
console.log(tips, devs, donation);

Pick random combination from 194481 possibilities

I have a file of 194481 permutations for
0,1,2,3,4,5,6,...,21
which looks like this;
[0,0,0,0],[0,0,0,1],[0,0,0,2],[0,0,0,3],[0,0,0,4],[0,0,0,5],[0,0,0,6],[0,0,0,7],[0,0,0,8],[0,0,0,9],[0,0,0,10],[0,0,0,11],[0,0,0,12],[0,0,0,13],[0,0,0,14],[0,0,0,15],[0,0,0,16],[0,0,0,17],[0,0,0,18],[0,0,0,19],[0,0,0,20],[0,0,1,0],[0,0,1,1],[0,0,1,2],[0,0,1,3],[0,0,1,4],[0,0,1,5],[0,0,1,6],[0,0,1,7],[0,0,1,8],[0,0,1,9],[0,0,1,10],[0,0,1,11],[0,0,1,12],[0,0,1,13],[0,0,1,14],[0,0,1,15],[0,0,1,16],[0,0,1,17],[0,0,1,18],[0,0,1,19],[0,0,1,20],[0,0,2,0],[0,0,2,1],[0,0,2,2],[0,0,2,3],[0,0,2,4],[0,0,2,5],[0,0,2,6],[0,0,2,7],[0,0,2,8],[0,0,2,9],[0,0,2,10],[0,0,2,11],[0,0,2,12],[0,0,2,13],[0,0,2,14],[0,0,2,15],[0,0,2,16],[0,0,2,17],[0,0,2,18],[0,0,2,19],[0,0,2,20],[0,0,3,0],[0,0,3,1],[0,0,3,2],[0,0,3,3],[0,0,3,4],[0,0,3,5],[0,0,3,6],[0,0,3,7],[0,0,3,8],[0,0,3,9],[0,0,3,10],[0,0,3,11],[0,0,3,12],[0,0,3,13],[0,0,3,14],[0,0,3,15],[0,0,3,16],[0,0,3,17],[0,0,3,18],[0,0,3,19],[0,0,3,20],[0,0,4,0],[0,0,4,1],[0,0,4,2],[0,0,4,3],[0,0,4,4],[0,0,4,5],[0,0,4,6],[0,0,4,7],[0,0,4,8],[0,0,4,9],[0,0,4,10],[0,0,4,11],[0,0,4,12],[0,0,4,13],[0,0,4,14],[0,0,4,15],[0,0,4,16],[0,0,4,17],[0,0,4,18],[0,0,4,19],[0,0,4,20],[0,0,5,0],[0,0,5,1],[0,0,5,2],[0,0,5,3],[0,0,5,4],[0,0,5,5],[0,0,5,6],[0,0,5,7],[0,0,5,8],[0,0,5,9],[0,0,5,10],[0,0,5,11],[0,0,5,12],[0,0,5,13],[0,0,5,14],[0,0,5,15],[0,0,5,16],[0,0,5,17],[0,0,5,18],[0,0,5,19],[0,0,5,20],[0,0,6,0],[0,0,6,1],[0,0,6,2],[0,0,6,3],[0,0,6,4],[0,0,6,5],[0,0,6,6],[0,0,6,7],[0,0,6,8],[0,0,6,9],[0,0,6,10],[0,0,6,11],[0,0,6,12],[0,0,6,13],[0,0,6,14],[0,0,6,15],[0,0,6,16],[0,0,6,17],[0,0,6,18],[0,0,6,19],[0,0,6,20],[0,0,7,0],[0,0,7,1],[0,0,7,2],[0,0,7,3],[0,0,7,4],[0,0,7,5],[0,0,7,6],[0,0,7,7],[0,0,7,8],[0,0,7,9],[0,0,7,10],[0,0,7,11],[0,0,7,12],[0,0,7,13],[0,0,7,14],[0,0,7,15],[0,0,7,16],[0,0,7,17],[0,0,7,18],[0,0,7,19],[0,0,7,20],[0,0,8,0],[0,0,8,1],[0,0,8,2],[0,0,8,3],[0,0,8,4],[0,0,8,5],[0,0,8,6],[0,0,8,7],[0,0,8,8],[0,0,8,9],[0,0,8,10],[0,0,8,11],[0,0,8,12],[0,0,8,13],[0,0,8,14],[0,0,8,15],[0,0,8,16],[0,0,8,17],[0,0,8,18],[0,0,8,19],[0,0,8,20],[0,0,9,0],[0,0,9,1],[0,0,9,2],[0,0,9,3],[0,0,9,4],[0,0,9,5],[0,0,9,6],[0,0,9,7],[0,0,9,8],[0,0,9,9],[0,0,9,10],[0,0,9,11],[0,0,9,12],[0,0,9,13],[0,0,9,14],[0,0,9,15],[0,0,9,16],[0,0,9,17],[0,0,9,18],[0,0,9,19],[0,0,9,20],[0,0,10,0],[0,0,10,1],[0,0,10,2],[0,0,10,3],[0,0,10,4],[0,0,10,5],[0,0,10,6],[0,0,10,7],[0,0,10,8],[0,0,10,9],[0,0,10,10],[0,0,10,11],[0,0,10,12],[0,0,10,13],[0,0,10,14],[0,0,10,15],[0,0,10,16],[0,0,10,17],[0,0,10,18],[0,0,10,19],[0,0,10,20],[0,0,11,0],[0,0,11,1],[0,0,11,2],[0,0,11,3],[0,0,11,4],[0,0,11,5],[0,0,11,6],[0,0,11,7],[0,0,11,8],[0,0,11,9],[0,0,11,10],[0,0,11,11],[0,0,11,12],[0,0,11,13],[0,0,11,14],[0,0,11,15],[0,0,11,16],[0,0,11,17],[0,0,11,18],[0,0,11,19],[0,0,11,20],[0,0,12,0],[0,0,12,1],[0,0,12,2],[0,0,12,3],[0,0,12,4],[0,0,12,5],[0,0,12,6],[0,0,12,7],[0,0,12,8],[0,0,12,9],[0,0,12,10],[0,0,12,11],[0,0,12,12],[0,0,12,13],[0,0,12,14],[0,0,12,15],[0,0,12,16],[0,0,12,17],[0,0,12,18],[0,0,12,19],[0,0,12,20],[0,0,13,0],[0,0,13,1],[0,0,13,2],[0,0,13,3],[0,0,13,4],[0,0,13,5],[0,0,13,6],[0,0,13,7],[0,0,13,8],[0,0,13,9],[0,0,13,10],[0,0,13,11],[0,0,13,12],[0,0,13,13],[0,0,13,14],[0,0,13,15],[0,0,13,16],[0,0,13,17],[0,0,13,18],[0,0,13,19],[0,0,13,20],[0,0,14,0],[0,0,14,1],[0,0,14,2],[0,0,14,3],[0,0,14,4],[0,0,14,5],[0,0,14,6],[0,0,14,7],[0,0,14,8],[0,0,14,9],[0,0,14,10],[0,0,14,11],[0,0,14,12],[0,0,14,13],[0,0,14,14],[0,0,14,15],[0,0,14,16],[0,0,14,17],[0,0,14,18],[0,0,14,19],[0,0,14,20],[0,0,15,0],[0,0,15,1],[0,0,15,2],[0,0,15,3],[0,0,15,4],[0,0,15,5],[0,0,15,6],[0,0,15,7],[0,0,15,8],[0,0,15,9],[0,0,15,10],[0,0,15,11],[0,0,15,12],[0,0,15,13],[0,0,15,14],[0,0,15,15],[0,0,15,16],[0,0,15,17],[0,0,15,18],[0,0,15,19],[0,0,15,20],[0,0,16,0],[0,0,16,1],[0,0,16,2],[0,0,16,3],[0,0,16,4],[0,0,16,5],[0,0,16,6],[0,0,16,7],[0,0,16,8],[0,0,16,9],[0,0,16,10],[0,0,16,11],[0,0,16,12],[0,0,16,13],[0,0,16,14],[0,0,16,15],[0,0,16,16],[0,0,16,17],[0,0,16,18],[0,0,16,19],[0,0,16,20],[0,0,17,0],[0,0,17,1],[0,0,17,2],[0,0,17,3],[0,0,17,4],[0,0,17,5],[0,0,17,6],[0,0,17,7],[0,0,17,8],[0,0,17,9],[0,0,17,10],[0,0,17,11],[0,0,17,12],[0,0,17,13],[0,0,17,14],[0,0,17,15],[0,0,17,16],[0,0,17,17]... etc.
It ends at [20,20,20,20].
I need to pick 50 combinations from the file and assign it to a variable so it would be like
var combinationsArr = [
[0,0,17,9],[0,0,17,10],[0,0,17,11],[0,0,17,12]
]; //BUT 50 of them
it's okay if it is just in order like [0,0,0,0],[0,0,0,1],[0,0,0,2],[0,0,0,3],[0,0,0,4],[0,0,0,5],[0,0,0,6],[0,0,0,7],[0,0,0,8],[0,0,0,9],[0,0,0,10],[0,0,0,11],[0,0,0,12] and doesn't have to be super random like [1,2,3,4],[9,12,13,15],[20,12,6,7]
as long as it is able to pick 50 of them.
I am doing this because 194481 combinations are a lot and makes my program carsh. so I just decided i'll put it in a text file and pick random points from the text file like from [0,0,0,1] to [0,0,0,50] OR
from [0,1,0,0] to [0,1,0,49] if that's possible.
because i have to generate a random combination. I have another array of combinations which are not supposed to be generated. Let's call it notAllowedArr.
var notAllowedArr = [
[0,0,17,9],[0,0,17,12]
];
I am thinking, i'll just generate 50 combinations and remove the ones listed in notAllowedArr then pick one from combinationsArr as the final result. I will still have to find code to remove those from combinationsArr but the result should be like.
var combinationsArr = [[0,0,17,10],[0,0,17,11]];
then i'll have a code to pick a random value from combinationsArr.
example. combinationsArr[0].
so the final result would be; [0,0,17,10]
Does anyone have a better solution?
If I understand correctly, you need to pick one random combination, which is not present in a list of forbidden combinations.
You can consider a combination of four numbers from 0 to 20 as a number from 0 to 194480 in base-21 notation. So instead of having to store all combinations in a file, we just pick a random number and convert it to base-21.
To choose a random number in a range where some values are forbidden, choose a number in the range from 0 to the maximum minus the number of forbidden values; then iterate over the forbidden values from small to large, and increment the random number every time you find a smaller or equal forbidden value.
This will make sure that every combination has the same probability of being chosen, and avoids the possibility of repeatedly choosing a forbidden combination.
function randomBase21(skip) {
var dec = [], result = [], num;
// CONVERT FORBIDDEN COMBINATIONS FROM BASE-21 TO DECIMAL AND SORT
for (var i = 0; i < skip.length; i++) {
dec[i] = skip[i][0] * 9261 + skip[i][1] * 441 + skip[i][2] * 21 + skip[i][3];
}
dec.sort(function(a, b){return a - b});
// GENERATE RANDOM NUMBER FROM 0 TO MAX - NUMBER OF FORBIDDEN COMBINATIONS
num = Math.floor(Math.random() * (194481 - skip.length));
// INCREMENT RANDOM NUMBER FOR EVERY SMALLER FORBIDDEN COMBINATION
for (var i = 0; i < skip.length && num >= dec[i]; i++) {
++num;
}
// CONVERT RANDOM NUMBER TO FOUR BASE-21 DIGITS
for (var i = 3; i >= 0; i--, num /= 21) {
result[i] = Math.floor(num % 21);
}
return result;
}
var notAllowed = [[0,0,17,9],[0,0,17,12],[20,19,17,12],[15,16,17,12]];
document.write(randomBase21(notAllowed));
Something like this should work (off the top of my head and not tested/debugged):
var samples = new Array();
for(var index = 0; index < 50; index++) {
samples.push(generatePermutation());
}
function generatePermutation() {
var result = [Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1];
}
I just thought of a better way.
I think I will make a function that generates a random combination.
Then check if it exists in notAllowedArr. If it exists, it will generate another one. If not then that will return that combination :D
I think this will work faster ^^;

Javascript conditional find/replace

For my javascript project, I have a list that looks like this:
<li id="1">101.33, "book name 1"</li>
<li id="2">600.01, book name 2</li>
<li id="3">001.11, book name 3</li>
etc...
Of which I am supposed to do the following:
Remap the bullet list entries to a new (consistent) tag type (your choice – make it look pretty!).
For entries between 100 and 200, add 100 to the Dewey decimal number.
For entries between 400 and 500, add 200 to the Dewey decimal number.
Entries between 850 and 900 need to have 100 removed from the Dewey decimal number.
Entries between 600 and 650 need to have 17 added to the Dewey decimal number
For items that get changed, append “changed” to the record.
For items that do not get changed, append “no change” to the record.
For records that are incorrect, append “invalid record” to the record
But I'm not sure how to go about it. I want to target any number in the body, or within a list item. Right now I have this:
var z = document.body.li.innerHTML;
if (z >+ 100 && z <= 200)
{
var q = z + 100;
document.body.li.innerHTML=q;
}
}
Can anyone point me in the right direction of the best approach to do this in javascript? Should I be using find/replace instead?
EDIT: Attempted to amend the last ternary if else statement in David Thomas' code. Can't seem to get it to work:
//define valid record number as at-least-one-integer.at-least-one-integer
var reggie = /\d+(.)+d/
if (_newText = reggie) {
'Invalid Record';
}
else if (_newText === a[textProp]) {
'no change';
}
else(_newText != a[textProp]) {
'changed';
}
+ ')';
One approach, is the following (using plain JavaScript, albeit you'll need to use an up-to-date browser):
// first, we need to get all the 'li' items:
var lis = document.querySelectorAll('ul > li'),
// find the relevant text-property for this browser:
textProp = 'textContent' in document ? 'textContent' : 'innerText',
// empty string variable to allow assessment of changes:
_newText = '';
// Remap the bullet list entries to a new (consistent) tag type (your choice – make it look pretty!).
// do this one yourself.
// a function to zero-pad the numbers (I believe a requirement of Dewey Decimal):
function leftPadNumber(num, numLength, padChar) {
var nString = num.toString(),
major = parseInt(num, 10),
minor = parseFloat(nString.substring(nString.indexOf('.'))),
diff = numLength - major.toString().length;
if (diff > 0) {
return new Array(diff + 1).join(padChar || 0) + (major + minor);
} else {
return num;
}
}
// For entries between 100 and 200, add 100 to the Dewey decimal number.
// For entries between 400 and 500, add 200 to the Dewey decimal number.
// Entries between 850 and 900 need to have 100 removed from the Dewey decimal number.
// Entries between 600 and 650 need to have 17 added to the Dewey decimal number
// note that I've taken a very literal interpretation of 'between' (amend if necessary):
function amendedDeweyDecimal(num) {
if (num > 100 && num < 200) {
num += 100;
} else if (num > 400 && num < 500) {
num += 200;
} else if (num > 850 && num < 900) {
num -= 100;
} else if (num > 600 && num < 650) {
num += 17;
}
// happens if num falls somewhere outside of the above constraints:
return num;
}
// iterates over each element in the 'lis' nodeList/collection:
[].forEach.call(lis, function (a) {
/* replaces the found numbers ('m') in the string, using the two
functions, above, and assigns those to the _newText variable:
_newText = a[textProp].replace(/(\d{3}\.\d{2})/, function (m) {
return leftPadNumber(amendedDeweyDecimal(parseFloat(m)).toFixed(2), 3);
});
// For items that get changed, append “changed” to the record.
// For items that do not get changed, append “no change” to the record.
// returns the original text to the element, along with '(no change)'
// (if 'a[textProp]' is exactly equal to '_newText') or with '(changed)'
// (if the two variables are not identical):
a[textProp] = _newText + ' (' + (_newText === a[textProp] ? 'no change' : 'changed') + ')';
});
// For records that are incorrect, append “invalid record” to the record
// I have absolutely no idea how to assess an 'incorrect' record.
JS Fiddle demo.
References:
Array.prototype.forEach().
document.querySelectorAll().
Number.toFixed().
Number.toString().
String.parseFloat().
String.parseInt().
String.replace().
try jQuery .each
$('li').each(function(index, value) {
var val = $(this).text().split(','); //split into array
if (index >= 100 && index < 200) {
//do stuff
}
if (index >= 400 && index < 500) {
//do stuff
}
//etc
});
Regardless if you want to solve this using pure JavaScript or a helper library (like jQuery for example), i would suggest to disassemble your problem into smaller tasks and solve them one by one. At the end they will fit one into another and will build the complete solution. I would have started with three simple functions (reading your description they will be needed often):
the ability to list all LI elements separately
extract the number from the LI content
check if the number in in a given range
The code can look like this:
// count of all LI items
var elements = 0;
// fetch LI item one at a time
var element = document.getElementById(elements+1);
while (element != undefined) {
// get the number
var number = Number(getNumber(element.innerHTML));
// do something with number and or LI element
if (inRange(number, 100, 200)) { /* add 100 ...*/ } // and so on
// go to next element
elements++;
element = document.getElementById(elements+1);
}
function getNumber(elementContent) {
return elementContent.split(",")[0]; // TODO error handling
}
function inRange(number, min, max) {
return (number >= min) && (number <= max);
}
You can introduce simple objects and arrays to store information and states to track the changes of your content.

Categories