Comparing elements in an array, finding the largest sum of the elements - javascript

I am attempting to write a single function in javascript that compares credit card numbers listed strings within an array. The function should find the credit card number with the largest sum, and return that number as the original string within the input array. I am completely stuck, and cannot get past this 'undefined' error message. Here is what I have:
function highest(inputArray) {
var sum = 0;
var currentHighest = 0;
var largest = 0;
for (a = 0; a < inputArray.length; a++) {
var tempArray = inputArray[a].replace(/\D/g, '');
}
function sumDigits(str) {
sum = 0;
for (i = 0; i < str.length; i++) {
sum += parseInt(str.charAt(i), 16);
}
return sum;
}
if (sumDigits(tempArray) >= currentHighest) {
currentHighest = sum;
largest = inputArray[a];
return largest;
} else {
return largest;
}
}
var numberArray = [];
console.log(highest(numberArray));

You have a good number of basic errors in your code. Rather than break it down, I will simply put the code revision in here.
var ipa = ['4916-2600-1804-0530', '4779-2528-0088-3972', '4252-2788-0093-7978', '4556-4242-9283-2260'];
function highest(inputArray) {
var currentHighest = 0;
var largest = 0;
var tempArray = [];
for (var a = 0; a < inputArray.length; a++) {
tempArray.push(inputArray[a].replace(/\D/g, ''));
}
function sumDigits(strA) {
var sum = 0;
for (var i = 0; i < strA.length; i++) {
sum += parseInt(strA.charAt(i), 10);
}
return sum;
}
for (var a = 0; a < tempArray.length; a++) {
var csum = sumDigits(tempArray[a]);
if (csum >= currentHighest) {
currentHighest = csum;
largest = inputArray[a];
}
}
return largest;
}
console.log(highest(ipa));

'use strict';
// initial array of numbers
let numbers = ['4916-2600-1804-0530', '4779-2528-0088-3972', '4252-2788-0093-7978', '4556-4242-9283-2260'];
// remove "-" symbol
let normilized = numbers.map(number => number.replace(/-/g, ''));
// get sum for each number
let sums = normilized.map(
number => [].reduce.call(number, (prev, value) => {
prev += +value;
return prev;
}, 0));
// find max sum
let max = Math.max.apply(null, sums);
// find position of that sum
let indexOfMax = sums.indexOf(max);
// get card number
console.log(numbers[indexOfMax]);

Based on my understanding of your question, I hope this is what you are looking for.
In addition to doing a basic loop over the array, you can also sort the array in ascending order and simply pick out the last item of the array for your largest credit card number.
Sample Fiddle here:
https://jsfiddle.net/xxo3m8zf/1/
Sample Function:
function largestSum(arr) {
arr.sort();
return largest = arr[arr.length-1];
}

Related

Finding the sum of a "counter" variable loop that ran ten times then was pushed into the "numbers" array. Each way I tried resulted with a list

I'm asking for help to find the sum of an array with elements that were pushed from a counter variable that had previously looped 10 times. I'm new to Javascript and was practicing for an assessment, and I've tried several different ways to do it and have only resulted with just a list of the elements within the numbers array.
var counter = 10;
var numbers = [];
for (i = 1; i <= 10; i ++) {
counter = [i + 73];
numbers.push(counter);
}
console.log(numbers);
function sum(arr) {
var s = 0;
for(var i = 0; i < arr.length; i++) {
s = s += arr[i];
}
return s;
}
console.log(sum([numbers]));
function getArraySum(a) {
var total = 0;
for (var i in a) {
total += a[i];
}
return total;
}
var numbers = getArraySum([numbers]);
console.log(numbers);
you should push only the value of counter without the brackets and then make a reduce to have the sum of each number in the array
var counter = 10;
var numbers = [];
for (i = 1; i <= 10; i++) {
counter = i + 73;
numbers.push(counter);
}
console.log(numbers.reduce((a,b) => a+b));
You had a couple of typos in the code:
Typos
You were wrapping the sum in square brackets:
counter = [i + 73];
You should just remove the brackets like:
counter = i + 73;
2. You were wrapping a value that is already an array in square brackets while passing it as an argument to a function:
sum( [numbers] )
// ...
getArraySum( [numbers] );
You should remove the brackets, like this:
sum( numbers );
// ...
getArraySum( numbers );
Fix
I updated the code that you shared to fix the above-mentioned things:
var numbers = [];
// Loop 10 times and push each number to the numbers array
for (var i = 1; i <= 10; i ++) {
var sumNumbers = i + 73;
numbers.push(sumNumbers);
}
console.log(numbers);
function sum(arr) {
var total = 0;
for(var i = 0; i < arr.length; i++) {
total += arr[i];
}
return total;
}
// Call the function by passing it the variable numbers, holding an array
var result1 = sum(numbers);
console.log( result1 );
function getArraySum(a) {
var total = 0;
for (var i in a) {
total += a[i];
}
return total;
}
var result2 = getArraySum(numbers);
console.log(result2);

