How to update innerHTML in very long running loop javascript - javascript

var star = 4125;
var moon = 2946;
var max = 50;
//-----------------------------------------------------------------------------------
var a,b,c,d,e,f;
var starx,moonx,tokenx;
var token = 0;
var txt;
for (a = max ; a >= 0 ; a--)
{
for (b = 0 ; b <= max ; b++)
{
for (c = 0 ; c <= max ; c++)
{
for (d = 0 ; d <= max ; d++)
{
for (e = 0 ; e <= max ; e++)
{
for (f = 0 ; f <= max ; f++)
{
starx = 75 * (a + b + c + d + e + f);
moonx = (10 * a) + (30 * b) + (50 * c) + (75 * d) + (125 * e) + (200 * f);
tokenx = (210 * a) + (235 * b) + (260 * c) + (300 * d) + (375 * e) + (500 * f);
if (starx <= star && moonx <= moon && tokenx >= token)
{
token = tokenx;
txt = tokenx + ',' + starx + ',' + moonx + ',' + a + ',' + b + ',' + c + ',' + d + ',' + e + ',' + f + '<br>\n';
document.getElementById("txt").innerHTML += txt;
console.log(txt);
}
}
}
}
}
}
}
Need help. I am very new to javascript. I would like to run those javascript in android. innerHTML don't update until the loop completed. And can't see console log in android too.

If you want to show the output of the loop at each iteration you can use setInterval()
like so:
for(let a = 0; a < 10; a++) {
document.body.innerHTML += "Hello world!" +a +"<br />";
}
document.body.innerHTML += "<br /> Loop but shows output at each iteration: <br />";
let a = 0;
let aLoop = setInterval(function() {
if(a < 10) {
document.body.innerHTML += "Hello world!" +a +"<br />";
a++;
} else {
clearInterval(iLoop);
}
}, 100);
However, this would require you to convert a lot of your code and would get messy. If all you wish to do is see the output on android you can try alert(txt); to see the output instead.

Use generator function* to yield text. DOM element innerHTML could be updated via setInterval timer.
function* cal() {
var star = 4125;
var moon = 2946;
var max = 50;
var a, b, c, d, e, f;
var starx, moonx, tokenx;
var token = 0;
var txt;
for (a = max; a >= 0; a--) {
for (b = 0; b <= max; b++) {
for (c = 0; c <= max; c++) {
for (d = 0; d <= max; d++) {
for (e = 0; e <= max; e++) {
for (f = 0; f <= max; f++) {
starx = 75 * (a + b + c + d + e + f);
moonx = (10 * a) + (30 * b) + (50 * c) + (75 * d) + (125 * e) + (200 * f);
tokenx = (210 * a) + (235 * b) + (260 * c) + (300 * d) + (375 * e) + (500 * f);
if (starx <= star && moonx <= moon && tokenx >= token) {
token = tokenx;
txt = tokenx + ',' + starx + ',' + moonx + ',' + a + ',' + b + ',' + c + ',' + d + ',' + e + ',' + f + '<br>\n';
// document.getElementById("txt").innerHTML += txt;
console.log(txt);
yield txt;
}
}
}
}
}
}
}
}
function run() {
gen = cal();
setInterval(()=> document.getElementById("txt").innerHTML +=
gen.next().value, 10);
}
run();

