Quicksort in an array C++ - c++

I am trying to partition an array using a quicksort algorithm shown in the code. I believe the problem is in the while loop. Can you see/explain what I'm doing wrong and what I should do to fix it? Thanks!
Edited because I posted an earlier version of the code.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int intArray[10];
int sizeArray= 10;
int main(){
srand(time(0));
for(int i = 0; i < sizeArray; i++){
//random numbers from 1 to 10:
intArray[i] = rand() % 100 + 1;
}
for(int i = 0; i < sizeArray; i++){
cout << intArray[i] << " ";
}
int *pivot = &intArray[0];
int *first = &intArray[1];
int *last = &intArray[9];
cout<<"pivot "<<*pivot <<endl;
while(first<last)
{
while(*first<*pivot)
{
first++;
}
while(*last>*pivot)
{
last--;
}
if(*first>*last)
{
int aSwap = 0;
aSwap = *first;
*first = *last;
*last = aSwap;
}
if((first-1) > last)
break;
}
int bSwap=0;
bSwap = *first;
*first= *pivot;
*pivot = bSwap;
cout<<"After partition"<<endl;
for(int i = 0; i < sizeArray; i++){
cout << intArray[i] << " ";
}
}

I'll give you one immediate peice of advice re:
while(*first<*pivot)
If your pivot at array[0] is the largest value in the array, you're going to run off the end of the array and keep going, resulting in undefined behaviour.
The termination condition for that loop should include detecting if the first pointer has reached the last one.
Ditto for the loop that decrements last.
And, of course, once the pointers meet, there's no need to do a swap.
And your edit comparing the first against last values is actually worse. You're supposed to be looking for two values that you will swap across from where the pivot wiill eventually go.
I suggest reverting the code and simply adding the limiting check I suggested. Here is the correct code for doing the partition swapping operation, from some code I wrote not that long ago:
// Simplest form of pivot selection.
pvt = 0;
lft = 1;
rgt = 9;
// Continue until new pivot point found.
while (lft < rgt) {
// find value on left greater than pivot value.
while ((lft < rgt) && (array[lft] <= array[0]))
lft++;
// Then, assuming found, find value on right less than pivot value.
if (lft < rgt) {
while ((lft < rgt) && (array[rgt] >= array[0]))
rgt--;
// Swap them if found.
if (lft < rgt)
SWAP (array[lft], array[rgt]);
}
}
// Back up to find proper swap point for pivot value, then swap.
while ((lft > 0) && (array[lft] >= array[0]))
lft--;
if (lft != 0)
SWAP (array[lft], array[0]);
// Now everything left of pivot is less than pivot value, everything
// right is greater/equal. Go and sort the two sections.

You are making your life too complicated.
GCC 4.7.3: g++ -Wall -Wextra main.cpp
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int intArray[10];
int sizeArray= 10;
int main() {
srand(time(0));
for (int i = 0; i < sizeArray; ++i) {
//random numbers from 1 to 10:
intArray[i] = rand() % 100 + 1; }
for(int i = 0; i < sizeArray; ++i){
cout << intArray[i] << " "; }
int* pivot = &intArray[0];
cout << "pivot " << *pivot << endl;
for (int i = 0; i < sizeArray; ++i) {
if (intArray[i] < *pivot) {
std::swap(intArray[i], *(pivot + 1)); // move the pivot ahead one
std::swap(*pivot, *(pivot + 1)); // move the value into the hole
++pivot; }}
cout<<"After partition"<<endl;
for (int i = 0; i < sizeArray; i++){
cout << intArray[i] << " "; }
return 0; }

Related

Classis task for splitting weights into 2 trucks (C++) (Dynamic Programming)

I have a task that by given line of weights of cages and I have to split them into 2 trucks. The split should be done like this that |a - b| to have least value where 'a' is the common weight of the cages in the first truck and 'b' is the common weight of the cages of second truck. My program seems to work but when I upload it to hackerrank abort function is called. So where is my fault? Here is the code:
#include <iostream>
#include <vector>
#include <sstream>
#include <cstring>
using namespace std;
int main()
{
string input;
int k;
while (getline(cin, input))
{
/* splitting the input into integers */
vector<int> v;
istringstream iss(input);
while (iss >> k) v.push_back(k);
/* --- II --- */
unsigned long sum = 0;
unsigned i, j;
for (i = 0; i < v.size(); i++)
sum += v[i];
vector<char> can;
can.push_back(1);
for (i = 1; i <= sum; i++)
can[i] = 0;
for (i = 0; i < v.size(); i++)
{
for (j = sum; j+1 > 0; j--)
{
if (can[j])
{
can[j + v[i]] = 1;
}
}
}
for (i = sum / 2; i > 1; i--)
{
if (can[i])
{
if (i <= sum - i)
{
cout << i << " " << sum - i << endl;
break;
}
else
{
cout << "a should be <= b";
break;
}
}
}
}
return 0;
}
How can this work?
You create an empty vector of char, push one single value into it and that try to assign value passed the first:
...
vector<char> can;
can.push_back(1); // can contains one single value
for (i = 1; i <= sum; i++)
can[i] = 0; // Error "vector subscript out of range" in debug mode
If you do not ask the control of vector subscript you will just invoke undefined behaviour.
But if you just want to expand the vector, you can repeatedly can push_back:
for (i = 1; i <= sum; i++)
can.push_back(0);

