Advanced number formatting with incrementing suffix- javascript - javascript

I need some help with my function. I am new to coding and this task is part of Coderslang apprentice level tasks.
Implement a function that If n < 1000, it should be rounded to a single digit after a decimal point Else, to cut down the length of a number, we need to use letters 'K', 'M', 'B', 'T' to represent thousands, millions, billions or trillions. We're not really interested in being super precise here. If the number exceeds 999.99T it becomes 1.00aa, after 999.99aa goes 1.00ab.
When the number gets as high as 999.99az it will next turn into 1.00ba and so on.
The bold text is where I am having an issue, I am not sure how best to write this function and need help. Below is what I have tried so far but I am failing two parts of the test- The function formatNumber should work properly for numbers less than 999az. And the function formatNumber should not cut trailing zeros.
My code so far:
export const formatNumber = (n) => {
let number = n;
let suffix = [97, 92];
let newNumber = "";
if (n < 1000) {
return n.toFixed(1);
} else if (n < 1000000) {
return (n / 1000).toFixed(2) + 'K';
} else if (n < 1000000000) {
return (n / 1000000).toFixed(2) + 'M';
} else if (n < 1000000000000) {
return (n / 1000000000).toFixed(2) + 'B';
} else if (n < 1000000000000000){
return (n / 1000000000000).toFixed(2) + 'T';
}
while (number > 1000) {
(number /= 1000);
if (suffix[1] < 122) {
suffix[1]++;
} else {
suffix[0]++;
suffix[1] = 97
}
}
const stringNumber = String(number);
const i = stringNumber.indexOf(".");
if (i >= 0) {
newNumber = stringNumber.substring(0, i) + "." + stringNumber.substring(i + 1, i + 3);
} else {
newNumber = stringNumber + ".00";
}
return newNumber + String.fromCharCode(suffix[0]) + String.fromCharCode(suffix[1]);
}
I have searched this forum and others and am struggling, any help would be appreciated. I feel that either I am over complicating the thought process or I'm missing something obvious. Is it my while loop? I have tried number.toFixed and number.toExponential without luck

