Javascript Split Method with Additive Persistence - javascript

This is my first Stack Overflow post, so please let me know if I am not formatting properly!
I am trying to answer this Coderbyte question:
"Using the JavaScript language, have the function AdditivePersistence(num) take the num parameter being passed which will always be a positive integer and return its additive persistence which is the number of times you must add the digits in num until you reach a single digit. For example: if num is 2718 then your program should return 2 because 2 + 7 + 1 + 8 = 18 and 1 + 8 = 9 and you stop at 9."
However, my solution keeps returning "str.split is not a function". I thought that was a standard method for converting strings into arrays. Any idea why this code might not work?
function AdditivePersistence(num) {
let str = num.toString; //number into string
let arr = str.split(""); //string into array
// adds numbers in array, then repeats until left with single digit
let count = 0;
while(arr.length > 1) {
arr.reduce(function(a,b){ return Number(a) + Number(b) });
count++;
}
return count;
};
I tried searching Stack Overflow, Google, W3Schools, MDN and other Coderbyte answers but could not figure out why this doesn't work. Any help would be appreciated.

Try using String() constructor.
let str = String(num);
Note also, while loop does not conclude as arr is not redefined by call to .reduce(). You can redefine arr by using String() constructor and .split() again within while loop
function AdditivePersistence(num) {
let str = String(num); //number into string
let arr = str.split(""); //string into array
// adds numbers in array, then repeats until left with single digit
let count = 0;
while (arr.length > 1) {
// set `arr` to string then array with values returned from `.reduce()`
arr = String(arr.reduce(function(a, b) {
return Number(a) + Number(b)
})).split("");
count++;
}
return count;
};
var n = AdditivePersistence(2718);
console.log(n);

You can convert to string this way:
let str = num + '';

Related

Set the last number in a string to negative

I have a string with diffrent mathematical characters, and i want to make the last number negative/positive. Let's say the string is "100/5*30-60+333". The result i want is "100/5*30-60+(-333)", and i want to convert it back to positive ("100/5*30-60+333").
function posNeg() {
// hiddenText is a <input> element. This is not shown.
let n = hiddenText.value;
n.split('+');
n.split('-');
n.split('*');
n.split('/');
console.log(n);
}
What i get is the whole hiddenText.value, and not an array of all numbers. Any tips?
First, I'd match all of the basic math operators to get their order:
const operatorsArr = n.match(/\+|\-|\/|\*/g)
Then, split the string:
function posNeg() {
// hiddenText is a <input> element. This is not shown.
let n = hiddenText.value;
n = n.replace(/\+|\-|\/|\*/g, '|');
n = n.split('|');
console.log(n);
}
Then, you will have an array of numbers, in which you can mutate the last number easily:
n[n.lengh-1] *= -1;
Now we can combine the two arrays together:
let newArr;
for (let i = 0; i < n.length; i++) {
newArr.push(n[i]);
if (operatorsArr[i]) newArr.push(operatorsArr[i]);
}
At last, you can rejoin the array to create the new String with a seperator of your choosing. In this example I'm using a space:
newArr = newArr.join(' ')
Please let me know how that works out for you.
Let's say the string is "100/5*30-60+333". The result i want is
"100/5*30-60+(-333)", and i want to convert it back to positive
("100/5*30-60+333").
The following code does that:
let mathStr = '100/5*30-60+333';
console.log(mathStr);
let tokens = mathStr.split('+');
let index = tokens.length - 1;
let lastToken = tokens[index];
lastToken = '('.concat('-', lastToken, ')');
let newMathStr = tokens[0].concat('+', lastToken);
console.log(newMathStr); // 100/5*30-60+(-333)
console.log(mathStr); // 100/5*30-60+333
EDIT:
... and i want to convert it back to positive ("100/5*30-60+333").
One way is to declare mathStr (with the value "100/5*30-60+333") as a var at the beginning and reuse it, later as you need. Another way is to code as follows:
let str = "100/5*30-60+(-333)";
str = str.replace('(-', '').replace(')', '');
console.log(str); // 100/5*30-60+333
To get numbers You can use replace function and split check code bellow :
function posNeg() {
// hiddenText is a <input> element. This is not shown.
let n = "100/5*30-60+333";
n = n.replace('+','|+');
n = n.replace('-','|-');
n = n.replace('*','|*');
n = n.replace('/','|/');
n=n.split('|');console.log(n);
// to use any caracter from array use it in removeop like example
// if we have array (split return) have 100 5 30 60 333 we get 100 for example
// we need to make removeop(n[0]) and that reutrn 100;
// ok now to replace last value to negative in string you can just make
// var lastv=n[n.length-1];
// n[n.length-1] ='(-'+n[n.length-1])+')';
//var newstring=n.join('');
//n[n.length-1]=lastv;
//var oldstring=n.join('');
}
function removeop(stringop)
{
stringop = stringop.replace('+','');
stringop = stringop.replace('-','');
stringop = stringop.replace('*','');
stringop = stringop.replace('/','');
return stringop;
}
If you really need to add "()", then you can modify accordingly
<script>
function myConversion(){
var str = "100/5*30-60-333";
var p = str.lastIndexOf("+");
if(p>-1)
{
str = str.replaceAt(p,"-");
}
else
{
var n = str.lastIndexOf("-");
if(n>-1)
str = str.replaceAt(n,"+");
}
console.log(str);
}
String.prototype.replaceAt=function(index, replacement) {
return this.substr(0, index) + replacement+ this.substr(index + replacement.length);
}
</script>

