Median of an array in Javascript? - javascript

I am trying to find the median of an array.
I have done quite some research and if this seemed to be asked several times, no answers were satisfying.
Creating my array works perfectly but when I call the function the array is sorted but it returns different values, from NaN to the first value of the array
How to find the median value of the length, and then from it's index find the median value of the array?
var ar1 = [];
while (true) {
var enterValues = prompt("enter your values");
if (enterValues != "") {
ar1.push(enterValues);
} else {
break;
}
}
function calcMedian() {
var half = Math.floor(ar1.length / 2);
ar1.sort(function(a, b) { return a - b;});
if (ar1.length % 2) {
return ar1[half];
} else {
return (ar1[half] + ar1[half] + 1) / 2.0;
}
}
console.log(ar1);
console.log(ar1.length);
console.log(calcMedian());
console.log(ar1);
(ps:to stop filling the array just enter without value.)

You have 2 problems in your code:
You calculate half before you fill the array so it will always be 0.
You save the numbers as string so when you add them you don;t get the right results.
Working :
var ar1 = [];
while (true) {
var enterValues = prompt("enter your values");
if (enterValues != "") {
ar1.push(+enterValues);
} else {
break;
}
}
function calcMedian() {
var half = Math.floor(ar1.length / 2);
ar1.sort(function(a, b) { return a - b;});
if (ar1.length % 2) {
return ar1[half];
} else {
return (ar1[half] + ar1[half] + 1) / 2.0;
}
}
console.log(ar1);
console.log(ar1.length);
console.log(calcMedian());
console.log(ar1);

var ar1 = [];
while (true) {
var enterValues = prompt("enter your values");
if (enterValues != "") {
ar1.push(parseFloat(enterValues));
} else {
break;
}
}
function calcMedian() {
var half = Math.floor(ar1.length / 2);
ar1.sort(function(a, b) { return a - b;});
if (ar1.length % 2) {
return ar1[half];
} else {
return (ar1[half-1] + ar1[half]) / 2.0;
}
}
console.log(ar1);
console.log(ar1.length);
console.log(calcMedian());
console.log(ar1);
Math.floor(ar1.length) will return (for example) 4 is the length is 8. However, if you do ar1[4] it will actually return the fifth item in the array as the array index starts at zero. So ar1[4-1] will return the fourth item, add it to ar1[4] which is the fifth item and divide it by two to find the median. If the length is odd, it will return (for example) 3 if the length is 7. It then retrieves arr[3] which is the fourth item which is the median.

let values = [2, 56, 3, 41, 0, 4, 100, 23];
values.sort(function(a,b) {
return a - b;
});
let lowMiddle = Math.floor( (values.length - 1) / 2);
let highMiddle = Math.ceil( (values.length - 1) / 2);
let median = ( values[lowMiddle] + values[highMiddle]) / 2;
console.log(median);

Related

Generate Uniform Distribution of Floats in Javascript

I'm trying to generate random numbers in javascript that are evenly distributed between 2 floats. I've tried using the method from the mozilla docs to get a random number between 2 values but it appears to cluster on the upper end of the distribution. This script:
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
function median(values) {
if (values.length === 0) throw new Error("No inputs");
values.sort(function (a, b) {
return a - b;
});
var half = Math.floor(values.length / 2);
if (values.length % 2)
return values[half];
return (values[half - 1] + values[half]) / 2.0;
}
const total = 10_000_000
let acc = []
for (i = 0; i < total; i++) {
acc.push(getRandomArbitrary(1e-10, 1e-1))
}
console.log(median(acc))
consistently outputs a number close to .05 instead of a number in the middle of the range (5e-5). Is there any way to have the number be distributed evenly?
Thank you!
EDIT: changed script to output median instead of mean.
function log10(x) { return Math.log(x)/Math.LN10; }
function getLogRandomArbitrary(min, max) {
return Math.pow(10, log10(min) + (Math.random() * (log10(max) - log10(min))));
}
function median(values) {
if(values.length === 0) throw new Error("No inputs");
let a = [...values].sort((a,b)=>a-b);
return a[Math.floor(a.length/2)];
}
const iterations = 1_000_000;
let a = [];
for (let i=0; i<iterations; i++) {
a.push(getLogRandomArbitrary(1e-10, 1e-1));
}
console.log(median(a));
console.log(log10(median(a)));

