finding largest sum of array of credit cards - javascript

I am interested in finding the credit card number whose digits sum to the largest number. If more than one has the same largest sum of digits, I want the last one in the list with that sum.
I am trying to write a single function that takes one argument. That argument will be an array of credit card numbers. Assume the array can have any number of credit card numbers and each one is a string of digits and dashes. The function should return the credit card number that has the largest sum of digits.
Here is what I have so far-
function getSum(stringLength) {
var stringLength = ['1476-0089-5132-7420', '2034-6002-3978-5567', '6647-1123-5895-0038'];
var i;
for (i = 0; i < stringLength; i++);
for (string = 0; string < [3]; stringLength++);
//stringLength + i =Sum ;
if (0 > 1, 2) {
return string(0);
} else if (1 > 0, 2) {
return string(1);
} else(2 > 1, 0) {
return string(2);
}
console.log('1476-0089-5132-7420', '2034-6002-3978-5567', '6647- 1123-5895-0038');
console.log('The Larget Sum is:' + true);
}
/*criteria for code: Contain all variables and code needed within a function.
Have that function take one argument which will be an array of credit card number strings.
Determine the sum of digits for each credit card number.
Determine which credit card number has the last largest sum of digits.
Use a return statement to return the required card number in its’ original form.*/

You can try this approach:
Note: ;is used to end a statement, so when you do for(...); loop ends there and it does not do anything.
var cardNos = ['1476-0089-5132-7420', '2034-6002-3978-5567', '6647-1123-5895-0038'];
var largestSum = cardNos.reduce(function(p,c){
return Math.max(p, getSumOfDigits(c))
}, 0);
function getSumOfDigits(str){
var s = str.replace(/[^0-9]/g, '').split("");
return s.reduce(function(p,c){ return +p + +c});
}
console.log(largestSum);

Related

Calculate an alphabetic score for a word