why is vector subscript out of range

I have a vector full of monster objects which are initialized onto a 10X10 map which works. I am now playing with some code to prevent monsters being spawned on the same map co-ordinate. when i run the code it cuts and brings up "vector subscript out of range" and i have no idea why. Any help would be great.
main function
#include "stdafx.h"
#include "character.h"
#include "monster.h"
#include "player.h"
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
vector<monster*> monVec;
vector<int> monx;
vector<int> mony;
player player1;
bool collision();
void initialise();
int main(){
initialise();
player1.moveChar(3, 6);
bool temp;
temp = collision();
system("pause");
return 0;
}
initialize function
void initialize()
{
srand(time(NULL));
for (int n = 0; n < 10; n++)
{
int inx = rand() % 9;
int iny = rand() % 9;
if (n == 0){
monx.push_back(inx);
mony.push_back(iny);
}
for (int i = 0; i < n; i++)
{
-------->if (inx != monx[i] && iny != mony[i]){
monx.push_back(inx);
mony.push_back(iny);
}
else n--;
}
monVec.push_back(new monster());
monVec[n]->moveChar(inx, iny);
cout << endl << inx << ", " << iny << endl;
}
}
cout is just to check if its working once it runs and arrow indicates problem line.
thanks
In your initialize
you do the following
<for 10 times>
<when first time, add one item to the x,y vectors>
<access the up to 10nth element of the x,y vectors> //But vectors are only guaranteed to have at least one element each
<maybe add one item to the x,y vectors>
Problem is already that there is a path where there are not enough elements in your vectors. Plus the mistake about assignment and comparison in your if like #Michael Waltz already mentioned.
void initialize()
{
srand(time(NULL));
for (int n = 0; n < 10; n++)
{
int inx = rand() % 9;
int iny = rand() % 9;
if (n = 0){ //<<--------------------------- replace (n = 0) by (n == 0)
monx.push_back(inx);
mony.push_back(iny);
}
for (int i = 0; i < 10; i++)
{
// <<<< here monx and mony may contain only
// one element so monx[1] and mony[1] are invalid
if (inx != monx[i] && iny != mony[i]){
monx.push_back(inx);
mony.push_back(iny);
}
else n--;
}
monVec.push_back(new monster());
monVec[n]->moveChar(inx, iny);
cout << endl << inx << ", " << iny << endl;
}
}

Max Sum Of Integers