Web workers can do long running task.
See here:
https://www.w3schools.com/html/html5_webworkers.asp
Notes:
Chrome doesn't support web workers when load script from local.
You have to add option Chrome.exe --allow-file-access-from-files
Firefox allow local file.
<!DOCTYPE html>
<html>
<body>
<button onclick="startWorker()">Start Worker</button>
<button onclick="stopWorker()">Stop Worker</button><br><br>
<pre id="txt">
Hello
</pre>
<script>
var w;
function startWorker()
{
if(typeof(Worker) !== "undefined")
{
if(typeof(w) == "undefined")
{
w = new Worker("StarForge.js");
}
w.onmessage = function(event)
{
document.getElementById("txt").innerHTML += event.data;
};
}
else
{
document.getElementById("txt").innerHTML = "Sorry! No Web Worker support.";
}
}
function stopWorker()
{
w.terminate();
w = undefined;
}
</script>
</body>
</html>
And in the StarForge.js
function gen()
{
var moon = 2946;
var star = 4125;
var max = 50;
var a,b,c,d,e,f;
var moonx,starx,tokenx;
var token = 0;
var txt;
for (a = 0 ; a <= max ; a++)
{
for (b = 0 ; b <= max ; b++)
{
for (c = 0 ; c <= max ; c++)
{
for (d = 0 ; d <= max ; d++)
{
for (e = 0 ; e <= max ; e++)
{
for (f = 0 ; f <= max ; f++)
{
tokenx = (210 * a) + (235 * b) + (260 * c) + (300 * d) + (375 * e) + (500 * f);
moonx = (10 * a) + (30 * b) + (50 * c) + (75 * d) + (125 * e) + (200 * f);
starx = 75 * (a + b + c + d + e + f);
if (tokenx >= token && moonx <= moon && starx <= star)
{
token = tokenx;
txt = tokenx + ',' + moonx + ',' + starx + ',' + a + ',' + b + ',' + c + ',' + d + ',' + e + ',' + f;
postMessage(txt)
console.log(txt);
}
}
}
}
}
}
}
postMessage("--- End ---");
console.log("--- End ---");
}
gen();

Related

How to get String output as in single quote in javascript

Advance thanks, Question looks like simple but i could not able to find the solution.
function sumStrings(a, b)
{
return +a + +b;
}
sumStrings('1','2') //=>3
Expected output
sumStrings('1','2') // => '3'
After addition, add ' to beginning and end.
function sumStrings(a, b){
return "'" + (Number(a) + Number(b)) + "'";
}
console.log(sumStrings('1','2'));
function sumStrings(a, b) {
// Separate decimal part here
var pointa = a.indexOf(".");
var pointb = b.indexOf(".");
var deca = pointa != -1 ? a.substring(pointa + 1) : "0";
var decb = pointb != -1 ? b.substring(pointb + 1) : "0";
if (deca.length < decb.length)
deca += (Math.pow(10, decb.length - deca.length)).toString().substring(1);
else
decb += (Math.pow(10, deca.length - decb.length)).toString().substring(1);
var inta = pointa != -1 ? a.substring(0, pointa) : a;
var intb = pointb != -1 ? b.substring(0, pointb) : b;
// console.log(deca + " " + decb);
var decc = addBigInt(deca, decb);
var intc = addBigInt(inta, intb);
if (decc.length > deca.length) {
intc = addBigInt(intc, "1");
decc = decc.substring(1);
}
var lastZero = decc.length - 1;
while (lastZero >= 0 && decc[lastZero] == "0") {
lastZero--;
}
if (lastZero >= 0)
return intc + "." + decc.substring(0, lastZero + 1);
else
return intc;
}
function addBigInt(a, b) {
var inda = a.length - 1;
var indb = b.length - 1;
var c = [];
const zero = "0".charCodeAt(0);
var carry = 0;
var sum = 0;
while (inda >= 0 && indb >= 0) {
var d1 = a.charCodeAt(inda--) - zero;
var d2 = b.charCodeAt(indb--) - zero;
sum = (d1 + d2 + carry);
carry = Math.floor(sum / 10);
sum %= 10;
c.unshift(sum);
}
if (inda >= 0) {
while (carry && inda >= 0) {
sum = a.charCodeAt(inda--) - zero + carry;
c.unshift(sum % 10);
carry = Math.floor(sum / 10);
}
c.unshift(a.substring(0, inda + !carry));
} else {
while (carry && indb >= 0) {
sum = b.charCodeAt(indb--) - zero + carry;
c.unshift(sum % 10);
carry = Math.floor(sum / 10);
}
c.unshift(b.substring(0, indb + !carry));
}
if (carry)
c.unshift(carry);
return c.join("");
}
console.log(sumStrings("1","2"));
console.log(sumStrings("800","9567"));
console.log(sumStrings("99.1","1"));
console.log(sumStrings("00103","08567"));
console.log(sumStrings("50095301248058391139327916261.5","81055900096023504197206408605"));
If you want to escape the single quote, you can try to add a backslash before the single quote.
i.e.
var x = '\'5\'';
With the new template literal you can try this:
a=`'5'`;
console.log(a);

Unique in generated random number (no duplicate)

