Converting Infix to prefix notation in JavaScript - javascript

(I did ask a similar question in the past, but the documentation was wrong, so this is the correct version of that past question)
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") // should output "+ + 1 2 3"
infix("1 - 2 % 3 + 1 * 4") // should output "- % + * 1 2 3 1 4"

Your code is mostly there.
The main logic of your program needs to split your input string into two sections (arrays). One for symbols/operands, and another for numbers. Checking if x[i] is "+, -, ..." will allow us to check if the current symbol is an operand, which is a good start. However, we don't want to store it at index 0 of the output array. If you did this, then all of the symbols would be inputted in reverse order (which isn't what you want). Instead, you can add your symbols to the end of your array. In the code snippet below, I have pushed all symbols into the operands array.
So, how can we check if x[i] is a symbol? One way is to check x[i] against every symbol like so:
if(x[i] === "+" || x[i] === "-" || ... ) {
operands.push(x[i]); // add the symbol to the end of the array
}
Or, you could write this a little more cleanly using .includes(), which removes the need to multiple ||:
var symbols = ['+', '-', '*', '/', '%'];
...
if(symbols.includes(x[i])) {
operands.push(x[i]);
}
If the current character (x[i]) isn't a symbol then it must be a number (as we split on spaces). So, you can then add an else, and push the current character into the numbers array.
After you've looped through all characters, you'll have an array of operands, in the order that they appeared in the input string, and an array of numbers, also in the order they appeared in the input string. Our last step is to convert the operands and numbers array into strings, where each element in these arrays are separated by a space. The easiest way to do this is by using the .join() method, which will join every element in your array into a string, separating each element by the argument you give it.
By doing all of this, you can get your desired output:
function infix(input) {
var x = input.split(' '); // splits each character and stores it in an array
var operands = [];
var numbers = [];
var symbols = ['+', '-', '/', '*', '%'];
for (var i = 0; i < x.length; i++) {
if(symbols.includes(x[i])) {
operands.push(x[i]);
} else {
numbers.push(x[i]);
}
}
var final = operands.join(' ') +' ' +numbers.join(' ');
return final;
}
console.log(infix("1 + 2 + 3")); // "+ + 1 2 3"
console.log(infix("1 - 2 % 3 + 1 * 4")); // "- % + * 1 2 3 1 4"
Or, you can do this more concisely by using the .match() method to get the non-numeric (or space) characters and another to get the numeric characters:
const infix = input =>
[...input.match(/[^\d\s]/g), ...input.match(/\d+/g)].join(' ');
console.log(infix("1 + 2 + 3")); // "+ + 1 2 3"
console.log(infix("1 - 2 % 3 + 1 * 4")); // "- % + * 1 2 3 1 4"

Related

Split string in array on whitespace before the 10th character

