Math.max method on array with equal values - javascript

I'm working on some coderbyte code, and noticed that when I try to get the max item in an array of equal values undefined is returned. When logging the min value is logs 80 and not undefined. Why is this?
Updated Code:
function noRepeat(arr) {
tmp = []
if (arr.length === 2 && arr[0] === arr[1]) {
return arr;
}
for (var i = 0;i<arr.length;i++) {
if (tmp.indexOf(arr[i]) === -1) {
tmp.push(arr[i])
}
}
return tmp
}
function SecondGreatLow(arr) {
arr = noRepeat(arr).sort(function (a,b) {return a-b;});
var low = arr[arr.indexOf(Math.min.apply(Math,arr))+1];
console.log("low",low);
var high = arr[arr.indexOf(Math.max.apply(Math,arr))-1];
console.log("high",high);
return low +" "+high;
}
console.log(SecondGreatLow([80,80]));
Output:
"low" 80
"high" undefined
"80 undefined"

That's, actually, ok. How do you want to find the second largest \ smallest number in an array of two similar numbers?
It should output "no solution" or something else. Just like there is no solution for an empty array.
function SecondGreatLow(arr)
{
arr = noRepeat(arr).sort(function (a,b) {return a-b;});
if (arr.length < 2)
return "No solution";
console.log("low ", arr[1]);
console.log("high ", arr[arr.length - 2]);
return low + " " + high;
}
You don't need Math min and max functions as your array is sorted and values are unique. You need to take the second from beginning and the second from the end.
Also, you don't need this part as it is calculated right by algorithm.
if (arr.length === 2)
{
return arr[1] + " " + arr[0];
}
For example, you have an array [1, 1, 2].
You remove repetitions and get [1, 2].
Now your algorithms returns low = arr[1] = 2 and high = arr[2 - 2] = arr[0] = 1.
The answer is correct - 2 is the second minimum number and 1 is the second largest.

Related

passing an array of arrays into a recursive function in javascript

I'm trying to do this problem where you are given an array of arrays. You start at the first item and them move either 1 item to the right or 1 item down depending on which item is bigger. the goal is to make it to the bottom right corner with the highest sum possible. Maybe I'm missing the point, but I figured this was a recursive function.
let map = [
[8,3,5],
[4,3,4],
[2,2,3]
]
const find = (y,x,map) => {
if (y === map.length - 1 && x === map[map.length - 1].length - 1){
return map[y][x]
} else if(map[y + 1][x] > map[y][x + 1]){
return map[y][x] + find(((y + 1), x,map))
} else {
return map[y][x] + find((y,(x + 1),map))
}
}
console.log(find(0,0,map))
In this case the goal is to get 22 via 8->4->3->4->3, but whenever I pass the map into the next level of recursion, the array on the next level reads as undefined. Is there any way to pass down the array of arrays so that it can be read by other levels of the recursive function?
If you like to get the greatest sum by moving only right or down, you could take an recursive approach by creating an exit condition first, with the last possible value and then take another exit condition if indices are out of bound (meybe here is a value of -Infinity better to omit this value).
Then take the real possible value and decide which value you like to return for getting a maximum.
const find = (map, i = 0, j = 0) => {
if (i + 1 === map.length && j + 1 === map[map.length - 1].length) return map[i][j];
if (i === map.length || j === map[map.length - 1].length) return 0;
let a = find(map, i + 1, j),
b = find(map, i, j + 1);
return map[i][j] + (a > b ? a : b);
}
let map = [[8, 3, 5], [4, 3, 4], [2, 2, 3]];
console.log(find(map));

Need help on Highest and Lowest (codewars)