How can I generate a numeric score for a string, which I can later user to order things alphabetically?
(I'd like to add objectIds to a redis sorted set based on a name property. This needs a numeric score. My list-of-things might be too big to sort all at once, hence wanting to score each item individually)
Words earlier in an alphabetic list should have a lower score, with 'a' = 0.
My naive approach so far; (letter alphabetic position from Replace a letter with its alphabet position )
function alphaScoreString(inputString) {
let score = 0
inputString
.trim()
.toLowerCase()
.split('')
.map((letter, index) => {
const letterNumber = parseInt(letter, 36) - 10
if (letterNumber >= 0) {
score += letterNumber / (index + 1)
}
})
return score * 1000
}
This does not work, as
alphaScoreString('bb')
1500
alphaScoreString('bc')
2000
alphaScoreString('bbz')
9833.333333333334
You can see that 'bbz' has a higher score than 'bc', whereas it should be lower, as 'bbz' would come before 'bc' in an alphabetical list.
You can convert each character to its unicode (and ensure that every character is 4 digits by padding the string. e.g. "H" = 72 but is padded to 0072: Doing a word by word comparison, you can still determine the 'alphabetical order' of each string:
var instring = "Hello World";
var output = "";
for(i=0; i<instring.length;i++){
const newchar = String(instring.charCodeAt(i)).padStart(4, '0');
output = output.concat(newchar)
console.log(output);
}
Answer writen in python.
char_codex = {'a':0.01, 'b':0.02, 'c':0.03, 'd':0.04, 'e':0.05, 'f':0.06,
'g':0.07, 'h':0.08, 'i':0.09, 'j':0.10, 'k':0.11, 'l':0.12,
'm':0.13, 'n':0.14, 'o':0.15, 'p':0.16, 'q':0.17, 'r':0.18,
's':0.19, 't':0.20, 'u':0.21, 'v':0.22, 'w':0.23, 'x':0.24,
'y':0.25, 'z':0.26}
def alphabetic_score(word):
bitwiseshift = '1'
scores = [0.00] * len(word)
for index, letter in enumerate(word.lower()):
if index is 0:
scores[index] = char_codex[letter]
else:
bitwiseshift = bitwiseshift+'00'
scores[index] = char_codex[letter]/int(bitwiseshift)
return sum(scores)

How to get a JavaScript factorial programs' loop to show the working used?

Hello there I have been challenged to write a program in JavaScript despite not really knowing much about it that asks the user for a number and then calculates the factorial of that number. I used already asked questions and managed to get the calculation to work but couldn't get the required output. I have to get it in the following output without using any fancy libraries or extra variables/arrays (which I can't think of how to do) :
(assuming user input is 5):
The factorial of 5 is 5*4*3*2*1=120
OR
5! is 5*4*3*2*1=120
Here is the code I've got so far:
//prompts the user for a positive number
var number = parseInt(prompt("Please enter a positive number"));
console.log(number);
//checks the number to see if it is a string
if (isNaN(number)) {
alert("Invalid. Please Enter valid NUMBER")
}
//checks the number to see if it is negaive
else if (number < 0) {
alert("Please Enter valid positive number");
}
//if a positive integer is entered a loop is started to calculate the factorial of the number the user entered
else {
let factorial = 1;
for (count = 1; count <= number; count++) {
factorial *= count;
}
//Sends the inital number back to the user and tells them the factorial of that number
alert("The factorial of " + number + " is " + factorial + ".");
}
I know there are many similar questions to this as I looked around and used them to help me get this far but it is getting the output into the required format that I'm struggling with. I am told it is possible with a loop but don't know where to begin implementing that and I'm only allowed to use that solution.
Unfortunately this is part of a larger program in the challenge and I can only use the following variables:
Number (variable initialised as 0 to hold user input)
Factorial (variable initialised to 1 to hold value of calculated factorial)
Count (variable to hold number of times loop is executed for performing factorial calculation)
Probably you just need to build a string in that loop (on top of calculating the actual value):
let input=parseInt(prompt("Number?"));
let output="";
let result=1;
for(let i=input;i>1;i--){
result*=i;
output+=i+"*";
}
console.log(input+"! is "+output+"1="+result);
The "no-array clause" in your task presumably means that you are not supposed to build an array and use join() on it, like
let arr=[1,2,3,4,5];
console.log(arr.join("*"));
I have updated your code mainly here, Also make sure you are using the same variable num in your code and not number:
let factorials = [];
let result = 1;
for (count = num; count >= 1; count--) {
result *=count;
factorials.push(count);
}
//prompts the user for a positive number
var num = parseInt(prompt("Please enter a positive number"));
console.log(num);
//checks the number to see if it is a string
if (isNaN(num))
{
alert("Invalid. Please Enter valid NUMBER")
}
//checks the number to see if it is negaive
else if (num < 0)
{
alert("Please Enter valid positive number");
}
//if a positive integer is entered a loop is started to calculate the factorial of the number the user entered
else {
let factorials = [];
let result = 1;
for (count = num; count >= 1; count--) {
result *=count;
factorials.push(count);
}
//Sends the inital number back to the user and tells them the factorial of that number
alert("The " + num + "! is " + factorials.join('*') + " is " + result + ".");
}

How to make JS function faster/reduce complexity 0(n)/more efficient

I am working on some challenges on HackerRank and I am having some troubles with making functions faster/more efficient so that it does not timeout during the submit process. It usually times out for really large inputs (ex: string length of 1000 or more) with the number of loops I am using to get the function working. I know the loops make the complexity 0(n * n) or 0(n * n * n). I understand why the function is timing out because of the above complexity issue but I am not sure of how to make the function more efficient in order to handle larger inputs. I am a self-taught coder so please explain any answers thoroughly and simply so I can learn. Thanks!
Here is an example problem:
A string is said to be a special palindromic string if either of two conditions is met:
All of the characters are the same, e.g. aaa.
All characters except the middle one are the same, e.g. aadaa. (acdca will not satisfy this rule but aadaa will)
A special palindromic substring is any substring of a string which meets one of those criteria. Given a string, determine how many special palindromic substrings can be formed from it.
For example, given the string s = mnonopoo, we have the following special palindromic substrings:
m, n, o, n, o, p, o, o
oo
non, ono, opo
Function Description
Complete the substrCount function in the editor below. It should return an integer representing the number of special palindromic substrings that can be formed from the given string.
substrCount has the following parameter(s):
n: an integer, the length of string s
s: a string
function substrCount(n, s) {
//if each letter is its own palindrome then can start with length for count
let count = n;
//space used to get the right string slices
let space = 1;
//so we only get full strings with the split and no duplicates
let numberToCount = n;
for(let i = 0; i < n; i++){
for(let j = 0; j < n; j++){
//slice the string into the different sections for testing if palindrome
let str = s.slice(j, j+space);
if(numberToCount > 0){
//if it is an even length the all characters must be the same
if(str.length % 2 === 0){
let split = str.split('');
let matches = 0;
for(let k = 0; k < split.length; k++){
if(split[k] === split[k+1]){
matches++;
}
}
if(matches === split.length -1){
count++;
}
//if it is not even then we must check that all characters on either side
//of the middle are all the same
} else {
if(str.length > 1){
let splitMid = Math.floor(str.length / 2);
let firstHalf = str.slice(0, splitMid);
let lastHalf = str.slice(splitMid+1, str.length);
if(firstHalf === lastHalf){
if(str.length === 3){
count++;
} else {
let sNew = firstHalf + lastHalf;
let split = sNew.split('');
let matches = 0;
for(let k = 0; k < split.length; k++){
if(split[k] === split[k+1]){
matches++;
}
}
if(matches === split.length -1){
count++;
}
}
}
}
}
}
numberToCount--;
}
numberToCount = n-space;
space++;
}
return count;
}
i came up with a solution that i think is not too complex in terms of performance(one loop and a recursion at a time)
steps
split string and insert it into an array
check first for even pairs into a recursion
next check for odd pairs again into a recursion
check that the values inserted to final array are unique(not unique only for single chars)
please let me know if this is the correct solution or we can speed it up
const stirng = "mnonopoo";
const str = stirng.split("");
let finalArray = [];
str.forEach((x, index) => {
if (str[index] === str[index + 1]) {
checkEven(str, index, 1)
}
if (str[index - 1] === str[index + 1]) {
checkOdd(str, index, 0)
}
finalArray.push(x);
})
function checkOdd(str1, index, counter) {
if (str1[index - counter] === str1[index + counter]) {
counter++;
checkOdd(str1, index, counter);
} else {
pushUnique(finalArray, str1.slice(index - counter + 1, index + counter).join(""));
return str1.slice(index - counter, index + counter).join("")
}
}
function checkEven(str1, index, counter) {
if (str1[index] === str1[index + counter]) {
counter++;
checkEven(str1, index, counter);
} else {
pushUnique(finalArray, str1.slice(index, index + counter).join(""));
return;
}
}
function pushUnique(array, value) {
if (array.indexOf(value) === -1) {
array.push(value);
}
}
console.log(finalArray)
Since your only looking for special palindromes, and not all palindromes, that makes reducing complexity a bit easier, but even then, there will be some special cases, like "abababababababa....". No way I can see to reduce the complexity of that one too far.
I'd approach this like so. Start by grouping all the repeating numbers. I'm not sure of the best way to do that, but I'm thinking maybe create an array of objects, with object properties of count and letter.
Start with your totalCount at 0.
Then, select all objects with a count of 1, and check the objects to the left and right of them, and if they have the same letter value, take the MAX count, and add that value + 1 to your totalCount (the +1 being to account for the single letter by itself). If the letter values on either side do not match, just add 1 (to account for the letter by itself).
That handles all the odd number palindromes. Now to handle the even number palindromes.
Select all the objects with a count > 1, and take their count value and add the series from 1-count to the totalCount. The formula for this is (count/2)*(1+count).
Example:
In the string you have a run of 4 A's. There are the special palindromes (a, a, a, a, aa, aa, aa, aaa, aaa, aaaa) in that, for a total of 10. (4/2)*(1+4)=10.
I don't know how much that will reduce your processing time, but I believe it should reduce it some.

Comparing the numeric values of each array properties in Javascript

I am trying to find a solution for this:
Users are asked to type in a random set of numbers sequentially:
var num1 = prompt("Enter 1st set of numbers");
var num2 = prompt("Enter 2nd set of numbers");
var num3 = prompt("Enter 3rd set of numbers");
var myNumbers =[num1, num2, num3];
Now I am trying to take compare the sum of the digits in each element of the array. For instance, if myNumbers[0] = 32, myNumber[1] = 45, what's the function to compare 5 (3+2) and 9 (4+5)?
I am trying to compare the sum of each elements by adding the numbers in that element, and return the largest number. So if num1= 1234, then the sum of myNumbers[0] should be 10. By comparing , if num2 = 3456, then the sum should be 18, the function should return num2.
var num1 = prompt("Enter 1st set of numbers");
var num2 = prompt("Enter 2nd set of numbers");
var num3 = prompt("Enter 3rd set of numbers");
// finds the sum of your array, parsing each element as an integer
var sum = function(array){
var digits = array.split("")
return digits.reduce(function(a, b) {return parseInt(a, 10) + parseInt(b, 10)})
}
var myNumbers =[num1, num2, num3]
var findLargest = function(array){
var answer
var largest = 0
array.forEach(function(input){
// check if this is the largest sum
if (sum(input) == largest){
// check if there is already a running set of equal sums
if (typeof(answer) == Object) answer.push(input)
// create set of equal sums if not
else answer = [answer, input]
}
else if (sum(input) > largest) {
largest = sum(input)
answer = input
}
})
return answer
}
alert(findLargest(myNumbers))
https://jsfiddle.net/gmebk2Ly/7/
This also checks to see if there are multiple inputs that are equal
If you want to sort the list by the sums of the digits, you can do the following. The comparator function finds the sum of the digits in the members of the list, then compares them. If you just wanted to sum the digits in the string, you can just extract the code that does this from this solution too.
myNumbers.sort(function(a,b) {
var sumA = 0;
var sumB = 0;
a.split("").forEach(function(digit) {
sumA+=parseInt(digit);
});
b.split("").forEach(function(digit) {
sumB+=parseInt(digit);
});
return sumA-sumB;
});
Let's break this down into two sub-problems: first, finding the sum of digits; second, finding the maximum value of an array. For the second, we already have Math.max.
For the first, we'll break it down even further and first write a function just to get the digits:
function digits(x) { return String(x).match(/\d/g).map(Number); }
To sum up the digits, we just say
function sumDigits(x) { return sum(digits(x)); }
For sum, you can find many examples here on SO, but the simplest one is
function sum(array) { return array.reduce(add, 0); }
add is easy enough:
function add(a, b) { return a + b; }
Now, to get the maximum sum of digits from each element of an array:
function maxSumDigits(array) { return Math.max(...array.map(sumDigits)); }
The above uses ES6 spread operator. In ES5:
return Math.max.apply(0, array.map(sumDigits));
The advantage of writing your code this way is first, you end up with useful little utility routines that you can re-use; second, the code is easier to read and prove to yourself that it's right; and third, it's easier to deal with spec changes, such as wanting to find the minimum instead of the maximum, of the product of digits instead of the sum.
function digits(x) { return String(x).match(/\d/g) . map(Number); }
function sumDigits(x) { return sum(digits(x)); }
function sum(array) { return array . reduce(add, 0); }
function add(a, b) { return a + b; }
function maxSumDigits(array) { return Math.max(...array . map(sumDigits)); }
console.log(maxSumDigits([1234, 3456]));
This returns the largest sum. To find the element whose digits have the largest sum, the easiest way would be to remember the array of sums of digits, then look that up:
function maxSumDigits(array) {
var sums = array . map(sumDigits);
var max = Math.max(...sums);
return array[sums.indexOf(max)];
}

How to check if a digit is used in a number multiple times

Example: We have the number 1122. I would like to check that if given number contains the digit 1 more than once. In this case, it should return true.
I need the code to be flexible, it has to work with any number, like 3340, 5660, 4177 etc.
You can easily "force" JS to coerce any numeric value to a string, either by calling the toString method, or concatenating:
var someNum = 1122;
var oneCount = (someNum + '').split('1').length;
by concatenating a number to an empty string, the variable is coerced to a string, so you can use all the string methods you like (.match, .substring, .indexOf, ...).
In this example, I've chosen to split the string on each '1' char, count and use the length of the resulting array. If the the length > 2, than you know what you need to know.
var multipleOnes = ((someNum + '').split('1').length > 2);//returns a bool, true in this case
In response to your comment, to make it flexible - writing a simple function will do:
function multipleDigit(number, digit, moreThan)
{
moreThan = (moreThan || 1) + 1;//default more than 1 time, +1 for the length at the end
digit = (digit !== undefined ? digit : 1).toString();
return ((someNum + '').split(digit).length > moreThan);
}
multipleDigit(1123, 1);//returns true
multipleDigit(1123, 1, 2);//returns false
multipleDigit(223344,3);//returns 3 -> more than 1 3 in number.
Use javascript's match() method. Essentially, what you'd need to do is first convert the number to a string. Numbers don't have the RegExp methods. After that, match for the number 1 globally and count the results (match returns an array with all matched results).
​var number = 1100;
console.log(number.toString().match(/1/g).length);​
function find(num, tofind) {
var b = parseInt(num, 10);
var c = parseInt(tofind, 10);
var a = c.split("");
var times = 0;
for (var i = 0; i < a.length; i++) {
if (a[i] == b) {
times++;
}
}
alert(times);
}
find('2', '1122');
Convert the number to a string and iterate over it. Return true once a second digit has been found, for efficiency.
function checkDigitRepeat(number, digit) {
var i, count = 0;
i = Math.abs(number);
if(isNaN(i)) {
throw(TypeError('expected Number for number, got: ' + number));
}
number = i.toString();
i = Math.abs(digit);
if(isNaN(i)) {
throw(TypeError('expected Number for digit, got: ' + digit));
}
digit = i.toString();
if(digit > 9) {
throw(SyntaxError('expected a digit for digit, got a sequence of digits: ' + digit));
}
for(i = 0; i < number.length; i += 1) {
if(number[i] === digit) {
count += 1;
if(count >= 2) { return true; }
}
}
return false;
}
In the event that you want to check for a sequence of digits, your solution may lie in using regular expressions.
var myNum = '0011';
var isMultipleTimes = function(num) {
return !!num.toString().match(/(\d)\1/g);
}
console.log(isMultipleTimes(myNum));
JavaScript Match
Using #Aspiring Aqib's answer, I made a function that actually works properly and in the way I want.
The way it works is:
Example execution: multDig('221','2')
Split the number (first argument) to an array where each element is one digit.Output: ['2','2','1']
Run a for loop, which checks each of the array elements if they match with the digit (second argument), and increment the times variable if there is a match.Output: 2
Check inside the for loop if the match was detected already to improve performance on longer numbers like 2211111111111111
Return true if the number was found more than once, otherwise, return false.
And finally the code itself:
function multDig(number, digit){
var finalSplit = number.toString().split(''), times = 0;
for (i = 0; i < finalSplit.length; i++){
if (finalSplit[i] == digit){
times++
}
if (times > 1){
return true;
}
}
return false;
}

Categories