Get least significant digit including its value in a JavaScript - javascript

I would like to extract the least significant digit including its value from a number in JavaScript (so that no information is lost)
For example
12.0123323 -> 0.0000003
123299000 -> 9000
123001 -> 1
123001.01 -> 0.01
10000000 -> 10000000
etc...
Is there a neat way to do this?
Edit:
As people have noted because of Javascript:s way of handling numbers it can not represent 12.0123323, so let's assume it's a string in those corner cases.

You could check if the value is an integer number and choose a different replacement schema for getting the right least significant value.
function least(x) {
return x === Math.floor(x)
? +x.toString().replace(/.*(?=[1-9]0*$)/, '')
: +x.toString().replace(/\d(?=.*[1-9]$)/g, '0');
}
var array = [
12.0123323, // 0.0000003
123299000, // 9000
123001, // 1
123001.01, // 0.01
10000000 // 10000000
];
console.log(array.map(least));
.as-console-wrapper { max-height: 100% !important; top: 0; }

const least = num => [...num.toString()].reduceRight((res, d, i) => (+res ? (d === "." ? "." : "0") : d) + res, "");
Test Cases
It basically traverses the string presentation (toString) of the number from right to left (reduceRight) and if the current result has already a digit in it (+res) then
d === "." ? "." : "0"
it either takes over the dot or converts any other digit to 0. If there was no digit yet (:), it simply adds the current one d, and appends the already traversed part + res
If you rather like readable code:
function least(num){
var res = "";
for(var char of num.toString().split("").reverse()){
if(+res){
res = (char === "." ? "." : "0") + res;
} else {
res = char + res;
}
}
return res;
}

var foundNonzero = false
Number("324.034"
.split('')
.reverse()
.map((i)=>{
if(i==='.') return i
if(foundNonzero) return '0'
if(i!=='0'){
foundNonzero = true
}
return i
}).reverse().join(''))

Related

Disqualifying consecutive characters in an Alphabetical Order. Sol [ASCII Format]