I want only the generated random number will hava no duplicate, whenever i try to put the number, the generated random number has duplicate, any other idea. what should i change here?
See the fiddle
var arr = hello.toString(10).replace(/\D/g, '0').split('').map(Number);
for(i=0;i<arr.length;i++) arr[i] = +arr[i]|0;
//initialize variables
var z = arr[3];
var y = arr[2];
var x = arr[1];
var w = arr[0];
while((((a2 <= 0) || (a2 > 49)) || ((b <= 0) || (b > 49)) || ((c <= 0) || (c > 49)) || ((d <= 0) || (d > 49)) || ((e2 <= 0) || (e2 > 49)) || ((f <= 0) || (f > 49)) || ((g <= 0) || (g > 49) ))){
//loop ulit kapag hindi match yung random number sa value nung z
while( zRandomString != z){
zRandom = Math.floor(Math.random() * (109 - 100 + 1)) + 100;
zRandomRound = zRandom % 10;
zRandomString = zRandomRound.toString();
}
var zNew = zRandom; //new value ng z
document.getElementById("zebra").innerHTML = "Z = " + zNew + "<br />";// udsadsadsad
h = zNew;
while( yRandomString != y){
yRandom = Math.floor(Math.random() * (49 - 1 + 1)) + 1;
yRandomRound = yRandom % 10;
yRandomString = yRandomRound.toString();
}
var yNew = yRandom; //new value ng z
document.getElementById("yeah").innerHTML = "Y = " + yNew + "<br />";// udsadsadsad
h = h - yNew;
while( xRandomString != x){
xRandom = Math.floor(Math.random() * (h - 1 + 1)) + 1;
xRandomRound = xRandom % 10;
xRandomString = xRandomRound.toString();
}
var xNew = xRandom; //new value ng z
document.getElementById("ex").innerHTML = "X = " + xNew + "<br />";// udsadsadsad
h = h - xNew;
while( wRandomString != w){
wRandom = Math.floor(Math.random() * (h - 1 + 1)) + 1;
wRandomRound = wRandom % 10;
wRandomString = wRandomRound.toString();
}
var wNew = wRandom; //new value ng z
document.getElementById("weh").innerHTML = "W = " + wNew + "<br />";// udsadsadsad
//h = Math.abs(h - wNew); // new value of h
h = h - wNew;
a = Math.floor(Math.random() * (wNew - 1 + 1)) + 1;
a2 = wNew - a;
b = Math.floor(Math.random() * (a2 - 1 + 1)) + 1;
c = a - b;
d = yNew;
e = Math.floor(Math.random() * (xNew - 1 + 1)) + 1;
e2 = xNew - e;
f = Math.floor(Math.random() * (e2 - 1 + 1)) + 1;
g = e - f;
}
var combo = a2.toString() + ', ' + b.toString() + ', ' + c.toString() + ', ' + d.toString() + ', ' + e2.toString() + ', ' + f.toString() + ', ' + g.toString() + ', ' + h.toString();
document.getElementById("combo").innerHTML = combo;
Try to use this scheme:
var r;
do {
r = Math.floor(Math.random() * 10);
} while (r == 6);
It is not quite clear what you want, but one way to create a sequence on unique random numbers is to create a pool of numbers and sucessively pick and remove items from it:
function pick(pool) {
if (pool.length == 0) return undefined;
// pick an element from the pool
var k = (Math.random() * pool.length) | 0;
var res = pool[k];
// adjust array
pool[k] = pool[pool.length - 1];
pool.pop();
return res;
}
// example
var pool = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
while (pool.length) {
console.log(pick(pool));
}
Another method is to shoffle the pool first and then pop off elements:
function shuffle(arr) {
var n = arr.length;
while (n) {
// pick element
var k = (Math.random() * n--) | 0;
// swap last and picked elements
var swap = arr[k];
arr[k] = arr[n];
arr[n] = swap;
}
}
var pool = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
shuffle(pool);
while (pool.length) {
console.log(pool.pop());
}
These two methods aren't very different if you look at the pick and shuffle functions. Of course, eventually you will exhaust the pool. You can then decide to recreate or reshuffle the array. Also note that these methods will produce repeated elements if the pool has repeated entries.

Why this color conversion maps to gray so often?