Hello I'm stuck on an edge case in a coding challenge: would be great if someone could help;
In this little assignment you are given a string of space separated numbers, and have to return the highest and lowest number.
Example:
highAndLow("1 2 3 4 5"); // return "5 1"
highAndLow("1 2 -3 4 5"); // return "5 -3"
highAndLow("1 9 3 4 -5"); // return "9 -5"
Notes:
All numbers are valid Int32, no need to validate them.
There will always be at least one number in the input string.
Output string must be two numbers separated by a single space, and highest number is first.
Here is my code in Javascript:
function highAndLow(numbers){
numbers2=numbers.split(' ');
var highest =parseInt(numbers2[0]);
var lowest =parseInt(numbers2[0]);
if (numbers2.length==1) {
return numbers;
}
else {
for (i=0;i<numbers2.length;i++) {
if (parseInt(numbers2[i])>highest) {
highest = parseInt(numbers2[i]);
}
else if (parseInt(numbers2[i])<lowest) {
lowest = parseInt(numbers2[i]);
}
}
}
return(highest + " " + lowest);
}
I can pass 17 tests but am stuck on an Expected '42 42' because I am returning '42' which is puzzling to me. Any help appreciated :]
I think you should just add <= and >= instead of > and <so the both conditions are satisfied
You can also do it by sorting the array and then choosing the first and last element from the sorted array.
function highestAndLowest(nums) {
let numbers = nums.split(' ');
let sorted = numbers.sort(function (a, b) {
return Number(a) - Number(b);
});
return sorted[0] + " " + sorted[sorted.length - 1];
}
https://jsbin.com/farapep/edit?js,console
This can be faster depending on the browsers sort implementation, the size of the array, and the initial order of the array.
I think it will work well just like this
function highAndLow(numbers){
numbers = numbers.split(" ");
return Math.max(...numbers) +" "+ Math.min(...numbers);
}
if (numbers2.length==1) {
return numbers;
}
That means if just "42" passed, you return "42". Thats not required here. Just remove that and it should work. How i would write it:
function getMaxMin(numbers){
numbers = numbers.split(" ");
return Math.max(...numbers) +" "+ Math.min(...numbers);
}
or your code a bit beautified:
function getMaxMin(numbers){
var max,min;
numbers = numbers.split(" ");
for( var num of numbers ){
if( !max || num > max ) max = num;
if( !min || num < min ) min = num;
}
return max+" "+min;
}
Kotlin
fun highAndLow(numbers: String): String {
val s = numbers.split(" ").sorted()
return "${s.last()} ${s.first()}"
}
or in one line
fun highAndLow(numbers: String): String = numbers.split(" ").sorted().run { "${first()} ${last()}" }
Let us consider the given example:
highAndLow("1 2 3 4 5"); // return "5 1"
On calling function highAndLow with arguments ("1 2 3 4 5"), output should be "5 1".
So my function takes the argument. Each number is picked upon on the basis of space between them(used split method). I have used ParseInt to specify the datatype, because var can be anything(string/integer). The algorithm used is very basic one which considers the first number as the maximum and compares its with the rest of the arguments. Value of max is updated if it finds a number greater than itself. Same algorithm is used for min value also. The return statement is designed to get the value in specific way as mentioned in the example.
function highAndLow(numbers){
num=numbers.split(' ');
var max = parseInt(num[0]);
var min = parseInt(num[0]);
for (var i = 0; i <= num.length; i++) {
if(parseInt(num[i]) > max){
max = parseInt(num[i]);
}
}
for (var i = 0; i <= num.length; i++) {
if(parseInt(num[i]) < min){
min = parseInt(num[i]);
}
}
return (max + " " + min);
}
You can also use inbuilt methods min and max. I wanted to solve this question without using them.

Biggest sum from array without adding 2 consecutive value

