javascript exercise - recursive function with a string - javascript

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.

Related

Undefined in Split String

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 <

How should I fix this asynchronicity problem in my "Josephus Problem" code?

Background
I'm new to JavaScript and am solving various formulations of the Josephus Problem to better understand the syntax. Using a circularLinkedList implementation*, I've solved the classic formulation: Wikipedia||Numberphile. I've also solved the problem for any fixed number of fighters and a fixed number of skips between eliminations (e.g., if skipping two fighters between eliminations, 1 eliminates 4, 5 eliminates 8, etc). I am now trying to solve the problem given any function that indicates the number of skips at a given moment.
Problem
I can't access the return value of my skip function. I understand from 1, 2, 3 that my issue involves asynchronicity, but am having trouble isolating takeaways from the long responses involving AJAX and jQuery, which I'm unfamiliar with. Could I get an ELI5 solution? I apologize for my lack of understanding.
Code
function winnerStepFunc(num, func) {
let cll = new circularLinkedList(); //Initializing list with participants
for (let a = 0; a < num; a++) {
cll.append(a);
}
function next(funcSteps) { //Generating string indicating #steps from function's output
let toEvaluate = "start";
for (let i = 0; i < funcSteps; i++) {
toEvaluate += ".next"
}
return toEvaluate;
}
let start = cll.getHead(); //Selecting first eliminator
while (cll.size() > 1) {
let toCheck = func(); // PROBLEM LINE
console.log("toCheck = " + toCheck); //toCheck = undefined
let str = next(toCheck);
while (eval(str) !== start && cll.size() > 1) { //
let locCurrent = cll.indexOf(start.element);
start = eval(str).next;
cll.removeAt(((locCurrent + toCheck)% cll.size()));
}
cll.delete(eval(str).next.element);
start = start.next;
}
console.log(start.element + 1);
}
function callFunction(name, args) { // builds function string to be evaluated
let result = name + "(";
for (let i = 0; i < args.length -1; i++) {
result += args[i] + ", ";
}
result += args[args.length-1] + ")";
return result;
}
function callFunction(name) {
let result = `${name}()`;
return result;
}
function addOne() { //<--The first basic example I'm trying:
return ++globalTimes; //Make the step increase by one for each elimination
}
var globalTimes = 0;
winnerStepFunc(12, function(){eval(callFunction("addOne"))});
*CLL Implementation
You don't return in your function. I would remove all the eval stuff and just call the function directly.
winnerStepFunc(12, addOne);

Return a string of N spaces

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;
}
}

How can i make a loop that will show '-' mark x time iteration was? [duplicate]