Time Complexity for JavaScript Anagram Function

I had an assignment to right a function that will take 2 strings and return the number of characters needed to be deleted in order to make the 2 strings anagrams of each other. My question is what the time complexity of this function is and if there is a faster way to achieve the same result.
Here is my solution:
function anagramDelete(str1, str2){
let obj1 = {}, obj2 = {};
// Load obj1 with all characters of str1 and their count
str1.split('').forEach((char)=> {
if(char in obj1){
obj1[char]++;
} else {
obj1[char] = 1;
}
});
// Load obj2 with all characters of str1 and their count
str2.split('').forEach((char)=> {
if(char in obj2){
obj2[char]++;
} else {
obj2[char] = 1;
}
});
// Track # of chars deleted
let numOfDeletions = 0;
// Compare each char in obj1 w obj2 and count deletions
for(char in obj1){
if(obj2[char]){
numOfDeletions += Math.abs(obj2[char] - obj1[char]);
} else {
numOfDeletions += obj1[char];
}
}
// Compare each char in obj2 w obj1 and count deletions
for(char in obj2){
if(!obj1[char]){
numOfDeletions += obj2[char];
}
}
return numOfDeletions;
}
As far as I can tell, because there are 4 loops it would be O(4n) or just O(n). I say this because there are no nested loops. Is this correct? Any better solutions?
You could use a single object and sum only the absolut values.
This solution uses the strings as array like objects.
function anagramDelete(str1, str2) {
var letters = {};
Array.prototype.forEach.call(str1, char => letters[char] = (letters[char] || 0) + 1);
Array.prototype.forEach.call(str2, char => letters[char] = (letters[char] || 0) - 1);
return Object.keys(letters).reduce((r, k) => r + Math.abs(letters[k]), 0);
}
console.log(anagramDelete('anagram', 'function'));
Your code is O(n + m); in general one does not really care too much about constants in a complexity class. n is the length of the first string and m is the length of the second string.
Also:
To be precise in your case, since you mentioned O(4n) - I am not sure if that is accurate. You use the split function twice, which turns a string into an array of characters in your case. You did not account for that in your analysis.
O(n + m) would be the correct answer.
And if you want to detail the analysis it would be O(3n + 3m). That is because:
- for the first string you use split (O(n)), you loop over each character (O(n)) and you loop again for comparison (O(n))
- for the second string you use split (O(m)), you loop over each character (O(m)) and you loop again for comparison (O(m))
I assume your code is correct. I did not check that.
P.S.:
If you are interested in fine tuning the constants you can refer to the other answers, they are probably faster than your code in theory. In practice I don't think that matters really.
Not better but shorter:
function anagramDelete(str1, str2){
const chars = {};
var result = 0;
for(const char of str1)
chars[char] = (chars[char] || 0) +1;
for(const char of str2)
chars[char] = (chars[char] || 0) -1;
for(const [char, count] of Object.entries(chars))
result += Math.abs(count);
return result;
}

Splitting a number into an array

Alright so I'm trying to completely split a number into an Array. So for example:
var num = 55534;
var arr = []; <- I would want the Array to look like this [5,5,5,3,4]
Basically i want to to completely split the number apart and place each Number into its own element of the array. Usually in the past i would just convert the number into a string then use the .split() function. This is how i use to do it:
num += "";
var arr = num.split("");
But this time i actually need to use these numbers, so they can not be strings. What would you guys say be the way of doing this?
Update, after the edit for some reason my code is crashing every run:
function DashInsert(num) {
num += "";
var arr = num.split("").map(Number); // [9,9,9,4,6]
for(var i = 0; i < arr.length; i++){
if(arr[i] % 2 === 1){
arr.splice(i,0,"-");
}// odd
}
return arr.join("");
}
String(55534).split("").map(Number)
...will handily do your trick.
You can do what you already did, and map a number back:
55534..toString().split('').map(Number)
//^ [5,5,5,3,4]
I'll do it like bellow
var num = 55534;
var arr = num.toString().split(''); //convert string to number & split by ''
var digits = arr.map(function(el){return +el}) //convert each digit to numbers
console.log(digits); //prints [5, 5, 5, 3, 4]
Basically I'm converting each string into numbers, you can just pass Number function into map also.

