Why is it faster to perform an assignment than do nothing? - javascript

class Obj {
constructor() {
this.propA = ~~(Math.random() * 255 + 0.5);
this.propB = ~~(Math.random() * 300 + 0.5);
}
}
const arr1 = new Array(100000);
for (var i = 0; i < 100000; i ++) {
arr1[i] = new Obj();
}
function test1() {
let start = new Date();
for (var times = 0; times < 1000; times ++) {
let n = 0;
for (var i = 0; i < 100000; i++) {
if (arr1[i].propA > arr1[i].propB) {
n += 1;
//arr1[i].propB = arr1[i].propA; //<-- try uncomment it
}
}
}
console.log(new Date() - start + 'ms');
}
test1();
paste this code to developer tools(or a new .html file).
on my computer(win7 x64, chrome 63) it prints 1200-1600ms.
however when I uncomment the code it prints only 500-700ms.
I don't know why it happens...

I don't know why it happens...
Because after firs time when
arr1[i].propB = arr1[i].propA;
has been executed, from the next iteration
if (arr1[i].propA > arr1[i].propB)
will be false and hence that line n += 1; will not get executed.
Since you are saving one operations by replacing increment and assignment with only assignment, you see a improvement in speed.

Related

Not inserting element on call inserts after the entire execution

function loadval() {
r = Math.floor(Math.random() * load.length);
console.log(r);
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
var set = (i + 1) * 10 + j + 1;
var x = document.getElementById(set);
x.value = load[r][i][j];
console.log(load[r][i][j]);
sleep(25);
}
}
}
The element is not inserted one by one after the delay, all the elements are set after the whole function gets executed.
why not use setInterval or setTimeout instead sleep(25)?
// repeat at 2 second intervals
let timerId = setInterval (() => loadval(), 2000);
// stop output after 10 seconds
setTimeout (() => {clearInterval (timerId); alert ('stop');}, 10000);

How can I make my guess-password code's loop work?

I want to write this function "guessPasscode", but don't think my codes work. (the other functions are correct) It is supposed to guess every number from 0000 ~ 9999 as four-digit passcodes.
I run the function and it doesn't print out anything, and I also don't think the function works the way I wanted it to.
var guess = "";
var guessCode ="";
function start() {
var secretPasscode = generateRandomPasscode();
guessPasscode(secretPasscode);
}
// Checks whether the given guess passcode is the correct passcode
function isCorrect(guessCode, correctCode) {
return guessCode == correctCode;
}
// Generates a random 4 digit passcode and returns it as a String
function generateRandomPasscode() {
var randomPasscode = "";
for(var i = 0; i < 4; i++) {
var randomDigit = Randomizer.nextInt(0, 9);
randomPasscode += randomDigit;
}
return randomPasscode;
}
function guessPasscode(secretPasscode){
for (var a = 0; a < 10; a++){
guess += a;
for (var b = 0; b < 10; b++){
guess += b;
for(var c = 0; c < 10; c++){
guess += c;
for (var d = 0; d < 10; d++){
guess += d;
if (isCorrect(guessCode, secretPasscode)){
println("Success!");
break;
}
guess = 0; //I am not sure about this line though
}
}
}
}
if (isCorrect(guessCode, secretPasscode)){
println("Success!");
}
}
I expect it to print "success" and stop the loop after it has found the correct password.
Those nested for loops are really wild and incredibly inefficient. If you want to guess from 0 to 9999, just run the loop through and then pad zeroes to the left.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
for (let i = 0; i < 9999; i++) {
let guess = String(i).padStart(4, '0')
guessAnswer(guess)
//whatever logic here to exit loop on correct guess
}

Solving the seventh with O(n)

