Smallest Common Multiple [Javascript Challenge] - javascript

Question: Find the smallest common multiple of the provided parameters that can be evenly divided by both, as well as by all sequential numbers in the range between these parameters.
The range will be an array of two numbers that will not necessarily be in numerical order.
For example, if given 1 and 3, find the smallest common multiple of both 1 and 3 that is also evenly divisible by all numbers between 1 and 3, i.e. divisible by 1, 2 and 3. The answer here would be 6.
function smallestCommons(arr) {
var max=Math.max(...arr);
var min=Math.min(...arr);
var flag = 0;
var i = min;
while(true)
{for(var j=min;j<=max;j++)
{if(i%j!=0)
{flag=1;
break;}
}
if(flag==0)
{flag=5;
break;
}
i++;
}
console.log(i);
}
smallestCommons([1,5]);
For somereason my solution seems to go crazy and go into infinite looping. Although if I initialize var i to 60 (which is the desired output for this specific case i.e.[1,5]) the solution seems to be fine. Any fixes or guesses?

#Kevin has given a pretty good explanation of why it's not working. Your loop will only stop if flag is 0. But once it has been set to 1, you never reset it to 0.
function smallestCommons(arr) {
var max = Math.max(...arr);
var min = Math.min(...arr);
var flag = 0;
var i = min;
while (true) {
for (var j = min; j <= max; j++) {
if (i % j != 0) {
flag = 1;
break;
}
}
if (flag == 0) {
return i; // Return that common value
}
flag = 0; // Reset the flag
i++;
}
}
console.log(smallestCommons([1, 5]));
And here is an alternative way:
function smallestCommons(arr) {
const min = Math.min(...arr),
max = Math.max(...arr),
range = createRange(min, max);
let current = max;
while (true) {
const isFullyDivisible = range.every(n => current % n === 0);
if (isFullyDivisible) {
return current;
}
current++;
}
}
function createRange(min, max) {
return new Array(max - min + 1).fill(null).map((_, i) => min + i);
}
console.log(smallestCommons([1, 3])); // 6
console.log(smallestCommons([5, 1])); // 60
console.log(smallestCommons([1, 10])); // 2520

I did figure out the solution, thanks to the two programming geeks in the main comments sections.
function smallestCommons(arr) {
var max=Math.max(...arr);
var min=Math.min(...arr);
var flag = 0;
var count = 0;
var i = 1;
while(1){
for(var j=min;j<=max;j++)
{if(i%j!=0)
{flag=1;
break;}
if(j==max){
flag=0;
}
}
if(flag==0){
break;
}
i++;
}
console.log(i);
}
smallestCommons([10,2]);

Related

How to limit a number between several numbers (get the most nearest small number)? [duplicate]

