Join letters to 1 word - javascript

I'm playing around with PEG.js.
This is my grammar:
start = expression
expression = a:[a-z]+
{return a.join("");}
When I execute it in my browser:
obj = parser.parse("test");
for (var i = 0; i <= obj.length; i++) {
console.log(i + " - " + obj[i])
}
I get this output:
0 - t
1 - e
2 - s
3 - t
4 - undefined
Why isn't it joined to only 1 word, even though I used return a.join("") in my grammar?

parser.parse does return the single word "test"; you are just printing it one character at a time.
Did you mean to do this?
var result = parser.parse("test");
console.log(result) // "test"

To directly answer your question, you're getting one letter each iteration because a string acts like an array. So you're accessing one letter at a time by using obj[i] Try this to get one word returned.
obj = parser.parse("test");
for (var i = 0; i <= obj.length; i++) {
console.log(i + " - " + obj)
}

Related

Converting from infix to prefix notation in JavaScript

Please help me in JavaScript: The program that I am coding is one that takes in an expression in prefix notation and outputs the same expression in infix notation. The idea behind this program is as follows:
if the user enters 1 + 2 the expected output is + 1 2. All valid symbols are +, -, *, /, and %. The amount of numbers that the user can enter should be limitless (so for example, if I enter 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10, the program should return + 1 2 3 4 5 6 7 8 9 10).
Could someone please help me fill in the comment out portion of the loop, and if you think there's a better approach to the problem entirely, I am open to that!
function infix(input) {
var x = input.split(''); // splits each variable and stores it in an array
var output = [];
var final = " "; // will be used to store our infix expression
for (var i = 0; i < x.length; i++) {
//if x[i] is any of the following : "+, -, *, /, or %" , store it in array output at index 0
//else if x[i] is a number : store it in an index of array output that is >= 1
}
for (var j = 0; j < output.length; j++) {
var final = x[0] + x[j];
}
console.log(final);
}
infix("1 + 2 + 3")
Here's a snippet:
function infix(input){
const specialCharacters = ['+', '-', '*', '/', '%'];
const allCharacters = input.split('');
const prefixes = [];
const numbers = [];
// go through all chars of input
for (let i = 0; i < allCharacters.length; i++) {
const thisCharacter = allCharacters[i];
// If the char is contained within the list of 'special chars', add it to list of prefixes.
if (specialCharacters.includes(thisCharacter))
prefixes.push(thisCharacter);
// In case this is a whit space, just do nothing and skip to next iteration
else if (thisCharacter === ' ')
continue;
// If it's a number, just add it to the array of numbers
else
numbers.push(thisCharacter);
}
// Merge both arrays
const final = [...prefixes, ...numbers];
// Back to string
const finalString = final.join(' ');
console.log(final);
console.log('String format: ' + finalString);
}
infix('1 + 2 - 3');
Notice:
I replaced var by the new ES6 specification, const and let. (Use const always, use let if you have to re-write)
I am not sure if you want to keep all the symbols if you have them, so I made an array. If you want only one symbol, instead of keeping an array, just keep a single variable
Add an extra case for white spaces

Using two for loops to compare two strings

