I want to create an array of random/pseudo-random numbers using a seed. I want the very same array to be created when the same seed is used and I want to have little or no visible pattern in the array. I'm working in JavaScript.
This is the random function I'm using, which I'm quite happy with (sorry, I forgot who the original author is):
function random(seed) {
if (!seed) seed = new Date().getTime();
seed = (seed*9301+49297) % 233280;
return seed/(233280.0);
}
This is the array generation:
var superSeed = random();
var nRandom = 100;
var randomArray = new Array();
for (var i = 0 ; i < nRandom ; i++){
randomArray.push(random((superSeed*10)+ (i)));
}
Somehow the pattern seems to be quite similar, no matter how often I run it. This question seems to be similar, but since it's about matrixes, I don't understand what's being said.
Thanks!
Having worked on similar things before I think we can use a fairly simple series, which takes two initial values and then you can get a lot more.
var a1,b1;
function InitSequence(v1, v2) {
a1 = Math.pow(v1, 5) / Math.pow(v1, 3);
b1 = Math.pow(v2, 8);
lastrand = (a1 + b1) & 0x7fffffff;
}
function SequenceNext() {
var alast = a1;
var nextVal = (a1 + b1) & 0x7fffffff;
b1 = alast;
a1 = nextVal;
return nextVal;
}
Then use it like this:
InitSequence(75, 21);
for (var i = 0; i < 99; i++) {
v = SequenceNext();
}
I tested it like this:
var used = new Array();
InitSequence(75, 21); // any two values will do.
// fill 10k into array.
for (var i = 0; i < 9999; i++) {
v = SequenceNext();
if (undefined != used[v]) {
used[v]++;
} else used[v] = 1;
//document.write(i+": "+v+"<br>");
}
// see if there any duplicates.
var tdup = 0;
for (xx in used) {
ndup = used[xx];
if (ndup > 1) {
document.write("duplicated " + xx + " :" + ndup + "<br>");
tdup += ndup;
}
}
document.write("Total dups " + tdup + "<br>");
This is using the Fibonacci series, which in mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
. I'm starting with different values - (v1^5) / (v1^3) and v2 ^ 8; otherwise it would only ever be identical.
I like the "Super 7" PRNG. It is simple, fast (although the other answer with the fib. sequence is fast as well), and has the interesting property:
In the entire range -- albeit of a meager of 32k -- there are no duplicates using the "Super 7" PRNG.
Multiple 7's can be joined to increase the number of bits and/or provide multiple seeds. This non-duplication property can exposed or folded.
(The sequence of a PRNG is always the same given a starting seed: it's the distribution and cycle lengths that are interesting -- it is these properties that may make them ideal in different cases where "true randomness" isn't desired).
Happy coding.
Maybe you should try this
function s_random() {
s_random.m = 71402523; s_random.a = 409647; s_random.c = 1508892;
s_random.seed = (s_random.seed*s_random.a + s_random.c) % s_random.m;
return s_random.seed / s_random.m;
}
/*
generate IV
s_random.seed = Math.floor((new Date).getTime()/10000);
*/
s_random.seed = 130324232;
var CheckRandom = 4999999;
var PrintSamples = 100;
var used = new Array();
for (var i = 0; i < CheckRandom; i++) {
v = (Math.ceil(Math.sqrt(s_random())* 1000000000) * 8);
if (undefined != used[v]) {
used[v]++;
} else used[v] = 1;
if ( i< PrintSamples) document.write(i+": "+v+"");
}
/* see if there are any duplicates. */
var tdup = 0;
for (xx in used) {
ndup = used[xx];
if (ndup > 1) {
if (ndup < PrintSamples) document.write("duplicated " + xx + " :" + ndup + "");
tdup += ndup;
}
}
document.write("Total generated " + CheckRandom + "");
document.write("Total duplicates " + tdup + "");
Just got 5 million seeded, repeatable random numbers and no duplicates. Tested several times on Mac OS X with Safari.
Cheers,
Karl
Related
So I've already found posts on this topic, but that didn't really help me. On the one hand, I have tried something like this, for example, but it is not quite right in my case**(C#)**.
string temp;
foreach (var a in chaine)
temp = ( Convert.ToUInt16(a).ToString("X4"));
for (j = 0; j < intlenght; j+= 1)
{
arrayData[j + 1] = temp;
}
Why I think it doesn't really work is that my starting form looked a little different than the examples and I'm not really familiar with JavaScript. My starting shape looks like this**(javaScript)**:
for (j = 0; j < intlenght; j+= 1)
{
arrayData[j + 1] = x.charCodeAt(j) - 32;
}
the x in this case it is actually
var x = document.getElementById ("textIn"). value;
but in my method I have a string return value instead of the X
so how can i correctly get the
arrayData [j + 1] = x.charCodeAt (j) - 32;
translate in c #. In the end I need this in my method for Code128 encoder
EDIT for better Understanding:
So I have a TextBlock in my window, but there is a text in it in a barcode 128 font. However, this barcode cannot yet be read. So what I want to do is add the additional characters of the barcode so that at the end you can scan this barcode with a scanning program. To do that I come across this Stack Overflow answer: https://stackoverflow.com/a/60363928/17667316
However, the problem was with the question that the code is in JavaScript and not in C #. Since I've only found solutions where it works with libaries and nuggets (which I want to work around) I tried to convert this javaScript code into C #. I come across lines like this(javaScript):
arrayData[j + 1] = x.charCodeAt(j) - 32;
I didn't find a solution to this as I did this Javascript code:
var buttonGen = document.getElementById("btnGen");
buttonGen.onclick = function () {
var x = document.getElementById("textIn").value;
var i, j, intWeight, intLength, intWtProd = 0, arrayData = [], fs;
var arraySubst = [ "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê" ];
/*
* Checksum Calculation for Code 128 B
*/
intLength = x.length;
arrayData[0] = 104; // Assume Code 128B, Will revise to support A, C and switching.
intWtProd = 104;
for (j = 0; j < intLength; j += 1) {
arrayData[j + 1] = x.charCodeAt(j) - 32; // Have to convert to Code 128 encoding
intWeight = j + 1; // to generate the checksum
intWtProd += intWeight * arrayData[j + 1]; // Just a weighted sum
}
arrayData[j + 1] = intWtProd % 103; // Modulo 103 on weighted sum
arrayData[j + 2] = 106; // Code 128 Stop character
chr = parseInt(arrayData[j + 1], 10); // Gotta convert from character to a number
if (chr > 94) {
chrString = arraySubst[chr - 95];
} else {
chrString = String.fromCharCode(chr + 32);
}
// Change the font-size style to match the drop down
fs = document.getElementsByTagName("option")[document.getElementById("selList").selectedIndex].value;
document.getElementById("test").style.fontSize = fs + 'px';
document.getElementById("check").innerHTML =
'Checksum = ' + chr + ' or character ' + // Make It Visual
chrString + ', for text = "' + x + '"';
document.getElementById("test").innerHTML =
'Ì' + // Start Code B
x + // The originally typed string
chrString + // The generated checksum
'Î'; // Stop Code
}
Can convert into a working C # code.
Wondering how to quickly generate lots of unique, small random numbers. When I implemented it like this it slows down exponentially it seems like, to the point where it never finishes, or will take hours to complete. Probably because it creates tons of duplicates toward the end.
var intsmap = {}
var intsarray = []
var i = 100000
while (i--) {
var int = randominteger(6)
if (intsmap[int]) i++
else {
intsmap[int] = true
intsarray.push(int)
}
}
// return intsarray
function randominteger(exp) {
var string = rand(exp)
return pad(string, exp)
}
function pad(num, size) {
var s = rand(9) + num
return s.substr(s.length - size)
}
function rand(exp) {
var integer = Math.random() * Math.pow(10, exp) << 0
var string = toString(integer, '0123456789')
return string
}
function toString(value, code) {
var digit
var radix = code.length
var result = ''
do {
digit = value % radix
result = code[digit] + result
value = Math.floor(value / radix)
} while (value)
return result
}
Wondering how to accomplish that but the code works within a few seconds if possible.
Update
I would like for the set of numbers to be distributed evenly over an arbitrary range (in this example 1000000 strings, not necessarily from 0-1000000, eg maybe 5050000 is in there).
I would like for the numbers to not necessarily be valid numbers, just a string of integers. So for example they can include 01010101 as a valid string, even though that's not a valid number.
You can use an object as a look up and only insert unique random number
var intsmap = {};
var i = 100000;
while (i--) {
var int = Math.random() * Math.pow(10, 6) << 0;
if(intsmap[int])
continue;
else
intsmap[int] = true;
}
console.log(Object.keys(intsmap));
You can use also use Durstenfeld shuffle after generating number in the given range.
var arr = Array.from({length:1000000}, (_,i) => (i+1));
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
shuffleArray(arr);
console.log(arr);
Just try to shuffle the array of numbers 1 to maxNum
First create an array
var maxNum = 1000000;
var arr = Array(maxNum).fill().map((e,i)=>i+1);
Now shuffle the array
arr.sort(function() {
return .5 - Math.random();
});
Now you have the array of unique random numbers
Demo
var startTime = new Date().getTime();
var maxNum = 1000000;
var arr = Array(maxNum).fill().map((e, i) => i + 1);
arr.sort(function() {
return .5 - Math.random();
});
var endTime = new Date().getTime();
console.log( "Time taken to get " + maxNum + " size random unique number is " + ( endTime - startTime ) + " ms");
I can propose this approach:
generate a random number
cast it to a string (0.1234567812345678)
and extract 6 substrings of length of 10
Code:
var res = {},
s = "";
for (let i=0; i<1000000; ++i) {
s = Math.random().toString();
for (let j=0; j<6; ++j) {
res[s.substring(2+j, 12+j)] = true; // extract 10 digits
}
}
After 1,000,000 iterations, you have computed 6,000,000 numbers with very little collisions (1,800 in average). So you have your 1,000,000 numbers and more in few seconds.
If you need unique big array try to think in other way. Just create range 0 ... 100000 and shuffle it and apply you function that you need for this array.
var acc = 0;
const result = [];
for(var i = 0; i < 100000; i++)
result.push(acc += Math.floor(Math.random() * 10) + 1);
I think the most expensive operation is the hashtable lookup/insertion, so simply do it without it.
One place where you might loose performances is in the Math.random call.
It's a quite expensive call, and you are calling it a huge number of times to generate your strings.
One solution to leverage it is to grab the whole string from a single result of Math.random().
var intsmap = {}
var intsarray = []
var i = 100000
while (i--) {
var int = randominteger(6)
if (intsmap[int]) {
i++
} else {
intsmap[int] = true
intsarray.push(int)
}
}
console.log(intsarray);
// It takes the whole string from a single call to 'random'.
// The maximum length is 16.
function randominteger(length){
return (Math.random() + '').substr(2,length);
}
I am caching longitude and latitude (plus a bit more info) for possibly 1000s of locations, currently using a JavaScript hash, a {}. e.g.
var cache = {};
cache['Boston, MA'] = { id: someid, latlon: [lat, long] };
cache['Someotherplace, TX'] = { id: someotherid, latlon: [itslat, itslong]};
Everytime a new location comes up I do a geocode and add the results to the cache. I don't think Boston's latitude will change anytime soon...
Will lookups be reasonably fast? I don't need blazing fast, I'm not running Amazon, but as this data grows to, say 2000 locations, will it bog down? If so, what might be a good alternative?
Much of the performance of the entire javascript engine is based on property lookups on objects so I'm quite sure that significant effort has been paid to the performance of that in the basic JS engine.
But, as with all things related to performance you should measure yourself. It would only take a few minutes to build a test harness in jsperf and either compare it to an alternative or just see if regular JS lookup appears fast enough for you.
Here's a [little test harness][1] that shows more than 20,000 key lookups per ms on my computer. I would think that's fast enough for you.
function log(args) {
var str = "";
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] === "object") {
str += JSON.stringify(arguments[i]);
} else {
str += arguments[i];
}
}
var div = document.createElement("div");
div.innerHTML = str;
document.body.appendChild(div);
}
function addCommas(str) {
var amount = str + "";
var parts = amount.split(".");
amount = parts[0].split("").reverse();
var output = "";
for (var i = 0; i < amount.length; i++) {
output = amount[i] + output;
if ((i+1) % 3 == 0 && (amount.length-1) !== i) {
output = ',' + output;
}
}
if (parts.length > 1) {
output += "." + parts[1];
}
return output;
}
function now() {
return new Date().getTime();
}
// now fill the cache with a random set of keys
// the keys will var in length between minKeyLen and maxKeyLen
function createRandomKeys(num, minKeyLen, maxKeyLen, obj) {
function rand(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
var chars = "abcdefghijlkmnopqrstuvwzyz";
var len, key, numKeys = 0;
while (numKeys < num) {
// generate random key length
len = rand(minKeyLen, maxKeyLen);
key = "";
// now select len random chars and combine into a string
for (var j = 0; j < len; j++) {
key += chars.charAt(rand(0, chars.length))
}
// put this key into our object, only count it if it's not already there
if (!Object.prototype.hasOwnProperty.call(obj, key)) {
++numKeys;
obj[key] = true;
}
}
}
var cache = {};
// put all the keys into our object
createRandomKeys(200000, 3, 15, cache);
// now get the list of keys, just so we know what to fetch in our test
var keys = Object.keys(cache);
// now time getting every key
var total = 0;
var start = now();
for (var i = 0; i < keys.length; i++) {
if (cache[keys[i]]) {
++total;
}
}
var end = now();
var elapsed = end - start;
log("Elapsed time = " + elapsed + "ms for " + addCommas(keys.length) + " key lookups - found " + addCommas(total));
log(elapsed/keys.length + "ms per lookup");
log(addCommas((keys.length / elapsed).toFixed(2)) + " key lookups per ms");
// show some sample keys
log("<hr>Sample keys (first 100 keys):<br>");
log(keys.slice(0, 100).join(", "));
The story behind
I am creating a voice controlled application using x-webkit-speech which is surprisingly good (the feature, not my app), but sometimes the user (me) mumbles a bit. It would be nice to accept the command if some reasonable part of the word matches some reasonable part of some reasonable command. So I search for the holy grail called Algorithm of the Greatest Intersect of Word in Set of Words. Could some fresh bright mind drive me out of the cave of despair?
Example
"rotation" in ["notable","tattoo","onclick","statistically"]
should match tattoo because it has the longest intersect with rotation (tat_o). statistically is the second best (tati intersect), because longer part of the word needs to be ignored (but this is bonus condition, it would be acceptable without it).
Notes
I use Czech language where the pronunciation is very close to its written form
javascript is the preffered language, but any pseudocode is acceptable
the minimal length of the intersect should be a parameter of the algorithm
What have I tried?
Well, it is pretty embarassing....
for(var i=10; i>=4; --i) // reasonable substring
for(var word in words) // for all words in the set
for(var j=0; j<word.length-i; ++j) // search for any i substring
// aaargh... three levels of abstraction is too much for me
This is an algorithm that seems to work. I have no idea how good it performs compared to other already established algorithms (I suspect it perform worse) but maybe it gives you an idea how you could do it:
FIDDLE
var minInt = 3;
var arr = ["notable","tattoo","onclick","statistically"];
var word = "rotation";
var res = [];
if (word.length >= minInt) {
for (var i = 0; i < arr.length; i++) {
var comp = arr[i];
var m = 0;
if (comp.length >= minInt) {
for (var l = 0; l < comp.length - minInt + word.length - minInt + 1; l++) {
var subcomp = l > word.length - minInt ? comp.substring(l - word.length + minInt) : comp;
var subword = l < word.length - minInt ? word.substring(word.length - minInt - l) : word;
var minL = Math.min(subcomp.length, subword.length);
var matches = 0;
for (var k = 0; k < minL; k++) {
if (subcomp[k] === subword[k]) {
matches++;
}
}
if (matches > m) {
m = matches;
}
}
}
res[i] = m >= minInt ? m : null;
}
}
console.log(res);
What happens is, that it compares the two strings by "moving" on against the other and calculates the matching letters in each position. Here you see the compared "sub"words for rotation vs. notable:
ion / notable --> one match on index 1
tion / notable --> no match
ation / notable --> no match
tation / notable --> one match on index 2
otation / notable --> no match
rotation / notable --> three matches on index 1,2,3
rotation / otable --> no match
rotation / table --> no match
rotation / able --> no match
rotation / ble --> no match
As you see, the maximum number of matches is 3 and that is what it would return.
Here's an implementation of a Levenshtein Distance Calculator in Javascript.
It returns an object containing the matching command and distance.
var commandArr = ["cat", "dog", "fish", "copy", "delete"]
var testCommand = "bopy";
function closestMatch(str, arr)
{
//console.log("match called");
var matchDist = [];
var min, pos;
for(var i=0; i<arr.length; i++)
{
matchDist[i]=calcLevDist(str, arr[i]);
console.log("Testing "+ str + " against " + arr[i]);
}
//http://stackoverflow.com/questions/5442109/how-to-get-the-min-elements-inside-an-array-in-javascript
min = Math.min.apply(null,matchDist);
pos = matchDist.indexOf(min);
var output = { match : arr[pos],
distance : matchDist[pos]
};
return output;
}
function calcLevDist (str1, str2)
{
//console.log("calc running");
var cost = 0 , len1, len2;
var x = 1;
while(x > 0)
{
len1 = str1.length;
console.log("Length of String 1 = " + len1);
len2 = str2.length;
console.log("Length of String 2 = " + len2);
if(len1 == 0)
{
cost+= len2;
return cost;
}
if(len2 == 0)
{
cost+= len1;
return cost;
}
x = Math.min(len1,len2);
if(str1.charAt(len1 -1) != str2.charAt(len2 -1))
{
cost++;
}
else
console.log(str1.charAt(len1-1) + " matches " + str2.charAt(len2-1));
str1 = str1.substring(0, len1 -1 );
str2 = str2.substring(0, len2 -1 );
console.log("Current Cost = " + cost);
}
}
var matchObj = closestMatch(testCommand, commandArr);
var match = matchObj["match"];
var dist = matchObj["distance"];
$("#result").html("Closest match to " + testCommand + " = " + match + " with a Lev Distance of " + dist + "." )
You can mess around with the fiddle here.
Thank you basilikum and JasonNichols and also Mike and Andrew for the comments, it really helped me to finish the algorithm. I come up with my own brute force O(n^3) solution in case someone runs into this question with the same problem.
Anyone is invited to play with the fiddle to improve it.
The algorithm
/**
* Fuzzy match for word in array of strings with given accurancy
* #param string needle word to search
* #param int accurancy minimum matching characters
* #param array haystack array of strings to examine
* #return string matching word or undefined if none is found
*/
function fuzzyMatch(needle,accurancy,haystack) {
function strcmpshift(a,b,shift) {
var match=0, len=Math.min(a.length,b.length);
for(var i in a) if(a[i]==b[+i+shift]) ++match;
return match;
}
function strcmp(a,b) {
for(var i=0,max=0,now; i<b.length; ++i) {
now = strcmpshift(a,b,i);
if(now>max) max = now;
}
return max;
}
var word,best=accurancy-1,step,item;
for(var i in haystack) {
item = haystack[i];
step = Math.max(strcmp(item,needle),strcmp(needle,item));
if(step<=best) continue;
best=step, word=item;
};
return word;
}
Example
var word = "rotation";
var commands = ["notable","tattoo","onclick","statistically"];
// find the closest command with at least 3 matching characters
var command = fuzzyMatch(word,3,commands);
alert(command); // tattoo
I need to organize an array of strings of random length into the least number of new strings with a max size. Is there a function or something in javascript, or something that can be translated to javascript, that will do this?
For example, the new strings might have max lengths of 1000 characters. The array might have strings of lengths 100, 48, 29, etc. I would want to combine those strings into as few new strings as possible.
edit: Sorry if this doesn't make sense, I tried my best.
No standard method in Javascript, but plenty of theoretical work has been done on this (i.e. the bin packing problem).
http://en.wikipedia.org/wiki/Bin_packing_problem
Some sample pseudo code in the link - should be trivial to translate to javascript.
The algorithm shown isn't going to be optimal in every case. To find the optimal solution to your example you'll just need to iterate over every possibility which might not be that bad depending on how many strings you have.
For my own entertainment, I wrote a simple bin packing algorithm. I picked a simple algorithm which is to sort the input strings by length. Create a new bin. Put the first (longest remaining) string into the bin and then keep filling it up with the longest strings that will fit until no more strings will fit. Create a new bin, repeat. To test it, I allocate an array of strings of random lengths and use that as input. You can see the output visually here: http://jsfiddle.net/jfriend00/FqPKe/.
Running it a bunch of times, it gets a fill percentage of between 91-98%, usually around 96%. Obviously the fill percentage is higher if there are more short strings to fill with.
Here's the code:
function generateRandomLengthStringArrays(num, maxLen) {
var sourceChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY1234567890";
var sourceIndex = 0;
var result = [];
var len, temp, fill;
function getNextSourceChar() {
var ch = sourceChars.charAt(sourceIndex++);
if (sourceIndex >= sourceChars.length) {
sourceIndex = 0;
}
return(ch);
}
for (var i = 0; i < num; i++) {
len = Math.floor(Math.random() * maxLen);
temp = new String();
fill = getNextSourceChar();
// create string
for (var j = 0; j < len; j++) {
temp += fill;
}
result.push(temp);
}
return(result);
}
function packIntoFewestBins(input, maxLen) {
// we assume that none of the strings in input are longer than maxLen (they wouldn't fit in any bin)
var result = [];
// algorithm here is to put the longest string into a bin and
// then find the next longest one that will fit into that bin with it
// repeat until nothing more fits in the bin, put next longest into a new bin
// rinse, lather, repeat
var bin, i, tryAgain, binLen;
// sort the input strings by length (longest first)
input.sort(function(a, b) {return(b.length - a.length)});
while (input.length > 0) {
bin = new String(); // create new bin
bin += input.shift(); // put first one in (longest we have left) and remove it
tryAgain = true;
while (bin.length < maxLen && tryAgain) {
tryAgain = false; // if we don't find any more that fit, we'll stop after this iteration
binLen = bin.length; // save locally for speed/convenience
// find longest string left that will fit in the bin
for (i = 0; i < input.length; i++) {
if (input[i].length + binLen <= maxLen) {
bin += input[i];
input.splice(i, 1); // remove this item from the array
tryAgain = true; // try one more time
break; // break out of for loop
}
}
}
result.push(bin);
}
return(result);
}
var binLength = 60;
var numStrings = 100;
var list = generateRandomLengthStringArrays(numStrings, binLength);
var result = packIntoFewestBins(list, binLength);
var capacity = result.length * binLength;
var fillage = 0;
for (var i = 0; i < result.length; i++) {
fillage += result[i].length;
$("#result").append(result[i] + "<br>")
}
$("#summary").html(
"Fill percentage: " + ((fillage/capacity) * 100).toFixed(1) + "%<br>" +
"Number of Input Strings: " + numStrings + "<br>" +
"Number of Output Bins: " + result.length + "<br>" +
"Bin Legnth: " + binLength + "<br>"
);