I'm working on a challenge from codefights.com.
Given an array of integer (possibly negative) I need to return the biggest sum I can achieve without adding two consecutive integer (I can't change the order of the array).
Not easy to explain so here's a few examples:
input: [1, 2, 3, 4]: you're gonna pass the '1', take 2, can't take 3, take 4 and you get 6.
input: [1, 3, 1]: pass the '1', take 3 and you can't take 1 so you have 3.
I though I had it with this code :
function solve(vals) {
var even=0; var odd=0;
for(var i=0; i<vals.length; i++){
if(i%2==0){
even+=vals[i];
} else {
odd+=vals[i];
}
}
return Math.max(even, odd);
}
But then I got this testcase: [1,0,0,3] where it should return 4, skipping the two '0' which made me realize I've been looking at it all wrong.
And now I'm stuck, don't really know how to do it.
Any ideas ?
edit:
Using MrGreen's answer I got this:
function target_game(a) {
var dp=[], l=a.length-1;
dp[0]=a[0];
dp[1]=Math.max(a[0],a[1]);
for(var i=2; i<=a.length-1; i++){
dp[i]=Math.max(dp[i - 1], dp[i - 2] + a[i]);
}
return dp[l];
}
Which works fine unless the array contains negative value.
This input: [-1,0,1,-1] returns 0.
I'm still working on a fix but I'm editing the question to have a bullet proof solution :p
This is a classical dynamic programming problem.
Define dp[i] to be the maximum sum we can get if we consider the elements from 0 to i.
Then dp[i] = max(dp[i - 1], dp[i - 2] + a[i])
The intuition behind this, if you takea[i] in the sum then you cannot take a[i - 1]
Base cases: dp[0] = max(0, a[0]) and dp[1] = max(0, a[0], a[1])
You can check this lesson:
part-1 part-2 part-3 part-4
Here is the "best" answer from the challenge (shortest actually):
function solve(a) {
b = t = 0
for (i in a) {
c = b + a[i]
b = t
t = c > t ? c : t
}
return t
}
Here is a version where I renamed the variables to make it more understandable:
function solve(vals) {
prevTotal = total = 0
for (i in vals) {
alt = prevTotal + vals[i]
prevTotal = total
total = alt > total ? alt : total
}
return total
}

find median values from array in javascript (8 values or 9 values) [duplicate]

This question already has answers here:
Calculating median - javascript
(17 answers)
Closed 10 months ago.
How can i find median values from array in javascript
this is my array
var data = [
{ values: 4 },
{ values: 4 },
{ values: 4 },
{ values: 5 },
{ values: 2 },
{ values: 6 },
{ values: 6 },
{ values: 5 }
];
and i have tried this code
function findMedian(m) {
var middle = m.length - 1 / 2;
if (m.length - 1 % 2 == 1) {
return m[middle];
} else {
return (m[middle - 1] + m[middle]) / 2.0;
}
}
But it's return NaN value
My calculation formula is
Find the median of the data. Place the number of data in ascending order. Then, mark the place whose value we take into account when calculating the median.
This will do what you need - at the moment you've no logic to cope with reading the .values field out of each element of the array:
function findMedian(data) {
// extract the .values field and sort the resulting array
var m = data.map(function(v) {
return v.values;
}).sort(function(a, b) {
return a - b;
});
var middle = Math.floor((m.length - 1) / 2); // NB: operator precedence
if (m.length % 2) {
return m[middle];
} else {
return (m[middle] + m[middle + 1]) / 2.0;
}
}
EDIT I've padded out the code a bit compared to my original answer for readability, and included the (surprising to me) convention that the median of an even-length set be the average of the two elements either side of the middle.
For an array of numbers, e.g. [1,6,3,9,28,...]
// calculate the median
function median(arr){
arr.sort(function(a, b){ return a - b; });
var i = arr.length / 2;
return i % 1 == 0 ? (arr[i - 1] + arr[i]) / 2 : arr[Math.floor(i)];
}
What the code is doing:
Sort the numbers so that they are in order by value.
Find out the median's index in the array. If the array's length is even, the median is the average of the two numbers on either side of the index.
For arrays of odd length, it's easy to pluck out the middle number. But for arrays of even length, it's not. So, you test to find out whether your array is odd- or even-lengthed by finding out if dividing the array's length by two returns a whole number or not. If it's a whole number, that means the array's length is even, and you have to calculate the average of the two numbers on either side of the median.
In your question, your array can be flattened like so:
var myArray = data.map(function(d){ return d.values; });
And to get the median, use the function above like so:
var myMedian = median(myArray); // 4.5
Here about two things you have to be careful.
1) Operator precedence
When you are saying
var middle = m.length - 1 / 2;
It is same as
var middle = m.length - 0.5; //Because / has much precedence than -
So you should say
var middle = (m.length - 1) / 2;
Same problem with m.length - 1 % 2
2) You are not rounding middle so it's looking for decimal indexes in array. Which I think will return undefined.
In case you were wondering how to find median without using conditionals, here you are :)
Mind ES6.
/**
* Calculate median of array of numbers
* #param {Array<Number>} arr
* #return {Number}
*/
function median(arr) {
arr = [...arr].sort((a, b) => a - b);
return (arr[arr.length - 1 >> 1] + arr[arr.length >> 1]) / 2;
}
To answer the question:
median(data.map(x => x.values));
Here's a snippet that allows you to generate an array of numbers with either even or odd length. The snippet then sorts the array and calculates the median, finally printing the sorted array and the median.
(function() {
function makeNumArray(isEven) {
var randomNumArr = [];
var limit = isEven ? 8 : 9;
for (var i = 0; i < limit; i++) {
randomNumArr.push(Math.ceil(Math.random() * 10));
}
return randomNumArr;
}
function getMedian(arrOfNums) {
var result = [];
var sortedArr = arrOfNums.sort(function(num1, num2) {
return num1 - num2;
});
result.push("sortedArr is: [" + sortedArr.toString() + "]");
var medianIndex = Math.floor(sortedArr.length / 2);
if (arrOfNums.length % 2 === 0) {
result.push((sortedArr[medianIndex-1] + sortedArr[medianIndex]) / 2);
return result;
} else {
result.push(sortedArr[medianIndex]);
return result;
}
}
function printMedian(resultArr) {
var presentDiv = document.querySelector('#presentResult');
var stringInsert = '<div id="sortedArrDiv">' + resultArr[0].toString() + '<br>' + 'the median is: ' + resultArr[1].toString() + '</div>';
if (!document.querySelector('#sortedArrDiv')) {
presentDiv.insertAdjacentHTML('afterbegin', stringInsert);
} else {
document.querySelector('#sortedArrDiv').innerHTML = resultArr[0].toString() + "<br>" + 'the median is: ' + resultArr[1].toString();
}
};
function printEven() {
printMedian(getMedian(makeNumArray(1)));
}
function printOdd() {
printMedian(getMedian(makeNumArray(0)));
}
(document.querySelector("#doEven")).addEventListener('click', printEven, false);
(document.querySelector("#doOdd")).addEventListener('click', printOdd, false);
})();
#presentResult {
width: 70%;
margin: 2% 0;
padding: 2%;
border: solid black;
}
<h4>Calculate the median of an array of numbers with even (static length of 8) or odd (static length of 9) length. </h4>
<input type="button" value="Even length array of random nums" id="doEven">
<input type="button" value="Odd length array of random nums" id="doOdd">
<div id="presentResult"></div>
function median(a){
let arrlength = a.length;
if((arrlength%2) == 0){
let c = arrlength/2;
let b = (a[c]+a[c-1])/2;
return b;
}
else{
let e=Math.floor(arrlength/2);
return a[e];
}
}
median([1, 2, 10, 100]);
Try this simple one.
Findmedian(arr) {
arr = arr.sort(function(a, b){ return a - b; });
var i = arr.length / 2;
var result = i % 1 == 0 ? parseInt((arr[i - 1] + arr[i]) / 2) + ',' +
parseInt(arr[i]) : arr[Math.floor(i)];
return result;
}
it returns for odd number of array elements.