I am working through exercises on exercism.io and the third one asks us to compare two DNA strings and return the difference (hamming distance) between them.
So for example:
GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^ ^ ^ ^^
There are 7 different characters lined up in that comparison. My question is whether I'm taking the right approach to solve this. I created two empty arrays, created a function that loops through both strings and pushes the different letters when they meet.
I tried running it through a console and I always get an unexpected input error.
var diff = [];
var same = [];
function ham(dna1, dna2) {
for (var i = 0; i < dna1.length; i++)
for (var j = 0; j < dna2.length; i++){
if (dna1[i] !== dna2[j]) {
console.log(dna1[i]);
diff.push(dna1[i]);
}
else {
console.log(dna1[i]);
same.push(dna1[i]);
}
return diff.length;
}
ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff.length + ".");
Do not use globals.
Do not use nested loops if you don't have to.
Do not store useless things in arrays.
function ham(dna1, dna2) {
if (dna1.length !== dna2.length) throw new Error("Strings have different length.");
var diff = 0;
for (var i = 0; i < dna1.length; ++i) {
if (dna1[i] !== dna2[i]) {
++diff;
}
}
return diff;
}
var diff = ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff + ".");
The first problem is that you're missing a closing }. I think you want it right before the return statement.
secondly, there's a problem with your algorithm. You compare every item in dna1 (i) with every item in dna2 instead of coparing the item in the same position.
To use a shorter example so we can step through it, consider comparing 'CAT' and 'CBT'. you want to compare the characters in the same position in each string. So you don't actually want 2 for loops, you only want 1. You'd compare C to C ([0]), A to B ([1]), and T to T ( [2] ) to find the 1 difference at [1]. Now step through that with your 2 for loops in your head, and you'll see that you'll get many more differences than exist.
Once you use the same offset for the characters in each string to compare, you have to stat worrying that one might be shorter than the other. You'll get an error if you try to use an offset at the end of the string. So we have to take that into account too, and assumedly count the difference between string length as differences. But perhaps this is out of scope for you, and the the strings will always be the same.
You only need to have one single loop like below:
var diff = [];
var same = [];
function ham(dna1, dna2) {
for (var i = 0; i < dna1.length; i++) {
if (dna1[i] !== dna2[i]) {
console.log("not same");
diff.push(dna1[i]);
} else {
console.log("same");
same.push(dna1[i]);
}
}
return diff.length;
}
ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff.length + ".");
The edit distance is not really hard to calculate. More code is needed to cover the edge cases in parameter values.
function hamming(str1, str2) {
var i, len, distance = 0;
// argument validity check
if (typeof str1 === "undefined" || typeof str2 === "undefined") return;
if (str1 === null || str2 === null) return;
// all other argument types are assumed to be meant as strings
str1 = str1.toString();
str2 = str2.toString();
// the longer string governs the maximum edit distance
len = str1.length > str2.length ? str1.length : str2.length;
// now we can compare
for (i = 0; i < len; i++) {
if ( !(str1[i] === str2[i]) ) distance++;
}
return distance;
}
Execution of function:
ham( "GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT" );
of the following function definition:
function ham(A,B){
var D = [], i = 0;
i = A.length > B.length ? A : B;
for( var x in i)
A[x] == B[x] ? D.push(" ") : D.push("^");
console.log( A + "\n" + B +"\n" + D.join("") );
}
will output the log of:
GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^ ^ ^ ^^
Is capable of receiving different length strings, which depending on the requirement and data representation comparison can be modified to fill the blank with adequate standard symbols etc.
Demo:
ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
function ham(A, B) {
var D = [],
i = 0;
i = A.length > B.length ? A : B;
for (var x in i)
A[x] == B[x] ? D.push(" ") : D.push("^");
console.log(A + "\n" + B + "\n" + D.join(""));
};
I think that you would want to do something like this:
var dna1 = "GAGCCTACTAACGGGAT";
var dna2 = "CATCGTAATGACGGCCT";
function ham(string1, string2) {
var counter = 0;
for (i = 0;i < string1.length;i++) {
if (string1.slice(i, i + 1) != string2.slice(i, i + 1)) {
counter++
};
};
return(counter);
};
console.log("insert text here " + ham(dna1, dna2));
It checks each character of the string against the corresponding character of the other string, and adds 1 to the counter whenever the 2 characters are not equal.
You can use Array#reduce to iterate the 1st string, by using Function#call, and compare each letter to the letter of the corresponding index in the 2nd string.
function ham(dna1, dna2) {
return [].reduce.call(dna1, function(count, l, i) {
return l !== dna2[i] ? count + 1 : count;
}, 0);
}
var diff =ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff + ".");

JavaScript indexOf String Function 2nd argument is not working