I want to split a string into characters of 10. But I don't want to split inside a word.
So the string "Nine characters to go - then some more" would be split in ["Nine", "characters", "to go -", "then some", "more"].
The word can split if it's more than 10 characters.
The closest I got using regex was .{1,10}(?<=\s).
That would split "Nine characters to go - then some more" into ["Nine ", "haracters ", "to go - ", "then some "].
But the behaviour is weird. In the example string it completely skips the character "c". In other test strings it would only add "- " in a separate array item when just the dash would fit in with the array item before it. So it splits after the whitespace.
I also attempted to .split() on white spaces (.split(' ')) and using .reduce() or a for loop to join array items into other array items of max 10 characters.
for ( i = 0; i < splitArray.length; i++ ) {
if ( i === 0 ) {
// add first word in new array. Doesn't take into account yet that word can be longer than 10 characters
newArray.push( splitArray[i] );
} else {
if ( newArray[ newArray.length - 1 ].length + splitArray[i].length + 1 < 10 ) {
// if next word fits with the word in the new array (taking space into account), add it to it
newArray[ newArray.length - 1 ] = newArray[ newArray.length - 1 ] + " " + splitArray[i];
} else if ( newArray[ newArray.length - 1 ].length + splitArray[i].length + 1 >= 10 ) {
// next word doesn't fit
// split word and add only part to it and add the rest in separate item in newArray
const index = 9 - newArray[ newArray.length - 1 ].length
const prev = splitArray[i].slice( 0, index );
const next = splitArray[i].slice( index, splitArray[i].length );
newArray[ newArray.length - 1 ] = newArray[ newArray.length - 1 ] + " " + prev;
newArray.push( next );
} else {
// push new item in newArray
newArray.push( splitArray[i] );
}
}
}
Results in: ["Nine chara", "cters to g", "o - then s", "ome more"].
Without the else if: ["Nine", "characters", "to go -", "then some", "more"]
Without the else if other string: ["Paul van", "den Dool", "-", "Alphabet", "- word"]
This is close, but "Alphabet" won't join with the hyphen, because together they don't fit. I tried catching that with an else if statement but that is breaking words again that I don't want to break and is the same result as the regex above.
My mind is depleted on this issue, I need the hive mind for this. So any help on this is very much appreciated.
Context
I'm trying to display text on canvas in a limited sized box with a minimum font size. My solution would be to break the string, which can be entered by the user, into multiple lines if necessary. For this I need to split the string into an array, loop over it and position the text accordingly.
const string = "Nine characters to go - then some more"
let arr = string.split(" ");
for(let i = 1; i < arr.length; i++) {
if(arr[i].length >= 10 || arr[i].length + arr[i-1].length >= 10) {
continue;
}
if(arr[i].length < 10 && arr[i].length + arr[i-1].length <= 10) {
arr[i] = arr[i - 1] + " " + arr[i];
arr[i-1] = false;
}
}
arr = arr.filter(string => string)
console.log(arr);
Use
console.log(
"Nine characters to go - then some more"
.match(/.{1,10}(?=\s|$)/g)
.map(z => z.trim())
);
With .match(/.{1,10}(?=\s|$)/g), the items will be 1 to 10 characters long, and (?=\s|$) will assure a whitespace or end of string is matched.
If you need to split, use .split():
const str = 'Nine characters to go - then some more',
result = str.split(/(.{1,10})\s/).filter(Boolean)
console.log(result)
I can solve this using a simple for loop:
const str = "Nine characters to go - then some more";
// make an array with each words
const arr = str.trim().split(' ');
// This is the length, how much we want to take the length of the words
const length = 10;
const res = [];
/**
* Put the first word into the result array
* because if the word greater or less than
* the `length` we have to take it.
*/
res.push(arr[0]);
// Result array's current index
let index = 0;
for (let i = 1, l = arr.length; i < l; i++) {
/**
* If the length of the concatenation of the
* last word of the result array
* and the next word is less than or equal to the length
* then concat them and put them as the last value
* of the resulting array.
*/
if ((res[index] + arr[i]).length <= length) {
res[index] += ' ' + arr[i];
} else {
/**
* Otherwise push the current word
* into the resulting array
* and increase the last index of the
* resulting array.
*/
res.push(arr[i]);
index++;
}
}
console.log(res);
.as-console-wrapper{min-height: 100%!important; top: 0}

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

adding a space to every space in a string, then cycling back around until length is met