I want to convert the RGB Color to an indexed color, here is my code, it works. But although some colors are converted to blue or red, but others that look like blue or red got converted to gray. How to fix this? You can check my snippet, click the color from big table and see the results down there.
var palette = [0, 0xff0000, 0xff00, 0xffff00, 0xff, 0xff00ff, 0xffff, 0x808080]
function rgb(c) {
return [c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff]
}
// http://alienryderflex.com/hsp.html
function rgb2lum(r, g, b) {
return Math.sqrt(Pr * r * r + Pg * g * g + Pb * b * b)
}
var Pr = .2126,
Pg = .7152,
Pb = .0722;
var rd = 255,
gd = 255,
bd = 255,
maxDist = Math.sqrt(Pr * rd * rd + Pg * gd * gd + Pb * bd * bd);
function colorDist(a, b) {
a = rgb(a), b = rgb(b)
var rd = b[0] - a[0],
gd = b[1] - a[1],
bd = b[2] - a[2]
return Math.sqrt(Pr * rd * rd + Pg * gd * gd + Pb * bd * bd) / maxDist
}
function randomColor() {
var r = Math.floor(Math.random() * 256)
var g = Math.floor(Math.random() * 256)
var b = Math.floor(Math.random() * 256)
var c = (r + (g << 8) + (b << 16))
return c
}
function hex(c) {
c = c.toString(16)
while (c.length < 6) c = '0' + c
return '#' + c
}
function f(a) {
var id = -1,
val = 2
for (var i = 0; i < palette.length; i++) {
var c = palette[i],
d = colorDist(a, c)
if (d < val) id = i, val = d
}
out.innerHTML += ('<span style="border:1px solid black"><span style=background:' + hex(a) + '>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp</span><span style=background:' + hex(palette[id]) + '>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp</span></span>, ')
}
var W = 60,
H = 10
var s = '<table border=0 cellspacing=0 style=cursor:pointer>'
for (var y = 0; y < H; y++) {
s += '<tr>'
for (var x = 0; x < W; x++) {
var c = randomColor()
s += '<td style="background:' + hex(c) + '" onclick=f(' + c + ')> </td>'
}
s += '</tr>'
}
s += '</table>'
s += 'palette:<table border=1><tr>'
for (var x = 0; x < palette.length; x++) {
s += '<td style="background:' + hex(palette[x]) + '" onclick=f(' + palette[x] + ')> </td>'
}
s += '</tr></table>'
out.innerHTML = s
<span id=out></span>
It looks like you have your rgb arrays reversed.
function rgb(c) {
return [c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff]
}
rgb() produces an array of [b,g,r] and your HSP math assumes the returned array is [r,g,b]:
function colorDist(a, b) {
a = rgb(a), b = rgb(b) // <--- produces [b,g,r] arrays
var rd = b[0] - a[0], // <--- red is index 0
gd = b[1] - a[1],
bd = b[2] - a[2]
return Math.sqrt(Pr * rd * rd + Pg * gd * gd + Pb * bd * bd) / maxDist
}
This would seem to throw off the intended brightness calculations.

Fastest general purpose Levenshtein Javascript implementation

I am looking for a good general purpose Levenshtein implementation in Javascript. It must be fast and be useful for short and long strings. It should also be used many times (hence the caching). The most important thing is that it calculates a plain simple Levenshtein distance. I came up with this:
var levenshtein = (function() {
var row2 = [];
return function(s1, s2) {
if (s1 === s2) {
return 0;
} else {
var s1_len = s1.length, s2_len = s2.length;
if (s1_len && s2_len) {
var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
while (i1 < s1_len)
row[i1] = ++i1;
while (i2 < s2_len) {
c2 = s2.charCodeAt(i2);
a = i2;
++i2;
b = i2;
for (i1 = 0; i1 < s1_len; ++i1) {
c = a + (s1.charCodeAt(i1) === c2 ? 0 : 1);
a = row[i1];
b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
row[i1] = b;
}
}
return b;
} else {
return s1_len + s2_len;
}
}
};
})();
Now I have two questions:
Can this be faster? I know by writing out the first iteration of each loop one can gain about 20%.
Is this code well written to serve as general purpose code, to be used in a library for instance?
We had a competition for fun at work about making the fastest levenshtein implementation and I came up with a faster one. First of all, I must say that it was not easy to beat your solution which was the fastest to find "out there". :)
This is tested with node.js and it my benchmarks results indicates that this implementation is ~15% faster on small texts (random words size 2-10 characters) and over twice as fast on longer texts (with lengths 30+ containing random characters)
Note: I removed array caching of all implementations
function levenshtein(s, t) {
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h, k;
var p = new Array(n);
for (y = 0; y < n;) {
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
k = s.charCodeAt(y);
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== k) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== k) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== k) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== k) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== s.charCodeAt(y)) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
return h;
}
On longer texts it will get almost up to 3 times the speed of your implementation if it initially cache the inner loop's s.charCodeAt(y) in an Uint32Array. Longer texts also seemed to benefit from using a Uint16Array as a the distance cost array. Here is the code for that solution
function levenshtein(s, t) {
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h;
var p = new Uint16Array(n);
var u = new Uint32Array(n);
for (y = 0; y < n;) {
u[y] = s.charCodeAt(y);
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== u[y]) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== u[y]) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== u[y]) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== u[y]) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== u[y]) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
return h;
}
All benchmark results is from my tests and test-data might be different with your test-data.
The main 2 difference in this solution than to yours (and some other fast ones) I think is
Not always do compare of the characters in the inner loop if not necessary.
Sort of "Loop unrolling" in the outer loop doing 4 rows at a time in the levenshtein "matrix". This was a major performance win.
http://jsperf.com/levenshtein-distance/24
I will put this solution on github when I find the time :)
Update:
Finally, I put the solution on github
https://github.com/gustf/js-levenshtein. Its a bit modified/optimized but it is the same base algorithm.

