Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am solving one problem .but getting correct output for small array but my solution fail when array size is large
solution
/**
* #param {number[]} digits
* #return {number[]}
*/
var plusOne = function(digits) {
let str = parseInt(digits.join(''))+1+''
return str.split('')
};
Question
The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit.
You may assume the integer does not contain any leading zero, except the number 0 itself.
Example 1:
Input: [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Example 2:
Input: [4,3,2,1]
Output: [4,3,2,2]
Explanation: The array represents the integer 4321.
above cases are passed
failed cases
Input
[6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]
Output
[6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,0,0,0]
Expected
[6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,4]
let str = parseInt(digits.join(''))+1+''
With too many array elements, you are simply creating a number that is outside of the integer range here.
An implicit conversion to a float has to happen, and with that you get the inherent loss of precision - which then leads to several zeros in those places at the end, when you reverse the process.
Access the last array element specifically, and add 1 to the value. But if that last element had the value 9 already, you will of course have to repeat that same process for the previous one … basic application of “carry the one”.
var input = [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,9];
var output = [];
// loop over input array in reverse order
for(var i=input.length-1, toadd = 1; i>-1; --i) {
// add value `toadd` to current digit
var incremented = input[i] + toadd;
if(incremented < 10) {
output.unshift(incremented); // add to front of output array
toadd = 0; // reset toadd for all following digits, if we had no overflow
}
else {
output.unshift(0); // overflow occurred, so we add 0 to front of array instead
}
}
console.log(output)
This does take an “overflow” for 9 digits at the end into account; it does not handle the case when all digits are 9 though, if you need to handle that edge case as well, please implement that yourself.
This one recursively checks the last digits:
const test1 = [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]
const test2 = [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,9]
const plusOne = function(digits) {
if(digits[digits.length - 1] === 9){
digits = [...plusOne(digits.slice(0, -1)), 0]
}else{
digits[digits.length - 1]++
}
return digits;
};
console.log(plusOne(test1));
console.log(plusOne(test2));
You could do something like this :
var arr = [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3,9,9]
function plusOne(index){
if( index < 0 ) return ; // Base case
if(arr[index] === 9){
arr[index] = 0;
plusOne(index-1); // For carry ahead
}else{
arr[index] += 1
}
}
plusOne(arr.length-1) // start with last digit
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am trying to write a program to decrypt a encrypted message. The encrypted message is a very long set of numbers ".296.294.255.268.313.278.311.270.290.305.322.252.276.286.301.305.264.301.251.269.274.311.304.
230.280.264.327.301.301.265.287.285.306.265.282.319.235.262.278.249.239.284.237.249.289.250.
282.240.256.287.303.310.314.242.302.289.268.315.264.293.261.298.310.242.253.299.278.272.333.
272.295.306.276.317.286.250.272.272.274.282.308.262.285.326.321.285.270.270.241.283.305.319.
246.263.311.299.295.315.263.304.279.286.286.299.282.285.289.298.277.292.296.282.267.245.....ect".
Each character of the message is transformed into three different numbers (eg.first character of message is '230 .280 .264' second character is '.327.301.265' ect).
so i am trying to use javascript to add the groups of three numbers and then save them as their own variable. thanks
Assuming msg has that string in it, this will split it up and add the triplets together.
const [, triplets] = msg
.split('.')
.slice(1)
.map(v => +v)
.reduce(([count, list], val, i) => {
if ((i + 1) % 3) return [count + val, list];
return [val, list.concat(count)];
}, [0, []]);
It would depend on how the data is transmitted. It looks like you could bring the data in as a string (or parse it into a string) and then use the split method to create an array of all of your numbers.
var numbers = "234.345.456.567"
var arr = numbers.split(".")
You would then loop over the array doing whatever you need for every set of three
var newArray[]
var i
for(i = 0; i < length; i += 3){
//Add values here
//Parse back to int
newArray.push("sum Value")
}
Hope this was along the lines of what you need.
Use a regular expression to match all groups of three, then map each group to the number by splitting the string by .s and adding the 3 together:
const input = '296.294.255.268.313.278.311.270.290.305.322.252.276.286.301.305.264.301.251.269.274.311.304. 230.280.264.327.301.301.265.287.285.306.265.282.319.235.262.278.249.239.284.237.249.289.250. 282.240.256.287.303.310.314.242.302.289.268.315.264.293.261.298.310.242.253.299.278.272.333. 272.295.306.276.317.286.250.272.272.274.282.308.262.285.326.321.285.270.270.241.283.305.319. 246.263.311.299.295.315.263.304.279.286.286.299.282.285.289.298.277.292.296.282.267.245';
const groupsOfThree = input.match(/\d{3}\.\d{3}\.\d{3}\./g);
const sums = groupsOfThree.map((group) => {
const nums = group.split('.').map(Number);
return nums[0] + nums[1] + nums[2];
});
console.log(sums);
I am trying to solve the problem described here with JavaScript...
https://www.hackerrank.com/challenges/ctci-making-anagrams
I have to output the number of letters that would need to be removed from two strings in order for there to only be matching letters (compare the two strings for matching letters and total the letters that don't match)
for example...
string a = cbe
string b = abc
the only matching letter is between both strings is the two c's so I would be removing 4 letters (beab).
My code works, but it seems to keep timing out. If I download the individual test case instances, I seem to fail when variables a and b are set to large strings. If I test these individually, I seem to get the right output but i still also get the message "Terminated due to timeout".
I'm thinking it might be obvious to someone why my code timesout. I'm not sure it's the most elegant way of solving the problem but I'd love to get it working. Any help would be much appreciated...
function main() {
var a = readLine();
var b = readLine();
var arraya = a.split('');
var arrayb = b.split('');
var arraylengths = arraya.length + arrayb.length;
//console.log(arraylengths);
if (arraya.length <= arrayb.length) {
var shortestarray = arraya;
var longestarray = arrayb;
} else {
var shortestarray = arrayb;
var longestarray = arraya;
}
var subtract = 0;
for (x = 0; x < shortestarray.length; x++) {
var theletter = shortestarray[x];
var thenumber = x;
if (longestarray.indexOf(theletter, 0) > -1) {
var index = longestarray.indexOf(theletter, 0);
longestarray.splice(index, 1);
subtract = subtract + 2;
}
}
var total = arraylengths - subtract;
console.log(total);
}
Your algorithm is good. It's straight forward and easy to understand.
There are certain things you can do to improve the performance of your code.
You don't have to calculate the indexOf operation twice. you can reduce it to one.
the splice operation is the costliest operation because the JS engine has to delete the element from an array and reassign the indexes of all the elements.
A point to be noted here is that the JS engine does an extra step of correcting the index of the array, which is not required for your purpose. So you can safely remove longestarray.splice(index, 1); and replace it with delete longestarray[index]
Here is a snippet which will increase your performance of the code without changing your logic
for (var x = 0; x < shortestarray.length; x++) {
var theletter = shortestarray[x];
var thenumber = longestarray.indexOf(theletter, 0); // <-- check only once
if (thenumber > -1) {
var index = thenumber;
delete longestarray[index]; // <-- less costlier than splice
subtract = subtract + 2;
}
}
Note: I am not suggesting you to use delete for all the cases. It's useful here because you are not going to do much with the array elements after the element is deleted.
All the best. Happy Coding
I would suggest you hashing. make the characters of string key and its numbers of occurrences value. Do the same for both strings. After that take string 1 and match the count of its every character with the count of same character in string then calculate the difference in the number of occurrences of the same character and delete that character till the difference becomes 0 and count that how many times you performed delete operation.
ALGORITHM:
step 1: Let arr1[255]= an integer array for storing the count of string1[i]
and initialized to zero
ex: string1[i]='a', then arr1[97]=1, because ASCII value of a is 97
and its count is 1. so we made hash table for arr1 where key is
ASCII value of character and value is its no of occurrences.
step 2: Now declare an another array of same type and same size for string 2
step 3: For i=0 to length(string1):
do arr1[string1[i]]++;
step 4: For i=0 to length(string2):
do arr2[string2[i]]++;
step 5: Declare an boolean char_status[255] array to check if the
character is visited or not during traversing and initialize it to
false
step 6: set count=0;
step 7: For i=0 to length(string1):
if(char_status[string1[i]]==false):
count=count+abs(arr1[string1[i]]-arr2[string1[i]])
char_status[string1[i]]=true
step 8: For i=0 to length(string2):
if(char_status[string2[i]]==false):
count=count+abs(arr1[string2[i]]-arr2[string2[i]])
char_status[string2[i]]=true
step 9: print count
I have applied this algo just now and passed all test cases. You may improve this algo more if you have time.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Can anybody explain this while loop for me? It part of the roman numeral challenge on free code camp - it's not mine, I did my own but it was much more code. I'm trying understand this one to improve my own. Anyway, the while loop is totally throwing me. Any help would be awesome.
function romans(num){
var roman = "";
var romanNumerals = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"];
var numbers = [1000,900,500,400,100,90,50,40,10,9,5,4,1];
for (var i=0; i<numbers.length; i++) {
//If the num was 5 then then it would read 5 greater than 1000?
while (num >= numbers[i]) {
roman = roman + romanNumerals[i]
//5 minus 1000?
num = num - numbers[i]
}
}
return roman;
}
console.log(romans(5))
num starts as the desired input, then you find the numbers that add up to num, starting at the biggest roman numeral (numbers[0]).
You repeat with the while loop because you might need multiple copies of the letter (i.e. "III" == 3)
romans(5) will not trigger the while loop until numbers[10] (because as you say 5 >= 1000 == false,) at this point you append the character V to roman, and subtract 5 from num. The while loop will never again trigger since num is now 0.
Try thinking through it with romans(3001) and you will see the while loop trigger 3 times for M/1000, then get skipped 10 times, then trigger once for I/1
function romans(num){
var roman = "";
var romanNumerals=["M","CM","D","CD","C","XC","L","XL","X",
"IX","V","IV","I"];
var numbers = [1000,900,500,400,100,90,50,40,10,9,5,4,1];
for (var i=0; i<numbers.length; i++){
//If the num was 5 then then it would read 5 greater than 1000?
console.log("comparing: " + numbers[i]);
console.log(" with: " + num);
while(num >= numbers[i]){
console.log("entered");
roman = roman + romanNumerals[i]
//5 minus 1000?
num = num - numbers[i]
console.log('subtracting: ' + numbers[i]);
}
}
return roman
}
console.log(romans(44))
It will go down the line of numbers until it finds one that is smaller: for example 44:
In the for it'll go through the numbers array until it finds a number then 44 (during the iterations before the while loop is never entered).
When it finds a number smaller then 44 it enters the while loop and takes the romanNumerals at the position of i in that iteration, in this case 40. Then it lowers the original number by 40 (44-40=4) and then exits the loop going back into the for to search for a number lower then 4.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
This question will need to be answered in Javascript.
For example, I have an array of phone numbers:
var phoneNumbers = ['123-434-4455', '123-495-8475', '484-728-3456'];
The phone number at index 0 (123-434-4455) would be added as 1+2+3+4+3+4+4+4+5+5, totaling to 35.
I'm guessing this will involve some kind of loop (for loops, or the method .forEach), because I will need to do this for multiple phone numbers in an array that will probably be randomly generated by a computer, so length and amount will vary.
Also, I'm wondering if the hyphen will matter, in which case I have found .replaceAll("-","");.
I've researched some other methods on here that involve .split, .parsInt, .map, .toString, .reduce, .digitSum, and more. They seem pretty complicated, especially since I'm in a beginning course (however I'm totally new to programming - this is my first post btw). Also, I'd rather not post the full question because I really want to figure it out alone, but this is the part I'm most stuck on. Forgive me if this has been answered previously! Like I said...new to programming.
I also need to determine which phone number has the last largest sum of digits, and use a return statement to return the required phone number in its’ original form.
You can use map and reduce array methods:
['123-434-4455', '123-495-8475', '484-728-3456'].map(function(str) {
return str.split('').reduce(function(a,b) {
return a + (+b || 0);
}, 0);
}); // [ 35, 48, 51 ]
Some notes:
split('') splits a string into an array of characters
+b coerces b into a number, e.g. "5" to 5 and "-" to NaN.
+b || 0 will return 0 if +b is falsy (0 or NaN), and +b otherwise
This code will do it:
var phoneNumbers = ["123-434-4455", "123-495-8475", "484-728-3456"];
for (var i=0; i<phoneNumbers.length; i++) {//For every phone number
var total=0; //create a total variable
var indNumbers = phoneNumbers[i].replace(/-/g, ""); //remove all dashes
for (var j=0; j<indNumbers.length; j++) {//loop for all digits
total+=parseFloat(indNumbers[j]);//add each digit to total
}
console.log(total);//do stuff with it here
}
All pretty standard javascript stuff. Only confusing bit I might have used is the .replace method - my parameter is /-/g which might look scary, but it's the equivalent of passing in "-" except it tells the function to replace ALL instances of the dash. If you do pass "-", it only replaces the first instance.
If you're a beginner, the things in this code you'll want to learn about are .replace, parseFloat for loops, and accessing strings using square bracket notation.
var phoneNumbers = ["123-434-4455", "123-495-8475", "484-728-3456"];
function crossSum(arr, pos) {
var sum = 0;
var a = arr[pos].split("-").join("").split("");
a.forEach(function(e, i) {
sum += parseInt(a[i]);
})
return sum;
}
document.write(crossSum(phoneNumbers, 0));
This function will return the cross-sum of
your phone-number.
Just use crossSum(phoneNumers, 0) // 0 is the fist number of phoneNumbers.
This will return the crossSum.
Adding on #millerbr answer. If you don't want to use .replace you can just use parseInt/parseFloat on every char, if it is not a number those functions returns NaN which can be checked with isNaN() function
var phoneNumbers = ["123-434-4455", "123-495-8475", "484-728-3456"];
for (var i=0; i < phoneNumbers.length; i++) { //For every phone number
var total=0; //create a total variable
for (var j=0; j < phoneNumbers.length; j++) { //loop for all digits
var parsedNumber = parseInt(phoneNumbers[j]); // parse string to number or NaN if "-"
if (!isNaN(parsedNumber)) { // Check if result is NaN (Not a Number).
total += parsedNumber; //add each digit to total
}
}
console.log(total);//do stuff with it here
}
Assuming that phoneNumbers is an array of strings, you can indeed loop through the entire array and then in each element in the array you can loop through the string and check if the character is a number. If so, add it to your sum and then when you finish each element in the array you have the total sum for it and you can add it to another array full of your sums.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I try to convert Tricky's script (that generates a name from elite) to javascript here:
https://github.com/rubo77/eliteNameGen/blob/master/elite.js
But I get stuck at this LPC-code by Tricky:
digrams=ABOUSEITILETSTONLONUTHNO..LEXEGEZACEBISOUSESARMAINDIREAERATENBERALAVETIEDORQUANTEISRION
...
pairs = digrams[24..<1];
...
names[0..<2]
I couldn't find a manual to LPC that would explain this syntax.
In the End I want to create a javascript, that creates a random planet name from the old C64 game Elite.
I also found a python version, (but that seems a bit more complicated to me)
Ok I managed to port the code over, but I had to tweak a bit of the algorithm. The one that is provide by Tricky, for some reason, produces non-unique names. I used the tweakseed function to tweak the seeds to generate a list of random names.
Answer
To answer the question above, #MattBurland is correct. You would replace the following code:
pairs = digrams[24..<1];
with
pairs = digrams.substring(24);
The following code, however, is actually printing out the list of names. So you're indexing an array - in which case:
names[0..<2]
becomes
for (var i = 0; i < (names.length - 2); i++) {
names[i]
}
Analysis
Just to give this some more depth. I've analyzed the code and realized that rotatel, twist, tweakseed, and next were just used to create random numbers. I don't know enough about LPC, but I think that at the time it probably didn't have a pseudo-random number generator.
A lot of this code can be removed and just replaced with Math.random. The key part of this entire program is the variable digram. This sequence of characters produces Alien-like names. I figure it probably has something to do with alternation of consonants and vowels. Grabbing them in pairs randomly will almost always produce some sort of consonant + vowel pairing. There is the odd time where you'll end up with a name like 'Rmrirqeg', but in most cases, the names appear Alien-like.
Port
Below is a direct port of the code. You can use this jsFiddle to see it in action, but it uses AngularJS to print out the names instead of printing out a list like the code provided. genNames will produce an array of names, which you can use for whatever reason you want.
Note this port only works on IE9+, since it uses map, reduce, and forEach. Replace these with loops if you plan on using this on IE8 or below.
You can tweak this to produce names longer or shorter. However, the length of the names is dependent on the pairs array. Either use Math.random or something to make it completely wild.
var digrams = "ABOUSEITILETSTONLONUTHNO" +
"..LEXEGEZACEBISOUSESARMAINDIREA.ERATENBERALAVETIEDORQUANTEISRION";
function rotatel(x) {
var tmp = (x & 255) * 2;
if (tmp > 255) tmp -= 255;
return tmp;
}
function twist(x) {
return (256 * rotatel(x / 256)) + rotatel(x & 255);
}
function next(seeds) {
return seeds.map(function(seed) {
return twist(seed);
});
}
function tweakseed(seeds) {
var tmp;
tmp = seeds.reduce(function(total, seed) {
return total += seed;
}, 0);
return seeds.map( function ( seed, index, arr ) {
return arr[index + 1] || (tmp & 65535)
});
};
function makename(pairs, seeds)
{
var name = [];
/* Modify pair if you want to have names shorter or longer than 8 chars */
/* I'll leave that as an exercise for you. */
var pair = [0, 0, 0, 0];
var longname = seeds[0] & 64;
pair = pair.map(function() {
seeds = tweakseed(seeds);
return 2 * ((seeds[2] / 256) & 31);
});
pair.forEach(function(value, index, arr) {
if (longname || ( index < (arr.length - 1))) {
name.push(pairs[value]);
name.push(pairs[value + 1]);
}
});
return name.join('').toLowerCase()
.replace(/^\w/, function(letter) {
return letter.toUpperCase();
});
}
function genNames()
{
var names = [];
var pairs;
var num = 256;
var seeds = [23114, 584, 46931];
pairs = digrams.substring(24);
while (--num) {
names.push( makename(pairs, seeds) );
seeds = tweakseed(next(seeds));
}
return names;
}
For the range operator in LPC, this link helps:
http://www.unitopia.de/doc/LPC/operators.html
expr1[expr2..expr3] Extracts a
piece from an array or string.
expr2 or expr3 may be omitted, default is the begin
or end of expr1.
Negative numbers for expr2 or expr3
mean ``count from before the beginning'', i.e.
foo[-2..-1] is an empty array or string.
foo[<2..<1] gives the 2nd and last element of
the array resp. chars of the string.
So I'm guessing that:
pairs = digrams[24..<1];
Means get the substring starting at index 24 to the end of the string?