I was given this problem by my friend. The question asks to remove all the alphabetically consecutive characters from the string input given.
So I did it using Javascript, I need expert help if I performed it precisely.
I thought using Array.prototype.reduce will be the best way, do we have other possible ways?
/**
* #author Abhishek Mittal <abhishekmittaloffice#gmail.com>
* #description function can deal with both any types followed in a consecutive manner in ASCII Chart.
* #param {string} str
*/
function improvise(str) {
// Backup for original input.
const bck = str || '';
const bckArr = bck.split('').map( e => e.charCodeAt(0)); // converting the alphabets into its ASCII for simplicity and reducing the mayhem.
let result = bckArr.reduce( (acc, n) => {
// Setting up flag
let flag1 = n - acc.rand[acc.rand.length - 1];
let flag2 = n - acc.temp;
if(flag1 === 1 || flag2 === 1) {
(flag2 !== NaN && flag2 !== 1) ? acc.rand.pop() : null; // update the latest value with according to the case.
acc.temp = n
}else{
acc.rand.push(n); // updating the random to latest state.
acc.temp = null;
}
return acc;
}, {rand: [], temp: null} /* setting up accumulative situation of the desired result */)
result = result.rand.map(e => String.fromCharCode(e)).join('')
return result ? result : '' ;
}
function init() {
const str = "ab145c";
const final = improvise(str);
console.log(final)
}
init();
Well, the output is coming out to be correct.
Input: ab145c
Output: 1c
There's no way to solve this using any remotely reasonable regular expression, unfortunately.
I think it would be a lot clearer to use .filter, and check whether either the next character or the previous character is consecutive:
const code = char => char
? char.charCodeAt(0)
: -2; // will not be === to any other codes after addition or subtraction
function improvise(str) {
return [...str]
.filter((char, i) => {
const thisCode = code(char);
return (
thisCode !== code(str[i - 1]) + 1
&& thisCode !== code(str[i + 1]) - 1
);
})
.join('');
}
console.log(improvise('ab145c'));
(alternatively, you could check only whether the next character is consecutive, but then you'd have to check the validity of the last character in the string as well)
If you need continuously replace characters until no consecutive characters remain, then keep calling improvise:
const code = char => char
? char.charCodeAt(0)
: -2; // will not be === to any other codes after addition or subtraction
function improvise(str) {
return [...str]
.filter((char, i) => {
const thisCode = code(char);
return (
thisCode !== code(str[i - 1]) + 1
&& thisCode !== code(str[i + 1]) - 1
);
})
.join('');
}
let result = 'hishakmitalaaaaabbbbbbcccccclmnojqyz';
let same = false;
while (!same) {
const newResult = improvise(result);
if (newResult !== result) {
result = newResult;
console.log(result);
} else {
same = true;
}
}
console.log('FINAL:', result);
Well, that's great code but it doesn't gives the exact solution to the problem, see:
INPUT: hishakmitalaaaaabbbbbbcccccclmnojqyz
i got
Output: shakmitalaaaabbbbcccccjq
you see 'ab' & 'bc' remains intact, we need to increase the number of loops maybe to check those, can increase complexity as well.
But, my solution doesn't as well gives me the answer I desire e.g. for the above string I should get
ishakmitalaacccjq
but rather my solution gives
shakmitalcccccjq
hope you understand the question. We need a change in the way we traverse throughout the string.

Adding two numbers JS

I want to add two numbers from range 10-99,for example:
Input:16
Output:1+6=7
Input:99
Output:18
function digital_root(n) {
var z = n.toString().length;
if (z == 2) {
var x = z[0] + z[1]
return x;
}
}
console.log( digital_root(16) );
Output from this code is NaN.What should I correct?
You can try this:
function digital_root(n) {
var z = n.toString();
//use length here
if (z.length == 2) {
//convert to int
var x = parseInt(z[0]) + parseInt(z[1]);
return x;
} else {
return "not possible!";
}
}
console.log( digital_root(16) );
console.log( digital_root(99) );
console.log( digital_root(999) );
Use split to split the string in half and add the two using parseInt to convert to a number.
const sum = (s) => (''+s).split('').reduce((a,b) => parseInt(a)+parseInt(b))
↑ ↑ ↑ ↑
our coerce split sum
function to string in two both
Here a test :
const sum = (s) => (''+s).split('').reduce((a,b) => parseInt(a)+parseInt(b))
console.log(sum(12))
There are several approaches to sum digits of a number. You can convert it to a string but IDK if thats neccesary at all. You can do it with numerical operations.
var input = 2568,
sum = 0;
while (input) {
sum += input % 10;
input = Math.floor(input / 10);
}
console.log(sum);
Here's a fun short way to do it:
const number = 99
const temp = number.toString().split('')
const res = temp.reduce((a, c) => a + parseInt(c), 0) // 18
1.) Convert number to string
2.) Separate into individual numbers
3.) Use reduce to sum the numbers.
Your way would be the iterational way to solve this problem, but you can also use a recursive way.
Iterative solution (Imperative)
n.toString() Create String from number.
.split("") split string into chars.
.reduce(callback, startValue) reduces an array to a single value by applying the callback function to every element and updating the startValue.
(s, d) => s + parseInt(d) callback function which parses the element to an integer and adds it to s (the startValue).
0 startValue.
Recursive solution (Functional)
condition?then:else short-hand if notation.
n<10 only one digit => just return it.
n%10 the last digit of the current number (1234%10 = 4).
digital_root_recurse(...) call the function recursivly.
Math.floor(n / 10) Divide by 10 => shift dcimal point to left (1234 => 123)
... + ... add the last digit and the return value (digital root) of n/10 (1234 => 4 + root(123)).
function digital_root_string(n) {
return n.toString().split("").reduce((s, d) => s + parseInt(d), 0);
}
function digital_root_recurse(n) {
return n < 10 ? n : n % 10 + digital_root_recurse(Math.floor(n / 10));
}
console.log(digital_root_string(16));
console.log(digital_root_string(99));
console.log(digital_root_recurse(16));
console.log(digital_root_recurse(99));
The issue in your code is that you stored the length of n into z. The length is an integer, so both z[0] and [1] are undefined. The solution is to store the string into another variable and use that instead of z.
function digital_root(n) {
n = n.toString();
var l = n.length;
if (l === 2) {
return parseInt(n[0], 10) + parseInt(n[1], 10);
}
}
console.log( digital_root(16) );
Simply use var x = parseInt(n/10) + (n%10); and it will work for you.
function digital_root(n) {
var z = n.toString().length;
if (z == 2) {
var x = parseInt(n/10) + (n%10);
return x;
}
}
console.log( digital_root(16) );
console.log( digital_root(99) );
console.log( digital_root(62) );
Convert input to string, split it, convert each item back to number and sum them all:
function digital_root(n) {
return String(n).split('').map(Number).reduce((a,b) => a + b)
}
const result = digital_root(99);
console.log(result);

