I'm writing something that pulls some data from the internet; the thing is that one of the keys from the object that I get has weight and height and well, they're not formatted; they're like a whole integer; now, for example; if I get a weight key with a value of 1000 that means that it is 100.0kg; not just 1000, same with the height but sometimes I can get something like 10 on height which is 0.99m or 1m; 100 is 10.0m and so on, so, my question is; what can I do here to format these values properly adding a .0 to the final if the value doesn't have it and if it does have it just add the decimal point before the last character? I tried doing some ifs but they were hard coded and I looking very bad, plus it didn't work.
Output that I'm getting
Example:
Weight: 1000
Height: 20
Weight: 69
Height: 7
Weight: 432
Height: 12
Expected output:
Weight: 100.0
Height: 2,0
Weight: 6.9
Height: 0.7
Weight: 43.2
Height: 1.2
You could divide by 10 and use Number#toFixed for formatting a number.
The toFixed() method formats a number using fixed-point notation.
var values = [1000, 20, 69, 7, 432, 12];
values = values.map(function (v) {
return (v / 10).toFixed(1);
});
console.log(values);
Related
I'm working on this kata from Codewars. The task is:
Given a certain number, how many multiples of three could you obtain with its digits?
Supose that you have the number 362. The numbers that can be generated from it are:
362 ----> 3, 6, 2, 36, 63, 62, 26, 32, 23, 236, 263, 326, 362, 623, 632
I've written the following recursive function to calculate all possiblities:
const findMult_3 = (num) => {
const powerset = (set) => {
const combinations = []
const combine = (prefix, chars) => {
for (let i = 0; i < chars.length; i++) {
const newPrefix = parseInt(prefix + chars[i])
if (!combinations.includes(newPrefix)) {
combinations.push(newPrefix)
} else {
console.log('encountered duplicate')
}
combine(newPrefix, chars.filter((x, ind) => ind !== i))
}
}
combine('', set)
return combinations.sort((a, b) => a - b)
}
const allCombinations = powerset(num.toString().split(''))
const factorsOfThree = allCombinations.filter(x => x % 3 === 0).filter(x => x !== 0)
return [factorsOfThree.length, factorsOfThree.pop()]
}
findMult_3(43522283000229)
I noticed early on that I was encountered a lot of duplicate cases, hence the console.log('encountered duplicate') flag.
Execution of this algorithm is taking an extremely long time for large numbers, eg 43522283000229.
How can I improve the performance of this code, or should it be scrapped entirely?
With most coding katas, the choice of algorithm is far more important that implementation details, but before we get to that, let me point out the most glaring flaw of your implementation:
if (!combinations.includes(newPrefix)) {
combinations.push(newPrefix)
} else {
console.log('encountered duplicate')
}
combine(newPrefix, chars.filter((x, ind) => ind !== i))
combinations is an array, and includes works by iterating over the array and checking every element. That is, to check whether an element is a duplicate, you are comparing it with every previously encountered combination. Since there are exponentially many of those, this is going to be very slow. If you used a dictionary object or Map instead, your code would be far faster.
Also, did you notice you are proceeding with generating combination even if the combination is a duplicate? That's redundant.
So the cheap improvement would be:
const combinations = {};
if (combinations[prefix]) {
// duplicate, do nothing
} else {
combinations[prefix] = true;
combine(...);
}
The real improvement however is choosing a better algorithm. If you make use of the mathematical structure of the problem, you may be able to find the number of solutions without iterating over them all.
The following insights might help:
a number is divisible by three if and only if the sum of its digits is.
a sum of digits is divisible by 3 if and only if the sum of their remainders when divided by 3 is 0.
the order of digits in the input does not matter
One (first) optimization would be to only check or generate numbers where the sum of the digits is divisible by 3, since only those numbers are divisible by 3.
So in your example (362) you could skip all combinations with 3 and 2, 6 and 2 and all possible combinations with the 3 digits (because the sum of the 3 digits is not divisible by 3).
For the larger number (43522283000229) you can skip a lot more, for example all combinations with digits:
43, 35, 52, ...
435, 352, .., 283, ...
4352 (thus, including all possible combinations of those 4 digits), ...
43522, ...
43528, 43529, ...
43528309, ...
and so on
Possible algorithm:
Original number: 43522283000229
First, sort the digits: 00022222334589
Then find all distinct combinations of digits where
their sum is a multiple of 3:
left to right:
1 digit : 3, 9
2 digits: 03, 09, 24, 33, 39, 45, 48, ...
3 digits: 003, 009, 024, 033, 039, 222, 234, ...
n digits ...
Now, for all above numbers create every possible combination with their
digits, skip those with leading zeros.:
3, 9, 30, 90, 24, 42, 33, 39, 93, 45, 54, 48, 84, 300, 900,
204, 240, 402, 420, 309, 390, 903, 930, 222, 234, 243, ...
We don't have to check for division by 3, they all match.
We don't have to check for duplicates.
You could then sort the resulting list if needed.
This is the javascript to generate a random hex color:
'#'+(Math.random()*0xFFFFFF<<0).toString(16);
could anyone talk me through it?
I understand how the Math.random works (as well as the to String at the end), but I don't understand the syntax after that. Questions I have:
How can Math.random() multiplied by F output a number?
What does the <<0 mean?
What does the parameter of 16 on toString mean? (does it mean no
more than 16 letters?)
Would really appreciate any help with this.
Thanks,
Raph
It looks like you picked this up on codegolf.
How can Math.random() multiplied by F output a number?
It is not multiplied by F. 0xFFFFFF is converted to 16777215, as 0xFFFFFF is just the hexadecimal way of writing 16777215.
What does the <<0 mean?
<< is a bitshift operator. <<0 shifts all bits 0 places to the left (filler: 0). This doesn't make any sense though. In this case it just deletes any decimal places.
What does the parameter of 16 on toString mean? (does it mean no more than 16 letters?)
The 16 is the parameter for the numeral system. (2 is binary, 8 is octal, 10 is decimal/normal, 16 is hexadecimal, etc.).
The best way to generate random HEX color:
It contains of tow functions:
The fest one picks a random hex number.
and the second one creates an array with hex values.
// Returns one possible value of the HEX numbers
function randomHex() {
var hexNumbers = [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
'A',
'B',
'C',
'D',
'E',
'F'
]
// picking a random item of the array
return hexNumbers[Math.floor(Math.random() * hexNumbers.length)];
}
// Genarates a Random Hex color
function hexGenerator() {
hexValue = ['#'];
for (var i = 0; i < 6; i += 1) {
hexValue.push(randomHex());
}
return hexValue.join('');
}
// print out the random HEX color
document.write(hexGenerator());
good luck
I have a jQuery plugin progress meter that animates and has a callback function where I animate the text value up to the meter value.
https://github.com/kottenator/jquery-circle-progress
The callback value is in the format of 0.12798798 etc which I format to give 12%.
My problem is if the value is 100% my code returns 00%
$('#circle').circleProgress({
startAngle: 90,
size: 240,
thickness: 22,
fill: { gradient: [['#0681c4', .5], ['#4ac5f8', .5]], gradientAngle: Math.PI / 4 }
}).on('circle-animation-progress', function(event, progress, stepValue) {
$(this).find('strong').text(String(stepValue.toFixed(2)).substr(2)+'%');
});
I am sure there is a much better approach.
You can simplify as follows:
(stepValue*100).toFixed(0) + '%'
Seems like this should round to the nearest integer:
Math.round(0.12798798*100)
toFixed(2) gives you two decimal places... use 0 and you don't need the substr
$(this).find('strong').text(String(stepValue.toFixed(0))+'%');
How can I setup an axis that it shows not 5 or 10 or whatever number of ticks but rather show a tick each n units. In this case if a dataset looks like this:
[2,3,6,7,10,13,17,20]
The ticks will be on 0, 5, 10, 15, 20 if I configure it to show a tick for every 5th step.
How can it be achieved?
Here is a real example I am working on
I want on x axis show a tick after each 20 years, so it should be not 0, 10, 20, 30, ..., n, but 0, 20, 40, 60, 80, ..., n.
For y axis I need values to be 500k stepped, so it should be 0, 500k, 1m, 1.5m, ..., n.
Update
I have found a simple working solution. I call an axis via `.call(yAxis) as usual, then I find go through created ticks and check if their datum has a remainder when I divide their values by the step number I need. If there is no remainder, then I set opacity to 1, otherwise hide them by setting opacity to 0. Here is an example:
yAxisElement
.selectAll('.tick')
.style({
opacity: function (d, i) {
return d % 500000 ? 0 : 1;
}
})
It's not an ideal solution, because it can't add the ticks that are in the middle of existing ones by value, like on this image, if I want to use 0, 15, 30, 45 and so on, just show/hide those that are already there. In the case I need to add ticks for other values, I need to make a custom axis or use the solution suggested by Lars Kotthoff.
I have a javascript function that converts feet into a usable object that will take the total feet and break it down into feet / inch / fraction.
In the example below the decimal fraction portion should be zero and my inch should be 4
Lets say I've got the following.
var inches = 40;
Now when I call the function below like so unPackDecimalFeet(40 /12);
unPackDecimalFeet: function (feetInchFraction) {
var inchFraction = (feetInchFraction - ~~feetInchFraction) * 12;
return {
feet: ~~feetInchFraction,
inch: ~~inchFraction,
fraction: inchFraction - ~~inchFraction
};
}
My return value is below.
feet: 3
fraction: 0.9999999999999964
inch: 3
**The above return value should read.
feet: 3
fraction: 0
inch: 4
How would I need to process the feet so that I can get the correct return value?
I'd say multiply it by 1000 in the beginning, then do your calculations, and then divide by 1000. IEEE Floating Point arithmetic is the problem here. If you need more calculations, look into BigInteger libraries. (BigInt, sometimes)
var inchesIn;
inchesIn = 40;
document.writeln('Feet: ' + Math.floor(inchesIn/12));
document.writeln('Inches: ' + inchesIn%12);
You're doing a lot to try and save yourself from tiny little inconsequential fraction issues throughout your code. I think maybe simpler is better:
unPackDecimalFeet : (function (feet) {
var flooredFeet = 0 | feet,
flooredInches = 0 | ((feet - flooredFeet) * 12),
inchFraction = (feet * 12) - (0 | (feet * 12));
return {
feet: flooredFeet,
inch: flooredInches,
fraction: +(inchFraction.toFixed(2)) //Rounded to two decimals
};
})
The only "trickiness" there is with 0 | as an alternative to Math.floor(). Feel free to use Math.floor() if it makes you feel better about maintainability. Also, I rounded off the "fraction" part of the response to the nearest 100th of an inch. You can round more precisely if you want, but some rounding is encouraged to prevent things like 0.9999999999999994 or whatever due to IEEE-754 gone wild.