Why can't I swap characters in a javascript string?

I am trying to swap first and last characters of array.But javascript is not letting me swap.
I don't want to use any built in function.
function swap(arr, first, last){
var temp = arr[first];
arr[first] = arr[last];
arr[last] = temp;
}
Because strings are immutable.
The array notation is just that: a notation, a shortcut of charAt method. You can use it to get characters by position, but not to set them.
So if you want to change some characters, you must split the string into parts, and build the desired new string from them:
function swapStr(str, first, last){
return str.substr(0, first)
+ str[last]
+ str.substring(first+1, last)
+ str[first]
+ str.substr(last+1);
}
Alternatively, you can convert the string to an array:
function swapStr(str, first, last){
var arr = str.split('');
swap(arr, first, last); // Your swap function
return arr.join('');
}
Let me offer my side of what I understood: swapping items of an array could be something like:
var myFish = ["angel", "clown", "mandarin", "surgeon"];
var popped = myFish.pop();
myFish.unshift(popped) // results in ["surgeon", "angel", "clown", "mandarin"]
Regarding swaping first and last letters of an strings could be done using Regular Expression using something like:
"mandarin".replace(/^(\w)(.*)(\w)$/,"$3$2$1")// outputs nandarim ==> m is last character and n is first letter
I just ran your code right out of Chrome, and it seemed to work find for me. Make sure the indices you pass in for "first" and "last" are correct (remember JavaScript is 0-index based). You might want to also try using console.log in order to print out certain variables and debug if it still doesn't work for you.
EDIT: I didn't realize you were trying to manipulate a String; I thought you just meant an array of characters or values.
function swapStr(str, first, last) {
if (first == last) {
return str;
}
if (last < first) {
var temp = last;
last = first;
first = temp;
}
if (first >= str.length) {
return str;
}
return str.substring(0, first) +
str[last] +
str.substring(first + 1, last) +
str[first] +
str.substring(last + 1);
}
Swap characters inside a string requires the string to convert into an array, then the array can be converted into string again:
function swap(arr, first, last){
arr = arr.split(''); //to array
var temp = arr[first];
arr[first] = arr[last];
arr[last] = temp;
arr = arr.join("").toString() //to string
return arr;
}
Following usage:
str = "ABCDE"
str = swap(str,1,2)
console.log(str) //print "ACBDE"
I hope this piece of code will help somebody.
var word = "DED MOROZ";
var arr = word.split('');
for (var i = 0; i < arr.length/2; i++) {
var temp = arr[i];
arr[i] = arr[arr.length - i - 1];
arr[word.length - i - 1] = temp;
}
console.log(arr.join(""));
Run this code and your characters will be swapped.

Comparing 2 arrays to output total integer

I have 2 arrays of numbers. I want to go through each array and find the number of times 1 number from each array adds up to the particular amount x.
If the particular amount x is reached as many times as another set number n then the function should print 'YES'. If x does not reach the set number of n then the function should print 'NO'.
The values of x , n and both arrays are in a string input. These values have been split into arrays as seen below in the code.
I have set up 2 for loops to run through each array and an if statement that checks for the condition of x meeting n.
The arrays I'm using in this code should print out the result of 'YES' however every time I run the code I'm getting 'NO' ? I've tried tinkering with the code but nothing has worked.
Any idea on where this code is broke and how to fix the problem?
Thanks :)
code:
var input = '2\n3 10\n2 1 3\n7 8 9';
function processData(input) {
var inputArray = input.split('\n');
var n = inputArray[1][0];
var x = inputArray[1].split(' ')[1];
var arrayA = inputArray[2].split(' ');
var arrayB = inputArray[3].split(' ');
var total = 0;
for(var i = 0; i < arrayA.length; i++) {
for(var j = 0; j < arrayB.length; j++) {
if(arrayA[i] + arrayB[j] == x) {
total = total + 1;
} if (total == n) {
return 'YES';
}
}
}
return 'NO';
}
console.log(processData(input));
arrayA[i] and arrayB[j] are strings, so arrayA[i] + arrayB[j] will be the concatenation of them (ex: '2' + '3' === '23').
If your logic is correct (i didn't quite understand what you are trying to do), it should be enough to convert them to numbers before adding them, using parseInt or some other method:
if(+arrayA[i] + (+arrayB[j]) == +x) { // used unary + to convert to number
total = total + 1;
} if (total == n) {
return 'YES';
}
PS: A cleaner version would be to convert each string in the array to number, but that involves more than adding 3 characters to your code.
PS2: You have a weird way of getting the input data. If you get it from another place in your JS code, you could simply pass it as an object with the relevant structure, otherwise you could pass it around in a more ... common format, like JSON.

Categories

Resources