How can I clean up this code and write it more eloquently?

I'm working on some practice problems using higher- order functions and while I was able to solve this problem. I can't help but think this code is ugly and not the most eloquent it could be. Is there a way to combined map and reduce is a cleaner way than I have done ? Additionally, is there any other methods or improvements I could have used here ? I'm just looking to get better and any feedback would be appreciated.
Problem: Given a number, "sumDigits" returns the sum of all its digits.If the number is negative, the first digit should count as negative.
function sumDigits(num) {
//create array of number char
var string = num.toString().split('');
//if first char is negative symbol let the first numeric element be negative
if (string[0] === "-") {
string[1] = '-' + string[1];
string.shift();
}
//convert string to int
var toInteger = string.map(function(x) {
return Number(x);
});
//get sum
return toInteger.reduce(function(sum, current) {
sum += current;
return sum;
})
}
sumDigits(-316);
You don't need to use map at all, if you convert to number inside the reduce. Here I used the unary + operator to convert the string to a number instead of the Number constructor, but that is not better than the Number constructor, just a habit:
function sumDigits ( num ) {
const chars = num.toString( ).split( '' );
// Subtract first digit if the string starts with a '-'
// Needs to be subtracted twice, since it is included in the sum
return ( chars[0] === '-' ? -2*chars[1] : +chars[0] ) +
chars.slice( 1 ).reduce( (sum, value) => sum + +value, 0 )
;
}

Javascript: How to retrieve the number of decimals of a *string* number?