I have solved the seventh problem of Euler, it says:
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can
see that the 6th prime is 13.
What is the 10 001st prime number?
I solved it using, and in the array in which I keep the cousins, when it reaches the length of 10001, I return that number. The algorithm takes 1300 ms, which I tink that is very inefficient, what am I doing particularly in my implementation?
var start = performance.now();
function eratosthenes(n) {
var arr = [2], acc = 0;
// matrix to save the found prime numbers and mark their multiples
for(var i = 3; true; i += 2) { // loop
if(arr.length === n) return arr[arr.length - 1]; // if the array length is equal to n return the last number
if(!resolve(arr, i)) { // check if is multiple of the prime numbers, already found.
arr.push(i); // if isnt multiple, save it
}
}
}
function resolve(array, n) {
return array.some(cur => !(n%cur));
}
console.log(eratosthenes(10001)); // Tooks 1300 ms
var end = performance.now();
var time = end - start;
console.log(time);
Euler sieve, Pham knows this one :) 12ms
Uchu, I don't see where your code is marking the multiples. Isn't that what Sieve of Eratosthenes is supposed to do?
JavaScript code (this code is actually an adaptation of code by btilly, optimizing an idea of mine):
var start = performance.now();
n = 115000
a = new Array(n+1)
total = 0
s = []
p = 1
count = 0
while (p < n){
p = p + 1
if (!a[p]){
count = count + 1
if (count == 10001){
console.log(p);
end = performance.now();
time = end - start;
console.log(time);
break;
}
a[p] = true
s.push(p)
limit = n / p
new_s = []
for (i of s){
j = i
while (j <= limit){
new_s.push(j)
a[j*p] = true;
j = j * p
}
}
s = new_s
}
}
As requested by JaromandaX, this is the code for Sieve of Eratosthenes. 51 ms on my browser (OP solution is 750 ms)
var max = 1000000;
function eratosthenes(n) {
var arr = [], count = 0;
for (var i = 0; i < max; i++){
arr.push(true);
}
for (var i = 2; i < max; i++){
if(arr[i]){
count++;
if(count == n){
return i;
}
for (var j = i + i; j < max; j += i ){
arr[j] = false;
}
}
}
}
var start = performance.now();
console.log(eratosthenes(10001));
var end = performance.now();
var time = end - start;
console.log(time);
This has a similar running time to גלעד ברקן's answer (actually about 10% faster on my machine), but doesn't rely on knowing an approximate max before starting. It performs a seive of Eratosthenes up to max (starting at 2) and then doubles max, initialises the new elements in the array per the previously found primes and repeats.
function eratosthenes(n) {
let prev_max = 1, max = 2, i, j;
const primes = [], is_prime = new Array(max+1).fill(true);
while( true ) {
for ( i = prev_max + 1; i <= max; i++){
if ( ! is_prime[i] ) continue;
primes.push( i );
if ( primes.length === n )
return i;
for ( j = i + i; j <= max; j += i )
is_prime[j] = false;
}
const next_max = max*2;
is_prime.length = next_max + 1;
is_prime.fill( true, max + 1, next_max );
for ( i = 0; i < primes.length; i++ ) {
const prime = primes[i];
for ( j = max + prime - max%prime; j <= next_max; j += prime )
is_prime[j] = false;
}
prev_max = max;
max = next_max;
}
}
var start = performance.now();
console.log(eratosthenes(10001));
var end = performance.now();
var time = end - start;
console.log(time);
If it is a code-writing exercise, it is better to explore the earlier answers.
But if you are after a simple and fast solution, here's how you can solve it using prime-lib, which I created:
import {generatePrimes} from 'prime-lib';
const seekIndex = 10_001; // index of the prime being sought
const start = Date.now();
let a, c = 0;
const i = generatePrimes({boost: seekIndex + 1});
while ((a = i.next()) && !a.done && c++ < seekIndex) ;
console.log(`Prime: ${a.value}, took ${Date.now() - start}ms`);
On my PC it spits out:
Prime: 104759, took 5ms
And with the modern RXJS this becomes even simpler still:
import {generatePrimes} from 'prime-lib';
import {from, last} from 'rxjs';
const seekIndex = 10_001; // index of the prime being sought
const i = generatePrimes({boost: seekIndex + 1});
from(i).pipe(last()).subscribe(console.log);
//=> 104759

Why is passing in a variable (as a ref) slower than accessing the same variable defined in a closure?

Given:
(function() {
var items = [1, 2, 3, 4];
// In Chrome, this takes ~8-10 ms to execute.
for(var i = 0; i < items.length; i++) {
x(items);
}
// In Chrome, this takes 1-2 ms to execute.
for(var i = 0; i < items.length; i++) {
y();
}
function x(y) {
y[0] = -100;
}
function y() {
items[0] = 100;
}
})();
Why are the calls to x() 8-10 times slower than the calls to y()? Is it because variable resolution does not need to take place in the execution of y()?
I'm not seeing a difference in time except for the first iteration or 2 which suggests that there is no big difference except something getting added during start up. V8 doesn't optimize immediately AFAIK so that could explain why it takes a few iterations to balance out. Also cache misses.
function log() {
var div = document.createElement("div");
div.textContent = Array.prototype.join.call(arguments, " ");
document.body.appendChild(div);
};
(function() {
var items = new Array(10000000);
for (j = 0; j < 20; ++j) {
var xStart = performance.now();
for(var i = 0; i < items.length; i++) {
x(items);
}
var xDuration = performance.now() - xStart;
var yStart = performance.now();
for(var i = 0; i < items.length; i++) {
y();
}
var yDuration = performance.now() - yStart;
log(j, "x:", xDuration.toFixed(3) + "ms",
"y:", yDuration.toFixed(3) + "ms",
"diff:", (xDuration - yDuration).toFixed(3) + "ms");
}
function x(y) {
y[0] = -100;
}
function y() {
items[0] = 100;
}
})();
body { font-family: monospace; }

why var declaration fast than let

'use strict'
function test() {
let t = Date.now();
let p = 0;
for (let i = 0; i < 100000000; i++) {
p += i % 2;
}
console.log(p)
console.log('test: ', Date.now() - t);
}
function test1() {
var t = Date.now();
var p = 0;
for (var i = 0; i < 100000000; i++) {
p += i % 2;
}
console.log(p)
console.log('test1 : ', Date.now() - t);
}
test();
test1();
run the code above in chrome, why test1 is fast than test. is the let' fault or my fault?
50000000
test: 1146
50000000
test1 : 148
It might be worth mentioning that in es6 the let keyword in a for-loop has been designed to solve the notorious closure in a loop problem in JavaScript:
var log = msg => div.innerHTML += msg + "<br>";
for (var i=0; i < 3; i++) {
Promise.resolve().then(() => log(i)); // 3, 3, 3
}
for (let i=0; i < 3; i++) {
Promise.resolve().then(() => log(i)); // 0, 1, 2
}
<div id="div"></div>
As #loganfsmyth mentions in comments, it does this by effectively creating a new closure for each iteration of the loop.
This, and the fact that the feature is new, might account for some of the performance difference seen in Chrome. That said, there seems to be no difference in Firefox for your particular example, so it seems possible for browsers to optimize this.

Categories