Example: I have an array like this: [0,22,56,74,89] and I want to find the closest number downward to a different number. Let's say that the number is 72, and in this case, the closest number down in the array is 56, so we return that. If the number is 100, then it's bigger than the biggest number in the array, so we return the biggest number. If the number is 22, then it's an exact match, just return that. The given number can never go under 0, and the array is always sorted.
I did see this question but it returns the closest number to whichever is closer either upward or downward. I must have the closest one downward returned, no matter what.
How do I start? What logic should I use?
Preferably without too much looping, since my code is run every second, and it's CPU intensive enough already.
You can use a binary search for that value. Adapted from this answer:
function index(arr, compare) { // binary search, with custom compare function
var l = 0,
r = arr.length - 1;
while (l <= r) {
var m = l + ((r - l) >> 1);
var comp = compare(arr[m]);
if (comp < 0) // arr[m] comes before the element
l = m + 1;
else if (comp > 0) // arr[m] comes after the element
r = m - 1;
else // arr[m] equals the element
return m;
}
return l-1; // return the index of the next left item
// usually you would just return -1 in case nothing is found
}
var arr = [0,22,56,74,89];
var i=index(arr, function(x){return x-72;}); // compare against 72
console.log(arr[i]);
Btw: Here is a quick performance test (adapting the one from #Simon) which clearly shows the advantages of binary search.
var theArray = [0,22,56,74,89];
var goal = 56;
var closest = null;
$.each(theArray, function(){
if (this <= goal && (closest == null || (goal - this) < (goal - closest))) {
closest = this;
}
});
alert(closest);
jsFiddle http://jsfiddle.net/UCUJY/1/
Array.prototype.getClosestDown = function(find) {
function getMedian(low, high) {
return (low + ((high - low) >> 1));
}
var low = 0, high = this.length - 1, i;
while (low <= high) {
i = getMedian(low,high);
if (this[i] == find) {
return this[i];
}
if (this[i] > find) {
high = i - 1;
}
else {
low = i + 1;
}
}
return this[Math.max(0, low-1)];
}
alert([0,22,56,74,89].getClosestDown(75));
Here's a solution without jQuery for more effiency. Works if the array is always sorted, which can easily be covered anyway:
var test = 72,
arr = [0,56,22,89,74].sort(); // just sort it generally if not sure about input, not really time consuming
function getClosestDown(test, arr) {
var num = result = 0;
for(var i = 0; i < arr.length; i++) {
num = arr[i];
if(num <= test) { result = num; }
}
return result;
}
Logic: Start from the smallest number and just set result as long as the current number is smaller than or equal the testing unit.
Note: Just made a little performance test out of curiosity :). Trimmed my code down to the essential part without declaring a function.
Here's an ES6 version using reduce, which OP references. Inspired by this answer get closest number out of array
lookup array is always sorted so this works.
const nearestBelow = (input, lookup) => lookup.reduce((prev, curr) => input >= curr ? curr : prev);
const counts = [0,22,56,74,89];
const goal = 72;
nearestBelow(goal, counts); // result is 56.
Not as fast as binary search (by a long way) but better than both loop and jQuery grep https://jsperf.com/test-a-closest-number-function/7
As we know the array is sorted, I'd push everything that asserts as less than our given value into a temporary array then return a pop of that.
var getClosest = function (num, array) {
var temp = [],
count = 0,
length = a.length;
for (count; count < length; count += 1) {
if (a[count] <= num) {
temp.push(a[count]);
} else {
break;
}
}
return temp.pop();
}
getClosest(23, [0,22,56,74,89]);
Here is edited from #Simon.
it compare closest number before and after it.
var test = 24,
arr = [76,56,22,89,74].sort(); // just sort it generally if not sure about input, not really time consuming
function getClosest(test, arr) {
var num = result = 0;
var flag = 0;
for(var i = 0; i < arr.length; i++) {
num = arr[i];
if(num < test) {
result = num;
flag = 1;
}else if (num == test) {
result = num;
break;
}else if (flag == 1) {
if ((num - test) < (Math.abs(arr[i-1] - test))){
result = num;
}
break;
}else{
break;
}
}
return result;
}

How Can I find the first number greater than const M?

