Finding the mirror index in a palindrome + javascript - javascript

My code:
function palindrome(str) {
return str.split('').every((char, i) => {
return char === str[str.length - i - 1] ? true : false;
})
}
palindrome('abcba');
In using the debugger and console.log I get why in the comparison statement we write - i, because that gets us to the correct index on the opposite side but how would one know to do this from the very beginning?
Is there an explanation or a diagram of some sort that explains how or why - i will get you to the index of the character on the opposite side? Just finding it difficult to properly wrap my had around this one.
Any help much appreciated although I imagine this is a difficult one to explain.

Okay let's break it down.
str.split('')
This line breaks your 'abcba' string into an array. The result will be:
['a', 'b', 'c', 'b', 'a']
Now that you have an array that you can loop over and select certain indexes from the array. This is very useful in the case of a palindrome.
Because you want to know if the word is the same when it is mirrored. And you figure that out by starting at the head and tail of the array.
The first item in the array being the index of 0 [0] and the last one, well that depends on the array. But if you have the array and and subtract [array.length - 1], which in the word abcba is [5 - 1] and you end up with the last item in the array, which has the index of 4 [4].
// First iteration.
// First and last items in array.
// [0] and [array.length - 1] or [4].
↓ ↓
['a', 'b', 'c', 'b', 'a']
So in the loop you go from left to right in your array. And compare the first value with the last value. Your example uses the every method which at the end returns true if every condition in your loop has returned true, or false whenever that is not the case.
The loop also exposes a current index value. In your example called i, short for index. If you finished comparing the first and last value you want to shift over to the next item in the array to start comparing the second and first to last value. That's where the formula comes from.
str.split('').every((char, i) => {
return char === str[str.length - i - 1] ? true : false;
});
In the first iteration the value of i is 0. So you have the formula: length of the array, subtract 0 and subtract 1. Which gives you the last item.
In the second iteration i is now 1. Meaning we are in the second item of the array. If you apply i to the formula again, you can start to count back from the end of the array: length of the array, subtract 1 and subtract 1. Which adds up to 3.
// Second iteration.
// Second and first to last item in array.
// [1] and [array.length - 2] or [3].
↓ ↓
['a', 'b', 'c', 'b', 'a']
And with the next iteration you get an overlap, but not in cases with an even numbered word. But here they are both checking if c matches c.
// Third iteration.
// Third and and second to last item in array.
// [2] and [array.length - 3] or [2].
↓
↓
['a', 'b', 'c', 'b', 'a']
And this continues on until the last item in the array is reached with the loop continuing counting up, and the formula counting down.
I hope this makes sense and helps you understand it a bit more.

Related

Behind the scenes of Javascript sort comparison