Finding extremes and values between them for a graph

I need an algorithm to find extremes and a certain number of values between them for a graph. For example, the highest value I have is 0.805 and the lowest is 0.694; I want the extremes to be 0.81 and 0.69; given that the number of values in between is 6, I want these values to be 0.79, 0.78, 0.76, 0.74, 0.72, 0.71 or so.
Long ago I wrote a function that finds the high extreme, but it was intended for the graphs with the lowest value is always set to 0:
const BASE = 5;
const LENGTH = 2;
function graphTopValue(max_value, max_items) {
return restore(find(extract(max_value), max_items), max_value);
}
function numlen(n) {
return Math.ceil(Math.log10(n));
}
function isDivisible(v, i) {
var r = numlen(v) - 1;
if ([0, 3, 6, 9].includes(r)) return true;
return (v / i) % BASE == 0;
}
function extract(v) {
return parseInt(v.toString().substr(0, LENGTH)) + 1;
}
function restore(v, o) {
var oldlen = numlen(o);
if (oldlen <= LENGTH) return v;
return v * Math.pow(10, oldlen - LENGTH);
}
function find(v, i) {
if (v % i == 0 && isDivisible(v, i)) return v;
return find(v + i - (v % i), i);
}
var max_value = 999;
var max_items = 4;
console.log(graphTopValue(max_value, max_items)); // 1000
Now I need an algorithm to work with any values and also find pretty values between extremes. How can I do it?
OK, I've found out that this is called 'Nice Label Algorithm'. Here's one of implementations:
https://gist.github.com/igodorogea/4f42a95ea31414c3a755a8b202676dfd

Persistent Bugger - Help to get rid of some 0