I have a problem with this. I have to find the first prime number greater than my const M.
For example, I have M = 11, and I have to find the first prime number greater than M and it is 13.
How Can I do that?
// isPrime
const M = 11
function isPrime(num) {
if (num < 2) return false;
for (let i = 2; i < num; i++) {
if (num % i == 0) return false;
}
return true;
}
console.log(isPrime(M))
And I would like find for M = 11, primeNumber = 13, for M = 15, primeNumber = 17 etc.
You can iterate from M+1 until you find your prime number. You can do the following,
function isPrime(num) {
if (num < 2) return false;
for (let i = 2; i < num; i++) {
if (num % i == 0) return false;
}
return true;
}
findGreaterPrime = (m) => {
let i = m+1;
let found = false;
while(!found) {
if(isPrime(i)) {
found = true;
return i;
}
i++;
}
}
console.log(findGreaterPrime(11));
console.log(findGreaterPrime(13));
By the way, this method will be very slow for larger numbers. You can use some fast prime generators. You can follow the answers in this thread.
Simple and fast solution, via prime-lib (I'm the author).
The example below generates 2 primes, starting with 7 and upward:
import {generatePrimes, stopOnCount} from 'prime-lib';
const i = generatePrimes({start: 7}); // infinite prime-iterator
const s = stopOnCount(i, 2); // stop-iterator
const values = [...s]; // 7, 11
It checks if start is a prime, to be included then. If you need only a prime that follows, just check if the first number matches your M number, then take the next one instead:
if(values[0] === M) {
// use values[1]
} else {
// use values[0]
}

I need to create an infinite loop

For my purpose I need to create loop where one variable is looping in this way:
0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1...
It's look simple but more than hour I wonder how to do it.
My purpose is moving the star in this way
*....
.*...
..*..
...*.
....*
...*.
..*..
.*...
*....
*....
.*...
..*..
...*.
....*
Write that loop as a generator (function *... yield) and then consume it when you need it (for...of). Of course, the consuming code must provide some termination condition.
function* bounce(min, max) {
while (1) {
for (let i = min; i < max; i++)
yield i;
for (let i = max; i > min; i--)
yield i;
}
}
STEPS = 10
for(let x of bounce(0, 4)) {
console.log(x)
if (--STEPS === 0) break;
}
You can use the following code to generate the number pattern that you require. However, you wont be able to run it infinitely since it will crash the browser.
If you want to test, I have added instructions for making the loop infinite.
For you requirement, a larger value for rep variable will be enough.
let min = 0; // Start/min value
let max = 4; // Max value
let dir = 1; // Count direction (+1/-1)
let counter = min; // Your counter variable
let rep = 24; // Remove this line and change condition inside while to true for infinite loop
do {
console.log(counter);
dir = counter===max?-1:counter===min?1:dir;
counter+=dir;
} while (rep-->0); // Change this expression to true for infinite loop
You can use setTimeout or setInterval for doing that:
let number = 0;
let increment = 1;
const from = 0;
const to = 4;
const starDiv = document.getElementById("star");
function printStar(number) {
const text = [0, 1, 2, 3, 4].map(
i => (i === number) ? '*' : '-'
).join('');
starDiv.innerText = text;
}
function loop() {
printStar(number);
number += increment;
if (number == to) {
increment = -1;
} else if (number == from) {
increment = 1;
}
}
const time = 10; // 10 millisecond between step
setInterval(loop, time);
<div id="star">
</div>
You could have a simple counter and then use modulo 8 to get iterations.
let x = (i += direction) % 8;
let y = x > 4 ? 8 - x : x;
This example even prints the ascii art ;)
let i = -1;
let direction = +1;
const out = [
"*....",
".*...",
"..*..",
"...*.",
"....*",
"...*.",
"..*..",
".*...",
"*....",
];
setInterval(function() {
let x = (i += direction) % 8;
let y = x > 4 ? 8 - x : x;
window.document.write(y + " " + out[x] + "<br>");
}, 1000);
(function(min,max,max_loops)
{
for(var loop = 1; loop <= max_loops; loop++, [min,max] = [-max,-min])
{
for(num = min; num < max + (loop == max_loops); num++)
{
console.log(".".repeat(Math.abs(num)) + "*" + ".".repeat(Math.max(Math.abs(max),Math.abs(min)) - Math.abs(num)))
}
}
})(0,4,3)
But since you need an infinite loop, using generator should be more suitable.

Rolling a die 60,000 times using if-else-if

