How to make Web Worker async? - javascript

The task is: work with large amount of data in the Worker and render the result of the algorithm after each iteration (I render dataObj to the HTML). Using following code make web page freezed and slow. How to avoid it?
onmessage = (e) => {
let number = 0;
let totalNumbers = 0;
let primeNumbers = 0;
if (e.data === "start"){
while(true){
totalNumbers++;
if (isPrime(number)){
primeNumbers++;
}
number++;
let dataObj = {
totalNumbers: totalNumbers,
primeNumbers: primeNumbers
}
postMessage(dataObj);
}
} else{
}
}
function isPrime(n) {
if (n == 2 || n == 3 || n == 5 || n == 7) {
return true;
} else if ((n < 2) || (n % 2 == 0)) {
return false;
} else {
for (var i = 3; i <= Math.sqrt(n); i += 2) {
if (n % i == 0)
return false;
}
return true;
}
}

Related

How do i return the result of all loops in javascript?

I am trying to insert dashes ('-') between each two odd numbers and insert asterisks ('*') between each two even numbers, but I am only getting the last result.
I want to print out all the elements in the array.
For example: if num is 4546793 the output should be 454*67-9-3. I Did not count zero as an odd or even number.
function StringChallenge(num) {
let result = "";
for (let i = 0; i < num.length; i++) {
if (num[i] === 0) {
continue;
}
if (num[i - 1] % 2 == 0 && num[i] % 2 == 0) {
result = num[i - 1] + "*" + num[i];
continue;
}
if (num[i - 1] % 2 == !0 && num[i] % 2 == !0) {
result = num[i - 1] + "-" + num[i];
continue;
}
}
return result;
}
console.log(StringChallenge([4,5,4,6,7,9,3]));
You do not need to check as if&continue. Inserting given numbers to the result string and only adding "-" when index and previous are odd, and "*" when index and previous are even.
function StringChallenge(num) {
let result = "";
for (let i = 0; i < num.length; i++) {
if (num[i]%2 ===0) {// even
if(i !== 0 && num[i-1]%2===0){// previous is even either
result+="*"+num[i];
}else{
result+=num[i];
}
}else{// odd
if(i !== 0 && num[i-1]%2===1){// previous is odd either
result+="-"+num[i];
}else{
result+=num[i];
}
}
}
return result;
}
console.log(StringChallenge([4,5,4,6,7,9,3]));
Try this :)
function test(a){
let result=""
for(let i=0; i < a.length; i++){
if(a[i] != 0 && a[i-1] % 2 == 0 && a[i] % 2 == 0){
result = result + '*' + a[i]
}
else if (a[i] != 0 && a[i-1] % 2 != 0 && a[i] % 2 != 0){
result = result + '-' + a[i]
}
else{
result = result + a[i]
}
}
return result
}
console.log(test([4,5,4,6,7,9,3]));
As everyone has identified, the problem is you are not adding to result.
But here is a suggestion to make your code easier to read
// These one line functions make your code easier to read
function IsEven(num){
return num % 2 === 0;
}
function IsOdd(num){
return num % 2 !== 0;
}
function StringChallenge(numArray) {
// return empty string if not an array or empty array
if(!Array.isArray(numArray) || numArray.length === 0) return "";
let result = "" + numArray[0]; // use "" to coerce first element of numArray from number to string
for (let i = 1; i < numArray.length; i++) {
// focus on the conditions to determine the separator you want between each element
separator = "";
if (numArray[i] !== 0) {
if (IsEven(numArray[i]) && IsEven(numArray[i - 1])) {
separator = "*";
} else if (IsOdd(numArray[i]) && IsOdd(numArray[i - 1])){
separator = "-";
}
}
// build the result
result += separator + numArray[i];
}
return result;
}
I will do that this way :
== some advices for 2 cents ==
1 - try to make your code as readable as possible.
2 - use boolean tests rather than calculations to simply do a parity test
3 - ES7 has greatly improved the writing of JS code, so take advantage of it
console.log(StringChallenge([4,5,4,6,7,9,3])); // 454*67-9-3
function StringChallenge( Nums = [] )
{
const
isOdd = x => !!(x & 1) // Boolean test on binary value
, isEven = x => !(x & 1) && x!==0 // zero is not accepted as Even value
;
let result = `${Nums[0]??''}`; // get first number as
// result if Nums.length > 0
for (let i=1; i<Nums.length; i++)
{
if ( isOdd(Nums[i-1]) && isOdd(Nums[i]) ) result += '-';
if ( isEven(Nums[i-1]) && isEven(Nums[i]) ) result += '*';
result += `${Nums[i]}`; // same as Nums[i].toString(10);
}
return result
}
I hope this helps. I tried to keep it as simple as possible.
function StringChallenge(num) {
//start with a string to concatenate, or else interpreter tries to do math
operations
let result = num[0].toString();
function checkOdd(num){ //helper function to check if odd
return num % 2
}
for (let i = 0; i < num.length - 1; i++) {
if (checkOdd(num[i]) && checkOdd(num[i+1])) { //checks if both odd
result += `-${num[i+1]}`; //adds - and next number
} else if (!checkOdd(num[i]) && !checkOdd(num[i+1])) { //checks if both even
result += `*${num[i+1]}`; //adds * and next number
} else { //otherwise
result += num[i+1]; //just add next number
}
}
return result;
}
console.log(StringChallenge([4,5,4,6,7,9,3]));
Use +=. And, change your logic, your code prints out "4*67-99-3".
The zero check was pretty hard for me I hope the variables in my code explain itself. If not, let me know.
function even(num) {
return num % 2 === 0;
}
function odd(num) {
return num % 2 !== 0;
}
function StringChallenge(num) {
let result = "";
for (let i = 0; i < num.length; i++) {
var currentZero = num[i] === 0
var previousZero = num[i-1] === 0
var bothEven = even(num[i]) && even(num[i-1])
var bothOdd = odd(num[i]) && odd(num[i-1])
var firstNumber = (i === 0)
if (!currentZero) {
if (firstNumber) {
result += num[i]
} else {
if (bothEven && !previousZero) {
result += "*" + num[i]
} else if (bothOdd && !currentZero) {
result += "-" + num[i]
} else {
result += num[i]
}
}
}
}
return result;
}
console.log(StringChallenge([0,4,5,0,4,6,7,9,3]));