I have a set of string numbers having decimals, for example: 23.456, 9.450, 123.01... I need to retrieve the number of decimals for each number, knowing that they have at least 1 decimal.
In other words, the retr_dec() method should return the following:
retr_dec("23.456") -> 3
retr_dec("9.450") -> 3
retr_dec("123.01") -> 2
Trailing zeros do count as a decimal in this case, unlike in this related question.
Is there an easy/delivered method to achieve this in Javascript or should I compute the decimal point position and compute the difference with the string length? Thanks
function decimalPlaces(num) {
var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match) { return 0; }
return Math.max(
0,
// Number of digits right of decimal point.
(match[1] ? match[1].length : 0)
// Adjust for scientific notation.
- (match[2] ? +match[2] : 0));
}
The extra complexity is to handle scientific notation so
decimalPlaces('.05')
2
decimalPlaces('.5')
1
decimalPlaces('1')
0
decimalPlaces('25e-100')
100
decimalPlaces('2.5e-99')
100
decimalPlaces('.5e1')
0
decimalPlaces('.25e1')
1
function retr_dec(num) {
return (num.split('.')[1] || []).length;
}
function retr_dec(numStr) {
var pieces = numStr.split(".");
return pieces[1].length;
}
Since there is not already a regex-based answer:
/\d*$/.exec(strNum)[0].length
Note that this "fails" for integers, but per the problem specification they will never occur.
You could get the length of the decimal part of your number this way:
var value = 192.123123;
stringValue = value.toString();
length = stringValue.split('.')[1].length;
It makes the number a string, splits the string in two (at the decimal point) and returns the length of the second element of the array returned by the split operation and stores it in the 'length' variable.
Try using String.prototype.match() with RegExp /\..*/ , return .length of matched string -1
function retr_decs(args) {
return /\./.test(args) && args.match(/\..*/)[0].length - 1 || "no decimal found"
}
console.log(
retr_decs("23.456") // 3
, retr_decs("9.450") // 3
, retr_decs("123.01") // 2
, retr_decs("123") // "no decimal found"
)
I had to deal with very small numbers so I created a version that can handle numbers like 1e-7.
Number.prototype.getPrecision = function() {
var v = this.valueOf();
if (Math.floor(v) === v) return 0;
var str = this.toString();
var ep = str.split("e-");
if (ep.length > 1) {
var np = Number(ep[0]);
return np.getPrecision() + Number(ep[1]);
}
var dp = str.split(".");
if (dp.length > 1) {
return dp[1].length;
}
return 0;
}
document.write("NaN => " + Number("NaN").getPrecision() + "<br>");
document.write("void => " + Number("").getPrecision() + "<br>");
document.write("12.1234 => " + Number("12.1234").getPrecision() + "<br>");
document.write("1212 => " + Number("1212").getPrecision() + "<br>");
document.write("0.0000001 => " + Number("0.0000001").getPrecision() + "<br>");
document.write("1.12e-23 => " + Number("1.12e-23").getPrecision() + "<br>");
document.write("1.12e8 => " + Number("1.12e8").getPrecision() + "<br>");
A slight modification of the currently accepted answer, this adds to the Number prototype, thereby allowing all number variables to execute this method:
if (!Number.prototype.getDecimals) {
Number.prototype.getDecimals = function() {
var num = this,
match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match)
return 0;
return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
}
}
It can be used like so:
// Get a number's decimals.
var number = 1.235256;
console.debug(number + " has " + number.getDecimals() + " decimal places.");
// Get a number string's decimals.
var number = "634.2384023";
console.debug(number + " has " + parseFloat(number).getDecimals() + " decimal places.");
Utilizing our existing code, the second case could also be easily added to the String prototype like so:
if (!String.prototype.getDecimals) {
String.prototype.getDecimals = function() {
return parseFloat(this).getDecimals();
}
}
Use this like:
console.debug("45.2342".getDecimals());
A bit of a hybrid of two others on here but this worked for me. Outside cases in my code weren't handled by others here. However, I had removed the scientific decimal place counter. Which I would have loved at uni!
numberOfDecimalPlaces: function (number) {
var match = ('' + number).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match || match[0] == 0) {
return 0;
}
return match[0].length;
}
Based on Liam Middleton's answer, here's what I did (without scientific notation):
numberOfDecimalPlaces = (number) => {
let match = (number + "").match(/(?:\.(\d+))?$/);
if (!match || !match[1]) {
return 0;
}
return match[1].length;
};
alert(numberOfDecimalPlaces(42.21));
function decimalPlaces(n) {
if (n === NaN || n === Infinity)
return 0;
n = ('' + n).split('.');
if (n.length == 1) {
if (Boolean(n[0].match(/e/g)))
return ~~(n[0].split('e-'))[1];
return 0;
}
n = n[1].split('e-');
return n[0].length + ~~n[1];
}

Pad a number with leading zeros in JavaScript [duplicate]