I'm new to javascript and am facing trouble with the following problem.
Simulate rolling a die 60,000 times and display the frequency with which each face of the die finishes uppermost.
Use 6 variables to capture the frequencies and a 6-way if-else-if control structure need in the loop to increment them appropriately.
I know that I have to create an empty array which includes 6 variables and I have started the first iteration with 1.
What I don't understand is how to use the if-else-if statement to work through the 60000 iterations.
var array = [0, 0, 0, 0, 0, 0];
var i = 1;
You could introduce another variable for a random value between equal or greater than 0 and smaller than 6 and use it as index for the counting array.
Then you need a for loop, for counting the distribution of 60000 random values.
var array = [0, 0, 0, 0, 0, 0],
i,
r;
for (i = 0; i < 60000; i++) { // iterate 60000 times
r = Math.floor(Math.random() * 6); // generate random value
array[r]++; // increment counter
}
console.log(array);
for, Math.random:
var freqs = [0, 0, 0, 0, 0, 0];
var freqsLength = freqs.length; //* save array length into variable for more productivity
var rolls = 6000; //* how many time we want to roll dice
for(var i = 0; i < rolls; i++) { //* start rolling in loop
var j = Math.floor(Math.random() * freqsLength); //* get ramdom value
freqs[j]++; //* save freq result
}
alert(freqs);
Here's a working example with if-else:
var array = [0, 0, 0, 0, 0, 0];
var randomNumber;
for (var i = 0; i < 60000; i++) {
randomNumber = Math.floor(Math.random() * 6) + 1;
if(randomNumber === 1){
array[0]++;
}
else if(randomNumber === 2){
array[1]++;
}
else if(randomNumber === 3){
array[2]++;
}
else if(randomNumber === 4){
array[3]++;
}
else if(randomNumber === 5){
array[4]++;
}
else if(randomNumber === 6){
array[5]++;
}
}
console.log(array);
This question seems to be a homework, since you have to use if..else.
However, you don't need to use a if...else for this:
var arr = [0,0,0,0,0,0];
for(var i = 0; i < 60000; i++){
arr[~~(Math.random()*6)]++;
};
console.log(arr)
Explanation
The code has an for loop, which starts at 0 and ends at 60,000:
for(var i = 0; i < 60000; i++){
//...
};
For each iteration, a random value from 0 to 6 is generated...
Math.random()*6
... and converted to an integer using ~~.
Then, the element in the array at that random position is incremented:
arr[~~(Math.random()*6)]++;
Homework
Since this is in fact a homework and your requirements are:
Six variables
A six-way if..else
You can use this ugly, cumbersome and awkward code:
var one = two = three = four = five = six = 0;
for (var i = 0; i < 60000; i++) {
var random = ~~(Math.random() * 6) + 1;
if (random === 1) {
one++
} else if (random === 2) {
two++
} else if (random === 3) {
three++
} else if (random === 4) {
four++
} else if (random === 5) {
five++
} else if (random === 6) {
six++
}
};
var arr = [one, two, three, four, five, six];
console.log(arr)
Here's how I'd do it:
function randBetween(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
let counters = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0};
for (let i = 0; i < 60000; i++) {
counters[randBetween(1, 6)]++;
}
console.log(counters);
And here's what I'm guessing your teacher wants:
function randBetween(min, max) {
return Math.floor(Math.random() * max) + min;
}
let one = 0;
let two = 0;
let three = 0;
let four = 0;
let five = 0;
let six = 0;
for (let i = 0; i < 60000; i++) {
const n = randBetween(1, 6);
if (n === 1) { one++; }
else if (n === 2) { two++; }
else if (n === 3) { three++; }
else if (n === 4) { four++; }
else if (n === 5) { five++; }
else { six++; }
}
console.log(one, two, three, four, five, six);
You can decide for yourself which you think is the superior solution (Hint: How would you change each example to reflect rolling of a 100 sided die?)

Find the largest prime factor with Javascript