I need some help with a task which is about creating a function that only accepts integer numbers to then multiply each other until getting only one digit. The answer would be the times:
Example: function(39) - answer: 3
Because 3 * 9 = 27, 2 * 7 = 14, 1 * 4 = 4 and 4 has only one digit
Example2: function(999) - answer: 4
Because 9 * 9 * 9 = 729, 7 * 2 * 9 = 126, 1 * 2 * 6 = 12, and finally 1 * 2 = 2
Example3: function(4) - answer: 0
Because it has one digit already
So trying to figure out how to solve this after many failures, I ended up coding this:
function persistence(num) {
let div = parseInt(num.toString().split(""));
let t = 0;
if(Number.isInteger(num) == true){
if(div.length > 1){
for(let i=0; i<div.length; i++){
div = div.reduce((acc,number) => acc * number);
t += 1;
div = parseInt(div.toString().split(""))
if(div.length == 1){
return t } else {continue}
} return t
} else { return t }
} else { return false }
}
console.log(persistence(39),3);
console.log(persistence(4),0);
console.log(persistence(25),2);
console.log(persistence(999),4);
/*
output: 0 3
0 0
0 2
0 4
*/
It seems I could solve it, but the problem is I don't know why those 0s show up. Besides I'd like to receive some feedback and if it's possible to improve those codes or show another way to solve it.
Thanks for taking your time to read this.
///EDIT///
Thank you all for helping and teaching me new things, I could solve this problem with the following code:
function persistence(num){
let t = 0;
let div;
if(Number.isInteger(num) == true){
while(num >= 10){
div = (num + "").split("");
num = div.reduce((acc,val) => acc * val);
t+=1;
} return t
}
}
console.log(persistence(39));
console.log(persistence(4));
console.log(persistence(25));
console.log(persistence(999));
/*output: 3
0
2
4
*/
You've got a few issues here:
let div = parseInt(num.toString().split("")); You're casting an array to a number, assuming you're trying to extract the individual numbers into an array, you were close but no need for the parseInt.
function persistence(input, count = 0) {
var output = input;
while (output >= 10) {
var numbers = (output + '').split('');
output = numbers.reduce((acc, next) {
return Number(next) * acc;
}, 1);
count += 1;
}
​
return count;
};
For something that needs to continually check, you're better off using a recurssive function to check the conditions again and again, this way you won't need any sub loops.
Few es6 features you can utilise here to achieve the same result! Might be a little too far down the road for you to jump into es6 now but here's an example anyways using recursion!
function recursive(input, count = 0) {
// convert the number into an array for each number
const numbers = `${input}`.split('').map(n => Number(n));
// calculate the total of the values
const total = numbers.reduce((acc, next) => next * acc, 1);
// if there's more than 1 number left, total them up and send them back through
return numbers.length > 1 ? recursive(total, count += 1) : count;
};
console.log(recursive(39),3);
console.log(recursive(4),0);
console.log(recursive(25),2);
console.log(recursive(999),4);
function persistance (num) {
if (typeof num != 'number') throw 'isnt a number'
let persist = 0
while(num >= 10) {
let size = '' + num
size = size.length
// Get all number of num
const array = new Array(size).fill(0).map((x, i) => {
const a = num / Math.pow(10, i)
const b = parseInt(a, 10)
return b % 10
})
console.log('here', array)
// actualiser num
num = array.reduce((acc, current) => acc * current, 1)
persist++
}
return persist
}
console.log(persistance(39))
console.log(persistance(999))
console.log() can take many argument...
So for example, console.log("A", "B") will output "A" "B".
So all those zeros are the output of your persistence function... And the other number is just the number you provided as second argument.
So I guess you still have to "persist"... Because your function always returns 0.
A hint: You are making this comparison: div.length > 1...
But div is NOT an array... It is a number, stringified, splitted... And finally parsed as integer.
;) Good luck.
Side note, the calculation you are attempting is known as the Kaprekar's routine. So while learning JS with it... That history panel of the recreational mathematic wil not hurt you... And may be a good line in a job interview. ;)
My best hint
Use the console log within the function to help you degug it. Here is your unchanged code with just a couple of those.
function persistence(num) {
let div = parseInt(num.toString().split(""));
let t = 0;
console.log("div.length", div.length)
if (Number.isInteger(num) == true) {
if (div.length > 1) {
for (let i = 0; i < div.length; i++) {
div = div.reduce((acc, number) => acc * number);
t += 1;
div = parseInt(div.toString().split(""));
if (div.length == 1) {
console.log("return #1")
return t;
} else {
continue;
}
}
console.log("return #2")
return t;
} else {
console.log("return #3")
return t;
}
} else {
console.log("return #4")
return false;
}
}
console.log(persistence(39), 3);
console.log(persistence(4), 0);
console.log(persistence(25), 2);
console.log(persistence(999), 4);

application spits the numbers back at me even though it should return another value

