How to store and optimize large values in cookies - javascript

I need to store the user preferences in a cookie.
I have three multiple select drop downs & date.
User is allowed to select all the values in dropdowns.
If I store all the unique (8 characters) values in a cookie, then it will get overloaded. I need a mechanism to do some mapping so that minimal value is stored in cookie.
My requirement matches this question, but only difference is that I have large data set (100 items per select column).

Two possibilities:
A) Make your values numeric and powers of 2 (1,2,4,8,16,etc) and store a single value in the cookie as a bitmap. (Or in the server-side code, map the distinct values to powers of 2.)
B) Store the values in the cookie as a delimited list.
Updated: 6:40PM
Seeing that you have the possibility of a large number of selections, neither of my original solutions is going to work. To deal with that large an amount of data, I think you're going to need to create a "session id" of some sort, save the actual settings in a database or other persistent storage, and store the session id in the cookie.
(You'll of course want to make the cookie only persist for the duration of the browser session and delete the stored settings after you can be reasonably certain the browser session has ended -- perhaps a week or so.)

That's a good question. Given your requirements, I don't see much choices left on how to proceed. As ThatBlairGuy suggested, a bit map seems to be the way to go. Your 300 choices translate to 300 bits. Now I personally would stick to use only 6 bits per byte, to make a quick and easy translation to base64, for storage purpose. 300 / 6 = 50 characters for the values coming from the drop-down.
The value of any preference has to be hardcoded for good though, you can't remove or add any in the middle: Any new preference will have to be added at the end of the bit map, or use a bit that is no longer used somewhere in the map.
Edit: Given the comments re. bit map, I will flesh out what I had in mind for the implementation. Assuming a bit, each corresponding to a off-on switch of a particular option (an entry in the drop-box):
this.bitmap = [];
this.customBase64code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-";
...
// index=index of bit within bit map, on=state of the bit
this.setOption=function(index,on) {
var islot = Math.floor(index / 6);
var ibit = index % 6;
if ( this.bitmap[islot] === undefined ) {
while ( this.bitmap.length <= islot ) {
this.bitmap.push(0);
}
}
if (on) {
this.bitmap[islot] |= (1 << ibit);
}
else {
this.bitmap[islot] &= ~(1 << ibit);
}
};
this.getOption=function(index) {
var islot = Math.floor(index / 6);
if ( this.bitmap[islot] === undefined ) {
return 0;
}
return this.bitmap[islot] & (1 << (index % 6));
};
this.getStringFromOptions=function() {
var bitmap64 = [];
var encoder64 = customBase64code.split('');
var n = this.bitmap.length;
for ( var i = 0; i < n; i++ ) {
bitmap64.push(encoder64[this.bitmap[i]]);
}
return bitmap64.join('');
};
this.getOptionsFromString=function(s) {
var bitmap64 = s.split('');
var decoder64 = this.customBase64code;
var n = bitmap64.length;
for ( var i = 0; i < n; i++ ) {
this.bitmap.push(decoder64.indexOf(bitmap64[i]));
}
};
Disclaimer: I didn't test any of the above.

You can store the indexes of the selected items. For example, if the user has selected item 1 and 3 from list A, item 4 from list B and the first 10 items of list C, you'd get something like this:
A[0,2],B[3],C[0-9]
You'd have to write some simple parsing code to read out the values though.
In the worst case scenario, when the user has selected all the odd or even items, you'll need about 150 characters for a list containing a total of 100 items. If the user has selected all 100 items, you'll only need A[0-99].

Related

Get every possible combination of numbers (fastest possible method)

I am trying to get every single combination of elements into an array. Now I can use the method below, and remove the duplicates, but this way is far to slow for my use.
The code below would find every possible combination for 2 digits below 4. Now in the code I actually want to use this for, the least possible code would be 6 for loops (within each other) with the amount being 18 (rememeber this is the minimum).
The code below would execute amount^[amount of for loops], or amount^2 which in this case is 16. That means that in the code I want to use this for, it executes 18^6 times, or 34 million times. And this is the minimum, which would get much higher.
After trying to run my code (with 6 foor loops in which amount = 18), it crashed my browser... My question is: Is there any faster and more efficient (not elegant. I don't care how elegant it is) in which my browser won't crash?
Note: This question is not a duplicate question. All the other questions simply ask for a way to do this, however I already have a way. I am just trying to make it more efficient and faster so that it actually works correctly.
let combinations = [];
let amount = 4;
for (let a = 0; a < amount; a++) {
for (let b = 0; b < amount; b++) {
combinations.push(`${a}${b}`);
}
}
console.log(combinations);
Below is a snippet providing a possible example for how my code would work.
let possibilities = [];
let amount = 6; //Amount is set by me, so don't worry about it being incorrect
for (let a = 0; a < amount; a++) {
for (let b = 0; b < amount; b++) {
possibilities.push(a + b);
}
}
possibilities = [...new Set(possibilities)]; //Removes duplicates
possibilities.sort((a, b) => b - a); //Sorts in descending order
possibilities = possibilities.slice(0, 3); //Gets top 3 values
console.log(possibilities);
Ok, as discussed in the comments, if you need top 3 values for a particular amount, you could just do something simple like below:
let amount = 6;
let highest = amount - 1,second_highest = amount - 2,third_highest = amount - 3;
let possibilities = [
highest + highest,
highest + second_highest,
highest + third_highest
];
console.log(possibilities);
I don't know the any better solution for this, but yes there are some conditions you need to check first.
If(amount <= 0) return 'Invalid amount, Please enter a valid amount"
So if somebody enters a negative or zero value your loop will goes into infinite loop, and make the situation more worst.
if(amount === 1) return '1 possible combination'
As amount less than 1 is 0 only and combinations for 0 is 1 only, you need not to parse whole loop for 6 digits or n digits for 0 so it will get solve in complexity of 1 instead of N(no. of digits).
And for amount greater then 1 you can create manual loops, like here you created 2 loops for 2 digits, you create 6 loops for 6 digits, better create dynamic logic for this to create number of loops automatically.
You need to consider 1111, 1112 this type of combinations as well right?
Or if only 1234, 2134, 2314 this kind of scenarios are required? This can be done in very less complexity.
For duplication you can store combinations as a key value pair. and then Object.Keys will be your combinations.

Sorting with constraint no consecutive equals

I would like to sort a news feed according to created date, which is trivial, but I don't want 2 consecutive posts with the same userId field.
This might not be theoritically possible because what if I have only 2 posts with the same userId field?
I am looking for an algorithm that sorts according to fieldA but doesn't have 2 consecutive elements with the same fieldB.
It would also nice to have a parametrized algorithm about the required number of different posts between same user's different posts. (In the first scenario this parameter is 1)
I'm not looking for performance (O(n^2) would be okay) but a clever & simple way, maybe with 5 lines of code.
Language doesn't matter but Javascript is preferred.
To solve this problem in 5 lines is somewhat difficult,I'm trying to give a short pseudocode and you may translate it to js.
First we group the input to A[1],A[2],...,A[k].A[i] is a container contains all posts of i-th user,this can be easily done via O(n) scanning.
code:
for i = 1 to k
lastOccurPosition[i] = -intervalLength; //that is the interval length specified by parameter
for i = 1 to k
sort(A[i]);
for i = 1 to n
minElement = INF; //find the minimum
minUserId = -1; //record whose post is minimun
for j = 1 to k
if(i - lastOccurPosition[i] <= intervalLength) //if the user has occured within interval length,the user's post shouldn't be choosen
continue;
if(A[j][1] < minElement)
minElement = A[j][1];
minUserId = j;
answer[i] = minElement; //put min element into answer array
lastOccurPosition[minUserId] = i; //update choosen user's last occur position
A[minUserId].pop_front(); //delele first element
It is easy to analyse this algorithm's complexity is O(n^2) and I haven't thought out a more concise solution.
Hope to be helpful.
Put the atributes in an array, and sort that array:
arr.sort();
Put the second atribute in another array and sort that array according to the first one.
var newarr = [arr[0]];
for (var i=1; i<arr.length; i++) {
if (arr[i]!=arr[i-1]) newarr.push(arr[i]);
}
Now this just remove duplicates.
This all feels kind of trivial, am I missing something?
Hope this helps.
Cheers,
Gijs

Determining Powers of 2?

I am creating a simple bracket system and I need a way to check if there are a correct number of teams, OR if my program needs to compensate for bye rounds.
Right now, I am checking for "powers of two" with this function:
function validBracket(data) {
var x = data.teams.length;
return ((x != 0) && !(x & (x - 1)));
}
This works pretty well, but I am needing to know how many Bye rounds to add.
For instance, if I had 16 teams, I would not need to add anymore teams. However, if I had 12 teams, I would need the first 4 teams to get a bye round.
How can I calculate number of bye rounds to add to my bracket? And would hard-coding an array of powers of two be better?
In pseudo code, something like this is what i was thinking of:
if(validateBracket(data)) {
// Valid number of teams (power of two). Keep going.
} else {
var byeRounds = calculateByeRounds();
}
NOTE: I would rather not use an array of powers of two like below:
var powersOfTwo = [2,4,8,16,32,...];
The reasoning behind this is that I would be limiting the number of teams that could be put in the system (however, I don't think a person would have over 256 teams).
var needed = (1 << Math.ceil(Math.log2(n))) - n;
More generalized solution for extreme cases:
var needed = Math.pow(2, Math.ceil(Math.log2(n))) - n;

How many unique jsbin url shortcode combinations can exist?

This is jsbin's function that generates each bin's identification shortcode:
function shortcode() {
var vowels = 'aeiou',
consonants = 'bcdfghjklmnpqrstvwxyz',
word = '', length = 6, index = 0, set;
for (; index < length; index += 1) {
set = (index % 2 === 0) ? vowels : consonants;
word += set[Math.floor(Math.random() * set.length)];
}
return word;
}
How many different combinations could it produce? If I've calculated well, there are 3.08915776e+8 combinations when using 6 letters from a set of 26 letters(a-z). But how would this be calculated, since there are sets of 5(vowels) and sets of 21(consonants) alternating to produce memorizable shortcodes like 'ecamit', 'izafij', 'erowih', 'avimog' etc...
Would that be (5x21)^3 = 121,550,625 ?
The shortcode method was recently updated because we kept hitting duplicates too often, and in fact the version of code you see also appended numbers on the end to increase force them to become unique.
I believe the number of variations, based on this code alone (the code above, not what's in jsbin's production code base) is: 1,157,625 (5 * 21 * 5 * 21 * 5 * 21) - which really isn't much.
The simple method comes from my old password generator: http://remysharp.com/2008/04/14/pronounceablely-random/ - but recently I had to change it in jsbin's production.
It now keeps adding characters on each positive hit on the database, but also the letters are duplicated in uppercase, so the range of url combinations are much much higher now.

Creating a random number generator in jscript and prevent duplicates

We are trying to create a random number generator to create serial numbers for products on a virtual assembly line.
We got the random numbers to generate, however since they are serial numbers we don't want it to create duplicates.
Is there a way that it can go back and check to see if the number generated has already been generated, and then to tell it that if it is a duplicate to generate a new number, and to repeat this process until it has a "unique" number.
The point of a serial number is that they're NOT random. Serial, by definition, means that something is arranged in a series. Why not just use an incrementing number?
The easiest way to fix this problem is to avoid it. Use something that is monotonically increasing (like time) to form part of your serial number. To that you can prepend some fixed value that identifies the line or something.
So your serial number format could be NNNNYYYYMMDDHHMMSS, where NNNN is a 4-digit line number and YYYY is the 4 digit year, MM is a 2 digit month, ...
If you can produce multiple things per second per line, then add date components until you get to the point where only one per unit time is possible -- or simply add the count of items produced this day to the YYYYMMDD component (e.g., NNNNYYYYMMDDCCCCCC).
With a truly random number you would have to store the entire collection and review it for each number. Obviously this would mean that your generation would become slower and slower the larger the number of keys you generate (since it would have to retry more and more often and compare to a larger dataset).
This is entirely why truly random numbers just are never used for this purpose. For serial numbers the standard is always to just do a sequential number - is there any real real for them to be random?
Unique IDs are NEVER random - GUIDs and the like are based on the system time and (most often) MAC address. They're globally unique because of the algorithm used and the machine specifics - not because of the size of the value or any level of randomness.
Personally I would do everything I could to either use a sequential value (perhaps with a unique prefix if you have multiple channels) or, better, use a real GUID for your purpose.
is this what you are looking for?
var rArray;
function fillArray (range)
{
rArray = new Array ();
for(var x = 0; x < range; x++)
rArray [x] = x;
}
function randomND (range)
{
if (rArray == null || rArray.length < 1)
fillArray (range);
var pos = Math.floor(Math.random()*rArray.length);
var ran = rArray [pos];
for(var x = pos; x < rArray.length; x++)
rArray [x] = rArray [x+1];
var tempArray = new Array (rArray.length-1)
for(var x = 0; x < tempArray.length; x++)
tempArray [x] = rArray [x];
rArray = tempArray;
return ran;
}

Categories