I'm trying to calculate the quantity of the ingredients by the serve count. But, the counter i have implemented is not supporting fraction values such as 3/4 teaspoon, 2 1/2 teaspoon. Here is the sample code:
var gcd = function(a, b) {
if (b < 0.0000001) return a;
return gcd(b, Math.floor(a % b));
};
const decimalToFraction = ( ) => {
var fraction = result;
var len = fraction.toString().length - 2;
var denominator = Math.pow(10, len);
var numerator = fraction * denominator;
var divisor = gcd(numerator, denominator);
numerator /= divisor;
denominator /= divisor;
console.log(Math.floor(numerator) + '/' + Math.floor(denominator));
}
const stringToDecimal = (parseQuantity) => {
let split = parseQuantity.split('/');
let result = parseInt(split[0], 10) / parseInt(split[1], 10);
return result;
}
const serveQuantity = (count) =>{
let listOfIngredients=[];
if(count<1 && serve >= 1){
setServe(serve => serve-1);
listOfIngredients =ingredients.map((item,index)=>{
if(quantity[index] < 1){
item.quantity._text = item.quantity._text - parseInt(quantity[index]);
}else{
item.quantity._text = parseInt(item.quantity._text) - parseInt(quantity[index]);
}
return item;
})
}
if(count===1 && serve >= 1){
setServe(serve => serve+1);
listOfIngredients = ingredients.map((item, index)=>{
if(quantity[index] < 1){
item.quantity._text = item.quantity._text + parseInt(quantity[index]);
}else{
item.quantity._text = parseInt(item.quantity._text) + parseInt(quantity[index]);
}
return item;
})
}
setIngredients(listOfIngredients);
}
when the user clicks on the serve +/- button, i'm calling serveQuantity(2) function.
Related
I am trying to solve the Fibonacci algorithm using matrices. My target time complexity is an o(logn) instead of an o(n). The return output of the program is not the number for the series but the sixth significant digits. Its why I am returning the remainder of the solution divided by a million.
I have written the code and it runs well but I noticed that for extremely large inputs, I get a NAN(not a number) instead of an output
const fib = (n) => {
let fibMatrix = [[1,1], [1,0]]
if(n == 0){
return 0;
}
raiseToPower(fibMatrix, n - 1);
return Math.floor(fibMatrix[0][0] % 1000000)
}
const raiseToPower = (matrix, n) => {
if(n == 0 || n == 1){
return;
}
let newMatrix = [[1,1], [1,0]]
raiseToPower(matrix, Math.floor(n / 2))
multiplyMatrices(matrix, matrix)
if(n % 2 !== 0){
multiplyMatrices(matrix, newMatrix)
}
}
const multiplyMatrices = (matrix, newMatrix) => {
let x = matrix[0][0]*newMatrix[0][0] + matrix[0][1]*newMatrix[1][0];
let y = matrix[0][0]*newMatrix[0][1] + matrix[0][1]*newMatrix[1][1];
let z = matrix[1][0]*newMatrix[0][0] + matrix[1][1]*newMatrix[1][0];
let w = matrix[1][0]*newMatrix[0][1] + matrix[1][1]*newMatrix[1][1];
matrix[0][0] = x;
matrix[0][1] = y;
matrix[1][0] = z;
matrix[1][1] = w;
}
console.log(fib(2000))
Thats my code above. Is there anything I could change to actually make this much more performant?
I actually found the error. My numbers were getting larger than the maximum value.
I changed this by instead returning the remainder of my value divided by a million to the matrix and then returning the value from the matrix instead of returning the value and then dividing by a million. The former is efficient and works for any sized inputs.
const fib = (n) => {
let fibMatrix = [[1,1], [1,0]]
if(n == 0){
return 0;
}
raiseToPower(fibMatrix, n - 1);
return (fibMatrix[0][0])
}
const raiseToPower = (matrix, n) => {
if(n == 0 || n == 1){
return;
}
let newMatrix = [[1,1], [1,0]]
raiseToPower(matrix, Math.floor(n / 2))
multiplyMatrices(matrix, matrix)
if(n % 2 !== 0){
multiplyMatrices(matrix, newMatrix)
}
}
const multiplyMatrices = (matrix, newMatrix) => {
let x = (matrix[0][0]*newMatrix[0][0] + matrix[0][1]*newMatrix[1][0]);
let y = (matrix[0][0]*newMatrix[0][1] + matrix[0][1]*newMatrix[1][1]);
let z = (matrix[1][0]*newMatrix[0][0] + matrix[1][1]*newMatrix[1][0]);
let w = (matrix[1][0]*newMatrix[0][1] + matrix[1][1]*newMatrix[1][1]);
matrix[0][0] = x % 1000000;
matrix[0][1] = y % 1000000;
matrix[1][0] = z % 1000000;
matrix[1][1] = w % 1000000;
}
console.log(fib(10000))
I'm generating a number based on a fixed character set.
function generator()
{
var text = "";
var char_list = "LEDGJR", number_list = "0123456789";
for(var i=0; i < 2; i++ )
{
text += char_list.charAt(Math.floor(Math.random() * char_list.length));
}
for(var j=0; j < 2; j++ )
{
text += number_list.charAt(Math.floor(Math.random() *
number_list.length));
}
return text;
}
Result :
RE39, JE12 etc...
Once all the permutation related to the above sequence is done, then the generator should generate string as RE391, JE125 means adding one more number to the complete number.
How can I get the permutation count of sequence?
For simplicity consider the case where:
chars = "AB"
nums = "123";
and we want to generate a 4-digit sequence of two chars and two numbers.
We define these variables
rows = [chars, chars, nums, nums]
rowSizes = rows.map(row => row.length) // [2, 2, 3, 3]
It’s easy to see the set size of all possible permuations equals:
spaceSize = rowSizes.reduce((m, n) => m * n, 1) // 2*2*3*3 = 36
And we define two set of utility functions, usage of which I'll explain in detail later.
decodeIndex() which gives us uniqueness
function euclideanDivision(a, b) {
const remainder = a % b;
const quotient = (a - remainder) / b;
return [quotient, remainder]
}
function decodeIndex(index, rowSizes) {
const rowIndexes = []
let dividend = index
for (let i = 0; i < rowSizes.length; i++) {
const [quotient, remainder] = euclideanDivision(dividend, rowSizes[i])
rowIndexes[i] = remainder
dividend = quotient
}
return rowIndexes
}
getNextIndex() which gives us pseudo-randomness
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (let i = 5; i * i <= n; i = i + 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
function findNextPrime(n) {
if (n <= 1) return 2;
let prime = n;
while (true) {
prime++;
if (isPrime(prime)) return prime;
}
}
function getIndexGeneratorParams(spaceSize) {
const N = spaceSize;
const Q = findNextPrime(Math.floor(2 * N / (1 + Math.sqrt(5))))
const firstIndex = Math.floor(Math.random() * spaceSize);
return [firstIndex, N, Q]
}
function getNextIndex(prevIndex, N, Q) {
return (prevIndex + Q) % N
}
Uniqueness
Like mentioned above, spaceSize is the number of all possible permutations, thus each index in range(0, spaceSize) uniquely maps to one permutation. decodeIndex helps with this mapping, you can get the corresponding permutation to an index by:
function getSequenceAtIndex(index) {
const tuple = decodeIndex(index, rowSizes)
return rows.map((row, i) => row[tuple[i]]).join('')
}
Pseudo-Randomness
(Credit to this question. I just port that code into JS.)
We get pseudo-randomness by polling a "full cycle iterator"†. The idea is simple:
have the indexes 0..35 layout in a circle, denote upperbound as N=36
decide a step size, denoted as Q (Q=23 in this case) given by this formula‡
Q = findNextPrime(Math.floor(2 * N / (1 + Math.sqrt(5))))
randomly decide a starting point, e.g. number 5
start generating seemingly random nextIndex from prevIndex, by
nextIndex = (prevIndex + Q) % N
So if we put 5 in we get (5 + 23) % 36 == 28. Put 28 in we get (28 + 23) % 36 == 15.
This process will go through every number in circle (jump back and forth among points on the circle), it will pick each number only once, without repeating. When we get back to our starting point 5, we know we've reach the end.
†: I'm not sure about this term, just quoting from this answer
‡: This formula only gives a nice step size that will make things look more "random", the only requirement for Q is it must be coprime to N
Full Solution
Now let's put all the pieces together. Run the snippet to see result.
I've also includes the a counter before each log. For your case with char_list="LEDGJR", number_list="0123456789", the spaceSize for 4-digit sequence should be 6*6*10*10 = 3600
You'll observe the log bump to 5-digit sequence at 3601 😉
function euclideanDivision(a, b) {
const remainder = a % b;
const quotient = (a - remainder) / b;
return [quotient, remainder];
}
function decodeIndex(index, rowSizes) {
const rowIndexes = [];
let divident = index;
for (let i = 0; i < rowSizes.length; i++) {
const [quotient, remainder] = euclideanDivision(divident, rowSizes[i]);
rowIndexes[i] = remainder;
divident = quotient;
}
return rowIndexes;
}
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (let i = 5; i * i <= n; i = i + 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
function findNextPrime(n) {
if (n <= 1) return 2;
let prime = n;
while (true) {
prime++;
if (isPrime(prime)) return prime;
}
}
function getIndexGeneratorParams(spaceSize) {
const N = spaceSize;
const Q = findNextPrime(Math.floor((2 * N) / (1 + Math.sqrt(5))));
const firstIndex = Math.floor(Math.random() * spaceSize);
return [firstIndex, N, Q];
}
function getNextIndex(prevIndex, N, Q) {
return (prevIndex + Q) % N;
}
function generatorFactory(rows) {
const rowSizes = rows.map((row) => row.length);
function getSequenceAtIndex(index) {
const tuple = decodeIndex(index, rowSizes);
return rows.map((row, i) => row[tuple[i]]).join("");
}
const spaceSize = rowSizes.reduce((m, n) => m * n, 1);
const [firstIndex, N, Q] = getIndexGeneratorParams(spaceSize);
let currentIndex = firstIndex;
let exhausted = false;
function generator() {
if (exhausted) return null;
const sequence = getSequenceAtIndex(currentIndex);
currentIndex = getNextIndex(currentIndex, N, Q);
if (currentIndex === firstIndex) exhausted = true;
return sequence;
}
return generator;
}
function getRows(chars, nums, rowsOfChars, rowsOfNums) {
const rows = [];
while (rowsOfChars--) {
rows.push(chars);
}
while (rowsOfNums--) {
rows.push(nums);
}
return rows;
}
function autoRenewGeneratorFactory(chars, nums, initRowsOfChars, initRowsOfNums) {
let realGenerator;
let currentRowOfNums = initRowsOfNums;
function createRealGenerator() {
const rows = getRows(chars, nums, initRowsOfChars, currentRowOfNums);
const generator = generatorFactory(rows);
currentRowOfNums++;
return generator;
}
realGenerator = createRealGenerator();
function proxyGenerator() {
const sequence = realGenerator();
if (sequence === null) {
realGenerator = createRealGenerator();
return realGenerator();
} else {
return sequence;
}
}
return proxyGenerator;
}
function main() {
const char_list = "LEDGJR"
const number_list = "0123456789";
const generator = autoRenewGeneratorFactory(char_list, number_list, 2, 2);
let couter = 0
setInterval(() => {
console.log(++couter, generator())
}, 10);
}
main();
How to solve this giving undesired result, getting false always.
function isPelindrom(n) {
if (n < 0) return false;
let orgNum = n
let reversed = 0
for (let x = 0; x <= orgNum; x++) {
let lastDigit = orgNum % 10;
reversed = (reversed * 10) + lastDigit;
orgNum = parseInt(orgNum / 10);
}
return n == reversed
}
isPelindrom(12321)
function Palindrome(num) {
let numToStringArray = num.toString();
const reversed = numToStringArray.toString().split('').reverse().join('');
return numToStringArray === reversed ? "It's a palindrome" : "It's not a palindrome";
}
console.log(Palindrome(989));
console.log(Palindrome(23));
console.log(Palindrome(9));
function Palindrome(number) {
var temp = number, final = 0;
while (number > 0) {
rem = number % 10;
number = parseInt(number / 10);
final = final * 10 + rem;
}
if (temp == final) {
return "It's Palindrome";
}
else {
return "It's not Palindrome";
}
}
console.log(Palindrome(989));
console.log(Palindrome(23));
console.log(Palindrome(9));
You can change it to a for loop and either set it to greater or equal to 0.1 or just greater than 0.
function isPelindrom(n) {
if (n < 0) return false;
let orgNum = n
let reversed = 0
while(orgNum>=0.1) {
let lastDigit = orgNum % 10;
reversed = (reversed * 10) + lastDigit;
orgNum = parseInt(orgNum / 10);
}
return n == reversed
}
console.log(isPelindrom(12321))
console.log(isPelindrom(12322))
Does while loop count?
const isPalindrome = num => {
const origin = num
let reversed = 0
while (num !== 0) {
const digit = num % 10
reversed = reversed * 10 + digit
num = Math.floor(num / 10)
}
return origin === reversed
}
console.log(isPalindrome(12321))
console.log(isPalindrome(12331))
You can try this:
function isPelindrom(n) {
if (n < 0) return false;
let orgNum = n
let reversed = 0
var numberOfDigits = 0;
for(i = orgNum; i > 1; ++i){
++numberOfDigits;
i = Math.floor(i/10);
}
for (let x = 0; x < numberOfDigits; x++) {
let lastDigit = orgNum % 10;
reversed = (reversed * 10) + lastDigit;
orgNum = parseInt(orgNum / 10);
}
return n == reversed
}
can anyone come with an idea of how to sort an integer without using an array, and without using string methods as well as sort() method?
for example
input: 642531
output: 123456
I started by writing 2 simple functions - one which checks the length of the number, the other one splits the integer at some point and switches between 2 desired numbers. Below are the 2 functions.
I got stuck with the rest of the solution...
function switchDigits(num, i) { // for input: num=642531, i = 4 returns 624135
let temp = num;
let rest = 0;
for (let j = 0; j < i - 1; j++) {
rest = rest * 10;
rest = rest + temp % 10;
temp = (temp - temp % 10) / 10;
}
let a = temp % 10;
temp = (temp - a) / 10;
let b = temp % 10;
temp = (temp - b) / 10;
temp = Math.pow(10, i - 2) * temp;
temp = temp + 10 * a + b;
temp = Math.pow(10, i - 1) * temp;
temp = temp + rest;
return temp;
}
function checkHowManyDigits(num) { //input: 642534, output: 6 (length of the integer)
let count = 0;
while (num > 0) {
let a = num % 10;
num = (num - a) / 10;
count++;
}
return count;
}
let num = 642534;
let i = checkHowManyDigits(num);
console.log(switchDigits(num));
It actually complicated requirement and so does this answer. It's pure logic and as it is it's a question from a test you should try understanding the logic on your own as a homework.
function checkHowManyDigits(num) { //input: 642534, output: 6 (length of the integer)
let count = 0;
while (num > 0) {
let a = num % 10;
num = (num - a) / 10;
count++;
}
return count;
}
function sortDigit(numOriginal) {
let i = checkHowManyDigits(numOriginal);
let minCount = 0;
let min = 10;
let num = numOriginal;
while (num > 0) {
let d = num % 10;
num = (num - d) / 10;
if (d < min) {
min = d;
minCount = 0;
} else if (d === min) {
minCount++;
}
}
let result = 0;
while (minCount >= 0) {
result += min * Math.pow(10, i - minCount - 1);
minCount--;
}
let newNum = 0;
num = numOriginal;
while (num > 0) {
let d = num % 10;
num = (num - d) / 10;
if (d !== min) {
newNum = newNum * 10 + d;
}
}
if (newNum == 0) return result;
else return result += sortDigit(newNum);
}
console.log(sortDigit(642531));
You could have a look to greater and smaller pairs, like
64
46
The delta is 18, which gets an idea if you compare other pairs, like
71
17
where the delta is 54. Basically any difference of two digits is a multiple of 9.
This in mind, you get a function for taking a single digit out of a number and a single loop who is sorting the digits by using the calculated delta and subtract the value, adjusted by the place.
function sort(number) {
const
getDigit = e => Math.floor(number / 10 ** e) % 10,
l = Math.ceil(Math.log10(number)) - 1;
let e = l;
while (e--) {
const
left = getDigit(e + 1),
right = getDigit(e);
if (left <= right) continue;
number += (right - left) * 9 * 10 ** e;
e = l;
}
return number;
}
console.log(sort(17)); // 17
console.log(sort(71)); // 17
console.log(sort(642531)); // 123456
console.log(sort(987123654)); // 123456789
So eventually I found the best solution.
*This solution is based on a Java solution I found in StackOverFlow forums.
let store = 0;
function getReducedNumbr(number, digit) {
console.log("Remove " + digit + " from " + number);
let newNumber = 0;
let repeateFlag = false;
while (number>0) {
let t = number % 10;
if (t !== digit) {
newNumber = (newNumber * 10) + t;
} else if (t == digit) {
if (repeateFlag) {
console.log(("Repeated min digit " + t + " found. Store is : " + store));
store = (store * 10) + t;
console.log("Repeated min digit " + t + " added to store. Updated store is : " + store);
} else {
repeateFlag = true;
}
}
number = Math.floor(number / 10);
}
console.log("Reduced number is : " + newNumber);
return newNumber;}
function sortNum(num) {
let number = num;
let original = number;
let digit;
while (number > 0) {
digit = number % 10;
console.log("Last digit is : " + digit + " of number : " + number);
temp = Math.floor(number/10);
while (temp > 0) {
console.log("subchunk is " + temp);
t = temp % 10;
if (t < digit) {
digit = t;
}
temp = Math.floor(temp/10);
}
console.log("Smallest digit in " + number + " is " + digit);
store = (store * 10) + digit;
console.log("store is : " + store);
number = getReducedNumbr(number, digit);
}
console.log(("Ascending order of " + original + " is " + store));
return store;
}
console.log(sortNum(4214173));
you can see how it works here https://jsfiddle.net/9dpm14fL/1/
Assume we have an integer 16.
Is there a function, that returns random array of numbers, which compose its sum?
For example 7 1 2 4 1 1 or 1 5 2 3 6
I wonder if some elegant method of doing this in JavaScript exists.
No there's not existing function, but e.g.:
var n = 16;
var a = [];
while (n > 0) {
var s = Math.round(Math.random()*n);
a.push(s);
n -= s;
}
a contains the array.
you can consider this method too
function getRandomInt(max) {
return Math.floor(Math.random() * max + 1);
}
const total = 100;
const max = 20;
const nbrounds = 9;
function fillWithRandom(max, total, len) {
let arr = new Array();
let sum = 0;
newmax = max;
do {
newtotal = total - sum;
//max depending on length
console.log(arr.length,len);
if (arr.length+1 == len) {
arr.push(newtotal);
} else {
maxbylen = parseInt(newtotal / (len - arr.length));
// console.log('maxbylen', maxbylen, arr.length);
if (max > maxbylen) {
rndmax = max;
} else {
rndmax = maxbylen;
}
if (newtotal > max) {
rnd = getRandomInt(rndmax);
} else {
rnd = getRandomInt(newtotal);
}
arr.push(rnd);
}
sum = arr.reduce((acc, val) => acc + val, 0);
// console.log('sum', sum, 'newtotal', newtotal, 'rnd', rnd, arr);
} while (sum < total);
// console.log(arr);
//random order
return arr.map((value) => ({value, sort: Math.random()})).sort((a, b) => a.sort - b.sort).map(({ value }) => value);
}
;
console.log(fillWithRandom(max, total, nbrounds));