It was a very simple fix, I was over complicating this.
export const formatNumber = (n) => {
let number = n;
let suffix = [97, 92];
let newNumber = "";
if (n < 1000) {
return n.toFixed(1);
} else if (n < 1000000) {
return (n / 1000).toFixed(2) + 'K';
} else if (n < 1000000000) {
return (n / 1000000).toFixed(2) + 'M';
} else if (n < 1000000000000) {
return (n / 1000000000).toFixed(2) + 'B';
} else if (n < 1000000000000000){
return (n / 1000000000000).toFixed(2) + 'T';
}
while (number > 1000) {
(number /= 1000);
if (suffix[1] < 122) {
suffix[1]++;
} else {
suffix[0]++;
suffix[1] = 97
}
}
newNumber = number.toFixed(2);
return newNumber + String.fromCharCode(suffix[0]) + String.fromCharCode(suffix[1]);
}```

Related

Bug while trying to find sum of primes with javascript

I am trying to get the sum of an array of prime numbers, and I understand there are more elegant ways to do that and have seen the links to those solutions.
My problem is something that's wrong within this specific script, and I'm trying to understand what's causing THIS code to fail.
The issue is that the numbers 9, 15 and many others are being being added into the primes array, even though they all, correctly, fail a test to check if they're prime numbers. I can't wrap my head around what in the script is causing the numbers to push to the array despite failing that test. Again, I'm not looking for a completely different/better approach to summing the primes, but some help in identifying what exactly is wrong in this script would be really appreciated.
function totalPrime(num) {
var nums = [];
var primes = [];
for (var i = 1;
(num - i) > 1; i++) {
nums.push(num - i);
}
nums.forEach(isPrime);
function isPrime(n) {
var a = [];
var test;
if (n === 1) {} else if (n === 2) {
primes.push(n);
} else {
for (var i = 1;
(n - i) > 1; i++) {
a.push(n - i);
}
a.forEach(function(x) {
if ((n % x) === 0) {
test = false;
} else {
test = true;
}
});
if (test) {
primes.push(n);
} else {}
};
}
console.log(primes.reduce(function(a, b) {
return a + b
}));
}
totalPrime(5);
Same script with logging I was using to debug:
function totalPrime(num) {
var nums = [];
var primes = [];
for (var i = 1;
(num - i) > 1; i++) {
nums.push(num - i);
}
nums.forEach(isPrime);
function isPrime(n) {
var a = [];
var test;
if (n === 1) {
console.log(n + ' is NOT a prime number');
} else if (n === 2) {
console.log(n + ' IS a prime number');
primes.push(n);
} else {
for (var i = 1;
(n - i) > 1; i++) {
a.push(n - i);
}
a.forEach(function(x) {
if ((n % x) === 0) {
test = false;
console.log(n + ' % ' + x + ' equals 0');
console.log(x + ' fails check');
} else {
test = true;
console.log(n + ' % ' + x + ' does NOT equal 0');
console.log(x + ' passes check');
}
});
if (test) {
console.log(n + ' IS a prime number.');
primes.push(n);
} else {
console.log(n + ' is NOT a prime number.');
}
};
}
console.log(primes);
console.log(primes.reduce(function(a, b) {
return a + b
}));
}
totalPrime(5);
Your test value in each test override the previous check. Thus, actualy only the last check (divide in 2) become relevant, and all the odd primes fail.
You can correct it by change the default of test to true, and remove the exist line in the code test = true;.
The corrected code:
function isPrime(n) {
var a = [];
var test = true;
if (n === 1) {} else if (n === 2) {
primes.push(n);
} else {
for (var i = 1;
(n - i) > 1; i++) {
a.push(n - i);
}
a.forEach(function(x) {
if ((n % x) === 0) {
test = false;
}
});
if (test) {
primes.push(n);
}
};
}

How to find nth Fibonacci number using Javascript with O(n) complexity

Trying really hard to figure out how to solve this problem. The problem being finding nth number of Fibonacci with O(n) complexity using javascript.
I found a lot of great articles how to solve this using C++ or Python, but every time I try to implement the same logic I end up in a Maximum call stack size exceeded.
Example code in Python
MAX = 1000
# Create an array for memoization
f = [0] * MAX
# Returns n'th fuibonacci number using table f[]
def fib(n) :
# Base cases
if (n == 0) :
return 0
if (n == 1 or n == 2) :
f[n] = 1
return (f[n])
# If fib(n) is already computed
if (f[n]) :
return f[n]
if( n & 1) :
k = (n + 1) // 2
else :
k = n // 2
# Applyting above formula [Note value n&1 is 1
# if n is odd, else 0.
if((n & 1) ) :
f[n] = (fib(k) * fib(k) + fib(k-1) * fib(k-1))
else :
f[n] = (2*fib(k-1) + fib(k))*fib(k)
return f[n]
// # Driver code
// n = 9
// print(fib(n))
Then trying to port this to Javascript
const MAX = 1000;
let f = Array(MAX).fill(0);
let k;
const fib = (n) => {
if (n == 0) {
return 0;
}
if (n == 1 || n == 2) {
f[n] = 1;
return f[n]
}
if (f[n]) {
return f[n]
}
if (n & 1) {
k = Math.floor(((n + 1) / 2))
} else {
k = Math.floor(n / 2)
}
if ((n & 1)) {
f[n] = (fib(k) * fib(k) + fib(k-1) * fib(k-1))
} else {
f[n] = (2*fib(k-1) + fib(k))*fib(k)
}
return f[n]
}
console.log(fib(9))
That obviously doesn't work. In Javascript this ends up in an infinite loops. So how would you solve this using Javascript?
Thanks in advance
you can iterate from bottom to top (like tail recursion):
var fib_tail = function(n){
if(n == 0)
return 0;
if(n == 1 || n == 2)
return 1;
var prev_1 = 1, prev_2 = 1, current;
// O(n)
for(var i = 3; i <= n; i++)
{
current = prev_1 + prev_2;
prev_1 = prev_2;
prev_2 = current;
}
return current;
}
console.log(fib_tail(1000))
The problem is related to scope of the k variable. It must be inside of the function:
const fib = (n) => {
let k;
You can find far more good implementations here list
DEMO
fibonacci number in O(n) time and O(1) space complexity:
function fib(n) {
let prev = 0, next =1;
if(n < 0)
throw 'not a valid value';
if(n === prev || n === next)
return n;
while(n >= 2) {
[prev, next] = [next, prev+next];
n--;
}
return next;
}
Just use two variables and a loop that counts down the number provided.
function fib(n){
let [a, b] = [0, 1];
while (--n > 0) {
[a, b] = [b, a+b];
}
return b;
}
console.log(fib(10));
Here's a simpler way to go about it, using either iterative or recursive methods:
function FibSmartRecursive(n, a = 0, b = 1) {
return n > 1 ? FibSmartRecursive(n-1, b, a+b) : a;
}
function FibIterative(n) {
if (n < 2)
return n;
var a = 0, b = 1, c = 1;
while (--n > 1) {
a = b;
b = c;
c = a + b;
}
return c;
}
function FibMemoization(n, seenIt = {}) {//could use [] as well here
if (n < 2)
return n;
if (seenIt[n])
return seenIt[n];
return seenIt[n] = FibMemoization(n-1, seenIt) + FibMemoization(n-2, seenIt);
}
console.log(FibMemoization(25)); //75025
console.log(FibIterative(25)); //75025
console.log(FibSmartRecursive(25)); //75025
You can solve this problem without recursion using loops, runtime O(n):
function nthFibo(n) {
// Return the n-th number in the Fibonacci Sequence
const fibSeq = [0, 1]
if (n < 3) return seq[n - 1]
let i = 1
while (i < n - 1) {
seq.push(seq[i - 1] + seq[i])
i += 1
}
return seq.slice(-1)[0]
}
// Using Recursion
const fib = (n) => {
if (n <= 2) return 1;
return fib(n - 1) + fib(n - 2);
}
console.log(fib(4)) // 3
console.log(fib(10)) // 55
console.log(fib(28)) // 317811
console.log(fib(35)) // 9227465

Create a percentage preloader with words instead of number?

I am trying to create a percentage preloader that has words instead of numbers.... i.e. ONE PERCENT, TWO PERCENT, etc. up to ONE HUNDRED PERCENT.
I know it will move very fast...
Not quite sure where to even start? Have googled and tried my hand at a bit, just a push in the right direction is all I'm looking for!
Thx!!!
This is the function I'm going to use to convert a number below 100 to the english version:
function numberToString(n) {
var toFifteen = "ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,ELEVEN,TWELVE,THIRTEEN,FOURTEEN,FIFTEEN".split(",");
var tens = "TEEN,TWENTY,THIRTEE,FOURTY,FIFTY,SIXTY,SEVENTY,EIGHTY,NINETY".split(",");
if (n == 0)
return "ZERO";
if (n <= 15)
return toFifteen[n - 1];
if (n < 20)
return (toFifteen[- -(n+"")[1] - 1] || "") + "TEEN";
if (n == 100)
return "ONE HUNDRED";
return tens[- -(n+"")[0] - 1] + " " + (toFifteen[- -(n+"")[1] - 1] || "");
}
I provide 2 approach, the first works if you only want one or you use arrays, the second works if you want multiple ones and you want to manage them easily.
First approach:
// Create progress bar element
var progress = document.createElement("span");
var currProgress = 0;
progress.innerHTML = numberToString(currProgress)
// You should put the el
document.body.appendChild(progress);
// This following part updates the progress bar, change this
// to whatever way you want it to get updated
setInterval(function() {
currProgress++;
if (currProgress > 100)
currProgress = 0;
progress.innerHTML = numberToString(currProgress);
}, 100);
function numberToString(n) {
var toFifteen = "ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,ELEVEN,TWELVE,THIRTEEN,FOURTEEN,FIFTEEN".split(",");
var tens = "TEEN,TWENTY,THIRTEE,FOURTY,FIFTY,SIXTY,SEVENTY,EIGHTY,NINETY".split(",");
if (n == 0)
return "ZERO";
if (n <= 15)
return toFifteen[n - 1];
if (n < 20)
return (toFifteen[- -(n+"")[1] - 1] || "") + "TEEN";
if (n == 100)
return "ONE HUNDRED";
return tens[- -(n+"")[0] - 1] + " " + (toFifteen[- -(n+"")[1] - 1] || "");
}
This allows you to have 1 progress bar on the page, but I'd recommend using a more object oriented solution:
function ProgressBar(startingProgress) {
// This makes the argument optional
// If the user doesn't enter a number, then it will
// default to 0
if (!startingProgress)
startingProgress = 0;
this.progress = 0;
this.element = document.createElement("span");
this.element.innerHTML = ProgressBar.numberToString(this.progress);
}
ProgressBar.prototype.step = function(amount) {
// Same as with startingProgress
if (!amount)
amount = 1;
this.progress += amount;
this.element.innerHTML = ProgressBar.numberToString(this.progress);
}
// "Static" method
ProgressBar.numberToString = function(n) {
var toFifteen = "ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,ELEVEN,TWELVE,THIRTEEN,FOURTEEN,FIFTEEN".split(",");
var tens = "TEEN,TWENTY,THIRTEE,FOURTY,FIFTY,SIXTY,SEVENTY,EIGHTY,NINETY".split(",");
if (n == 0)
return "ZERO";
if (n <= 15)
return toFifteen[n - 1];
if (n < 20)
return (toFifteen[- -(n+"")[1] - 1] || "") + "TEEN";
if (n == 100)
return "ONE HUNDRED";
return tens[- -(n+"")[0] - 1] + " " + (toFifteen[- -(n+"")[1] - 1] || "");
}
var progress = new ProgressBar();
document.body.appendChild(progress.element);
setInterval(function() {
progress.step(1);
}, 100);

Recursive function exponential function

I need implement recursive function exponential function (e^x) with help row Taylor:
e^x = 1 + x + x2/2! + x3/3! + ...
But i can't understand what i do wrong
I have next code:
function fact(n){
return n * fact(n - 1);
}
function myPow(x, n){
return x * myPow(x, n - 1);
}
function expon(x ,n){
if(n == 1){
return expon(x, n - 1) * x;
}
else{
return expon(x, n - 1) + (myPow(x, n)/fact(n));
}
}
console.log(expon(1, 10));
Your factorial function has no base case.
function fact(n) {
if (n == 1)
return 1;
if (n < 1)
return 0;
return n * fact(n - 1);
}
A similar change will be needed for myPow. Although since powers are funny, I think if n == 0 return 1.
Your code should look like this:
function fact(n){
if (n == 1)
return 1;
return n * fact(n - 1);
}
function myPow(x, n){
if(n == 1)
return n;
return x * myPow(x, n - 1);
}
function expon(x ,n){
if(n == 1){
return 1;
}
else{
return expon(x, n - 1) + (myPow(x, n)/fact(n));
}
console.log(expon(1, 10));
This looks like an assignment so I won't debug your code but give you some hints.
You seem to not understand how recursion ends with giving a result in the end.
You have to provide a simple case where you return a value with a non recursive call.
Sometimes you don't write any if (bad!), and sometimes there is an if, but both cases use a recursive call.
This will solve your problem:
function fact(n) {
if (n == 1) return 1;
return n * fact(n - 1);
}
function myPow(x, n) {
if (n == 0) return 1;
return x * myPow(x, n - 1);
}
function expon(x, n) {
if (n == 0) return 1;
return expon(x, n - 1) + myPow(x, n) / fact(n);
}
console.log(expon(1, 10));

Converting big numbers to bigger factors in JavaScript

I have counter and sometimes it can get very big number, so I need to convert numbers like:
1300 => 1.3K
1000000 => 1M
And so on. How is this possible in JavaScript?
// Truncate a number to ind decimal places
function truncNb(Nb, ind) {
var _nb = Nb * (Math.pow(10,ind));
_nb = Math.floor(_nb);
_nb = _nb / (Math.pow(10,ind));
return _nb;
}
// convert a big number to k,M,G
function int2roundKMG(val) {
var _str = "";
if (val >= 1e9) { _str = truncNb((val/1e9), 1) + ' G';
} else if (val >= 1e6) { _str = truncNb((val/1e6), 1) + ' M';
} else if (val >= 1e3) { _str = truncNb((val/1e3), 1) + ' k';
} else { _str = parseInt(val);
}
return _str;
}
I picked up a nifty bit of code when looking for something to abbreviate and label byte sizes (e.g. 1024 bytes -> "1 KB") and changed it just a bit to suit your needs (1000 -> "1 K").
function abbreviate_number(num) {
var sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
if (num < 1000) return num;
var i = parseInt(Math.floor(Math.log(num) / Math.log(1000)));
return ((i == 0) ? (num / Math.pow(1000, i)) : (num / Math.pow(1000, i)).toFixed(1)) + ' ' + sizes[i]; // use .round() in place of .toFixed if you don't want the decimal
};
Just for reference, here's what I needed.
function format_bytes(bytes) {
var sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
if (bytes == 0) return '';
if (bytes == 1) return '1 Byte';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return ((i == 0)? (bytes / Math.pow(1024, i)) : (bytes / Math.pow(1024, i)).toFixed(1)) + ' ' + sizes[i];
};
Pseudocode:
factor = 0;
while (value > 1000) {
value = value/1000;
factor++;
}
output value (you might perhaps limit output to 3 decimal places)
convert factor to unit and output (0 = none, 1 = K, 2 = M, 3 = G...)
You could just use a classic cascading number formatter of sorts
function format_num(num) {
if( num < 1000 )
return num;
else if( num < 1000000 )
return parseInt(num / 1000) + "K";
else if( num < 1000000000 )
return parseInt(num / 1000000) + "M";
//....
}
You just have to take care of rounding appropriately.
I came up to these answers late when I was looking for a clean way to do it but just in case if anyone was looking for copy pasting an angular filter doing that here is mine. same logic as above responses:)
just to make you sure for 001234 it returns 1k
html:
<div ng-repeat="d in data>
<div class="numbers">{{d | KGMPformat}}</div>
</div>
js:
// controller:
$scope.data = [123,12345,1234567,12345678,12345678901]
// filter:
(function(app) {
app.filter('KGMPformat', function() {
return function(value) {
if (value<1e3) return value;
if (value<1e6) return (value - value%1e3)/1e3 + "K";
if (value<1e9) return (value - value%1e6)/1e6 + "G";
if (value<1e12) return (value - value%1e9)/1e9 + "M";
if (value<1e15) return (value - value%1e12)/1e12 + "P";
return value;
};
});
})(myApp);

Categories

Resources