Find subset of elements in an array that when summed equal any other element in the array

I'd like to write an algorithm in Javascript for the following problem.
Given the following array [1,2,3,4,6], provide the number of subsets that equal any other element in the array.
For instance:
1+2 = 3
1+3 = 4
2+4 = 6
1+2+3 = 6
Answer: 4 subsets
I can calculate the sum of pairs of numbers that equal any other element in the array; however, I cannot find the sum of 2 or more elements (1+2+3) that equal any other element in the array.
How would I write an algorithm for this? Thanks!
Here's a very simple solution that should be easy to grasp. Note that this is not a very fast algorithm, but for shorter arrays it works well.
The idea is to generate a bit mask for every combination, and then for each mask add the numbers in the array indicated by a 1 in the bit mask string:
console.log("Number of subsets: " + getNumberOfSubsets([1, 2, 3, 4, 6], 2));
function getNumberOfSubsets(numbers, minimumNumbersInSubset) {
var numberOfBits = Math.pow(2, numbers.length);
var numOfSubsets = 0;
for (var i=0;i<numberOfBits;i++) {
var bitField = i.toString(2);
while(bitField.length < numbers.length) {
bitField = "0" + bitField;
}
var sum = 0;
var addedNumbers = [];
for (j=0;j<bitField.length;j++) {
if (bitField.charAt(j) == "1") {
sum += numbers[j];
addedNumbers.push(numbers[j]);
}
}
if (addedNumbers.length >= minimumNumbersInSubset && numbers.indexOf(sum) !== -1) {
numOfSubsets += 1;
console.log("Iteration " + i + ": " +
bitField+", " + (addedNumbers.join("+") + "=" + sum));
}
}
return numOfSubsets;
}
Outputs the following in the console to show the successful combinations:
Iteration 10: 01010, 2+4=6
Iteration 20: 10100, 1+3=4
Iteration 24: 11000, 1+2=3
Iteration 28: 11100, 1+2+3=6
Number of subsets: 4
Here's a jsfiddle: http://jsfiddle.net/9HhSs/

Categories

Resources