recursion on returning vectors c++ - javascript

Hey guys I am trying trying to right this javascript code into c++. I am doing quick sort and everything is straight forward minus the last step.
function quickSort(arr)
{
//base case if the arr is 1 or 0 then return the array
if(arr.length === 1 || arr.length === 0)
{
return arr;
}
var pivotIndex = Math.floor(arr.length/2);
var pivotValue = arr[pivotIndex];
var before = [];
var after = [];
for(var counter = 0; counter < arr.length; counter++)
{
if(counter === pivotIndex)
continue;
if(pivotValue <= arr[counter])
{
before.push(arr[counter])
}
else
{
after.push(arr[counter])
}
}
//this step I am having trouble rewriting in c++
return quickSort(after).concat(pivotValue).concat(quickSort(before));
}
I am having a hard time rewriting the recursive step in c++. I am not sure how concat 2 vector. I tried using the insert method but I keep getting an error about invalid use of void expression.
vector<int> quickSort(vector<int> arr)
{
if(arr.size() == 1 || arr.size() == 0)
{
return arr;
}
int pivotIndex = arr.size()/2;
int pivotValue = arr[pivotIndex];
vector<int> before;
vector<int> after;
//put values in before or after the piv
for(size_t counter = 0; counter < arr.size(); counter++)
{
if(counter == pivotIndex)
continue;
if(pivotValue <= arr[counter])
before.push_back( arr[counter]);
else
after.push_back( arr[counter]);
}
return //????? not sure how to do this
}

So, you realized that your core question was "how to concatenate two vectors", and you found a right answer: using insert. Now your question is about why you were getting "an error about invalid use of void expression." (That's the assumption my answer is for, at least.)
That's because you were likely trying to do something like the following:
return quickSort(after).insert( /* stuff */ );
which is wrong. In JavaScript, array.concat returns the concatenated array. It's return type is effectively Array, and so doing return arr.concat(arr2) returns an Array because arr.concat would return an Array. Further, in JavaScript, array.concat doesn't modify the array it was called on, but rather returns a new array.
In C++, however, vector.insert (#4 in the reference) returns void. That means it returns nothing. So when you try to return the result of insert, you get that error about invalid use of a void expression. Further, in C++, vector.insert does modify the vector it was called on.
So how do you use insert in this case?
vector<int> quickSort(vector<int> arr)
{
// ...
// Sort `before` and `after`
before = quickSort(before);
after = quickSort(after);
// Modify `after` and return it.
after.push_back(pivotValue);
after.insert(after.end(), before.begin(), before.end());
return after;
}
Note: My code isn't optimal and the idea of rewriting JS in C++ is also oddly specific. My answer is to simply outline the problem asked in the question, not to give a good C++ implementation of quick sort.

To concat two vector , you can use std::merge
like:std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));

Related

Leetcode Two sum problem question about why my code doesn't work

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
var twoSum = function(nums, target) {
let comp = {};
for(let i =0; i<nums.length; i++){
let match = target - nums[i]
my question is why doesn't my code work if remove comp[match]>=0 and use comp[match] instead?
if(comp[match]>=0){
return [comp[match], i]
console.log(comp)
}
else{
comp[nums[i]]= i
}
console.log(comp)
}
};
Snippet:
var twoSum = function(nums, target) {
let comp = {};
for (let i = 0; i < nums.length; i++) {
let match = target - nums[i]
if (comp[match]) {
return [comp[match], i]
console.log(comp)
} else {
comp[nums[i]] = i
}
console.log(comp)
}
};
twoSum([2, 7, 11, 15], 9)
The idea behind comp is to store the indexes of the values previously seen while you're looping through your array of numbers. This means that it is possible for a key in your object to point to the index 0.
In JavaScript, 0 is considered falsy, so when put into a if statement, it will skip the if block as it is considered false, and instead, execute the else block.
if(0) {
console.log("truthy"); // doesn't execute
} else {
console.log("falsy");
}
So, if you were to use if(comp[match]) and comp[match] was to give you the index value of 0, your else block would trigger, when instead, you actually need your if block to trigger (as you have previously seen a number which you can now add with the current number). That's why the following works as expected:
if(comp[match] >= 0)
In this scenario, if comp[match] returns back the index value of 0, the code in your if-block will be triggered as needed. It is possible for comp[match] to return undefined though. In this case, your else block will trigger so your code will work fine (as undefined >= 0 is false). However, if you want to make your condition more readable you can instead use:
if(conp[match] !== undefined)

Why is the first argument of reduce() returning undefined?