In Perl I can repeat a character multiple times using the syntax:
$a = "a" x 10; // results in "aaaaaaaaaa"
Is there a simple way to accomplish this in Javascript? I can obviously use a function, but I was wondering if there was any built in approach, or some other clever technique.
These days, the repeat string method is implemented almost everywhere. (It is not in Internet Explorer.) So unless you need to support older browsers, you can simply write:
"a".repeat(10)
Before repeat, we used this hack:
Array(11).join("a") // create string with 10 a's: "aaaaaaaaaa"
(Note that an array of length 11 gets you only 10 "a"s, since Array.join puts the argument between the array elements.)
Simon also points out that according to this benchmark, it appears that it's faster in Safari and Chrome (but not Firefox) to repeat a character multiple times by simply appending using a for loop (although a bit less concise).
In a new ES6 harmony, you will have native way for doing this with repeat. Also ES6 right now only experimental, this feature is already available in Edge, FF, Chrome and Safari
"abc".repeat(3) // "abcabcabc"
And surely if repeat function is not available you can use old-good Array(n + 1).join("abc")
Convenient if you repeat yourself a lot:
String.prototype.repeat = String.prototype.repeat || function(n){
n= n || 1;
return Array(n+1).join(this);
}
alert( 'Are we there yet?\nNo.\n'.repeat(10) )
Array(10).fill('a').join('')
Although the most voted answer is a bit more compact, with this approach you don't have to add an extra array item.
An alternative is:
for(var word = ''; word.length < 10; word += 'a'){}
If you need to repeat multiple chars, multiply your conditional:
for(var word = ''; word.length < 10 * 3; word += 'foo'){}
NOTE: You do not have to overshoot by 1 as with word = Array(11).join('a')
The most performance-wice way is https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
Short version is below.
String.prototype.repeat = function(count) {
if (count < 1) return '';
var result = '', pattern = this.valueOf();
while (count > 1) {
if (count & 1) result += pattern;
count >>>= 1, pattern += pattern;
}
return result + pattern;
};
var a = "a";
console.debug(a.repeat(10));
Polyfill from Mozilla:
if (!String.prototype.repeat) {
String.prototype.repeat = function(count) {
'use strict';
if (this == null) {
throw new TypeError('can\'t convert ' + this + ' to object');
}
var str = '' + this;
count = +count;
if (count != count) {
count = 0;
}
if (count < 0) {
throw new RangeError('repeat count must be non-negative');
}
if (count == Infinity) {
throw new RangeError('repeat count must be less than infinity');
}
count = Math.floor(count);
if (str.length == 0 || count == 0) {
return '';
}
// Ensuring count is a 31-bit integer allows us to heavily optimize the
// main part. But anyway, most current (August 2014) browsers can't handle
// strings 1 << 28 chars or longer, so:
if (str.length * count >= 1 << 28) {
throw new RangeError('repeat count must not overflow maximum string size');
}
var rpt = '';
for (;;) {
if ((count & 1) == 1) {
rpt += str;
}
count >>>= 1;
if (count == 0) {
break;
}
str += str;
}
// Could we try:
// return Array(count + 1).join(this);
return rpt;
}
}
If you're not opposed to including a library in your project, lodash has a repeat function.
_.repeat('*', 3);
// โ†’ '***
https://lodash.com/docs#repeat
For all browsers
The following function will perform a lot faster than the option suggested in the accepted answer:
var repeat = function(str, count) {
var array = [];
for(var i = 0; i < count;)
array[i++] = str;
return array.join('');
}
You'd use it like this :
var repeatedString = repeat("a", 10);
To compare the performance of this function with that of the option proposed in the accepted answer, see this Fiddle and this Fiddle for benchmarks.
For moderns browsers only
In modern browsers, you can now do this using String.prototype.repeat method:
var repeatedString = "a".repeat(10);
Read more about this method on MDN.
This option is even faster. Unfortunately, it doesn't work in any version of Internet explorer. The numbers in the table specify the first browser version that fully supports the method:
In ES2015/ES6 you can use "*".repeat(n)
So just add this to your projects, and your are good to go.
String.prototype.repeat = String.prototype.repeat ||
function(n) {
if (n < 0) throw new RangeError("invalid count value");
if (n == 0) return "";
return new Array(n + 1).join(this.toString())
};
String.repeat() is supported by 96.39% of browsers as of now.
function pad(text, maxLength){
return text + "0".repeat(maxLength - text.length);
}
console.log(pad('text', 7)); //text000
/**
* Repeat a string `n`-times (recursive)
* #param {String} s - The string you want to repeat.
* #param {Number} n - The times to repeat the string.
* #param {String} d - A delimiter between each string.
*/
var repeat = function (s, n, d) {
return --n ? s + (d || "") + repeat(s, n, d) : "" + s;
};
var foo = "foo";
console.log(
"%s\n%s\n%s\n%s",
repeat(foo), // "foo"
repeat(foo, 2), // "foofoo"
repeat(foo, "2"), // "foofoo"
repeat(foo, 2, "-") // "foo-foo"
);
Just for the fun of it, here is another way by using the toFixed(), used to format floating point numbers.
By doing
(0).toFixed(2)
(0).toFixed(3)
(0).toFixed(4)
we get
0.00
0.000
0.0000
If the first two characters 0. are deleted, we can use this repeating pattern to generate any repetition.
function repeat(str, nTimes) {
return (0).toFixed(nTimes).substr(2).replaceAll('0', str);
}
console.info(repeat('3', 5));
console.info(repeat('hello ', 4));
Another interesting way to quickly repeat n character is to use idea from quick exponentiation algorithm:
var repeatString = function(string, n) {
var result = '', i;
for (i = 1; i <= n; i *= 2) {
if ((n & i) === i) {
result += string;
}
string = string + string;
}
return result;
};
For repeat a value in my projects i use repeat
For example:
var n = 6;
for (i = 0; i < n; i++) {
console.log("#".repeat(i+1))
}
but be careful because this method has been added to the ECMAScript 6 specification.
function repeatString(n, string) {
var repeat = [];
repeat.length = n + 1;
return repeat.join(string);
}
repeatString(3,'x'); // => xxx
repeatString(10,'๐ŸŒน'); // => "๐ŸŒน๐ŸŒน๐ŸŒน๐ŸŒน๐ŸŒน๐ŸŒน๐ŸŒน๐ŸŒน๐ŸŒน๐ŸŒน"
This is how you can call a function and get the result by the helps of Array() and join()
using Typescript and arrow fun
const repeatString = (str: string, num: number) => num > 0 ?
Array(num+1).join(str) : "";
console.log(repeatString("๐ŸŒท",10))
//outputs: ๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท
function repeatString(str, num) {
// Array(num+1) is the string you want to repeat and the times to repeat the string
return num > 0 ? Array(num+1).join(str) : "";
}
console.log(repeatString("a",10))
// outputs: aaaaaaaaaa
console.log(repeatString("๐ŸŒท",10))
//outputs: ๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท๐ŸŒท
Here is what I use:
function repeat(str, num) {
var holder = [];
for(var i=0; i<num; i++) {
holder.push(str);
}
return holder.join('');
}
I realize that it's not a popular task, what if you need to repeat your string not an integer number of times?
It's possible with repeat() and slice(), here's how:
String.prototype.fracRepeat = function(n){
if(n < 0) n = 0;
var n_int = ~~n; // amount of whole times to repeat
var n_frac = n - n_int; // amount of fraction times (e.g., 0.5)
var frac_length = ~~(n_frac * this.length); // length in characters of fraction part, floored
return this.repeat(n) + this.slice(0, frac_length);
}
And below a shortened version:
String.prototype.fracRepeat = function(n){
if(n < 0) n = 0;
return this.repeat(n) + this.slice(0, ~~((n - ~~n) * this.length));
}
var s = "abcd";
console.log(s.fracRepeat(2.5))
I'm going to expand on #bonbon's answer. His method is an easy way to "append N chars to an existing string", just in case anyone needs to do that. For example since "a google" is a 1 followed by 100 zeros.
for(var google = '1'; google.length < 1 + 100; google += '0'){}
document.getElementById('el').innerText = google;
<div>This is "a google":</div>
<div id="el"></div>
NOTE: You do have to add the length of the original string to the conditional.
Lodash offers a similar functionality as the Javascript repeat() function which is not available in all browers. It is called _.repeat and available since version 3.0.0:
_.repeat('a', 10);
var stringRepeat = function(string, val) {
var newString = [];
for(var i = 0; i < val; i++) {
newString.push(string);
}
return newString.join('');
}
var repeatedString = stringRepeat("a", 1);
Can be used as a one-liner too:
function repeat(str, len) {
while (str.length < len) str += str.substr(0, len-str.length);
return str;
}
In CoffeeScript:
( 'a' for dot in [0..10]).join('')
String.prototype.repeat = function (n) { n = Math.abs(n) || 1; return Array(n + 1).join(this || ''); };
// console.log("0".repeat(3) , "0".repeat(-3))
// return: "000" "000"