EDIT: solved! I was treating negative numbers test case as 0, instead of having the output be negative as well. thanks for the help!
Here is the challenge description: https://www.codeeval.com/open_challenges/17/
I keep getting a partially solved score. I want to know why. As in my eyes, this code works. And I believe that it is O(N) time. Thanks for looking!
Here is my code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
int max(int a, int b)
{
if (a > b)
return a;
else return b;
}
int maxSubArray(vector<int> values)
{
int max_so_far = values[0];
int curr_max = values[0];
for(int i = 1; i < values.size(); ++i)
{
curr_max = max(values[i], curr_max + values[i]);
max_so_far = max(max_so_far, curr_max);
}
return max_so_far;
}
int main(int argc, char *argv[])
{
std::vector<vector<int> > Values; //to hold the values of the stock price change
ifstream file(argv[1]);
std::string line; //for the txt file input
int value = 0; //for holding the value of stock change
while (std::getline(file, line))
{
int pos = 0;
if(line.length() == 0)
continue;
else
{
std::istringstream iss(line);
std::vector<int> list; // temporary list of values to be pushed back into the 2-d vector
while (iss >> value)
{
list.push_back(value);
}
Values.push_back(list);
}
}
for(int i = 0; i < Values.size(); ++i)
{
cout << maxSubArray(Values[i]);
cout << endl;
}
/*
cout << " Printing the values : " << endl;
for (int j = 0; j < Values.size(); ++j)
{
for (int k = 0; k < Values[j].size(); ++k)
cout << Values[j][k] << " ";
cout << endl;
}
*/
return 0;
}
so I swapped out some code now. I get better score but I it's still a partial.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
using namespace std;
int max(int a, int b)
{
if (a > b)
return a;
else return b;
}
int maxSubArray(vector<int> values)
{
int max_so_far = values[0];
int curr_max = values[0];
if (curr_max < 0)
{
curr_max = 0;
max_so_far = 0;
}
for(int i = 1; i < values.size(); ++i)
{
curr_max = max(values[i], curr_max + values[i]);
curr_max = max(curr_max, 0);
max_so_far = max(max_so_far, curr_max);
}
return max_so_far;
}
int main(int argc, char *argv[])
{
std::vector<vector<int> > Values; //to hold the values of the stock price change
ifstream file(argv[1]);
std::string line; //for the txt file input
std::string token; //for the subtring that will be converted from char to int
int value = 0; //for holding the value of stock change
int count = 0;// for holding how many total cases
while (!file.eof())
{
int pos = 0;
getline(file, line);
if(line.length() == 0)
continue;
else
{
std::vector<int> list; // temporary list of values to be pushed back into the 2-d vector
while ((pos = line.find(",")) != std::string::npos )
{
token = line.substr(0,pos);
value = atoi(token.c_str());
line.erase(0, pos + 1);
list.push_back(value);
}
value = atoi(line.c_str());
list.push_back(value);
Values.push_back(list);
++count;
}
}
for(int i = 0; i < Values.size(); ++i)
{
cout << maxSubArray(Values[i]);
cout << endl;
}
cout << " Printing the values : " << endl;
for (int j = 0; j < Values.size(); ++j)
{
for (int k = 0; k < Values[j].size(); ++k)
cout << Values[j][k] << " ";
cout << endl;
}
return 0;
}
Why are you passing the vector by value here?
int maxSubArray(vector<int> values)
That looks like a significant optimization opportunity.
I think you don't read the problem exactly right. When they say 'all contiguous sub ararys', they mean you have to take the max over all i andj of for(idx = i; i < j; ++i) { total += vec[idx]; }. Right now your code basically assumes i = 0 which isn't what you are supposed to do.
Just from looking at the output examples they provide, I can see that your code isn't going to give the answer that they expect.
it seems right, the only thing I can think of is that when the list gets long, your result can overflow, so change int to long long.
Besides technical optimizations suggested in other answers, concerning the algorithm, i think a little fix can make your algorithm work. When curr_max drops to a negative value, due to encountering a negative integer that exceeds curr_max, you can simply drop all the previous integers including the current value and start over. This fix is simple, you can add one line to your loop like this:
for(int i = 1; i < values.size(); ++i)
{
curr_max = max(values[i], curr_max + values[i]);
curr_max = max(curr_max, 0); // <---------------- add this line
max_so_far = max(max_so_far, curr_max);
}

not declared in scope c++ [duplicate]

