I am trying to solve a problem from jshero.net. The problem is the following:
Write a function spaces that takes a natural number n and returns a string of n spaces. spaces(1) should return ' '.
I need to use a while loop to solve this challenge. The best solution I could come up with is:
function spaces(num) {
let mySpaces = '';
while(mySpaces === num) {
mySpaces+= num}
}
}
But it returns the following errors:
spaces(0) does not return '', but undefined.
Test-Error! Correct the error and re-run the tests!
Does anyone know how to solve this?
Make sure to return your output, and subtract from num each iteration:
function spaces(num) {
let mySpaces = '';
while (num-- > 0)
mySpaces += ' ';
return mySpaces;
}
console.log(
JSON.stringify(spaces(1)),
'\n',
JSON.stringify(spaces(5))
);
Ultimately, this seems to be the most elegant (and performant) approach:
const spaces = (n) => Array(n + 1).join(' ');
console.log(
JSON.stringify(spaces(1)),
'\n',
JSON.stringify(spaces(5))
);
1.1M ops/s for Array.join vs. 86k for the while loop.
EDIT
Totally blanked on String.repeat, thanks to Daniel for that. Pushing 2M ops/s:
const spaces = (n) => " ".repeat(n);
console.log(
JSON.stringify(spaces(1)),
'\n',
JSON.stringify(spaces(5))
);
I just succeeded to resolve it with the litle help of other peoples answers here.
This is the code that solved :
function spaces(num){
let s = '';
while(s.length < num){
s = ' '.repeat(num);
return s;
}
}
spaces=(n)=>{
let a='';
while(a.length<n){
a= a+ ' ';
}
return a;
}
This snippet worked for me; All tests passed!
function spaces(n){
let a = '';
while ( a.length<n ){
a = a + ' ';}
return a;
}
This is the correct Code you need to put s.length<=num
function spaces(num){
let s = '';
while(s.length <= num){
s = ' '.repeat(num);
return s;
}
}
Related
i have a function to split string into 2 part, front and back. Then reverse it to back and front. Here is my code
function reverseString(string) {
let splitString = ""
let firstString = ""
for(i = 0; i <= string.length/2 - 1; i++) {
firstString += string[i]
}
for(i = string.length/2; i <= string.length; i++) {
splitString += string[i]
}
return splitString + firstString
}
Sorry for bad explanation, this is test case and expected result (first one is expected result, the second one is my result)
console.log(reverseString("aaabccc")); // "cccbaaa" "undefinedundefinedundefinedundefinedaaa"
console.log(reverseString("aab")); // "baa" "undefinedundefineda"
console.log(reverseString("aaaacccc")); // "ccccaaaa" "ccccundefinedaaa"
console.log(reverseString("abcdefghabcdef")); // "habcdefabcdefg" "habcdefundefinedabcdefg"
could you help me, whats wrong with it. Thank you
You could try another approach and use the slice function
function reverseString(string)
{
if (string.length < 2) { return string; }
let stringHalfLength = string.length / 2;
let isLengthOdd = stringHalfLength % 1 !== 0;
if (isLengthOdd) {
return string.slice(Math.ceil(stringHalfLength), string.length + 1) + string[Math.floor(stringHalfLength)] + string.slice(0, Math.floor(stringHalfLength));
}
return string.slice(stringHalfLength, string.length + 1) + string.slice(0, stringHalfLength);
}
console.log(reverseString("aaabccc") === "cccbaaa");
console.log(reverseString("aab") === "baa");
console.log(reverseString("aaaacccc") === "ccccaaaa");
console.log(reverseString("abcdefghabcdef") === "habcdefabcdefg");
A more efficient way to reverse the string would be to split the string, then use the built-in reverse javascript function (which reverses the elements of the split string), and then re-join the elements using the join function.. No need to re-invent the wheel?
You can concatenate the functions in shorthand (.split.reverse.join etc...) so your function would look something like this:
function reverseString(string) {
return string.split("").reverse().join("");
}
Try it out!
function reverseString(string) {
return string.split("").reverse().join("");
}
console.log(reverseString("hello"));
console.log(reverseString("aaabbbccc"));
If there's a particular reason you're opting not to use the in-built functions (i.e. if I've missed something?) , feel free to comment.
The short version of what you need:
function reverseString(string) {
const splitPosition = Math.ceil(string.length / 2);
return string.substring(splitPosition) + string.substring(0, splitPosition);
}
The key to your question is the middle element. To accomplish that, you probably want to use Math.floor that round under.
console.log(reverseString("aaabccc")); // "cccbaaa"
console.log(reverseString("abcdefghabcdef")); // "habcdefabcdefg"
function reverseString (str) {
if (str.length<2) {
return str
}
var half = Math.floor(str.length / 2);
return (str.slice(-half) + (str.length%2?str[half]:"") + str.slice(0,half));
}
reverseString('')
> ""
reverseString('1')
> "1"
reverseString('12')
> "21"
reverseString('123')
> "321"
reverseString('1234')
> "3412"
reverseString('12345')
> "45312"
reverseString("aaabccc")
> "cccbaaa"
reverseString("abcdefghabcdef")
> "habcdefabcdefg"
So basically your problem is not to grab 2 parts of the string and rearrange, it is to grab 3 parts.
1 part: str.slice(0,half)
2 part: str.length%2 ? str[half] : ""
3 part: str.slice(-half)
The second part is empty if the string length is even and the middle character if is odd.
So the code version in long self explanatory code:
function reverseString (str) {
if (str.length<2) {
return str
}
var half = Math.floor(str.length / 2);
var firstPart = str.slice(0,half);
var midlePart = str.length % 2 ? str[half] : ""; // we could expand also this
var endPart = str.slice(-half);
return endPart + midlePart + firstPart;
}
And also, notice the precondition, so I don't have to deal with the easy cases.
Also, in your code, you got undefined because you access in the last loop to:
string[string.length] you need to change <= by <
May I ask my first question. Sorry if the title is so bad. It was a bit annoy me. So I was build a function to reverse a string that have 5 character or more like this.
function spinWords(str) {
str2 = str.split(" ");
str3 = [];
for (i = 0; i < str2.length; i++) {
str3 = str2[i].split("");
if (str3.length >= 5) {
str3.reverse();
}
str4 = str3.join("");
return str4;
}
}
spinWords("Welcome To The Club");`
The output that I expected is like this
emocleW To The Club
But that code output is this
emocleW
To
The
Club
Is there any solution, at least to combine the four iteration string into one line?
Every help would be very nice. Thanks!!!
function spinWords(str) {
function reverseString(str) {
return str.split("").reverse().join("");
}
const words = str.split(" ");
const spinnedWords = words.map(word => {
if (word.length >=5 ) return reverseString(word);
else return word;
});
return spinnedWords.join(' ');
}
spinWords("Welcome To The Club");
Seems you are printing the array which would give that result, you would need to join the array to get it on one line like so
myArray.join(" ");
A short example that would do the thing you want
function spinWords(str) {
return str.split(" ")
.map((word) => word.length > 4
? word.split('').reverse().join('') // Reverses a string
: word
)
.join(" ");
}
Other SO 'Replace string with alphabet positions' questions didn't utilize map, which is what I'm trying to learn how to use to solve this.
Problem:
Given a string, replace every letter with its position in the alphabet.
If anything in the text isn't a letter, ignore it and don't return it.
"a" = 1, "b" = 2, etc.
What I've tried is:
-looping over a new array instance and setting the index value to String.fromCharCode()
- taking input string making it lowercase
-splitting to array
-return array.map().join(' ')
function alphabetPosition(text) {
let alphabet = new Array(26);
for (let i = 0; i<26; ++i) {
let char = String.fromCharCode(97 + i);
alphabet[i] = char;
}
text = text.toLowerCase();
let arr = text.split('');
return arr.map(element => { return element = alphabet.indexOf(element+1) }).join(' ');
}
expected it to return a string of alphabet positions, but got nothing at all. What is wrong with my implementation of Array.map()?
In your map element would be a letter, "a" for example. Then you add (concat) 1 to it, which results in "a1" which is not in your alphabet. Also element = is unneccessary, returning the position is enough.
You've complicated the solution, the simplest approach would be to just find the charcode and return that.
function alphabetPosition(text) {
let str = '';
for (var i = 0; i < text.length; i++) {
str += (text[i] + (text.charCodeAt(i) - 96));
}
return str;
}
I totally understand that is a coding challenge, interview question or likewise so if you really need to use map() you should only return the result of the callback passed to map as follows :
return arr.map(x => alphabet.indexOf(x) + 1).join(' ')
However reduce() seems more appropriate in your case :
return arr.reduce((ac, cv) => ac + (alphabet.indexOf(cv) + 1) + ' ', '')
Your map() last line of the function was returning the value of
an assignment.
return arr.map(element => { return element = alphabet.indexOf(element+1) }).join(' ');
Just alphabet.indexOf(element) would have sufficed.
This will give you the result you want:
alphabetPosition = text => {
let alphabet = new Array(26);
for (let i = 0; i < 26; ++i) {
let char = String.fromCharCode(97 + i);
alphabet[i] = char;
}
return text.toLowerCase().split('').map(element =>
alphabet.indexOf(element)
).join(' ');
}
console.log(alphabetPosition("This is a string"));
Hope this helps,
I have this simple calculator script, but it doesn't allow power ^.
function getValues() {
var input = document.getElementById('value').value;
document.getElementById('result').innerHTML = eval(input);
}
<label for="value">Enter: </label><input id="value">
<div id="result">Results</div>
<button onclick="getValues()">Get Results</button>
I tried using input = input.replace( '^', 'Math.pow(,)');
But I do not know how to get the values before '^' and after into the brackets.
Example: (1+2)^3^3 should give 7,625,597,484,987
Use a regular expression with capture groups:
input = '3 + 2 ^3';
input = input.replace(/(\d+)\s*\^\s*(\d+)/g, 'Math.pow($1, $2)');
console.log(input);
This will only work when the arguments are just numbers. It won't work with sub-expressions or when you repeat it, like
(1+2)^3^3
This will require writing a recursive-descent parser, and that's far more work than I'm willing to put into an answer here. Get a textbook on compiler design to learn how to do this.
I don't think you'll be able to do this with simple replace.
If you want to parse infix operators, you build two stacks, one for symbols, other for numbers. Then sequentially walk the formula ignoring everything else than symbols, numbers and closing parenthesis. Put symbols and numbers into their stacks, but when you encounter closing paren, take last symbol and apply it to two last numbers. (was invented by Dijkstra, I think)
const formula = '(1+2)^3^3'
const symbols = []
const numbers = []
function apply(n2, n1, s) {
if (s === '^') {
return Math.pow(parseInt(n1, 10), parseInt(n2, 10))
}
return eval(`${n1} ${s} ${n2}`)
}
const applyLast = () => apply(numbers.pop(), numbers.pop(), symbols.pop())
const tokenize = formula => formula.split(/(\d+)|([\^\/\)\(+\-\*])/).filter(t => t !== undefined && t !== '')
const solver = (formula) => {
const tf = tokenize(formula)
for (let l of formula) {
const parsedL = parseInt(l, 10)
if (isNaN(parsedL)) {
if (l === ')') {
numbers.push(applyLast())
continue
} else {
if (~['+', '-', '*', '/', '^'].indexOf(l))
symbols.push(l)
continue
}
}
numbers.push(l)
}
while (symbols.length > 0)
numbers.push(applyLast())
return numbers.pop()
}
console.log(solver(formula))
Get your input into a string and do...
var input = document.getElementById('value').value;
var values = input.split('^'); //will save an array with [value1, value 2]
var result = Math.pow(values[0], values[1]);
console.log(result);
This only if your only operation is a '^'
EDIT: Saw example after edit, this no longer works.
function getValues() {
var input = document.getElementById('value').value;
// code to make ^ work like Math.pow
input = input.replace( '^', '**');
document.getElementById('result').innerHTML = eval(input);
}
The ** operator can replace the Math.pow function in most modern browsers. The next version of Safari (v10.1) coming out any day supports it.
As said in other answers here, you need a real parser to solve this correctly. A regex will solve simple cases, but for nested statements you need a recursive parser. For Javascript one library that offers this is peg.js.
In your case, the example given in the online version can be quickly extended to handle powers:
Expression
= head:Term tail:(_ ("+" / "-") _ Term)* {
var result = head, i;
for (i = 0; i < tail.length; i++) {
if (tail[i][1] === "+") { result += tail[i][3]; }
if (tail[i][1] === "-") { result -= tail[i][3]; }
}
return result;
}
Term
= head:Pow tail:(_ ("*" / "/") _ Pow)* { // Here I replaced Factor with Pow
var result = head, i;
for (i = 0; i < tail.length; i++) {
if (tail[i][1] === "*") { result *= tail[i][3]; }
if (tail[i][1] === "/") { result /= tail[i][3]; }
}
return result;
}
// This is the new part I added
Pow
= head:Factor tail:(_ "^" _ Factor)* {
var result = 1;
for (var i = tail.length - 1; 0 <= i; i--) {
result = Math.pow(tail[i][3], result);
}
return Math.pow(head, result);
}
Factor
= "(" _ expr:Expression _ ")" { return expr; }
/ Integer
Integer "integer"
= [0-9]+ { return parseInt(text(), 10); }
_ "whitespace"
= [ \t\n\r]*
It returns the expected output 7625597484987 for the input string (1+2)^3^3.
Here is a Python-based version of this question, with solution using pyparsing: changing ** operator to power function using parsing?
console.log( ‘blah’.repeatMe( 3 ) );
Using Javascript write the code that would make the previous function print:
Output: blahblahblah
Oh, it's too fun to pass up a functional style solution.
String.prototype.repeatMe = function(n) {
if (n <= 0) return "";
if (n%2 === 1) return (""+this) + this.repeatMe(n-1);
var half = this.repeatMe(n/2);
return half + half;
}
document.body.innerHTML = "tester".repeat(10)
I'll let you work out what's happening as an exercise.