JavaScript Countdown program

im trying to write a program in JavaScript that fulfils this prompt
Write a JavaScript function
countDown(i)
that takes an integer argument and returns a \countdown" from i to 0, with a space appearing between
each number.
For example, countDown(5) should return the string "5 4 3 2 1 0". As for the rst problem, you may
want to test your solution on the computer.
sofar I have this
var i= "";
function countdown(i)
{
while( i > 0)
{
console.log(integer);
i--;
}
}
countdown();
can someone please help me im very new to programing
Hopefully this makes enough sense:
function countdown(i) {
//initialize the variable to be returned with the initial i
var ret = i;
//in each iteration, assigns i to i-1 then checks if i >= 0
while (--i >= 0) {
//concatenates a space and the current i value to the return string
ret += ' ' + i;
}
//returns the string
return ret;
}
Fiddle
I hope you read the comments I've put in the code and learn.
// you write comments in JavaScript with two forward slashes
// i is the integer parameter of your countdown function
// i is passed to countdown when called, i.e. countdown(9)
function countdown(i)
{
// this is an ret string variable that is private to the countdown function
// you can't access ret from outside of this function
var ret = "";
// your loop should include 0 according to your requirements
while( i >= 0)
{
// here you are appending i to your ret string which you'll return at the end of this function
ret += i;// += is a short hand form of saying ret = ret + i
// you want to append an empty space for every i except the last one (0)
if(i > 0) {
ret += " ";
}
i--; // here you are decrementing i
}
return ret;
}
// here you are making the actual call to the function with integer 5
// you are assigning the returned value of your function call to result variable
var result = countdown(5);
// here you are printing your result string variable to the log
console.log(result);
Here another solution (bit more advanced) using recursion, alternative to for/while loops where a function calls itself:
// here is an implementation using recursion
function countdown(i)
{
if(i<=0)
return i;
return i + " " + countdown(--i);
}
Here is the answer:
function countdown(i) {
answer = '';
while( i >= 0) {
answer = answer + i.toString() + ' ';
i--;
}
return answer;
}
countdown(5);
Here's a way to do it using recursion:
//define countdown function
var countdown = function countdown(i) {
//loop while the passed in parameter "i" is >= 0
while (i >= 0) {
//return a space concatenated with the value of i
//and call the countdown function again (by
//concatenating the result) to continue counting down
return ' ' + i + countdown(i -= 1);
}
return ''; //out of loop, return an empty string
};
console.log(countdown(5));
You want to include 0 in your countdown, so you want
while (i >= 0)
as opposed to while (i > 0), which excludes 0 at the end.
Also, as some of the comments mentioned, var i = "" defines i to be a string, so you cannot perform operations like i--. You should define i to be an integer, e.g. var i = 5.
recursive way ;)
โ€‹var countdown=function(i) {
ย  ย ย console.log(i);
ย  ย  i>0 &&ย countdown(i-1);
}
ย  ย  countdown(10);

Categories

Resources