Splitting Numbers and adding them all - JavaScript

I have a function that returns the sum of all its digits For both POSITIVE and NEGATIVE numbers.
I used split method and converted it to string first and then used reduce to add them all. If the number is negative, the first digit should count as negative.
function sumDigits(num) {
var output = [],
sNum = num.toString();
for (var i = 0; i < sNum.length; i++) {
output.push(sNum[i]);
}
return output.reduce(function(total, item){
return Number(total) + Number(item);
});
}
var output = sumDigits(1148);
console.log(output); // --> MUST RETURN 14
var output2 = sumDigits(-316);
console.log(output2); // --> MUST RETURN 4
Instead of returning the sum, it returned 4592 -1264
Am I doing it right or do I need to use split function? Or is there any better way to do this?
Sorry newbie here.
I think you'll have to treat it as a string and check iterate over the string checking for a '-' and when you find one grab two characters and convert to an integer to push onto the array. Then loop over the array and sum them. Of course you could do that as you go and not bother pushing them on the array at all.
function sumDigits(num) {
num = num + '';
var output = [];
var tempNum;
var sum = 0;
for (var i = 0; i < num.length; i++) {
if (num[i] === '-') {
tempNum = num[i] + num[i + 1];
i++;
} else {
tempNum = num[i];
}
output.push(parseInt(tempNum, 10));
}
for (var j = 0; j < output.length; j++) {
sum = sum + output[j];
}
return sum;
}
var output = sumDigits(1148);
console.log(output); // --> MUST RETURN 14
var output2 = sumDigits(-316);
console.log(output2); // --> MUST RETURN 4

longest substring of non repeating characters javascript