This question already has answers here:
'foo' was not declared in this scope c++
(3 answers)
Closed 6 years ago.
I am getting an error that breed is not declared in scope even though it is right below the fucntion. What is wrong?
The exact error is: prog.cpp: In function ‘void best(std::string*)’:
prog.cpp:131:15: error: ‘breed’ was not declared in this scope
breed(bestRats)
#include <iostream>
#include <sstream>
#include <vector>
#include <math.h>
#include <map>
#include <string.h>
#include <queue>
#include <regex>
#include <bitset>
#include <stdlib.h>
#include <climits>
// #include "dungeonrats.cpp"
using namespace std;
/*
Finds the maximum integer in an array of integers.
Size is the size of the given array.
*/
int getMax(int* numbers, int size) {
int maximum = INT_MIN;
for (int i = 0; i < size; i++) {
if (numbers[i] > maximum) maximum = numbers[i];
}
return maximum;
}
int getMaxi(int* numbers, int size) {
int maximum = INT_MIN;
int maxi;
for (int i = 0; i < size; i++) {
if (numbers[i] > maximum) {
maximum = numbers[i];
maxi = i;
}
}
return maxi;
}
/*
"randomly" generates a new maze (but is it REALLY random?)
aim is 65% empty tiles
10% food tiles
10% obstacles
15% pits
*/
string getNewMaze(string mapseed) {
string maze = mapseed.substr(6); // get everything except the 25:25:
for (int i = 0; i < 626; i++) {
int percentile = rand() % 100; // from 0 to 99
if (percentile < 65) {
maze[i] = '.';
}
else if (percentile >= 65 && percentile < 75) {
maze[i] = '$';
}
else if (percentile >= 75 && percentile < 85) {
maze[i] = '*';
}
else maze[i] = 'X';
}
return maze;
}
/*
A function used to print how many of each kind of tile
exist in the maze.
*/
void testFrequency(string mapseed) {
int numEmpty = 0;
int numFood = 0;
int numObs = 0;
int numPit = 0;
for (int i = 0; i < 626; i++) {
if (mapseed[i] == '.') {
numEmpty++;
}
if (mapseed[i] == '$') {
numFood++;
}
if (mapseed[i] == '*') {
numObs++;
}
if (mapseed[i] == 'X') {
numPit++;
}
}
cout << "Number of empty tiles is " << numEmpty << endl;
cout << "Number of food tiles is " << numFood << endl;
cout << "Number of obstacles is " << numObs << endl;
cout << "Number of pits is " << numPit << endl;
}
/*
Returns an array of size 2 containing the best two rats.
*/
void best(string r[]) {
// r is the array of five rat genomes
//int moves = simulator(mapseed, genome, start_row, start_col);
int* ratMoves = new int[5]; // array that stores how long each rat lasted
int maxIndex = 0;
int max = INT_MIN;
string originalMapseed = "25:25:..$.$.X.............X....$X.X*..X$..X...*X$..$...X$.$......X.$.X...XX.$.X*.*.*..X..X.**.......X..$$$...........XX.....................$...X...*.$..X..$X..........$.*..X.....$.X..$*.$X......$...X.*X$......$.**.X.X..XX$X..*....*..X.X....$...X...X........$.X....$...*...X$*........X..$*$$......$$...$*..X.$.$......$.$.$...$..X.*.....X..$......$.XX*..X.$.X......X$*.**.....X*...$..XX..X.....$....X....X...X....X.$X$..X..........$...*.X$..X...$*...........*....XXX$$.$.$..*$XX..XX..*.....$......X.XX$..$$..X$.XX.$$..X.*..*......X......$..$.$$..*...X.........$X....$X.$$.*.$.$.$..**.....X.$.$X.*.$.........$**..X.X.X$X.$.*X.X*..$*.";
for (int i = 0; i < 5; i++) {
string mapseed = getNewMaze(originalMapseed);
int sumTurns = 0;
for (int k = 0; k < 10; k++) {
string mapseed = getNewMaze(originalMapseed);
// sumTurns += simulator(mapseed,r[i],12,12); // uncomment this line once in correct file
}
ratMoves[i] = sumTurns / 10; // average of rat's performance
// over 10 random maps
if (ratMoves[i] > max) { // find the best
max = ratMoves[i];
maxIndex = i;
}
}
string bestRats[2];
bestRats[0] = r[maxIndex]; // store the best
ratMoves[maxIndex] = INT_MIN; // remove the best from array of rat moves
bestRats[1] = r[getMaxi(ratMoves, 5)]; // get the second best & store it
breed(bestRats);
}
void breed(string r[]) {
int cap = 10;
string c[5];
for (int j = 0; j<5; j++)
for (int i = 0; i<190; i++) {
int check = rand() % cap + 1;
if (check % 2 == 0) {
if (check == 0)
c[j] += rand() % 81 + 42;
else
c[j] += r[1][i];
}
else
c[j] += r[0][i];
}
best(c);
}
int main() {
string c[5];
for (int j = 0; j<5; j++)
for (int i = 0; i<190; i++)
c[j] += rand() % 81 + 42;
best(c);
}
Declare
void breed(string r[]);
on the top of file before first usage or include appropriate header file containing this declaration.
c++ checks for function names at the moment it reads them in the code (symbolically). if it hasn't read it yet, it doesn't know it exists. that's why you at least need to declare a function's prototype before using it in your code.
ergo, here you need to at least put
void breed(string r[]);
before using the function.
When the compiler processes your code, it starts at the top and goes to the end. At any given point in this process, it only "knows" about things it's already seen. So when you try to call the breed function from the best function, it doesn't know what you're talking about because it hasn't seen anything called breed yet.
To fix this, you need to let the compiler know what the breed function is before you attempt to use it. There are a few ways to do this. The easiest would be to move the entire breed function above the best function in your source file. An alternate would be to declare the breed function higher up in the file before defining it later. To declare it, simply include the line void breed (string r[]); somewhere (don't forget the ; at the end). This way the compiler knows that "breed" refers to a function that takes an array of strings and returns nothing, which is enough for it to compile calls to the function.

copy one array to another without duplicates C++

The problem is that, I have an array of 10 integers, having some duplicates. The task is to copy this array to another array of same size, but without duplicate values. That is, read one element from array1, compare it with all the elements in array2, if it's already in array2, just skip it or print that it's already in array2, go to second element of array1, and repeat the process.
Now, I've tried this but don't know where's the problem:
#include <iostream>
using namespace std;
int main()
{
int temp;
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
break;
}
}
array2[i] = array1[i-1];
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl;
system("pause");
}
array1 has 10 elements and array2 has 11, so right away the requirements haven't been met. Presumably, having 11 elements was a workaround for using incorrect index values in the for loops; the index should run from 0 to 9, not from 1 to 10.
When you add an element to the second array, you should only check it value against the elements that have already been added, not against the values in the entire array.
Finally, there's an underspecification. Once you've eliminated duplicates, you have fewer than 10 elements; array2 has 10 elements; what values should the extra elements have?
std::unique_copy is your friend:
http://en.cppreference.com/w/cpp/algorithm/unique_copy
remember to sort the source array first
In C++, break immediately ends one loop structure, and starts execution immediately after it. Thus, the line array2[i] = array1[i-1]; executes redardless of whether the inner for loop finds a duplicate. One solution is to set a variable indicating that the value is a duplicate:
int main() {
int temp;
bool isDuplicate; //added this line
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
isDuplicate=false;//added this line
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
isDuplicate=true; //added this line
break;
}
}
if(!isDuplicate) //added this line
array2[i] = array1[i-1];
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl; system("pause"); }
Alternatively (though many programmers would disagree with this practice) you could use a goto statement instead of a break statement:
int main()
{
int temp;
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
goto duplicate; //added this line
}
}
array2[i] = array1[i-1];
//added next line
duplicate:
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl;
system("pause");
}
You could use a std::set to ensure uniqueness for you.
http://en.cppreference.com/w/cpp/container/set
You have three approaches:
compare each element one by one (O(N^2) performance)
sort your reference array and use a binary search to determine if the element exists (O(N*lnN) performance)
create a lookup hash (O(1) performance)
I can see two main sources of problems in your code: 1) the break statement, as it is, does not solve the problem of differentiating between the case when duplicate is found, and when the element in array1 should be added to array2. 2) There is no counter which would store the number of elements inserted so far into array2, this way they could not be copied to array2 next to each other. The code which fixes both is:
#include <iostream>
using namespace std;
int main()
{
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[10];
int array2_elements_inserted = 0;
for(int i = 0; i < 10; i++)
{
int temp = array1[i];
bool isDuplicate = false;
for(int j = 0; j < array2_elements_inserted; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
isDuplicate = true;
break;
}
}
if (!isDuplicate)
{
array2[array2_elements_inserted] = temp;
++array2_elements_inserted;
}
}
for(int k = 0; k < array2_elements_inserted; k++)
cout << array2[k] << " " << endl;
// system("pause");
}
Output:
10
2
5
4
6
9
8
First of all, use dynamic containers. Especially have a look at those provide by
the standard library, e.g. std::vector. Second, you should use a set data structure
to keep track of the elements you have seen before, e.g., std::set.
Then it's just an iteration on the input array and appending new elements to the
output array.
Here's an example:
#include <vector>
#include <set>
#include <iostream>
int main() {
// define and print input data
std::vector<int> v1 = {10,2,5,4,10,5,6,9,8,10};
for (int i : v1)
std::cout << i << " ";
std::cout << "\n";
// this will soon contain the output data
std::vector<int> v2;
// a set to keep track of the already seen elements
std::set<int> set;
// iterate the input array using range-based for loop
for (int i : v1) {
// check for duplicates
if (set.find(i) == set.end()) {
// first occurrence, insert to set, append to output data
set.insert(i);
v2.push_back(i);
}
else {
// seen before, do nothing
}
}
// print output data
for (int i : v2)
std::cout << i << " ";
std::cout << "\n";
}
The output:
$ g++ test.cc -std=c++11 && ./a.out
10 2 5 4 10 5 6 9 8 10
10 2 5 4 6 9 8
For reference:
http://en.cppreference.com/w/cpp/container/vector
http://en.cppreference.com/w/cpp/language/range-for
http://en.cppreference.com/w/cpp/container/set
http://en.cppreference.com/w/cpp/container/set/find