I'm trying to make this front end web application where you provide acres and karats in a prompt in this form e.g. 3.22 and calculates them and give the total back in the chrome JS console
For example, you have 3.22 acres of land and another land that is 2.2 acres. If you get the sum of these numbers it should give you 5.42, no I want them to return 6, because acres have 24 karats and if you calculate 3 acres and 22 karats + 2 acres and 2 karats it should give you 6 acres, that's what I'm trying make here. I've been trying all night and every time the numbers I put in the prompt gets spit back at me in the console, so here's my code:
window.setTimeout(function() {
var acres = [];
var floats = [];
var wholes = [];
var input = prompt("What would you like to do?");
while (input !== "quit") {
if (input === "total") {
console.log("***********");
acres.forEach(function(total, i) {
console.log(i + ": " + total);
})
console.log("***********");
} else if (input === "calc") {
var num = prompt("Please enter a number");
while (num !== "back") {
if (num === "back") {
break;
}
acres.push(num);
var ftotal = 0
var wtotal = 0;
floats = [];
wholes = [];
for(var i = 0; i < acres.length; i++) {
alert("entered the for loop");
var acresNum = acres.pop();
var str = acresNum.toString();
var number = Math.floor((str).split(".")[1]);
floats.push(number);
ftotal += floats[i];
//-------------------------
var num2 = Math.floor(acresNum);
wholes.push(num2);
wtotal += wholes[i];
}
alert("exited the for loop");
console.log(ftotal);
console.log(wtotal);
if (ftotal > 23) {
wtotal++;
}
acres.push(wtotal + "." + ftotal);
var num = prompt("Please enter a number");
}
}
var input = prompt("What would you like to do?");
}
console.log("OK, YOU QUIT THE APP");}, 500)
The whole logic in this application is in that for loop in the else if(input === "calc") area.
You could take a numerical approach, but you went into the trap of floating point arithmetic (Is floating point math broken?) and get a number which does not match the given value of 42.
function sum(a, b) {
var s = a + b,
i = Math.floor(s),
p = (s - i) * 100;
console.log(p);
if (p >= 42) { // never reached
p -= 42;
++i;
}
return i + p / 100;
}
console.log(sum(3.22, 2.2));
As solution, you could separate the places as a string and add integer values and check if the value is greater than one acre, then return an adjusted value.
function sumD(a, b, threshold) {
return [a, b]
.map(v => v.toString().split('.'))
.reduce((r, a) => {
a.forEach((v, i) => r[i] += +v);
r[0] += Math.floor(r[1] / threshold);
r[1] %= threshold;
return r;
}, [0, 0])
.join('.');
}
console.log(sumD(3.22, 2.2, 24));
Separate the decimal values from your numbers.(Already done)
Ex: 3.22 -> 0.22 and 2.2 -> 0.2
Add them -> 0.22 + 0.2
Divide them by 0.24 -> (0.22+0.2)/.24 = 1
Add that to the wtotal -> 3.00 + 2.00 = 5 -> 5 + 1
I think this should be the logic mathematically.

Generate random integer with ALL digits from 1-9

How do I generate a 9-digit integer that has all digits from 1-9? Like 123456798, 981234765, 342165978, etc.
Doing this:
var min = 100000000;
var max = 999999999;
var num = Math.floor(Math.random() * (max - min + 1)) + min;
does not work give me the integer that I want most of the time (does not have ALL digits from 1 to 9).
111111119 is not acceptable because each number must have at least one "1" in it, "2", "3", ... and a "9" in it.
Just start with the string 123456789 and shuffle it randomly as described in How do I shuffle the characters in a string in JavaScript?
String.prototype.shuffle = function () {
var a = this.split(""),
n = a.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return a.join("");
}
This program, with little tweaks, will be a good addition to your custom utility belt.
Adapted from the _.shuffle function of Underscore.js library, which shuffles the list of data with Fisher-Yates Shuffle algorithm.
function getRandomNumber() {
var rand, index = 0, shuffled = [1, 2, 3, 4, 5, 6, 7, 8, 9];
shuffled.forEach(function(value) {
rand = Math.floor(Math.random() * ++index);
shuffled[index - 1] = shuffled[rand];
shuffled[rand] = value;
});
return shuffled.reduce(function(result, current) {
return result * 10 + current;
}, 0);
}
console.log(getRandomNumber());
This program will always return a number which has all the 9 numbers in it and the length is also 9.
Recurse!
var randomize = function (str) {
if (str.length == 9) return str;
var newDigit = Math.floor(Math.random()*9 + 1);
if (str.indexOf(newDigit) == -1) {
return randomize(str + newDigit);
} else {
return randomize(str);
}
}
There's a lot of room for optimisation there. Or just use a simple loop.
Working fiddle

Categories

Resources