Automatically fire a JavaScript code after loading a page in Google Chrome

I have a Javascript code, which I use to bring Night Mode effect on an HTML page...
The code goes something like this-
javascript: (function () {
function RGBtoHSL(RGBColor) {
with(Math) {
var R, G, B;
var cMax, cMin;
var sum, diff;
var Rdelta, Gdelta, Bdelta;
var H, L, S;
R = RGBColor[0];
G = RGBColor[1];
B = RGBColor[2];
cMax = max(max(R, G), B);
cMin = min(min(R, G), B);
sum = cMax + cMin;
diff = cMax - cMin;
L = sum / 2;
if (cMax == cMin) {
S = 0;
H = 0;
} else {
if (L <= (1 / 2)) S = diff / sum;
else S = diff / (2 - sum);
Rdelta = R / 6 / diff;
Gdelta = G / 6 / diff;
Bdelta = B / 6 / diff;
if (R == cMax) H = Gdelta - Bdelta;
else if (G == cMax) H = (1 / 3) + Bdelta - Rdelta;
else H = (2 / 3) + Rdelta - Gdelta; if (H < 0) H += 1;
if (H > 1) H -= 1;
}
return [H, S, L];
}
}
function getRGBColor(node, prop) {
var rgb = getComputedStyle(node, null).getPropertyValue(prop);
var r, g, b;
if (/rgb\((\d+),\s(\d+),\s(\d+)\)/.exec(rgb)) {
r = parseInt(RegExp.$1, 10);
g = parseInt(RegExp.$2, 10);
b = parseInt(RegExp.$3, 10);
return [r / 255, g / 255, b / 255];
}
return rgb;
}
function hslToCSS(hsl) {
return "hsl(" + Math.round(hsl[0] * 360) + ", " + Math.round(hsl[1] * 100) + "%, " + Math.round(hsl[2] * 100) + "%)";
}
var props = ["color", "background-color", "border-left-color", "border-right-color", "border-top-color", "border-bottom-color"];
var props2 = ["color", "backgroundColor", "borderLeftColor", "borderRightColor", "borderTopColor", "borderBottomColor"];
if (typeof getRGBColor(document.documentElement, "background-color") == "string") document.documentElement.style.backgroundColor = "white";
revl(document.documentElement);
function revl(n) {
var i, x, color, hsl;
if (n.nodeType == Node.ELEMENT_NODE) {
for (i = 0; x = n.childNodes[i]; ++i) revl(x);
for (i = 0; x = props[i]; ++i) {
color = getRGBColor(n, x);
if (typeof (color) != "string") {
hsl = RGBtoHSL(color);
hsl[2] = 1 - hsl[2];
n.style[props2[i]] = hslToCSS(hsl);
}
}
}
}
})()
I have saved this as a Bookmarklet in my Bookmark Bar on Google Chrome, but I want this to be automatically applied to every page I load. What should I do to achieve this?
You should write this as a userscript and run it with something like tampermonkey

Categories

Resources