For some reason, my indexOf 2nd arg (where to start the search) is not working. It just always returns 4 or -1.
Where string test = "Bob jr" and I am using built-in JavaScript console on about:blank:
> var test = "Bob jr";
> test.indexOf('j', 0);
< 4 = $3
> test.indexOf('j', 1);
< 4 = $3
> test.indexOf('j', 12);
< -1 = $2
Why is this not working and how can I get it working?
Whether you start looking at 0 or index 1, the j is still at index 4.
Your final example proves the argument does work, because you said to start after the j (beyond the end of the string entirely), and sure enough, it didn't find it.
Let's see indexOf's second argument in action:
var str = "j and j and j x";
console.log("Search string: '" + str + "'");
for (var n = 0; n < str.length; ++n) {
test(str, n);
}
function test(s, start) {
var index = s.indexOf("j", start);
console.log("Starting at " + start + ": " + index);
}
If you want to find out how far after the index you've given it is to the j, you can do that in two ways:
Subtract your index from the result you get:
console.log("Distance: " + (test.indexOf('j', 1) - 1));
Search a substring:
console.log("Distance: " + test.substring(1).indexOf('j');
Check the documentation of indexOf here
str.indexOf(searchValue[, fromIndex])
There is no j after position 12 and that is why you are getting -1 in the last case.
indexOf always return the index within the calling String object of the first occurrence of the specified value, starting the search at fromIndex. The reason your return value isn't changing is because "j" is still the 5th character in your string, regardless of whether you begin your search a few characters into the string.

Counting vowels in javascript

I use this code to search and count vowels in the string,
a = "run forest, run";
a = a.split(" ");
var syl = 0;
for (var i = 0; i < a.length - 1; i++) {
for (var i2 = 0; i2 < a[i].length - 1; i2++) {
if ('aouie'.search(a[i][i2]) > -1) {
syl++;
}
}
}
alert(syl + " vowels")
Obviously it should alert up 4 vowels, but it returns 3.
What's wrong and how you can simplify it?
Try this:
var syl = ("|"+a+"|").split(/[aeiou]/i).length-1;
The | ensures there are no edge cases, such as having a vowel at the start or end of the string.
Regarding your code, your if condition needs no i2
if('aouie'.search(a[i]) > -1){
I wonder, why all that use of arrays and nested loops, the below regex could do it better,
var str = "run forest, run";
var matches = str.match(/[aeiou]/gi);
var count = matches ? matches.length : 0;
alert(count + " vowel(s)");
Demo
Try:
a = "run forest, run";
var syl = 0;
for(var i=0; i<a.length; i++) {
if('aouie'.search(a[i]) > -1){
syl++;
}
}
alert(syl+" vowels")
First, the split is useless since you can already cycle through every character.
Second: you need to use i<a.length, this gets the last character in the string, too.
The simplest way is
s.match(/[aeiou]/gi).length
You can use the .match to compare a string to a regular expression. g is global which will run through the entire string. i makes the string readable as upper and lower case.
function getVowels(str) {
var m = str.match(/[aeiou]/gi);
return m === null ? 0 : m.length;
}

How can I parse a string in Javascript?

I have string looking like this:
01
02
03
99
I'd like to parse these to make them into strings like:
1. 2. 3. 99. etc.
The numbers are a maximum of 2 characters. Also I have to parse some more numbers later in the source string so I would like to learn the substring equivalent in javascript. Can someone give me advice on how I can do. Previously I had been doing it in C# with the following:
int.Parse(RowKey.Substring(0, 2)).ToString() + "."
Thanks
Why, parseInt of course.
// Add 2 until end of string
var originalA = "01020399";
for (var i = 0; i < originalA.length; i += 2)
{
document.write(parseInt(originalA.substr(i, 2), 10) + ". ");
}
// Split on carriage returns
var originalB = "01\n02\n03\n99";
var strArrayB = originalB.split("\n");
for (var i = 0; i < strArrayB.length; i++)
{
document.write(parseInt(strArrayB[i], 10) + ". ");
}
// Replace the leading zero with regular expressions
var originalC = "01\n02\n03\n99";
var strArrayC = originalC.split("\n");
var regExpC = /^0/;
for (var i = 0; i < strArrayC.length; i++)
{
document.write(strArrayC[i].replace(regExpC, "") + ". ");
}
The other notes are that JavaScript is weakly typed, so "a" + 1 returns "a1". Additionally, for substrings you can choose between substring(start, end) and substr(start, length). If you're just trying to pull a single character, "abcdefg"[2] will return "c" (zero-based index, so 2 means the third character). You usually won't have to worry about type-casting when it comes to simple numbers or letters.
http://jsfiddle.net/mbwt4/3/
use parseInt function.
parseInt(09) //this will give you 9
var myString = parseInt("09").toString()+". "+parseInt("08").toString();
string = '01\n02\n03\n99';
array = string.split('\n');
string2 = '';
for (i = 0; i < array.length; i++) {
array[i] = parseInt(array[i]);
string2 += array[i] + '. ';
}
document.write(string2);
var number = parseFloat('0099');
Demo
Substring in JavaScript works like this:
string.substring(from, to);
where from is inclusive and to is exclusive. You can also use slice:
string.slice(from, to)
where from is inclusive and to is exclusive. The difference between slice and substring is with slice you can specify negative numbers. For example, from = -1 indicates the last character. from(-1, -3) would give you the last 2 characters of the string.
With both methods if you don't specify end then you will get all the characters to the end.
Paul
Ii they are always 2 digits how about;
var s = "01020399";
var result = []
for (var i = 0; i < s.length; i+=2)
result.push(parseInt(s.substr(i, 2), 10) + ".")
alert( result[2] ) // 3.
alert( result.join(" ") ) // 1. 2. 3. 99.

Categories

Resources