Thanks for reading. Pretty new to Javascript and programming in general.
I'm looking for a way to return the largest prime factor of a given number. My first instinct was to work with a while loop that counts up and finds prime factors of the number, storing the factors in an array and resetting each time it finds one. This way the last item in the array should be the largest prime factor.
var primerizer = function(input){
var factors = [];
var numStorage = input
for (x=2; numStorage != 1; x++){ // counter stops when the divisor is equal to the last number in the
// array, meaning the input has been fully factorized
if (result === 0) { // check if the number is prime; if it is not prime
factors.push(x); // add the divisor to the array of prime numbers
numStorage = numStorage/x // divide the number being calculated by the divisor
x=2 // reset the divisor to 2 and continue
};
};
primeFactor = factors.pop();
return primeFactor;
}
document.write(primerizer(50))
This only returned 2, undefined, or nothing. My concern was that the stop condition for the for loop must be defined in terms of the same variable as the start condition, so I tried it with a while loop instead.
var primerizer = function(input){
var factors = [];
var numStorage = input
x=2
while (numStorage != 1){
var result = numStorage%x;
if (result === 0) {
factors.push(x);
numStorage = numStorage/x
x=2
}
else {
x = x+1
}
}
return factors.pop();
}
document.write(primerizer(50)
Same problem. Maybe there's a problem with my syntax that I'm overlooking? Any input is much appreciated.
Thank you.
The shortest answer I've found is this:
function largestPrimeFactor(n){
var i=2;
while (i<=n){
if (n%i == 0){
n/=i;
}else{
i++;
}
}
console.log(i);
}
var a = **TYPE YOUR NUMBER HERE**;
largestPrimeFactor(a)
You can try with this
var x = 1, div = 0, primes = [];
while(primes.length != 10001) {
x++;
for(var i = 2; i < x && !div; i++) if(!(x % i)) div++;
if(!div) primes.push(x); else div = 0;
}
console.log(primes[primes.length-1]);
or this: (This solution uses more of your memory)
var dont = [], max = 2000000, primes = [];
for (var i = 2; i <= max; i++) {
if (!dont[i]) {
primes.push(i);
for (var j = i; j <= max; j += i) dont[j] = true;
}
}
console.log(primes);
here is my own solution.
//function
function largestPrimeFactor (num) {
//initialize the variable that will represent the divider
let i = 2;
//initialize the variable that will represent the quotient
let numQuot = num;
//array that will keep all the dividers
let primeFactors = [];
//execute until the quotient is equal to 1
while(numQuot != 1) {
/*check if the division between the number and the divider has no reminder, if yes then do the division keeping the quotient in numQuot, the divider in primeFactors and proceed to restart the divider to 2, if not then increment i by one an check again the condition.*/
if(numQuot % i == 0){
numQuot /= i;
primeFactors.push(i);
i = 2;
} else {
i++;
}
}
/*initialize the variable that will represent the biggest prime factor. biggest is equal to the last position of the array, that is the biggest prime factor (we have to subtract 1 of .length in order to obtain the index of the last item)*/
let biggest = primeFactors[primeFactors.length - 1];
//write the resutl
console.log(biggest);
}
//calling the function
largestPrimeFactor(100);
<script>
function LPrimeFactor() {
var x = function (input) {
var factors = [];
var numStorage = input;
x = 2;
while (numStorage != 1) {
var result = numStorage % x;
if (result === 0) {
factors.push(x);
numStorage = numStorage / x;
x = 2;
}
else {
x = x + 1;
}
}
return factors.pop();
}
document.write(x(50));
}
</script>
<input type="button" onclick="LPrimeFactor();" />
Here is an example i tried with your code
Here is the solution I used that should work in theory... except for one small problem. At a certain size number (which you can change in the code) it crashes the browser due to making it too busy.
https://github.com/gordondavidescu/project-euler/blob/master/problem%203%20(Javascript)
Adding the code inline:
<p id="demo">
</p>
<script>
function isPrime(value) {
for(var i = 2; i < value; i++) {
if(value % i === 0) {
return false;
}
}
return value > 1;
}
function biggestPrime(){
var biggest = 1;
for(var i = 600851470000; i < 600851475143; i++){
if (isPrime(i) != false)
{
biggest = i;
}
document.getElementById("demo").innerHTML = biggest;
}
}
biggestPrime();
</script>
</p>
<script>
//Finds largest prime factor
find = 2165415 ; // Number to test!
var prime = 0;
loop1:
for (i = 2; i < find; i++){
prime = 0;
if (find%i == 0){
document.write(find/i);
for (j = 2; j < (find / i); j++){
if ((find / i )%j == 0){
document.write(" divides by "+j+"<br>");
prime = prime + 1;
break;
}
}
if (prime == 0){
document.write("<br>",find/i, "- Largest Prime Factor")
prime = 1;
break;
}
}
}
if (prime==0)
document.write("No prime factors ",find," is prime!")

Categories

Resources