const arr = [3, 89, 1, 120, 23];
console.log(arr.sort((a, b) => a - b));
The code above sorts the array.
However, how does sort know that a = current index and that b = next index???
We never specify to sort what they are and to what they're equal to.
And after that, how does .sort figure out that the returned value from that anonymous arrow function means that the value need to be moved?
Example: [1, 2]
sort((a, b) => a - b))
sort((1, 2) => 1 - 2))
sort((1, 2) => -1))
sort(-1));
See? How does .sort know what to do with -1?
I've been Googling and YouTubing for the past 2 hours and can't find the answer... :(
However, how does sort know that a = current index and that b = next index?
No, a is current value, b is next value.
The sort function you see is not just run once, it runs again and again, depending on which length your array has.
In your case, in the first run, a equals 3 and b equals 89. And the second run, a equals 3, b equals 1.
The sort function is work for an array of strings, so if you need to sort an array of strings, just use array.sort()
Compare function is required when you need to sort a numeric array.
If not, it gets the wrong result: "25" is bigger than "100", because "2" is bigger than "1".
Compare function just return three kinds of number:
Negative number (-1,-2,...): it means a less than b
Zero (0): it means a equals b
Positive number (1,2,3..): it means a greater than b
So, you can more clearly return inside the Compare function like this:
if(a === b)
return 0;
if(a < b)
return -1;
return 1;
But, simpler, you can a using a trick, you just need to return a-b to determine whether a is greater than b or not.
See more: JavaScript Sorting Arrays

array.reverse() block-wise in flat array

I'm writing a pixel animation reading data from a Unit8Array holding
5 frames, 72 binaries each. Now I thought to reverse the frames to reverse animation. So my question:
Is there a way to reverse block-wise, or has anybody a creative idea, how I could do so?
(I can't just run backwards, as each frame needs the info of previous)
const myArr = [1,2,3,4,5,6,7,8];
console.log(myArr.reverse());//8,7,6,5,4,3,2,1
//how to reach [7,8,5,6,3,4,1,2]?
//would work fine with 2D array,
//but don't have 2D
const my2D = [[1,2],[3,4],[5,6],[7,8]];
This should do it:
const reversed = myArr
.map((_, i, a) => a[i ^ 1])
.reverse()
The way it works is that it maps each array element to another element with the index changed by inverting the 1 bit using XOR (for example 4^1=5, 5^1=4, 6^1=7, 7^1=6, etc.) and then reversing the whole array.
This trick can be used for any power of two: You can reverse groups of 4 elements using ^ 3 to flip the 1 and 2 bits, groups of 8 using ^ 7 to flip the 4, 2 and 1 bits and so on. (If you'd need other group sizes, you would have to use a more expensive operation like i + size - 1 - 2 * (i % size) instead.)
map calls the callback with several arguments - the first one is the value of the element but we don't need it really, so we'll assign it to an unused variable _. The second one is the index, and the third one is the array itself. Actually we only need the index, but with the third argument we can avoid writing the name of the array twice in the line (myArr.map((_, i) => myArr[i ^ 1]) would work too).
Note: depending on your exact use case maybe another option would be to do an array.length - i ^ 1 operation on the index when accessing the data, instead of creating a new array.
Inspired by CherryDT's answer, it can be done with one map call:
const arr = [1,2,3,4,5,6,7,8];
console.log(
arr.map((_, i) => arr[arr.length - i - 1 ^ 1])
);

Find the highest subset of an integer array whose sums add up to a given target

I am trying to find a subset of values within an array which add up to a given number and return an array of that subset. I need the return array to contain the highest possible largest value.
The integer array will always be in ascending order but there will not always be a valid answer. If there is no valid answer I need to return a string along the lines of 'No valid answer'.
For example:
If the int array is: [1, 2, 3, 5, 7, 9, 11] and the target is 19 - I want the return array to be [1, 7, 11].
I would not like to return [9, 7, 3] because 11 is larger than 9, and I would not like to return [3, 5, 11] because 7 is larger than 5.
I am assuming that I will need a for loop within a recursive function to get my answer but have been unable to figure out how to do it.
I have found variations of the question in Java:
https://codereview.stackexchange.com/questions/36214/find-all-subsets-of-an-int-array-whose-sums-equal-a-given-target
I have also found a solution in JavaScript which returns pairs of values (although this is pretty straight forward):
https://codereview.stackexchange.com/questions/74152/given-an-array-of-integers-return-all-pairs-that-add-up-to-100
I was thinking that you would need to start your loop with the last element of the array and loop backwards through the array to check if there is a combination of 2 numbers whose sum is the target.
If there is not a pair, you would need to start with the highest pair of numbers whose sum is less that the target and loop though the array to find if there is a combination.
This operation would need to be continued until the subset is found or you discover that there is no valid answer.
Please help!
The basic pattern for recursion is:
Return known value for simple case(s). For this problem, the simple cases are (a) a target of 0 (solution is the empty array) and (b) a negative target (failure).
Recurse and return some calculation based on the answer. For this problem, we look at each candidate value, and recurse with a target reduced by that value, returning an array composed of the result of the recursion with the addition of the current element.
So:
// Find subset of a that sums to n.
function subset_sum(n, a) {
// SIMPLE CASES
if (n < 0) return null; // Nothing adds up to a negative number
if (n === 0) return []; // Empty list is the solution for a target of 0
// RECURSIVE CASE
a = a.slice();
while (a.length) { // Try remaining values
var v = a.shift(); // Take next value
var s = subset_sum(n - v, a); // Find solution recursively
if (s) return s.concat(v); // If solution, return
}
}
To enforce the rule that you want to prefer higher values first, pass this function an array of values that is pre-sorted in descending order.
> subset_sum(19, [11, 9, 7, 5, 3, 2, 1])
< [1, 7, 11]

Puzzling javascript behavior

I typed the following into the chrome console:
> Array.prototype.slice.call([1,2], 0)
[1, 2]
> Array.prototype.slice.call([1,2], 1)
[2]
Why does the first call not return 1?
Array.prototype.slice.call([1,2], 0) returns all elements of the array starting from index 0, and puts the whole into the array.
Array.prototype.slice.call([1,2], 1) returns all elements of the array starting from index 1, and puts the whole into the array, however this time it finds only 1 element, the 2.
Slice with one argument returns the array from the index position you give in the argument. In your case 0 marks the index position 0, so it returns the whole array.
Array.prototype.slice.call([1,2,3,4,5], 0)
//=> [1,2,3,4,5] because index to start is 0
Array.prototype.slice.call([1,2,3,4,5], 2)
//=> [3,4,5] because index to start is 2
The second argument would be how many element it slices out starting from index, so:
Array.prototype.slice.call([1,2,3,4,5], 0, 1)
//=> [1] because index to start is 0 and number of elements to slice is 1
Array.prototype.slice.call([1,2,3,4,5], 2, 2)
//=> [3,4] because index to start is 2 and number of elements to slice is 2
Find more in the documentation here
As indicated here, the slice method accepts a start and optionally an end offset, not the index of the element to slice out. If no offset is provided, it will slice to the end of the array.
In your first example, slice starts from element 0, while in the second example it starts from element 1. In both occassions it will any elements it can find at that index and after, since you have not specified an offset.
First parameter to slice is the start index in the array (counting from zero).
The second parameter (which is not given in either of your examples), is the end. Precisely it is: one past the inclusive end index. Anyway, it defaults to the end of the array, which is the behaviour you see.
Array.prototype.slice.call([1,2], 0, 1)
should give you [1]
slice.call(arguments, Fromindex);
The Fromindex means to slice the arguments list from index to the end.
as your case
slice the arguments from index 1
thats why you get [2]

How does the sort() work in javascript?

var numArray = [4,2,5,3];
numArray.sort(function(a,b){
console.log("a:" + a + ", b:" + b);
return a-b;
});
The three possible return numbers are: <0 (less than 0), 0, or >0 (greater than 0):
Less than 0: Sort "a" to be a lower index than "b"
Zero: "a" and "b" should be considered equal, and no sorting performed.
Greater than 0: Sort "b" to be a lower index than "a".
I am getting like this on console
a:4, b:2
a:4, b:5
a:5, b:3
a:2, b:3
a:4, b:3
[2, 3, 4, 5]
May I know how the values of a and b are getting changed as seen above?
In the first step
a=4 and b=2. In this case it will swap.
then the array becomes [2,4,5,3];
In the second step
a=4 and b=5. In this case the items remains same.
then the array becomes [2,4,5,3];
In the third step
a=5 and b=3. In this case it will swap.
then the array becomes [2,4,3,5];
Until this step it is okay. But after that how the value of a and b becomes 2 and 3 > respectively instead of 2 and 4.
Anyone can help me?
Thanks in advance
There is no guarantee that the sort method uses a simple compare and swap algorithm.
More likely your browser uses something like merge sort, but the specific algorithm will depend on the browser and version.
Since Firefox is open source you can see how sort is implemented by checking the source code. It uses a merge sort.

Categories