I'm trying to write a function that takes in an array as an input. If the integer is positive, it counts it. If the integer is negative, it sums it.
I figured that that the reduce() helper in js would be the best way to go about this, but I keep returning undefined for my first argument when it runs.
Here's my code:
function countPositivesSumNegatives(input) {
let countPositive = 0;
let sumNegative = 0
if (input === null || input === []){
return [];
} else {
return input.reduce(function(prev,num){
if (num > 0) {
countPositive++;
}else{
sumNegative = prev + num};
}, 0);
}
return [countPositive, sumNegative];
}
It throws me a TypeError that says:
TypeError: Cannot read property '0' of undefined
When I log 'prev' to the console inside of the reduce function, it logs undefined for all inputs except the first one. The first one, as expected, is 0. But for each following input it logs undefined. Why is this happening?
Thanks in advance.
The callback you pass to .reduce() needs to return the cumulative value (the value that will be passed as prev to the next iteration of the loop. Since you are returning nothing, you get undefined for the next iteration of your loop.
This complicates what you're trying to do because you are trying to keep track of two values in your loop. As such, you would either have to avoid using prev at all or you'd have to make it be a data structure that had both your values in it. Your use is not a textbook example for .reduce(). Your code is probably simpler with an iteration using .forEach() or for/of.
function countPositivesSumNegatives(input) {
let countPositive = 0;
let sumNegative = 0
if (!input || input.length === 0){
return [];
} else {
input.forEach(function(num){
if (num > 0) {
++countPositive;
} else {
sumNegative += num;
});
}
return [countPositive, sumNegative];
}
Well sorry but this is not a good implementation of this function. But we can correct your function as follows;
function countPositivesSumNegatives(input) {
let countPositive = 0;
let sumNegative = 0;
if (input === null || input === []){
return [];
} else {
sumNegative = input.reduce(function(prev,num){
if (num > 0) {
countPositive++;
} else {
prev += num;
}
return prev; // <---- THE MISSING PART
}, 0);
}
return [countPositive, sumNegative];
}
var data = [1,2,3,4,5,-4,7,-3];
console.log(countPositivesSumNegatives(data));
However while the code works just fine it still involves many issues. When getting into functors like .reduce() you should be able to keep everthing contained within itself and should not refer to variables at the outer scope. Accordingly one can simply rephrase this code as follows;
var data = [1,2,3,4,5,-4,7,-3],
cpsn = a => a.reduce((p,c) => c > 0 ? (p[0]++,p) : (p[1]+=c,p) ,[0,0]);
console.log(cpsn(data))

FreeCodeCamp: checking for palindromes

This is my first question, so I apologize if this isn't formatted correctly or placed in the proper area.
I just completed the FreeCodeCamp checking for palindromes challenge. I can't help but think my solution was very inelegant.
function palindrome(str) {
var cleanString = str.replace(/[^A-Za-z0-9]/g, '');
var lowerCleanString = cleanString.toLowerCase();
var lowerArr = lowerCleanString.split('');
var reverseArr = lowerArr.reverse();
var joinedArr = reverseArr.join('');
if (joinedArr === lowerCleanString) {
return true;
}
// Good luck!
else {
return false;
}
}
I know it worked, but is it possible to do some of these steps together or in a cleaner way?
Simple function to check for palindromes
function checkPalindrome(palindrome) {
return palindrome == palindrome.split('').reverse().join('');
}
function palindrome(str) {
var newstr = str.replace(/[\W_]/g,'').toLowerCase();
if(newstr === newstr.split('').reverse().join('')){
return true;
}
return false;
}
palindrome("five|\_/|four");
You can use many methods in one row like I've used them .It's more simple :)
Good luck
Wow, I really like the answers comparing the string to a string.split('').reverse().join('') version of itself. I didn't think about that. Forgot about the .reverse() function. I ended up processing the string and splitting it out into an array and then using a double counter for the loop to compare the first and last items in the array. Was kinda fun to learn how to do that, but I like the .reverse() function use better.
In case someone is curious about the for loop I used ...
for(let i = 0, j = arr.length-1; i < j; i++, j--) {
if (arr[i] !== arr[j]) {
return false;
}
}

what is the order of boolean logic in Javascript?

I wanted to use two Not and one and in booleans to test if the variable is neither upper case nor lower case.
I used this code so far but it didn't work as required:
else if ((x[i]) !== (x[i].toUpperCase()) && (x[i]!== x[i].toLowerCase()) ){
x.splice(x[i], 1);
}
This code was for a function that sorts entered strings yet uppercase are sorted first.
Here is the full code, I am also open to understanding better ways to create this function apart from boolean logic and the array methods I used.
function alpha(str){ // United States
var x = str.split(""); // [U,n,i,t,e,d,S,t,a,t,e,s]
var cap = [];
var small = [];
for (var i = 0; i<x.length; i++){
if (x[i] == x[i].toUpperCase()){
cap.push(x[i]);
}
else if ((x[i]) !== (x[i].toUpperCase()) && (x[i]!== x[i].toUpperCase()) ) {
x.splice(x[i], 1);
}
else {small.push(x[i]);}
}
var z = cap.sort();
var y = small.sort();
return z.concat(y).join("");
}
Please note the second else if statement is only useful because the code adds an empty space string at the beginning of the output, I'm not sure where it comes from, so please let me know if you have any idea how to sort this even without using the second else if.
In the ASCII table, upper case letters come first. That's why they come first when you sort alphabetically. Here's a link to a page on Wikipedia that shows the table with the upper case letters appearing first and their numerical equivalents. It's even printable.
Also, I took the liberty of simplifying your code a little. Seems like .splice() was not necessary.
function alpha( str ) {
var x = str.split(""); // [U,n,i,t,e,d,S,t,a,t,e,s]
var cap = [];
var small = [];
var length = x.length;
for (var i = 0; i < length; i++) {
if (x[i] === x[i].toUpperCase()) {
cap.push(x[i]);
} else if (x[i] === x[i].toLowerCase()) {
small.push(x[i]);
}
}
return cap.sort().concat(small.sort()).join("");
}
Maybe explain what you're trying to do? It most likely has been done before in some form and you definitely came to the right place to find an answer.
Is this what you want to do?
var str = "United States";
function alpha(str) {
return str.split('').sort().join('');
}
alert(alpha(str));
In all programming languages (as far as i know), boolean expressions are always evaluated from the left to the right with brackets of course.
So in the following example my_func() is called first, and then if there is the chance that the complete expression becomes true my_other_func() is called
if (my_func() && my_other_func()) {
// I only get here if my_func() AND my_other_func() return true
// If my_func() returns false, my_other_func() is never called
}
The same is true for the "or" operator in the following example
if (my_func() || my_other_func()) {
// I only get here if my_func() OR my_other_func() return true
// If my_func() returns true, my_other_func() is not called
}
So back to your code, in details this part (I reformated it a bit for better readability):
if (x[i] == x[i].toUpperCase()){
// only uppercase here
cap.push(x[i]);
} else if (x[i] !== x[i].toUpperCase() && x[i] !== x[i].toUpperCase()) {
// tested twice the same thing, so Im really sure that its not uppercase :D
// only lowercase here
x.splice(x[i], 1);
} else {
// I will never reach this
small.push(x[i]);
}
Im not sure what you want to do, but I hope the comments help to understand your code.

How can I remove an object from an array if I know the value of one field of the object?

I tried to find out some good examples but SO seems to have mainly examples from 4-5 years ago and I would like to use a solution that would work using modern browser capabilities.
Ihave an array of test objects:
var tests;
Each test object contains a testId.
How can I remove test object with testId = 25 from the array tests. I was thinking of a for loop but is there a cleaner way to do this?
The best answer depends on whether you know in advance whether there's at most one match, or potentially more than one (and in the latter case whether you want to remove all of them or just the first)
Removing all matches
The "simplest" way is to use filter, although strictly that produces a new array without the matching element:
tests = tests.filter(function(e) {
return e.testId !== 25;
});
This is OK, unless other code is holding a reference to the original array.
Modifying the array safely "in-place" still appears to require a combination of a for loop with .splice:
for (var i = 0; i < tests.length; ) { // nb: deliberate .length test
if (tests[i].testId === 25) {
tests.splice(i, 1);
} else {
++i;
}
}
The "safely" caveat is because the functional methods of iterating through an entire array will get confused if the current element in the array is removed. That is not a concern in the "first match" methods shown below.
Removing first (or only) match
The plain for method is still pretty simple (and probably most efficient, too!)
for (var i = 0, n = tests.length; i < n; ++i) {
if (tests[i].testId === 25) {
tests.splice(i, 1);
break;
}
}
The .some method per Johan's answer can iterate through an array and then exit on first match (although some may object on philosophical grounds to a boolean predicate function also mutating the array):
var didRemove = tests.some(function(e, i, a) {
if (e.testId === 25) {
a.splice(i, 1);
return true; // causes the loop to exit
}
});
In ES6-draft there's .findIndex, which is a generalisation of .indexOf:
var index = tests.findIndex(function(e) {
return e.testId === 25;
});
if (index >= 0) {
tests.splice(index, 1);
}
One way is to loop through all objects and splice a matching object out of the array.
Instead of forEach I use some (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some). Because with the some method you can "break" the loop by returning true so that you don't need to go through all objects if a match has been found.
tests.some(function(testObject, index) {
if (testObject.testId === 25) {
tests.splice(index, 1);
return true;
}
});
Or wrap it in a function
var removeObjectById = function(id) {
tests.some(function(testObject, index) {
if (testObject.testId === id) {
tests.splice(index, 1);
return true;
}
});
}
removeObjectById(25)

Categories