Make a find prime number function in javascript. I want to let it display the values to textarea whenever it finds a prime number.
However, it will only show the result when the function is fully executed.
Here is my code:
let start = performance.now()
let textarea = document.querySelector('textarea')
let time = document.getElementById('time')
let texts = document.getElementById('texts')
let amount = document.getElementById('amount')
let status = document.getElementById('status')
let logs = [];
let number = 0
let prime = [];
function check(){
status.textContent = 'processing'
amount.textContent = 'processing'
time.textContent = 'processing'
textarea.textContent =logs
setTimeout(function(){reallycheckprimenumber()},0)
}
function reallycheckprimenumber(){
number = 0;
let start = performance.now()
let value = texts.value
if(value ==''){
value = texts.placeholder;
}
for (var i = 0;i<value;i++){
time.textContent = ''
amount.textContent = ''
var nums = 2;
for (let x = 0;x<=i/2;x++){
if(nums>3){
break;
}
if(i!==0 && i!==1 && i !== x){
if(i%x === 0){
nums++;
}
}
}
if(nums === 3){
prime.push(i)
textarea.textContent += prime
number +=1
}
if(i === value-1){
status.textContent = 'done'
let end = performance.now()
time.textContent = (end-start).toFixed(5) +'ms'
amount.textContent = number
}
}
}
check()
<h1>Get Prime number application:</h1>
<h2>Prime Number: <span></span></h2>
<h3 >Processing Time: <span id = 'time'>0 ms</span></h3>
<h3>Number: <span id = 'amount'>0</span></h3>
<h3>Status: <span id = 'status'>Processing</span></h3>
<label for = 'texts'>Enter the range you want to get number from</label>
<input type = 'text' id = 'texts' placeholder = '100'>
<input type = 'button' id = 'button' value = 'set' onclick = 'check()'>
<textarea readonly></textarea>
I have tried several ways to make the application displays prime number while it is finding other prime number. However, I failed.
I found that only console will work.
I really have no idea on how to solve this problem.
Anyone have an idea and know how to solve it?
Thanks so much for any helps and supports
Start with 2,3 already, you do not have to check for them every time with === . It should be enough to check until the sqrt of the number. The below snippet will print the list to a textArea if it finds one.
Note that using setTimeout or any sort of fixed interval update does not seem like a good idea because prime numbers get sparse over time, which means it will take longer and longer to log something on the screen.
(function(start){
const list = start,
myarea = document.getElementById("myarea");
let nCurrent = start[start.length - 1];
function recurse(){
let _sqrt = Math.sqrt(nCurrent);
for (let i = 2; i <= _sqrt; ++i) {
if(!(nCurrent % i)){
break;
}
if (i === Math.floor(_sqrt)){
list.push(nCurrent);
myarea.textContent = list.toString();
}
}
nCurrent++;
};
setInterval(recurse,500);
}([2,3]))
<textArea id="myarea"></textArea>
Explanation:
Outer most function is an immediately invoked function expression (iife), which gets 1 parameter, a list to start with. In this case we start with [2,3], first 2 primes.
Inside we create 3 variables:
the list, that holds all primes found until now
nCurrent, which is the current number we are checking if prime
recurse, a recursive function that will be called by setInterval.
For every nCurrent, lets say 120, it is sufficient to look until the sqrt of 120, and see whether numbers <= sqrt(120) divides 120. If it does, the operator % will return 0, and !(nCurrent % i) will therefore return true (!0 is true). In that case we know this is not a prime number, we terminate early, increment nCurrent and wait until the next call of recurse.
If all the i's until sqrt(nCurrent) is tested and does not divide it, then we have a prime and we push it to the list.
list.toString() is defult stringification of an array in JS, which return all the elements joined by comma.
Related
Can't seem to find an answer to this, say I have this:
setInterval(function() {
m = Math.floor(Math.random()*7);
$('.foo:nth-of-type('+m+')').fadeIn(300);
}, 300);
How do I make it so that random number doesn't repeat itself. For example if the random number is 2, I don't want 2 to come out again.
There are a number of ways you could achieve this.
Solution A:
If the range of numbers isn't large (let's say less than 10), you could just keep track of the numbers you've already generated. Then if you generate a duplicate, discard it and generate another number.
Solution B:
Pre-generate the random numbers, store them into an array and then go through the array. You could accomplish this by taking the numbers 1,2,...,n and then shuffle them.
shuffle = function(o) {
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
var randorder = shuffle([0,1,2,3,4,5,6]);
var index = 0;
setInterval(function() {
$('.foo:nth-of-type('+(randorder[index++])+')').fadeIn(300);
}, 300);
Solution C:
Keep track of the numbers available in an array. Randomly pick a number. Remove number from said array.
var randnums = [0,1,2,3,4,5,6];
setInterval(function() {
var m = Math.floor(Math.random()*randnums.length);
$('.foo:nth-of-type('+(randnums[m])+')').fadeIn(300);
randnums = randnums.splice(m,1);
}, 300);
You seem to want a non-repeating random number from 0 to 6, so similar to tskuzzy's answer:
var getRand = (function() {
var nums = [0,1,2,3,4,5,6];
var current = [];
function rand(n) {
return (Math.random() * n)|0;
}
return function() {
if (!current.length) current = nums.slice();
return current.splice(rand(current.length), 1);
}
}());
It will return the numbers 0 to 6 in random order. When each has been drawn once, it will start again.
could you try that,
setInterval(function() {
m = Math.floor(Math.random()*7);
$('.foo:nth-of-type(' + m + ')').fadeIn(300);
}, 300);
I like Neal's answer although this is begging for some recursion. Here it is in java, you'll still get the general idea. Note that you'll hit an infinite loop if you pull out more numbers than MAX, I could have fixed that but left it as is for clarity.
edit: saw neal added a while loop so that works great.
public class RandCheck {
private List<Integer> numbers;
private Random rand;
private int MAX = 100;
public RandCheck(){
numbers = new ArrayList<Integer>();
rand = new Random();
}
public int getRandomNum(){
return getRandomNumRecursive(getRand());
}
private int getRandomNumRecursive(int num){
if(numbers.contains(num)){
return getRandomNumRecursive(getRand());
} else {
return num;
}
}
private int getRand(){
return rand.nextInt(MAX);
}
public static void main(String[] args){
RandCheck randCheck = new RandCheck();
for(int i = 0; i < 100; i++){
System.out.println(randCheck.getRandomNum());
}
}
}
Generally my approach is to make an array containing all of the possible values and to:
Pick a random number <= the size of the array
Remove the chosen element from the array
Repeat steps 1-2 until the array is empty
The resulting set of numbers will contain all of your indices without repetition.
Even better, maybe something like this:
var numArray = [0,1,2,3,4,5,6];
numArray.shuffle();
Then just go through the items because shuffle will have randomized them and pop them off one at a time.
Here's a simple fix, if a little rudimentary:
if(nextNum == lastNum){
if (nextNum == 0){nextNum = 7;}
else {nextNum = nextNum-1;}
}
If the next number is the same as the last simply minus 1 unless the number is 0 (zero) and set it to any other number within your set (I chose 7, the highest index).
I used this method within the cycle function because the only stipulation on selecting a number was that is musn't be the same as the last one.
Not the most elegant or technically gifted solution, but it works :)
Use sets. They were introduced to the specification in ES6. A set is a data structure that represents a collection of unique values, so it cannot include any duplicate values. I needed 6 random, non-repeatable numbers ranging from 1-49. I started with creating a longer set with around 30 digits (if the values repeat the set will have less elements), converted the set to array and then sliced it's first 6 elements. Easy peasy. Set.length is by default undefined and it's useless that's why it's easier to convert it to an array if you need specific length.
let randomSet = new Set();
for (let index = 0; index < 30; index++) {
randomSet.add(Math.floor(Math.random() * 49) + 1)
};
let randomSetToArray = Array.from(randomSet).slice(0,6);
console.log(randomSet);
console.log(randomSetToArray);
An easy way to generate a list of different numbers, no matter the size or number:
function randomNumber(max) {
return Math.floor(Math.random() * max + 1);
}
const list = []
while(list.length < 10 ){
let nbr = randomNumber(500)
if(!list.find(el => el === nbr)) list.push(nbr)
}
console.log("list",list)
I would like to add--
var RecordKeeper = {};
SRandom = function () {
currTimeStamp = new Date().getTime();
if (RecordKeeper.hasOwnProperty(currTimeStamp)) {
RecordKeeper[currTimeStamp] = RecordKeeper[currTimeStamp] + 1;
return currTimeStamp.toString() + RecordKeeper[currTimeStamp];
}
else {
RecordKeeper[currTimeStamp] = 1;
return currTimeStamp.toString() + RecordKeeper[currTimeStamp];
}
}
This uses timestamp (every millisecond) to always generate a unique number.
you can do this. Have a public array of keys that you have used and check against them with this function:
function in_array(needle, haystack)
{
for(var key in haystack)
{
if(needle === haystack[key])
{
return true;
}
}
return false;
}
(function from: javascript function inArray)
So what you can do is:
var done = [];
setInterval(function() {
var m = null;
while(m == null || in_array(m, done)){
m = Math.floor(Math.random()*7);
}
done.push(m);
$('.foo:nth-of-type('+m+')').fadeIn(300);
}, 300);
This code will get stuck after getting all seven numbers so you need to make sure it exists after it fins them all.
The question I'm doing is:
Write a JavaScript program to create a function which returns the number of times required to replace a given number with the sum of its digits until it converts to a single digit number. Like if given number is 123, number of times required to convert it into a single digit number is 1 (1+2+3=6). Your output code should be in the format console.log("Result is ", variableName)
I could not find the solution to this problem so I googled it and found this page.
The code on this page is in C/C++ ,Java etc...I took the C++ code and tried to convert it to javascript myself and this is the result:
var num=prompt("Enter a number");
var a= num.toString();
function test(x)
{var temporary_sum = 0, count = 0;
while (x.length() > 1)
{
temporary_sum = 0;
// computing sum of its digits
for (var i = 0; i < x.length(); i++)
temporary_sum += ( x[ i ] - '0' ) ;
// converting temporary_sum into string
// x again .
x = temporary_sum.toString() ;
// increase the count
count++;
}
return count;
}
var output = test(a) ;
console.log("Result is: ", output);
This code does not give any output at all. How can I fix this? Is there a better way to do this question?
Here is a better way to do that using recursion. And reduce
function test(x,count=0){
if(String(x).length === 1) return count;
let sum = String(x).split('').reduce((ac,a) => Number(a) + ac,0);
return test(sum,++count);
}
console.log(test(123)) //1
console.log(test(456)) //2
console.log(test(99999999999)) //3
I'll answer your last question - yes, there is a better way to do this question. You want to use recursion. You can also split the string on '' to convert its digits into an array, and you want to use parseInt to turn it back into a number.
I will use a different approach (I don't say it would be better). First, I will skip the mapping from number to string and wraps the logic that sums the digits of some number into a function called sumDigits(). This way you have a resusable method you can use for other purposes later. The second step is to define your test function using the previously created sumDigits mainly using the while loop you already have but testing with another condition and generalized to accept also integer negative numbers:
const sumDigits = (num) =>
{
let sum = 0;
while (num)
{
sum += num % 10, num = Math.floor(num / 10);
}
return sum;
}
const test = (num) =>
{
let counter = 0;
num = Math.abs(num);
while (num >= 10)
{
num = sumDigits(num), counter++;
}
return counter;
}
console.log(test(123));
console.log(test(456));
console.log(test(-789));
Question:
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
Suggested Solution:
function ListNode(val) {
this.val = val;
this.next = null;
}
// adding two Linked Lists.
var addTwoNumbers = function(l1, l2) {
const temp = new ListNode(0);
let resultPointer = temp;
var digit = 0;
var carryover = 0;
while(
l1!== null ||
l2 !== null
){
var sum = 0;
if(l1!== null){
sum += l1.val;
l1 = l1.next;
}
if(l2!== null){
sum += l2.val;
l2 = l2.next;
}
sum = sum + carryover;
carryover = sum >= 10 ? 1 : 0;
resultPointer.next = new ListNode(sum % 10);
resultPointer = resultPointer.next;
}
return temp.next;
};
Output: [7,0,8];
Why does the following change outputs an [] list.
let resultPointer = new ListNode(0);
return resultPointer.next();
Any Suggestions would be helpful.
When you declare
let resultPointer = new ListNode(0);
It creates a new linked list. It doesn't have any connection whatsoever with temp. Then after the execution of while loop, your resultPointer points to the last entry of that list and it doesn't have any linked list further to that pointer. So when you return resultPointer.next() - it's actually an empty list.
On the contrary - in your suggested solution, temp is actually the head of the linked list. For iteration - it uses the resultPointer.
So even after executing the while loop, temp is still the head of the linked list. So returning temp.next() is actually returning the list further to that head of the linked list.
Hope that helps.
NB: It's not an answer!
There's something wrong on your code; you should add another dimension, otherwise when you have carryover after adding last digit, it will give wrong result;
9 8
2 2
Result: 20
For, over coming this wrongness, you have to add the last carryOver at the list;
if((sum/10) !== 0){
resultPointer.next = new ListNode(sum / 10);
resultPointer = resultPointer.next;
}
this will add the last carryOver in the list;
I made a Javascript code that should take two numbers in an array, arrange them from lowest to highest, and then return the sum of every number between and including them. So sumAll(1, 4) // returns the sum of 1 + 2 + 3 + 4 which is 10. However, when I do it, my variable total does not change from 0 with my for loop.
var sumAll = function(arr) {
var lower = Math.min(arr[0], arr[1]);
var upper = Math.max(arr[0], arr[1]);
var total = 0;
for (var i = lower; i <= upper; i++) {
total += i;
}
return total;
}
This code should return 10 when using 1 and 4, but it gives 0 because var total = 0. When I manually change var total to equal 10, then it turns to ten, which means my for loop is not working the way it should, and I have no idea why. Any help is greatly appreciated, I am super new to coding and have been working on this for a while.
Also, this is a TDD project so it is attached to a spec js file. So the only other part of this code is not actually me calling the array but
module.exports = sumAll
The spec file asks for this:
var sumAll = require('./sumAll')
describe('sumAll', function() {
it('sums numbers within the range', function() {
expect(sumAll(1, 4)).toEqual(10);
});
The code in your question works well, however, if you still have issues you could try this:
function sumAll(n1, n2) {
var numbers = [];
numbers.length = Math.abs(n2-n1)+1; numbers.fill(0);
numbers = numbers.map((i, j) => (Math.min(n1,n2)+j))
return numbers.reduce((acc, i) => (acc+=i))
}
sumAll(1,4); //10
I ran into the challenge where I need a function that returns a random number within a given range from 0 - X. Not only that, but I require the number returned to be unique; not duplicating numbers that have already been returned on previous calls to the function.
Optionally, when this is done (e.g. the range has been 'exhausted'), just return a random number within the range.
How would one go about doing this?
This should do it:
function makeRandomRange(x) {
var used = new Array(x),
exhausted = false;
return function getRandom() {
var random = Math.floor(Math.random() * x);
if (exhausted) {
return random;
} else {
for (var i=0; i<x; i++) {
random = (random + 1) % x;
if (random in used)
continue;
used[random] = true;
return random;
}
// no free place found
exhausted = true;
used = null; // free memory
return random;
}
};
}
Usage:
var generate = makeRandomRange(20);
var x1 = generate(),
x2 = generate(),
...
Although it works, it has no good performance when the x-th random is generated - it searches the whole list for a free place. This algorithm, a step-by-step Fisher–Yates shuffle, from the question Unique (non-repeating) random numbers in O(1)?, will perform better:
function makeRandomRange(x) {
var range = new Array(x),
pointer = x;
return function getRandom() {
pointer = (pointer-1+x) % x;
var random = Math.floor(Math.random() * pointer);
var num = (random in range) ? range[random] : random;
range[random] = (pointer in range) ? range[pointer] : pointer;
return range[pointer] = num;
};
}
(Demo at jsfiddle.net)
Extended version which does only generate one "group" of unique numbers:
function makeRandomRange(x) {
var range = new Array(x),
pointer = x;
return function getRandom() {
if (range) {
pointer--;
var random = Math.floor(Math.random() * pointer);
var num = (random in range) ? range[random] : random;
range[random] = (pointer in range) ? range[pointer] : pointer;
range[pointer] = num;
if (pointer <= 0) { // first x numbers had been unique
range = null; // free memory;
}
return num;
} else {
return Math.floor(Math.random() * x);
}
};
}
(Demo)
You got some great programming answer. Here's one with a more theoretical flavor to complete your panorama :-)
Your problem is called "sampling" or "subset sampling" and there are several ways you could do this. Let N be the range you are sampling frame (i.e., N=X+1) and M be the size of your sample (the number of elements you want to pick).
if N is much larger than M, you'll want to use an algorithm such as the one suggested by Bentley and Floyd in his column "Programming Pearls: a sample of brilliance" (temporarily available without ACM's lock screen here), I really recommend this as they explicitly give code and discuss in terms of hash tables, etc.; there a few neat tricks in there
if N is within the same range as M, then you might want to use the Fisher-Yates shuffle but stop after only M steps (instead of N)
if you don't really know then the algorithm on page 647 of Devroye's book on random generation is pretty fast.
I wrote this function. It keeps its own array with a history of generated numbers, preventing initial duplicates, continuing to output a random number if all numbers in the range have been outputted once:
// Generates a unique number from a range
// keeps track of generated numbers in a history array
// if all numbers in the range have been returned once, keep outputting random numbers within the range
var UniqueRandom = { NumHistory: new Array(), generate: function(maxNum) {
var current = Math.round(Math.random()*(maxNum-1));
if (maxNum > 1 && this.NumHistory.length > 0) {
if (this.NumHistory.length != maxNum) {
while($.inArray(current, this.NumHistory) != -1) { current = Math.round(Math.random()*(maxNum-1)); }
this.NumHistory.push(current);
return current;
} else {
//unique numbers done, continue outputting random numbers, or we could reset the history array (NumHistory = [];)
return current;
}
} else {
//first time only
this.NumHistory.push(current);
return current;
}
}
};
Here's a working Fiddle
I hope this is of use to someone!
Edit: as pointed out by Pointy below, it might get slow with a large range (here is a
fiddle, going over a range from 0-1000, which seems to run fine). However; I didn't require a very large range, so perhaps this function is indeed not suited if you look to generate and keep track of an enormous range.
You may try generating the number using the current date and time value which would make it unique. To make it within the range, you may have to use some mathematical function.