Can anyone help me with Counter game solution?

When I try to run the input, it says that the time limit exceeded. Can anyone help me to reduce this code, thank you.
const counterGame = (n) => {
let count = 0;
for (let i = n; i > 0; i--) {
if (Math.pow(2, i) % 1 === 0 && Math.pow(2, i) === n) {
n /= 2;
count++;
if (n === 1) break;
} else if (Math.pow(2, i) <= n) {
n -= Math.pow(2, I);
count++;
if (n === 1) break;
}
}
if (count % 2 === 0) {
return 'Richard';
} else {
return 'Louise';
}
};
You don't have to iterate over the values to find if n is power of 2. You can use Math.log2() method. Like this,
function counterGame(n) {
let move = 0;
while(n > 1) {
let power = parseInt(Math.log2(n));
let max = 2**power;
if(n === max) {
n = parseInt(n/2);
} else {
n = n - max;
}
move++;
}
if(move %2 === 0) {
return 'Richard';
} else {
return 'Louise';
}
}
console.log(counterGame(6));
console.log(counterGame(8));
You don't need to loop for just checking whether n is power of 2. Check whether this helps or not.
const counterGame = (n) => {
if (n % 2 === 0) {
return 'Richard';
} else {
return 'Louise';
}
};

Find and print the biggest prime number (JS)

I'm studying node.js and have some interesting task - Write a program that finds and prints the biggest prime number which is <= N.
Input // Output - 13 // 13
126 // 113
26 // 23
In last course with java i have the same task and my code is really simple:
import java.util.Scanner;
public class BiggestPrimeNumber {
public static void main(String[] args){
int n;
Scanner in = new Scanner(System.in);
n=in.nextInt();
while(prim(n) == false){
n--;
}
System.out.println(n);
}
public static boolean prim(int m){
int n=m;
for(int i=2;i<n;i++){
if(n%i == 0){
return false;
}
}
return true;
}
}
I try similar way to test it, but I'm don't have idea how to convert it:
let n = 126;
while (isPrime(n) === false) {
n -= 1;
}
console.log(n);
let n = m;
for (let i = 2; i < n; i += 1) {
if (n % i === 0) {
return false;
}
}
return true;
Can you help me, because I'm really have problem with js using in console.
I think this is what you want. You only need to declare a function and use it as you are doing.
let n = 126;
while (isPrime(n) === false) {
n -= 1;
}
console.log(n);
function isPrime(m) {
let n = m;
for (let i = 2; i < n; i += 1) {
if (n % i === 0) {
return false;
}
}
return true;
}
If your running it with NodeJS in console, you can save it in a file called prime.js (for example) and execute it with: node prime.js.
You can pass parameters to the script like: node prime.js 126 and then get them in the code. That will be something like that:
const args = process.argv;
let n = args[2];
while (isPrime(n) === false) {
n -= 1;
}
console.log(n);
function isPrime(m) {
let n = m;
for (let i = 2; i < n; i += 1) {
if (n % i === 0) {
return false;
}
}
return true;
}
You're pretty close. First off, you don't have isPrime defined. Second, if you were to paste all of your code into the browser console, it isn't going to like that you are defining n twice. I also cleaned up your isPrime bit of code.
let n = 100;
let result = n;
const isPrime = num => {
for(let i = 2; i < num; i++)
if(num % i === 0) return false;
return num !== 1 && num !== 0;
}
while (isPrime(result) === false) {
result -= 1;
}
console.log(result + " is the next prime below " + n);
Also, remember that javascript is not a compiled language, so unless you are defining your function in a class, the browser will interpret the code sequentially. Therefore, you have to have isPrime defined before you use it.
The algorithm to find the nearest prime number can be further optimized. All prime numbers are of the form 6k+1 or 6k-1 except the numbers 2 and 3. Also, instead of checking all the way to the number the check can be made till Sqrt(n). Here is the modified isPrime function:
let n = 126;
while (isPrime(n) === false) {
n -= 1;
}
console.log(n);
function isPrime(num) {
if (num <= 1) return false;
if (num < 4) return true;
if (num%2 === 0 || num%3 === 0) return false;
for (var i = 5; i*i <= num; i+=6) {
if (num % i === 0 || num % (i + 2) === 0)
return false;
}
return true;
}

