I tried to find a recursive solution on my own to reverse a string s but it returns 'undefined' for strings >1 char.
Can somebody please help me to debug this?
I know it is not the elegant way but finding the error could help me advancing.
Thank U very much!
var revFunc = function (s, r, n, i) {
if (i > n) {
return r;
}
r = r + s[n - i];
i++;
revFunc(s, r, n, i);
};
var reverse = function (s) {
var r = "";
var n = s.length - 1;
var i = 0;
if (n < 1) {
return s;
}
return revFunc(s, r, n, i);
};
Not a good fit for recursion
While the minor correction already presented fixes your function, I want to suggest that this version shows a misunderstanding about recursion.
Your function is using recursion to update what would otherwise be local variables in a while loop. It could be rewritten like this:
var reverse = function (s) {
var r = "";
var n = s.length - 1;
var i = 0;
if (n < 1) {
return s;
}
while (i <= n) {
r = r + s[n - i]
i++
}
return r
};
console .log (reverse ('abcde'))
The recursion you use is just another means of writing that same code.
Recursion is meant for something a bit different. We want our algorithms to match our data structures. For recursion to really be meaningful, we should should use it on a recursive data structure.
But we can do so for this problem.
Thinking of a string recursively
There are often many different ways to think of a single data structure. We can think of a string as a recursive structure this way:
A string is either
The empty string, "", or
a character followed by a string
We can call the two parts of a non-empty string the head and the tail.
Using the recursive definition in a recursive algorithm
With that formulation, we can write a recursive algorithm that matches the structure:
The reversal of a string is either
The reversal of the empty string (which is still the empty string), or
The reversal of tail, followed by the head
Then the code practically writes itself:
const reverse = (string) =>
string .length == 0
? ""
: reverse (string .slice (1)) + string[0]
console .log (reverse ('abcdefg'))
Variants
There are certainly variations of this possible. We could want to be ready for when tail-call-optimization is finally common in JS environments, and could change this to a tail-recursive version, something like
const reverse = (string, result = "") =>
string .length == 0
? result
: reverse (string .slice (1), string [0] + result)
(Note that there is a potential problem with this style. Default parameters can get in the way of using the function in certain contexts. You cannot, for instance, successfully call strings .map (reverse) with this version. You could do this by splitting it into a helper function and a main function, but that's taking us afield.)
Or, taking advantage of the fact that strings are iterables, we could write a nicely simple version using parameter destructuring along with a default value:
const reverse = ([head = undefined, ...tail]) =>
head == undefined
? ""
: reverse (tail) + head
The advantages of recursion
And it's hard to imagine getting much simpler than that. This version captures the algorithm quite directly. And the algorithm is cleanly tied to our description of the data structure.
Note one thing that none of these functions use: local variables. Simple recursion can often be written in such a way that there is no need for them. This is a major blessing, because that means there is no place for mutable state to hide. And mutable state is the source of many, many programming errors.
You forgot to return
return revFunc(s, r, n, i);
Updated:
var revFunc = function (s, r, n, i) {
if (i > n) {
return r;
}
r = r + s[n - i];
i++;
return revFunc(s, r, n, i);
};
Suggestion: Please use better name for variables, it sucks s,r,n,i
Can you try a simple solution :
let str = "hello";
let reverse_str = str.split("").reverse().join("");
Related
Why does the comparison operator work faster regardless of the length of string?
Consider the following two functions which I use to compare strings with a length of 100 million:
With ===:
// O(?)
const compare1(a, b) {
return a === b;
}
With character by character comparison:
// O(N)
const compare2(a, b) {
if(a.length !== b.length) return false;
const n = Math.max(a.length, b.length);
for(var i=0; i<n; i++){
if(a[i] !== b[i]) return false;
}
return true;
}
When testing these two functions, I find that the speed of the compare1 function is significantly faster.
In the case of the compare2 function, I think the overhead will be severe in interpreting JavaScript code, accessing and comparing memory.
But from my understanding, the compare1 function may also have to compare N characters. Does it run so much faster because it all happens at a lower level?
There are two considerations:
=== comparison of string primitives is implemented with lower level, compiled code, which indeed executes faster than explicit JavaScript looping, which has additional work, including in updating a JavaScript variable (i), performing an access with that variable (a[i]); where all the prescribed ECMAScript procedures must be followed.
The JavaScript engine may optimise memory usage and use the knowledge that two strings are the same (for instance when that is already detected at parsing time, or one string is assigned to a second variable/property) and only store that string once (cf. String pool). In that case the comparison is a trivial O(1) comparison of two references. There is however no way in JavaScript to inspect whether two string primitives actually share the same memory.
As an illustration of the second point, note how the comparison-time is different for two cases of comparing long strings that are equal -- which probably is a hint that this string pooling is happening:
function compare(a, b) {
let sum = 0, start, p;
for (let i = 0; i < 10; i++) { // Perform 10 comparisons
start = performance.now();
p = a === b;
sum += performance.now() - start;
}
return sum / 10; // Return average time to make the comparison
}
console.log("Hold on while strings are being created...");
setTimeout(function () {
// Create long, non-trivial string
let a = Array.from({length: 10000000}, (_, i) => i).join("");
let b = a.slice(0); // Plain Copy - engine realises it is the same string & does not allocate space
let c = a[0] + a.slice(1); // More complex - engine does not realise it is the same string
console.log("Strings created. Test whether they are equal:", a === b && b === c);
console.log(compare(a, b) + "ms");
console.log(compare(a, c) + "ms");
});
I would like to know how I can sum an algebraic sum.
For example, I have a function with two parameters:
function sumAlga(paramA, paramB) {
return paramA + paramB;
}
How I should do it for algebraic sum in JavaScript?
Incorrect Code
As "don't angry me" has said in the comments, you have return paramA + paramBM not return paramA + paramB so that should fix that (assuming that was an unintentional typo, correct me if we're wrong).
More than two arguments
To accomplish this with any number of parameters you could do the following,
function algebraicSum() {
var sum = 0;
for (var i = 0; i < arguments.length; ++i) {
sum += arguments[i];
}
return sum;
}
Usage
algebraicSum(1,2,3,4) = 10;
algebraicSum(1,-2,3) = 2;
you can try something like this:
var age_child = parseInt(10);
var age_gap = parseInt(10);
alert(age_child+age_gap);
Unlike Java or C, which are strongly typed languages, Javascript is smart and hence is also called a weakly typed language. You don't have to specify the data-type of your variable while declaring it. but in this case, you should specify the data type to match with your operations.
The main purpose is to have a function which could be used as callback for Array#reduce, for example.
An array with values could be summed by taking the function and a start value of zero (this is necessary, if an empty array or an array with only one item is supplied).
function add(a, b) {
return a + b;
}
console.log([1, 2, -5].reduce(add, 0));
console.log([1].reduce(add, 0));
console.log([].reduce(add, 0));
The following code uses an arrow function, which has some differences to the standard function, but is sometimes shorter.
const add = (a, b) => a + b;
console.log([1, 2, -5].reduce(add, 0));
console.log([1].reduce(add, 0));
console.log([].reduce(add, 0));
I am trying to write a code that converts a Binary into string, i take solutions step by step, my first step is add charcodes then use fromCharcode, I don't know if this is possible but on this is my code:
function binaryAgent(str) {
var x = str.split(' ').map(function (item) { // split with space
return item.split(''); //split every character
});
var fg = [];
for(var i=0; i<x.length; i++) {
var f = x[i].reduce(function (toArray,item){
debugger;
var rightPattern = [128,64,32,16,8,4,2,1]; // i want to create this array on every iteration
var op = rightPattern.shift(); // on every iteration, shift a value from rightPattern, this is for binary pattern
if(item=='1'){ // if item is 1,i think it doesn't matter if it's string or num, I care for 0 and 1 only, push the variable op, shifted from array
return toArray.push(op); // push it on the initial value,
}
}, []); // []<-- initial array.
return x;
}
}
binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");
I checked this with debugger and I have observed that: ON every iteration, my rightPattern array is set to undefined again and reset, I also cannot use push and I have this error, TypeError: Cannot read property 'push' of undefined
on MDN, there is an example using concat() method so i tried to push Array.prototype.reduce()
I'd write your function like this:
function binaryAgent(encoded) {
return encoded.split(' ').map(function(bytestr) {
return String.fromCharCode(parseInt(bytestr, 2));
}).join('');
}
Converting binary representation into numbers is, well, an old task, and it's already solved for you. Even if you want to write your own implementation for studying purposes, it's better to abstract it (so that you can replace parseInt(bytestr, 2) line - but leave the rest of the code intact.
One possible reduce-using approach (not the most performant, mind you, but employing a pretty common technique):
function parseBinary(str) {
return str.split('').reduce(function(acc, el) {
return acc * 2 + +el;
}, 0);
}
That is, you don't have any 'pre-filled' arrays of powers of 2; instead your accumulator is multiplied by 2 at each reducer step, adding the current digit. As + operator is overloaded, you should convert the digit operand into a number (the easiest way is applying unary plus - +).
Answering the question given in the comments: you can easily convert any number to binary, octal or hex format by calling toString() on it, with a passed argument treated as a radix. But here's a function for it:
function toBinary(num, reslen) {
var res = '';
while (num || res.length < reslen) {
res = (num & 1) + res;
num >>= 1;
}
return res;
}
first of all - in your reduce function - if item wont be equal to one - in the next iteration toArray will be undefined.
you need to always return a value in the reduce function in order for the first argument (the accumulator) to be defined
should be something like that -
if (item == 1) {
toArray.push(op);
}
return toArray;
other than that as I understand your code - the rightPattern var should be outside the reduce function but inside the for loop.
Do you have any real-world example of the use of the second and third parameters for the callback to Array.prototype.some or Array.prototype.any?
According to MDN:
callback is invoked with three arguments: the value of the element, the index of the
element, and the Array object being traversed.
I've personally never used them.
I have been working for some time on the Javascript functional programming library, Ramda, and early on we made the controversial decision not to use the index and array parameters for other similar functions that we created. There are good reasons for this, which I don't need to get into here, except to say that for some functions, such as map and filter, we find such extra parameters do have some occasional utility. So we offer a second function which supplies them to your callback. (For example, map.idx(yourFunc, list).)
But I've never even considered doing so for some or every. I never imagined a practical use of these. But there is now a suggestion that we include these functions in our list of index-supporting ones.
So my question again is whether you have ever found an actual, live, real-world callback function to some or every which actually needs these parameters? If so, could you describe it?
Answers of "No, I never do," would be helpful data too, thanks.
Quick search in our code:
function isAscending(array) {
return array.every(function (e, idx, arr) {
return (idx === 0) ? true : arr[idx-1] <= e;
});
}
I could imagine something like the following code to check whether an array is duplicate-free:
….every(function(v, i, arr) {
return arr.indexOf(v, i+1) == -1;
})
Where … is a complex expression so that you'd really have to use the arr parameter - which is no more an issue if you'd properly factor out the functionality in an own function that takes the array as an argument.
The second parameter can be useful sometimes, but I support your position that it is rather seldom used.
Yes, they are helpful
These extra parameters actually do come in handy, but not that often.
In the recent past, I had written a function to find all the permutations of a list of elements:
permute :: [a] -> [[a]]
For example permute [1,2,3] would be:
[ [1,2,3]
, [1,3,2]
, [2,1,3]
, [2,3,1]
, [3,1,2]
, [3,2,1]
]
The implementation of this function is quite simple:
If the input is [] then return [[]]. This is the edge case.
If the input is say [1,2,3]:
Add 1 to every permutation of [2,3].
Add 2 to every permutation of [1,3].
Add 3 to every permutation of [1,2].
Of course, the function is recursive. In JavaScript, I implemented it as follows:
var permute = (function () {
return permute;
function permute(list) {
if (list.length === 0) return [[]]; // edge case
else return list.reduce(permutate, []); // list of permutations
// is initially empty
}
function permutate(permutations, item, index, list) {
var before = list.slice(0, index); // all the items before "item"
var after = list.slice(index + 1); // all the items after "item"
var rest = before.concat(after); // all the items beside "item"
var perms = permute(rest); // permutations of rest
// add item to the beginning of each permutation
// the second argument of "map" is the "context"
// (i.e. the "this" parameter of the callback)
var newPerms = perms.map(concat, [item]);
return permutations.concat(newPerms); // update the list of permutations
}
function concat(list) {
return this.concat(list);
}
}());
As you can see, I have used both the index and the list parameters of the permutate function. So, yes there are cases where these extra parameters are indeed helpful.
However, they are also problematic
However these superfluous arguments can sometimes be problematic and difficult to debug. The most common example of this problematic behavior is when map and parseInt are used together: javascript - Array#map and parseInt
alert(["1","2","3"].map(parseInt));
As you can see it produces the unexpected output [1,NaN,NaN]. The reason this happens it because the map function calls parseInt with 3 arguments (item, index and array):
parseInt("1", 0, ["1","2","3"]) // 1
parseInt("2", 1, ["1","2","3"]) // NaN
parseInt("3", 2, ["1","2","3"]) // NaN
However, the parseInt function takes 2 arguments (string and radix):
First case, radix is 0 which is false. Hence default radix 10 is taken, resulting in 1.
Second case, radix is 1. There is no base 1 numeral system. Hence we get NaN.
Third case, radix is 2 which is valid. However there's no 3 in base 2. Hence we get NaN.
As you see, superfluous arguments can cause a lot of problems which are difficult to debug.
But, there is an alternative
So these extra arguments are helpful but they can cause a lot of problems. Fortunately, there is an easy solution to this problem.
In Haskell if you want to map over a list of values and the indices of each value then you use do it as follows:
map f (zip list [0..])
list :: [Foo]
[0..] :: [Int]
zip list [0..] :: [(Foo, Int)]
f :: (Foo, Int) -> Bar
map f (zip list [0..]) :: [Bar]
You could do the same thing in JavaScript as follows:
function Maybe() {}
var Nothing = new Maybe;
Just.prototype = new Maybe;
function Just(a) {
this.fromJust = a;
}
function iterator(f, xs) {
var index = 0, length = xs.length;
return function () {
if (index < length) {
var x = xs[index];
var a = f(x, index++, xs);
return new Just(a);
} else return Nothing;
};
}
We use a different map function:
function map(f, a) {
var b = [];
if (typeof a === "function") { // iterator
for (var x = a(); x !== Nothing; x = a()) {
var y = f(x.fromJust);
b.push(y);
}
} else { // array
for (var i = 0, l = a.length; i < l; i++) {
var y = f(a[i]);
b.push(y);
}
}
return x;
}
Finally:
function decorateIndices(array) {
return iterator(function (item, index, array) {
return [item, index];
}, array);
}
var xs = [1,2,3];
var ys = map(function (a) {
var item = a[0];
var index = a[1];
return item + index;
}, decorateIndices(xs));
alert(ys); // 1,3,5
Similarly you can create decorateArray and decorateIndicesArray functions:
function decorateArray(array) {
return iterator(function (item, index, array) {
return [item, array];
}, array);
}
function decorateIndicesArray(array) {
return iterator(function (item, index, array) {
return [item, index, array];
}, array);
}
Currently in Ramda you have two separate functions map and map.idx. The above solution allows you to replace map.idx with idx such that:
var idx = decorateIndices;
var arr = decorateArray;
var idxArr = decorateIndicesArray;
map.idx(f, list) === map(f, idx(list))
This will allow you to get rid of a whole bunch of .idx functions, and variants.
To curry or not to curry
There is still one small problem to solve. This looks ugly:
var ys = map(function (a) {
var item = a[0];
var index = a[1];
return item + index;
}, decorateIndices(xs));
It would be nicer to be able to write it like this instead:
var ys = map(function (item, index) {
return item + index;
}, decorateIndices(xs));
However we removed superfluous arguments because they caused problems. Why should we add them back in? Two reasons:
It looks cleaner.
Sometimes you have a function written by somebody else which expects these extra arguments.
In Haskell you can use the uncurry function to solve this problem:
map (uncurry f) (zip list [0..])
list :: [Foo]
[0..] :: [Int]
zip list [0..] :: [(Foo, Int)]
f :: Foo -> Int -> Bar
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f :: (Foo, Int) -> Bar
map (uncurry f) (zip list [0..]) :: [Bar]
In JavaScript the uncurry function is simply apply. It is implemented as follows:
function uncurry(f, context) {
if (arguments.length < 2) context = null;
return function (args) {
return f.apply(context, args);
};
}
Using uncurry we can write the above example as:
var ys = map(uncurry(function (item, index) {
return item + index;
}), decorateIndices(xs));
This code is awesome because:
Each function does only one job. Functions can be combined to do more complex work.
Everything is explicit, which is a good thing according to the Zen of Python.
There's no redundancy. There's only one map function, etc.
So I really hope this answer helps.
What can be the most efficient way to find an item in an array, which is logical and understood by a web developer?
I came across this piece of code:
var inArray = function(a, b, c, d) {
for (c in b) d |= b[c] === a;
return !!d
};
It works fine. Can someone please explain me the code?
I also came across an exact same question that might make mine as a duplicate. But my real question lies in explanation of the above code and why bitwise operator has been used into it.
Also, can there be a way without any for loop, or iteration to get index of an item in an Array?
var inArray = function(a, b, c, d) {
for (c in b) d |= b[c] === a;
return !!d
};
That is some terrible code, and you should run away from it. Bitwise operators are completely unnecessary here, and c and d being parameters makes no sense at all (as Raymond Chen pointed out, the author of the code likely did it to safe space of declaring local variables -- the problem though is that if true is passed in for d the code is suddenly broken, and the extra parameters destroys any sense of understanding that glancing at the declaration would provide).
I'll explain the code, but first, here's a better option:
function inArray(arr, obj) {
for (var i = 0; i < arr.length; ++i) {
if (arr[i] === obj) {
return true;
}
}
return false;
}
Note that this is dependent on the array being an actual array. You could use a for (k in arr) type loop to generalize it to all objects.
Anyway, on to the explanation:
for (c in b) d |= b[c] === a;
This means that for every key in b (stored in c), we will check if b[c] === a. In other words, we're doing a linear scan over the array and checking each element against a.
d |= val is a bitwise or. The bits that are high in val will be set high in d. This is easier to illustrate in languages where bits are more exposed than in JS, but a simple illustration of it:
10011011
01000001
--------
11011011
It's just OR'ing each individual bit with the same location bit in the other value.
The reason it's an abuse here is that it convolutes the code and it depends on weird implicit casts.
x === y returns a boolean. A boolean being used in a bitwise expression makes little sense. What's happening though is that the boolean is being converted to a non-zero value (probably 1).
Similarly, undefined is what d will be. This means that d will be cast to 0 for the bitwise stuff.
0 | 0 = 0, but 0 | 1 = 1. So basically it's a glorified:
for (c in b) d = (d || (b[c] === a));
As for !!x that is just used to cast something to a bool. !x will take x, implicitly cast it to a bool and then negate it. The extra ! will then negate that again. Thus, it's likely implicitly casting to a bool (!!x being true implies that x is at least loosely true (1, "string", etc), and !!x implies that x is at least loosely false (0, "", etc).
This answer offers a few more options. Note though that all of them are meant to fallback to the native indexOf that will almost certainly be faster than anything we can code in script-land.
This code is pretty poorly written, and barely readable. I wouldn't qualify it as "awesome"...
Here's a rewritten version, hopefully more readable:
function inArray (aElt, aArray) {
var key;
var ret = false;
for (key in aArray)
ret = ret || (aArray[key] === aElt);
return ret;
}
The for loop seems like the most natural way to do that. You could do it recursively but that doesn't feel like the easiest approach here.
What can be the most efficient way to find an item in an array, which is logical and understood by a web developer?
Either the native method, haystack.indexOf(needle) !== -1 or a looped method which returns as soon as it can
function inArray(needle, haystack) {
var i = haystack.length;
while (i) if (haystack[--i] === needle) return true;
return false;
};
You asked for a recursive version
var inArray = function(arr, needle, index) {
index = index || 0;
if (index >= arr.length)
return false;
return arr[index] === needle
? true
: inArray(arr, needle, index + 1);
}
console.log(inArray([1,5,9], 9));