The problems asks "given a string, find the longest non-repeating sub-string without repeating characters". I am a little stumped why returning my code is not working for the string "dvdf" for example. Here is my code :
function lengthOfLongestSubstring(check) {
var letters = check.split("");
var max = 0;
var result = [];
for (var i = 0; i < letters.length; i++) {
var start = i
if (result.indexOf(letters[i]) === -1) {
result.push(letters[i])
} else {
i = i - 1
result = []
}
if (max === 0 || max < result.length) {
max = result.length
}
}
return max
}
This implementation gives the correct result for "dvdf".
It adds characters to current_string while there is no duplicate. When you find a duplicate cut current_string to the point of the duplicate. max is the max length current_string had at any time. This logic seems correct to me so I think it's correct.
function lengthOfLongestSubstring(string) {
var max = 0, current_string = "", i, char, pos;
for (i = 0; i < string.length; i += 1) {
char = string.charAt(i);
pos = current_string.indexOf(char);
if (pos !== -1) {
// cut "dv" to "v" when you see another "d"
current_string = current_string.substr(pos + 1);
}
current_string += char;
max = Math.max(max, current_string.length);
}
return max;
}
lengthOfLongestSubstring("dvdf"); // 3
The value of current_string in each round is "", "d", "dv", "vd", "vdf".
By replacing the result array with a map storing the last index for each encountered character, you can modify the loop body to jump back to one after the last index of an identical character and continue your search from there instead of just restarting from the current position via currently i = i - 1 which fails in cases such as 'dvdf':
Below is your code with changes to accommodate a map in place of an array:
function lengthOfLongestSubstring(check) {
var letters = check.split("");
var max = 0;
var result = new Map();
var start = 0;
for (var i = 0; i < letters.length; i++) {
if (!result.has(letters[i])) {
result.set(letters[i], i);
} else {
i = result.get(letters[i]);
result.clear();
}
if (max < result.size) {
max = result.size;
}
}
return max;
}
// Example:
console.log(lengthOfLongestSubstring("dvdf")); // 3
Here's a solution using Sliding window and HashMap.
var lengthOfLongestSubstring = function(str) {
if (!!!str.length || typeof str !== 'string') return 0;
if (str.length == 1) return 1;
let hashTable = {};
let longestSubstringLength = 0;
let start = 0;
for (let i = 0; i < str.length; i++) {
if (hashTable[str[i]] !== undefined && hashTable[str[i]] >= start) {
start = hashTable[str[i]] + 1;
}
hashTable[str[i]] = i;
longestSubstringLength = Math.max(longestSubstringLength, (i - start + 1))
}
return longestSubstringLength;
}
I figured out an easier solution:
function longestSubstring(str) {
let left = 0;
let max = 0;
let result = new Set();
for (let r = 0; r < str.length; r++) {
//The code will check for an existing item on the set
// If found, all the previously saved items will be deleted
// the set will return to being empty
while (result.has(str[r])) {
result.delete(str[left]);
left += 1;
}
result.add(str[r]);
max = Math.max(max, r - left + 1);
}
console.log(result);
return max;
}
console.log(longestSubstring('abcabccbc')); //3
Today (January 7th, 2021) this was the Leetcode question of the day. I initially used a solution very similar to the selected answer. Performance was okay but after reviewing the answer solution documentation I rewrote my answer using the sliding window technique (examples were only in Java and Python) since I was curious about how much of a performance improvement this would result in. It is slightly more performant (144ms versus 160ms) and has a lower memory footprint (42mb versus 44.9mb):
function lengthOfLongestSubstring(s: string): number {
let stringLength = s.length;
let maxLength = 0;
const charMap = new Map();
let pos = 0;
for (let i = 0; i < stringLength; i++) {
if (charMap.has(s[i])) {
pos = Math.max(charMap.get(s[i]), pos);
}
maxLength = Math.max(maxLength, i - pos + 1);
charMap.set(s[i], i + 1);
}
return maxLength;
}
console.log(lengthOfLongestSubstring("dvdf"));
Try this:
function lengthOfLongestSubstring (str) {
const map = new Map();
let max = 0;
let left = 0;
for (let right = 0; right < str.length; right++) {
const char = str[right];
if (map.get(char) >= left) left = map.get(char) + 1;
else max = Math.max(max, right - left + 1);
map.set(char, right);
}
return max;
}
You can try this:
function lengthOfLongestSubstring(str) {
let longest = "";
for (let i = 0; i < str.length; i++) {
if (longest.includes(str[i])) {
return longest.length
} else {
longest += str[i];
}
}
return longest.length;
}
console.log(lengthOfLongestSubstring("abcabcbb"));
console.log(lengthOfLongestSubstring("bbbbb"));
console.log(lengthOfLongestSubstring("abcdef"));
console.log(lengthOfLongestSubstring(""));
reset i to i -1 is incorrect. you need another loop inside the for loop. you try something like this (i didn't check the index carefully).
function lengthOfLongestSubstring(check){
var letters = check.split("");
var max = 0;
for (var i = 0; i < letters.length; i++) {
var result = [];
var j = i;
for(;j < letters.length; j++) {
if (result.indexOf(letters[j]) === -1) {
result.push(letters[j]);
} else {
break;
}
}
if(j - i > max) {
max = j - i;
}
}
return max;
}
You can try sliding window pattern to solve this problem.
function lengthOfLongestSubstring(str) {
let longest = 0;
let longestStr = "";
let seen = {};
let start = 0;
let next = 0;
while (next < str.length) {
// Take current character from string
let char = str[next];
// If current character is already present in map
if (seen[char]) {
// Check if start index is greater than current character's last index
start = Math.max(start, seen[char]);
}
// If new substring is longer than older
if (longest < next - start + 1) {
longest = next - start + 1;
// Take slice of longer substring
longestStr = str.slice(start, next + 1);
}
// Update current characters index
seen[char] = next + 1;
// Move to next character
next++;
}
console.log(str, "->", longestStr, "->", longest);
return longest;
}
lengthOfLongestSubstring("dvdfvev");
lengthOfLongestSubstring("hello");
lengthOfLongestSubstring("1212312344");
Find Longest Unique Substring using Map Method
var str = "aaabcbdeaf";
var start = 0;
var map = new Map();
var maxLength = 0;
var longStr = '';
for(next =0; next< str.length ; next++){
if(map.has(str[next])){
map.set(str[next],map.get(str[next])+1);
start = Math.max(start,map.get(str[next]));
}
if(maxLength < next-start+1){
maxLength = next-start+1;
longStr = str.slice(start,next+1);
}
map.set(str[next],next);
}
console.log(longStr);
You can try something like that:
function maxSubstring(s) {
const array = []
const lengthS = s.length
const pusher = (value) => {
if (value !== '') {
if (array.length > 0) {
if (array.indexOf(value) === -1) {
array.push(value)
}
} else {
array.push(value)
}
}
}
pusher(s)
for (const [index, value] of s.split('').entries()) {
let length = lengthS
let string = s
const indexO = s.indexOf(value)
pusher(value)
while (length > indexO) {
pusher(string.slice(index-1, length + 1))
length = --length
}
string = s.slice(index, lengthS)
}
array.sort()
return array.pop()
}
console.log(maxSubstring('banana'))
console.log(maxSubstring('fgjashore'))
console.log(maxSubstring('xyzabcd'))
Find Longest unique substring without using MAP(). Just simple slice().
The same can be used to return longest unique string.
Just replace "return max => return str"
const string = "dvdf";
var lengthOfLongestSubstring = function() {
if(string.length == 1) return 1;
if(string.length == 0) return 0;
let max = 0,i = 0, str = "";
while(i < string.length){
const index = str.indexOf(string.charAt(i));
if(index > -1) {
// s = "fiterm".slice(1,4) => ite
str = str.slice(index + 1, string.length);
}
str += string.charAt(i);
max = Math.max(str.length, max);
i++;
}
return max;
};
Logest unqiue substring:
function lengthOfLongestSubstring(s) {
if(s.length < 2) {
return s.length;
}
let longestLength = 1;
let currentStr = '';
for(let i=0 ; i < s.length ; i++){
if(currentStr.includes(s.charAt(i))){
let firstSeen = currentStr.indexOf(s.charAt(i));
currentStr = currentStr.substring(firstSeen+1,currentStr.length);
}
currentStr += s.charAt(i);
longestLength = Math.max(currentStr.length,longestLength);
}
return longestLength;
};
One liner with reduce method.
const subStrOfUniqueChar = str => [...str].reduce((p,c) => ( p.includes(c) ? (p += c, p.substr(p.indexOf(c)+1)) : p += c),'');
console.log(subStrOfUniqueChar('dvdf').length);
function lengthOfLongestSubstring(s: string): number {
const arr = s.split("");
let longest = 0;
const set: Set<string> = new Set();
for (let i = 0; i < arr.length; i++) {
set.add(arr[i]);
let tryIndex = i + 1;
while (arr[tryIndex] && !set.has(arr[tryIndex])) {
set.add(arr[tryIndex]);
tryIndex++;
}
if (set.size > longest) {
longest = set.size;
}
set.clear();
}
return longest;
}
I wanted to toss my hat in this ring because I feel like I've found a pretty creative solution to this. No if/else blocks are needed as the substring.indexOf() will attempt to find the matching string character in the array and delete the indexes of the array up to, and including, the match (+1). If an indexOf() call finds no match it will return a -1, which added to +1 becomes a .splice(0,0) which will remove nothing. The final Math check factors in the last character addition in the loop to determine which outcome is higher.
const findSubstring = string => {
let substring = [];
let maxCount = 0;
for (let i = 0; i < string.length; i++) {
maxCount = Math.max(substring.length, maxCount);
substring.splice(0, substring.indexOf(string[i]) + 1);
substring.push(string[i]);
}
maxCount = Math.max(substring.length, maxCount);
return maxCount;
}
uses sliding window concept
function lengthOfLongestSubstring(s) {
var letters = s.split("");
var subStr = "";
var result = [];
var len = 0;
let maxLen = 0;
for (var i = 0; i < letters.length; i++) {
const position = result.indexOf(letters[i]);
if (position === -1) {
result.push(letters[i]);
len += 1;
} else if (letters[i]) {
result = result.splice(position + 1);
len = result.length + 1;
result.push(letters[i]);
}
maxLen = len > maxLen ? len : maxLen;
}
return maxLen;
}
console.log(lengthOfLongestSubstring(" "));
Sliding Window Technique O(n)
you can use hash or Map in
loop through string char
Maintain dictionary of unique char
if char exist in memory take clear hash update the count in longest variable and clear count
start from first repeated char + 1 again.
var lengthOfLongestSubstring = function(s) {
if(s.length<2) return s.length;
let longest = 0;
let count=0;
let hash={}
for (let i = 0; i < s.length; i++) {
//If char exist in hash
if(hash[s[i]]!=undefined){
i=hash[s[i]];
hash={}
longest = Math.max(longest, count);
count = 0;
}else{
hash[s[i]]=i
count = count+1;
}
}
return Math.max(longest, count);
};
console.log(lengthOfLongestSubstring("abcabcbb"))
console.log(lengthOfLongestSubstring("au"))

Return a piece of an array after finding the highest integer in java script?

So after working on finding the highest sum of any given amount of credit card numbers I realized I dug myself into a bit of a hole. (currently using 3 cards "123-123, 234-234 and 345-345" as test numbers.) After writing this out:
var howM = prompt("How many cards?")
var arr = [];
for(var i = 0; i < howM; i++)
arr.push(prompt("Enter a card:"));
console.log(arr)
var sumpre = [];
for(var i = 0; i < howM; i++) {
var sum = 0;
var eXt = arr[i];
eXt = eXt.replace (/-/g, "");
for (var j = 0; j < eXt.length; j++) {
sum += parseInt(eXt.substr(j, 1));
}
sumpre.push(sum);
}
console.log(sumpre);
var highest = sumpre[0];
for (var i=1; i<=sumpre.length; i++){
if (sumpre[i]>highest){
highest=sumpre[i];
}
}
console.log(highest)
Which works to find the highest sum, however; I need it to return the card number with the highest sum in its original form at the end and am not sure what method would be best to get back to that or if I should reformat it from the start.
As I mentioned in a comment, or as shown in Gerardo's answer, one way to do it with minimal changes to your current code is to use highest to keep the index of the array item with the highest value, instead of keeping the actual value itself - then you could retrieve the original card value via that index.
But for fun, here's another way to do it:
function sumDigitsInString(s) {
return Array.prototype.reduce.call(s, function(p, c) { return p + (+c || 0); }, 0);
}
function itemWithLargestSum(a) {
return a.reduce(function(p, c) {
var sum = sumDigitsInString(c);
return p[0] > sum ? p : [sum, c];
}, [0])[1];
}
// given an array of strings:
var input = ["123-123", "234-234", "345-345", "111-111"];
var largest = itemWithLargestSum(input);
console.log(largest);
Further reading:
.call() method
Array .reduce()
Unary plus operator
|| operator
?: (ternary) operator
You could also do something like this, just with Array methods.
var inputCards = ["989-000", "123-999", "456-456"];
var sum = 0,
sumNumbers = {},
maxVal = 0;
inputCards.map(function(num) {
var replaceText = new RegExp(/-/g);
var number = num.replace(replaceText, "").split("");
var prevVal = 0;
sumNumbers[num] = number.reduce((prevVal, currentVal) =>
parseInt(prevVal, 10) + parseInt(currentVal, 10));
});
console.log(Object.keys(sumNumbers).reduce((maxVal, currentVal) =>
sumNumbers[maxVal] > sumNumbers[currentVal] ? maxVal : currentVal));

Strange performance quirk in javascript

I experience a strange differences in performance of simple task depending of array I am working with. The task is to calculate sum of those elements in array which are greater than 5. Task is performed on arrays with equal lenghts.
I try the very same approach on three different array objects:
1) var hugeArray1 - array with all elemenets randomly picked from 0:10 range
2) var hugeArray2 - copy of hugeArray1 sorted with Array.prototype.sort()
3) var hugeArray3 - handcrafted but sorted array with values from 0:10 range, spread to equaly cover this interval.
I try to calculate sum of elements greater than 5 many times for each Array and then average them. What is strange, time needed varies a lot for those three arrays.
1) hugeArray1: 5.805ms
2) hugeArray2: 15.738ms
3) hugeArray3: 3.753ms
Result for array sorted with sort() is extreamly poor. Why is that? it looks like sort() returns some kind of wraper/proxy instead of 'native' Array, which affects performance. I tried it on 2 computers. Also i tried to change order of testing.
I include code below, please tell me what is happening here.
// random array with elements 0-10 of size n
function randomArray(n) {
var arr = [];
for (var i = 0; i < n; ++i) {
arr.push(Math.random() * 10);
}
return arr;
};
// measures time of execution
function measureTime(f) {
var start = new Date().getTime();
f();
var stop = new Date().getTime();
return stop - start;
};
// enumerate ofer array and calculate sum of elementsgreater than 5
function sumGreaterThan5(arr) {
var sum = 0;
for (var i = 0; i < arr.length; ++i) {
if (arr[i] > 5.0)
sum += arr[i];
}
return sum;
}
// generate array os size 'size' with elements with constant step to fill interval 0:10
function generateSortedArr(size) {
var arr = [];
for (var i = 0; i < size; ++i) {
arr.push(i * 10 / size);
}
return arr;
}
var huge = 1000000;
var hugeArray1 = randomArray(huge);
var hugeArray2 = hugeArray1.slice(0).sort();
var hugeArray3 = generateSortedArr(huge);
var hugeArrays = [hugeArray1, hugeArray2, hugeArray3];
hugeArrays.forEach(x=> {
var res = [];
for (var i = 0; i < 1000; ++i) {
res.push(measureTime(function () {
sumGreaterThan5(x);
}));
}
console.log(res.reduce((prev, curr)=> prev + curr) / res.length);
});
// random array with elements 0-10 of size n
function randomArray(n) {
var arr = [];
for (var i = 0; i < n; ++i) {
arr.push(Math.random() * 10);
}
return arr;
};
// measures time of execution
function measureTime(f) {
var start = new Date().getTime();
f();
var stop = new Date().getTime();
return stop - start;
};
// enumerate ofer array and calculate sum of elementsgreater than 5
function sumGreaterThan5(arr) {
var sum = 0;
for (var i = 0; i < arr.length; ++i) {
if (arr[i] > 5.0)
sum += arr[i];
}
return sum;
}
// generate array os size 'size' with elements with constant step to fill interval 0:10
function generateSortedArr(size) {
var arr = [];
for (var i = 0; i < size; ++i) {
arr.push(i * 10 / size);
}
return arr;
}
var huge = 1000000;
var hugeArray1 = randomArray(huge);
var hugeArray2 = hugeArray1.slice(0).sort();
var hugeArray3 = generateSortedArr(huge);
var hugeArrays = [hugeArray1, hugeArray2, hugeArray3];
hugeArrays.forEach(function(x){
var res = [];
for (var i = 0; i < 1000; ++i) {
res.push(measureTime(function () {
sumGreaterThan5(x);
}));
}
console.log(res.reduce(function(prev, curr){return prev + curr},0) / res.length);
});

Categories