I have the following while loop as part of my text justify function. The idea is that I have text strings (str) that need to be justified (spaces added to existing spaces in between words) to equal to a given length (len)
The catch is I can only add one space to an existing space at a time before I iterate over to the next space in the string and add another space there. If that's it for all spaces in the string and it's still not at the required length, I cycle back over to the original space (now two spaces) and add another. Then it goes to the next space between words and so on and so on. The idea is that any spaces between words in the string should not have a differential of more than one space (i.e. Lorem---ipsum--dolor--sit, not Lorem----ipsum--dolor-sit)
From my research, I decided that using a substring method off the original string to add that first extra space, then I will increment the index and move to the next space in the string and repeat the add. Here's my code:
var indexOf = str.indexOf(" ", 0);
if ( indexOf > -1 ) {
while ( indexOf > -1 && str.length < len ) {
//using a regexp to find a space before a character
var space = /\s(?=\b)/.exec(str);
str = str.substring(0, indexOf + 1) + " " + str.substring(indexOf + 1);
//go to next space in string
indexOf = str.indexOf(space, indexOf + 2);
if ( indexOf === -1 ) {
//loops back to beginning of string
indexOf = str.indexOf(space, 0);
}
}
}
finalResults.push(str);
This code works most of the time, but I noticed that there are instances where the cycle of spacing is not correct. For example, it generates the following string:
sit----amet,--blandit
when the correct iteration would be
sit---amet,---blandit
Any assistance in making this code properly iterate over every space (to add one space) in the string once, then cycling back around to the beginning of the string to start over until the desired length is achieved would be most appreciated.
I think it's more efficient to compute the number spaces required in the beginning.
var s = "today is a friday";
var totalLength = 40;
var tokens = s.split(/\s+/);
var noSpaceLength = s.replace(/\s+/g,'').length;
var minSpace = Math.floor((totalLength - noSpaceLength)/(tokens.length-1));
var remainder = (totalLength - noSpaceLength) % (tokens.length-1);
var out = tokens[0];
for (var i = 1; i < tokens.length; i++) {
var spaces = (i <= remainder ? minSpace+1 : minSpace);
out += "-".repeat(spaces) + tokens[i];
}
$('#out').text(out);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="out"></div>
This solution
splits the string (s) into words in an array (a)
finds the number of spaces to be added between all words (add)
finds the remainder of spaces to be added between first words (rem)
then sticks the words with add spaces + one if rem is not exhausted
Code
var s = "Caballo sin Nombre"; // assume one space between words
var len = 21; // desired length
var need = len - s.length;
var a = s.split(/ /); // split s
// need>0 and at least two words
if (need > 0 && a.length>1) {
var add = Math.floor(need / (a.length-1)) + 1; // all spaces need that (+existing)
var rem = need % (a.length-1); // remainder
var sp = '';
while (add-- > 0) sp += ' ';
// replace
var i,res = ''; // result
for (i=0 ; i<a.length-1 ; i++) {
res += a[i] + sp;
if (rem-- > 0) res += ' '; // remainder
}
res += a[i];
s = res;
}
console.log("'" + s + "' is " + s.length + " chars long.");
This function adds the spaces using a global replace, carefully limiting the text size.
function expand (txt, colwidth) {
txt = txt.replace (/\s\s+/, ' '); // Ensure no multiple spaces in txt
for (var spaces = ' ', // Spaces to check for
limit = colwidth - txt.length; // number of additional spaces required
limit > 0; // do while limit is positive
spaces += ' ') // add 1 to spaces to search for
txt = txt.replace (RegExp (spaces, 'g'),
function (r) {
// If limit > 0 then add a space else do not.
return limit > 0 && --limit ? r + ' ' : r
});
return txt;
}
for (var w = 21; w--;) console.log (expand ('this is a test.', w));
Shows this on console:
this is a test.
this is a test.
this is a test.
this is a test.
14 this is a test.

I need a explaining for this short script

I have this code :
function list(target, letters, lvls) {
var index = 0;
(function iter(s, lvl) {
if(lvl++ == lvls)
return target.appendChild(document.createTextNode(
++index + ' - ' + s + '\n'
));
for(var i=0; i<letters.length; ++i)
iter(s + letters[i], lvl);
})('', 0);
}
list(document.getElementById('output'), 'abc', 3);
But I don't know this type of function syntax.
Can some one explain to me the function behavior and what this code exactly do step by step.
And thanks in advance
This seems to be iterating through the string 'abc' and creating as many X letter strings as possible with the combination of all the characters in the string.
So the call is list([element ID to output strings], [string of all possible letters], [size of strings to generate])
So the following example -
<script type="text/javascript">
function list(target, letters, lvls) {
var index = 0;
(function iter(s, lvl) {
if(lvl++ == lvls)
return target.appendChild(document.createTextNode(
++index + ' - ' + s + '\n'
));
for(var i=0; i<letters.length; ++i)
iter(s + letters[i], lvl);
})('', 0);
}
list(document.getElementById('output'), 'ab', 2);
</script>
<div id="output"></div>
will output all possible two letter strings (defined by param 3), using the characters from the input string (param 2) and will result in -
1 - aa 2 - ab 3 - ba 4 - bb
Explanation
Inside the method there is a second called iter with the arguments s and lvls. On
first run, the arguments parsed to the iter method are blank and 0. It hits the for
loop which runs until all of the letters in the string letters have been used up,
each time recursively calling the iter method. Each time it adds the current letter in
the iteration s, along with the next letter in the string letters[i]. Every time it
recursively calls itself it builds up the string until the number of specified levels have
been reached for that particular string and then returns the result, along with the index
value. This is just a numeric value to represent the string count.

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