Lets assume you can never know what string will be passed to the browser, any combination of any characters of any length and I want to limit this to lets say.. 50 chars.
This is what I have at the moment:
<script type="text/javascript">
var x = "Hello this sentance was created in the browser!"
for(i=0; i<x.length; i++){
if(i == 50){
}
}
</script>
Eventually x will be something like:
var x = $('#textBit').html();
How will I remove everything in the array (string) after position 50, will I need a new for loop kinda like this (it may be wrong just thinking it up) pseudo code:
loop remainder string{
do until end of array{
remove item
}
}
Or is there a better way of doing it? Thanks.
use the string.substring(indexA[, indexB]) method:
Returns a subset of a string between one index and another, or through
the end of the string.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/substring
No:
if (x.length <= 50)
return x;
else
return x.substring(0, 50);
Just use substr() (MDN docu). This will return the substring meeting you criteria, e.g., beginning at the start and having at most 50 characters:
var x = "Hello this sentance was created in the browser!"
var shortString = x.substr( 0, 50 );
Related
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.
I'm starting to learn javascript and I basically needed a countup that adds an x value to a number(which is 0) every 1 second. I adapted a few codes I found on the web and came up with this:
var d=0;
var delay=1000;
var y=750;
function countup() {
document.getElementById('burgers').firstChild.nodeValue=y+d;
d+=y;
setTimeout(function(){countup()},delay);
}
if(window.addEventListener){
window.addEventListener('load',countup,false);
}
else {
if(window.attachEvent){
window.attachEvent('onload',countup);
}
}
There's probably residual code there but it works as intended.
Now my next step was to divide the resultant string every 3 digits using a "," - basically 1050503 would become 1,050,503.
This is what I found and adapted from my research:
"number".match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
I just can't find a way to incorporate this code into the other. What should I use to replace the "number" part of this code?
The answer might be obvious but I've tried everything I knew without sucess.
Thanks in advance!
To use your match statement, you need to convert your number to a String.
Let's say you have 1234567.
var a = 1234567;
a = a + ""; //converts to string
alert(a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(","));
If you wish, you can wrap this into a function:
function baz(a) {
a = a + "";
return a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
}
Usage is baz(1234); and will return a string for y our.
While I do commend you for using a pattern matching algorithm, this would probably be easier to, practically speaking, implement using a basic string parsing function, as it doesn't look anywhere as intimidating from just looking at the match statement.
function foo(bar) {
charbar = (""+bar).split(""); //convert to a String
output = "";
for(x = 0; x < charbar.length; x++) { //work backwards from end of string
i = charbar.length - 1 - x; //our index
output = charbar[i] + output; //pre-pend the character to the output
if(x%3 == 2 && i > 0) { //every 3rd, we stick in a comma, except if it is not the leftmost digit
output = ',' + output;
}
}
return output;
}
Usage is basically foo(1234); which yields 1,234.
I'm trying to build a function that adds up all the numbers within a string... for example, 'dlsjf3diw62' would end up being 65.
I tried to be clever and put together a recursive function:
function NumberAddition(str) {
var numbers='1234567890';
var check=[];
str=str.split[''];
function recursive(str,check) {
if (str.length==0)
return check;
else if (numbers.indexOf(str[0])>=0)
{
for (i=0;i<str.length;i++){
if (numbers.indexOf(str[i])<0)
check.push(str.slice(0,i));
str=str.slice(i);
return recursive(str,check);
}
}
else
str.shift();
return recursive(str,check);
}
You'll see that I'm trying to get my numbers returned as an array in the array named check. Unfortunately, I have a maximum call stack size exceeded, and I'm not sure why! The recursion does have a base case!! It ends once str no longer has any contents. Why wouldn't this work? Is there something I'm missing?
-Will
You can achieve the same thing with a far easier solution, using regular expressions, as follows:
var str = 'dlsjf3diw62';
var check = str.match(/\d+/g); // this pattern matches all instances of 1 or more digits
Then, to sum the numbers, you can do this:
var checkSum = 0;
for (var i = 0; i < check.length; i++) {
checkSum += parseInt(check[i]);
}
Or, slightly more compact:
var checkSum = check.reduce(function(sum, num){ return sum + parseInt(num) }, 0);
The reason your recursion doesn't work is the case where you do enter the for loop, because you've found a digit, but the digits continue to the end of the string. If that happens, the return inside the for loop never happens, and the loop ends. After that, the .shift() does not happen, because it's in that else branch, so you return re-process the same string.
You shouldn't solve this particular problem that way, but the code makes a good example of the anti-pattern of having return statements inside if bodies followed by else. Your code would be clearer (and would work) if it looked like this:
function recursive(str, check) {
if (str.length == 0)
return check;
if (numbers.indexOf(str[0]) >= 0) {
// Find the end of the string of digits, or
// the end of the whole thing
for (var i = 0; i < str.length && numbers.indexOf(str[i]) >= 0; i++);
check.push(str.slice(0, i));
str = str.slice(i);
return recursive(str, check);
}
// A non-digit character
str.shift();
return recursive(str, check);
}
In that version, there are no else clauses, because the two if clauses always involve a return. The for loop is changed to simply find the right value of "i" for the subsequent slicing.
edit — one thing this doesn't fix is the fact that you're pushing arrays into your "check" list. That is, the substring "62" would be pushed as the array ["6", "2"]. That's not a huge problem; it's solved with the addition of a .join() in the right place.
I've done FizzBuzz several times but never had this problem. Perhaps, it is something fundamental about for-loops that I don't understand. For some reason, the code below runs 10x longer than it should (well, than I think it should). If the user enters 20, it runs to 200. I fixed the problem by setting i = 0; i < num and then printing i+1 to my div, but I still don't understand why the original code does not work as expected. And while I'm at it, I might as well admit that I still can't set up JSFiddle properly. http://jsfiddle.net/nngrey/hA4pg/ (This does not run at all.) So any thoughts on that would also be appreciated. Thanks!
<head>
<title>Fizz Buzz</title>
<script>
function fizzbuzz(){
var num = prompt("Please enter a number between 1 and 100: ");
for(var i=1; i<num+1; i++){
if (i%3===0 && i%5===0){
document.getElementById("div1").innerHTML = div1.innerHTML+"<p>Fizz Buzz</p>";
}else if (i%3===0){
document.getElementById("div1").innerHTML = div1.innerHTML+"<p>Fizz</p>";
}else if (i%5===0){
document.getElementById("div1").innerHTML = div1.innerHTML+"<p>Buzz</p>";
}else{
document.getElementById("div1").innerHTML = div1.innerHTML+"<p>"+i+"</p>";
}
}
}
</script>
</head>
<body onLoad = "fizzbuzz()">
<div id = "div1">
<h1>Fizz Buzz</h1>
</div>
</body>
In your code, prompt() returns a string. Javascript will evaluate this line:
for(var i=1; i<num+1; i++){
with num as a string. i.e num+1 becomes "20"+"1" (note the quotes) which is "201". the comparison is then evaluated numerically, so your loop runs ten times linger than it should.
In your revised version i < num is evaluated numerically, so the loop runs for the correct period.
You can force num to be a number like this:
var num = Number(prompt("Please enter a number between 1 and 100: "));
num is now a number, so 20 + 1 = 21 (note - no quotes) and both versions of your loop should operate correctly
You need to do:
var num = parseInt(prompt("Please enter a number between 1 and 100: "), 0);
prompt returns a string, so if you enter 20, num+1 is the string "201", not the number 21.
here num is a string you have to use parseInt to convert it to int
for(var i=1; i<parseInt(num)+1; i++){
}
The prompt() returns a string.
Simple use +prompt() instead. That should make it a number. Updated code demo.
Each string in an array is a number, for example array1 = ["1296", "12", "27"];
For each string above, if possible to divide by 6 evenly without remainders, I want to do so at least once, then if the result is still longer than 2 characters, repeat. Then replace the string in the same position, such that the array would become ["36", "2", "27"];
so far, my code partly works.
w=0;
function divideBySix(){
if ((array1[w] / 6) == (Math.floor(array1[w] / 6))) {
var temp = array1[w] / 6;
array1[w] = temp.toString();
if (array1[w].length < 3) {
w++;
}
divideBySix();
}
The function successfully divides the first string by 6 once, and then calls itself again and again until the result is within 2 chars long. At that point, it should continue calling itself, and do the same to the next string of the array. But it doesn't do the next string. I don't know why it stops after finishing the first string. So the array looks like this ["36", "12", "27"]; Also, w successfully gets incremented. So I know its getting at least that far...
The function you give has unbalanced { }. When I add one at the end and run it, I get the result you say you want — ["36", "2", "27"]. There must be something else wrong, or you have not copied the code correctly.
In order to understand the operation, I added this to the beginning of divideBySix:
console.log(w, array1.toString());
i think you could just go with the modulo operator, if this is what you wanted to achieve
if(array1[w] % 6 == 0) doSomething()
and to solve your current problem you could introduce a second function ; for me it works with :
function divideBySix(array){
for(var i = 0; i < array.length; i++){
array[i] = divideNumber(array[i], 0);
}
}
function divideNumber(nr, ct){
if((ct < 1 || nr > 99) && nr%6 == 0 ) return divideNumber(nr/6, ct+1);
else return nr;
}
var array1 = ["1296", "12", "27"];
divideBySix(array1);
alert(array1);
When I test the code, that's what it does:
http://jsfiddle.net/Guffa/x4fNP/