This question already has answers here:
How can I pad a value with leading zeros?
(76 answers)
Closed 3 years ago.
In JavaScript, I need to have padding.
For example, if I have the number 9, it will be "0009". If I have a number of say 10, it will be "0010". Notice how it will always contain four digits.
One way to do this would be to subtract the number minus 4 to get the number of 0s I need to put.
Is there was a slicker way of doing this?
ES2017 Update
You can use the built-in String.prototype.padStart()
n = 9;
String(n).padStart(4, '0'); // '0009'
n = 10;
String(n).padStart(4, '0'); // '0010'
Not a lot of "slick" going on so far:
function pad(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
When you initialize an array with a number, it creates an array with the length set to that value so that the array appears to contain that many undefined elements. Though some Array instance methods skip array elements without values, .join() doesn't, or at least not completely; it treats them as if their value is the empty string. Thus you get a copy of the zero character (or whatever "z" is) between each of the array elements; that's why there's a + 1 in there.
Example usage:
pad(10, 4); // 0010
pad(9, 4); // 0009
pad(123, 4); // 0123
pad(10, 4, '-'); // --10
function padToFour(number) {
if (number<=9999) { number = ("000"+number).slice(-4); }
return number;
}
Something like that?
Bonus incomprehensible-but-slicker single-line ES6 version:
let padToFour = number => number <= 9999 ? `000${number}`.slice(-4) : number;
ES6isms:
let is a block-scoped variable (as opposed to var’s functional scoping)
=> is an arrow function that, among other things, replaces function and is prepended by its parameters
If an arrow function takes a single parameter, you can omit the parentheses (hence number =>)
If an arrow function body has a single line that starts with return, you can omit the braces and the return keyword and simply use the expression
To get the function body down to a single line, I cheated and used a ternary expression
Try:
String.prototype.lpad = function(padString, length) {
var str = this;
while (str.length < length)
str = padString + str;
return str;
}
Now test:
var str = "5";
alert(str.lpad("0", 4)); //result "0005"
var str = "10"; // note this is string type
alert(str.lpad("0", 4)); //result "0010"
DEMO
In ECMAScript 2017 , we have new method padStart and padEnd which has below syntax.
"string".padStart(targetLength [,padString]):
So now we can use
const str = "5";
str.padStart(4, "0"); // "0005"
Funny, I recently had to do this.
function padDigits(number, digits) {
return Array(Math.max(digits - String(number).length + 1, 0)).join(0) + number;
}
Use like:
padDigits(9, 4); // "0009"
padDigits(10, 4); // "0010"
padDigits(15000, 4); // "15000"
Not beautiful, but effective.
You did say you had a number-
String.prototype.padZero= function(len, c){
var s= '', c= c || '0', len= (len || 2)-this.length;
while(s.length<len) s+= c;
return s+this;
}
Number.prototype.padZero= function(len, c){
return String(this).padZero(len,c);
}
You could do something like this:
function pad ( num, size ) {
return ( Math.pow( 10, size ) + ~~num ).toString().substring( 1 );
}
Edit: This was just a basic idea for a function, but to add support for larger numbers (as well as invalid input), this would probably be better:
function pad ( num, size ) {
if (num.toString().length >= size) return num;
return ( Math.pow( 10, size ) + Math.floor(num) ).toString().substring( 1 );
}
This does 2 things:
If the number is larger than the specified size, it will simply return the number.
Using Math.floor(num) in place of ~~num will support larger numbers.
This is not really 'slick' but it's faster to do integer operations than to do string concatenations for each padding 0.
function ZeroPadNumber ( nValue )
{
if ( nValue < 10 )
{
return ( '000' + nValue.toString () );
}
else if ( nValue < 100 )
{
return ( '00' + nValue.toString () );
}
else if ( nValue < 1000 )
{
return ( '0' + nValue.toString () );
}
else
{
return ( nValue );
}
}
This function is also hardcoded to your particular need (4 digit padding), so it's not generic.
For fun, instead of using a loop to create the extra zeros:
function zeroPad(n,length){
var s=n+"",needed=length-s.length;
if (needed>0) s=(Math.pow(10,needed)+"").slice(1)+s;
return s;
}
Since you mentioned it's always going to have a length of 4, I won't be doing any error checking to make this slick. ;)
function pad(input) {
var BASE = "0000";
return input ? BASE.substr(0, 4 - Math.ceil(input / 10)) + input : BASE;
}
Idea: Simply replace '0000' with number provided... Issue with that is, if input is 0, I need to hard-code it to return '0000'. LOL.
This should be slick enough.
JSFiddler: http://jsfiddle.net/Up5Cr/

Categories

Resources