How to generate equal amount of different strings

I have this now:
var generateIcons = function(playtime, players) {
var count = playtime / 2;
icons = [];
for (var i = 1; i <= count; i++) {
if (i % 8 === 0 && players === 8) {
icons.push("cyan");
}
else if (i % 7 === 0 && players >= 7) {
icons.push("violet");
}
else if (i % 6 === 0 && players >= 6) {
icons.push("orange");
}
else if (i % 5 === 0 && players >= 5) {
icons.push("black");
}
else if (i % 4 === 0 && players >= 4) {
icons.push("gold");
}
else if (i % 3 === 0 && players >= 3) {
icons.push("red");
}
else if (i % 2 === 0 && players >= 2) {
icons.push("blue");
}
else {
icons.push("green");
}
}
};
The problem is that, I get much more green than blue for example with: generateIcons(60,4);
How to get ~equal amount of green, blue, red, gold?
So, if I understand your problem correctly, this should work:
var generateIcons = function(playtime, players) {
var count = playtime / 2;
icons = [];
colors = ["cyan", "violet", "orange", "black", "gold", "red", "blue", "green"];
for (var i = 0; i < count; i++) {
icons.push(colors[i % players]);
}
return icons;
};
console.log(generateIcons(60, 4));
Check If that solution satisfies you :)
var generateIcons = function(playtime, players) {
var count = playtime / 2;
icons = [];
var randomNumber;
for (var i = 1; i <= count; i++) {
randomNumber = Math.floor((Math.random() * players) + 1); //generate random number from <1, players> probability for each color should be ~equal ;)
if(randomNumber == 1)
{
icons.push("green");
}
else if (randomNumber == 2)
{
icons.push("blue");
}
else if (randomNumber == 3)
{
icons.push("red");
}
else if (randomNumber == 4)
{
icons.push("gold");
}
else if (randomNumber == 5)
{
icons.push("black");
}
else if (randomNumber == 6)
{
icons.push("orange");
}
else if (randomNumber == 7)
{
icons.push("violet");
}
else
{
icons.push("cyan");
}
}
}
generateIcons(60,4);
console.log(icons);

Why is my prime number calculator not working?

Here is my code. It would really help me if someone could tell me what is wrong. And performance tips are also highly appreciated.
btw the html is just a button onclick prime().
function prime() {
var teller = 1;
var n = document.getElementById("a").value;
document.write("2, ");
checkPrime(n, 1);
}
function checkPrime(n, teller) {
if(isPrime(teller)) {
document.write(teller + ", ");
}
if(teller < n) {
checkPrime(n, teller = teller + 2);
}
}
function isPrime(n) {
var isPrime = true;
if (n < 2 || n != Math.round(n) ) {
return false;
}
for (var i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) {
isPrime = false;
}
}
return isPrime;
}
Your logic for checking with modulus seems correct but the teller variable seemed strange to me. Here is a fiddle and your code without the teller var.
function prime() {
var teller = 1;
var n = document.getElementById("a").value;
checkPrime(n);
}
function checkPrime(n) {
var primes = isPrime(n);
if (primes) alert(primes.length + " primes found : " + primes.join())
else alert("Error");
}
function isPrime(n) {
var isPrime = true;
var primeArray = new Array();
if (n <= 2 || n != Math.round(n)) {
return false;
}
for (var j = 3; j <= n; j++) {
var primeFound = true;
for (var i = 2; i <= Math.sqrt(j); i++) {
if (j % i == 0) {
primeFound = false;
}
}
if (primeFound) primeArray.push(j);
}
return primeArray;
}
This isn't the most efficient code though. It would be faster to check by only the primes already found instead of trying to divide by all the integers up to sqrt(j).

Categories

Resources