Bug in selection sort loop - c++

I need to make a program that will accept a input file of numbers(integer.txt) which will be sorted one number per line, into a vector, then use a selection sort algorithm to sort the numbers in descending order and write them to the output file (sorted.txt). I'm quite sure something is wrong in my selectionSort() function that is causing the loop not to get the right values, because after tested with cout I get vastly improper output. I'm sure it's a beginning programmer's goof.
vector<string> getNumbers()
{
vector<string> numberList;
ifstream inputFile ("integer.txt");
string pushToVector;
while (inputFile >> pushToVector)
{
numberList.push_back(pushToVector);
}
return numberList;
}
vector<string> selectionSort()
{
vector<string> showNumbers = getNumbers();
int vectorMax = showNumbers.size();
int vectorRange = (showNumbers.size() - 1);
int i, j, iMin;
for (j = 0; j < vectorMax; j++)
{
iMin = j;
for( i = j; i < vectorMax; i++)
{
if(showNumbers[i] < showNumbers[iMin])
{
iMin = i;
}
}
if (iMin != j)
{
showNumbers[j] = showNumbers [iMin];
}
}
return showNumbers;
}
void vectorToFile()
{
vector<string> sortedVector = selectionSort();
int vectorSize = sortedVector.size();
ofstream writeTo;
writeTo.open("sorted.txt");
int i = 0;
while (writeTo.is_open())
{
while (i < vectorSize)
{
writeTo << sortedVector[i] << endl;
i += 1;
}
writeTo.close();
}
return;
}
int main()
{
vectorToFile();
}

vectorRange defined but not used.

In your selectionSort(), the only command that changes the vector is:
showNumbers[j] = showNumbers [iMin];
Every time control reaches that line, you overwrite an element of the vector.
You must learn to swap two values, before you even think about sorting a vector.
Also, your functions are over-coupled. If all you want to fix is selectionSort, then you should be able to post that plus a main that calls it with some test data and displays the result, but no, your functions all call each other. Learn to decouple.
Also your variable names are awful.

Related

How to compare values of two vectors

Is anybody there who has a code on how to compare values of two arrays ?
I have two vectors and I am looking for the biggest and equal value of the both list.
Here is the code:
void fractionInLowestTerm(int fNumerator, int fDenominator)
{
//let's get the dividers of fNumerator and fDenominator
std::vector<int> dividerOfNumerator;
std::vector<int> dividerOfDenominator;
for (int i = 1; i <= fNumerator; i++) {
if (fNumerator % i == 0) {
dividerOfNumerator.push_back(i);
}
}
for (int j = 1; fDenominator <= j; j++) {
if (fDenominator % j == 0) {
dividerOfDenominator.push_back(j);
}
}
// let's get the greatest common divider of a and b;
int pgcd = 1;
// I do not know how to compare the values of dividers to get the greatest common value on a and b there is the code I started writing to get that
for (int m = 0; m <= dividerOfNumerator.size() && m <= dividerOfDenominator.size(); m++) {
}
}
If I understand the problem correctly, you want to compare the elements in two arrays for each index and save the greater one into a third array. In this case, just use your favourite max function for each index. For example:
void compare(int* array1, int* array2, int* array3, int size)
{
for (int member = 0; member < size; ++member) {
array3[member] = std::max(array1[member], array2[member]);
}
}
or if you want to compare lists and write into third array that which array has bigger value in that index you can use following code
void compare(int* array1, int* array2, int* array3, int size)
{
for (int member = 0; member < size; ++member) {
if (array1[member] > array2[member]) {
array3[member] = 1;
}
else if (array1[member] < array2[member]) {
array3[member] = 2;
}
else if (array1[member] == array2[member]) {
array3[member] = 0;
}
}
}
Since the vectors containing the divisors are already sorted, you can use the std::set_intersection algorithm like this:
std::vector<int> commonDivisors;
std::set_intersection(dividerOfNumerator.begin(), dividerOfNumerator.end(),
dividerOfDenominator.begin(), dividerOfDenominator.end(),
std::back_inserter(commonDivisors));
int pgcd = commonDivisors.back(); // guaranteed to be non-empty since 1 is always a divisor
Here's a demo.
Hello as you can see on the function name I wanted to write a function which put a function on the lowest term. I wanted to go through the gcd but I saw that it would consumes too much memory so here is what I've done. If it can help any member of the forum.
void fractionInLowestTerm(int fNumerator, int fDenominator){
//let's get on the divider of the number
for (int i = 1; i < fNumerator and i <fDenominator; i++) {
if (fNumerator%i == 0 and fDenominator%i == 0) {
fNumerator /= i;
fDenominator /= i;
i = 1;
}
}
}

vector not producing expected output c++

I am creating an idea bank to hold ideas inputted from a keyboard or from a txt file.
the idea follows the following pattern
ID:
Proposer:
keywords:
content:
i am then implementing an indexing algorithm for the idea bank using reverted index using the following struct
struct Index {
string key;
vector<int> idList;
};
where key represents a keyword in an idea and idList represent the ID for the idea.
I am then storing the index in an AVL tree.
here is my code to to create the inverted index.
void IdeaBank::AVLTreeIndexing(){
vector<string> kwords_vec;
vector<int> relevantIDs;
int foundIdIn;
string kword;
Index input;
for (int loop = 0; loop < newIdea.size(); loop++){
kwords_vec = newIdea[loop].getKeyword();
for (int i = 0; i < kwords_vec.size(); i++){
// goes through all ideas
for (int j = 0; j < newIdea.size(); j++){
if (newIdea[j].foundWordInBoth(kwords_vec[i])){
input.key = kwords_vec[i];
input.idList.push_back(newIdea[j].getID());
tree.AVL_Insert(input);
relevantIDs.push_back(input.idList[j]);
}// end of lookfor
}
}// end of kwords.size loop
}
}
my logic behind the above function is the following:
1) go through all the ideas and get the keyword
2) check if an idea contains the keyword
3) store the word as a key in my struct and store the ID in my vector in the struct
4) insert the struct into my avl tree
i am then trying to create a search function to print all the ideas that contain the word in their keyword. and this is where i believe i am having problems.
here is the code
void IdeaBank::searchQueryFromBank(string word){
Index index;
vector <int> test;
if (tree.AVL_Retrieve(word, index)){
cout << "found in tree"<<endl;
cout << "Relevant idea ID's for "
<< word << ":" << endl;
for (int i = 0; i < index.idList.size(); i++){
cout << index.idList[i] << endl;
test.push_back(index.idList[i]);
}
}
else
{
cout << "No relevant ideas found for " << word << endl;
}
cout << endl;
cout << "displaying the following Ideas"<<endl;
for (int i=0;i<test.size();i++)
{
displayIdeaByID(test[i]);
}
}
the problem i am having:
my ID list vector is being populated with numbers that dont contain the keyword.
for example say i have the two following ideas
ID: 1
Proposer: bob
keywords: computer,laptop
content: computer with built in microphone
ID: 2
Proposer: bob
keywords: smartphone
content: smartphone with built in microphone
if i was to search for the keyword "smartphone"
my result would print the following ID's
ID 0...
ID 0...
ID 1...
in my indexing function, the function foundWordInBoth is defined as
bool Idea::foundWordInBoth(string word){
if (find(keyword.begin(), keyword.end(), word) != keyword.end()){
return true;
}
size_t pos;
pos = content.find(word);
if (pos != string::npos)
{
return true;
}
return false;
the above function checks to see if a word is found in either the keyword or in the contents of the idea.
overall, i am unsure why it is printing out Ideas that do not contain a certain keyword
I would guess that the problem is here
void IdeaBank::AVLTreeIndexing(){
vector<string> kwords_vec;
vector<int> relevantIDs;
int foundIdIn;
string kword;
Index input;
for (int loop = 0; loop < newIdea.size(); loop++){
kwords_vec = newIdea[loop].getKeyword();
for (int i = 0; i < kwords_vec.size(); i++){
// goes through all ideas
for (int j = 0; j < newIdea.size(); j++){
if (newIdea[j].foundWordInBoth(kwords_vec[i])){
input.key = kwords_vec[i];
input.idList.push_back(newIdea[j].getID());
tree.AVL_Insert(input);
relevantIDs.push_back(input.idList[j]);
}// end of lookfor
}
}// end of kwords.size loop
}
}
You only declare one Index object, which you then push back IDs to for the entire execution of the function. So the list of IDs just builds and builds.
I'm finding the logic a little hard to follow because you only ever seem to have one ID for each key but clearly you need to move the declaration of input to some narrower scope.
Maybe it should look something like this (but really I'm guessing)
void IdeaBank::AVLTreeIndexing() {
for (int loop = 0; loop < newIdea.size(); loop++) {
vector<string> kwords_vec = newIdea[loop].getKeyword();
for (int i = 0; i < kwords_vec.size(); i++) {
Index input;
input.key = kwords_vec[i];
// goes through all ideas
for (int j = 0; j < newIdea.size(); j++) {
if (newIdea[j].foundWordInBoth(kwords_vec[i])) {
input.idList.push_back(newIdea[j].getID());
}// end of lookfor
}
tree.AVL_Insert(input);
}// end of kwords.size loop
}
}
In general get used to declaring variables where you need them, instead of declaring them all at the beginning of a function.

Reading values from file into 2D vector results in all values being zero

I'm trying to read a file of integer values and push each value into a 2D vector. For whatever reason, my resulting vector is full of zeros, rather than the values that I just read out of the file. Why is this and how do I fix it?
void populateVector(string file, vector<vector<int>>& v, int rows, int cols){
ifstream read(file);
int val;
if (!read.is_open()) {
throw runtime_error("Output file is not open.");
} else {
//Populate 2D vector with values from file
while (read >> val) {
cout << val << endl; //Prints each value being processed. Prints proper value.
for (int i = 0; i < rows; i++) {
vector<int> newCol;
v.push_back(newCol);
for (int j = 0; j < cols; j++) {
v.at(i).push_back(val);
}
}
}
}
}
When I print the vector it is populated solely of zeros, even though the read values that are printed to standard output are what I expect (the values from the file).
Your solution would push all the numbers 'cols' times into each row, that is you end up with row * (cols * n) matrix. Look at your loops correctly.
I assume you meant to read each number only once. Then change your loop to something like following (add error checking as necessary)
for (int i = 0; i < rows; i++)
{
std::vector<int> newRow;
for (int j = 0; j < cols; j++)
{
int val;
read >> val;
newRow.push_back(val);
}
v.push_back(newRow);
}
If you want to read one value at a time, you may want to consider a loop like this:
unsigned int column = 0;
std::vector<std::vector<int> > matrix;
std::vector<int> data_row;
while (read >> value)
{
data_row.push_back(value);
++column;
if (column > MAXIMUM_COLUMNS)
{
matrix.push_back(row_data);
data_row.clear();
column = 0;
}
}
The above code builds a row of data, one column at a time. When enough columns are read, the row is then appended to the matrix.

String matching algorithm trying to correct it

I'm trying to do string matching algorithm a brute force method. but The algorithm is not working correctly, I get an out of bound index error.
here is my algorithm
int main() {
string s = "NOBODY_NOTICED_HIM";
string pattern="NOT";
int index = 0;
for (int i = 0; i < s.size();)
{
for (int j = 0; j < pattern.size();)
{
if(s[index] == pattern[j])
{
j++;
i++;
}
else
{
index = i;
j = 0;
}
}
}
cout<<index<<endl;
return 0;
}
FIXED VERSION
I fixed the out of bound exception. I don't know if the algorithm will work with different strings
int main() {
string s = "NOBODY_NOTICED_HIM";
string pattern="NOT";
int index = 0;
int i = 0;
while( i < s.size())
{
i++;
for (int j = 0; j < pattern.size();)
{
if(s[index] == pattern[j])
{
index++;
j++;
cout<<"i is " <<i << " j is "<<j <<endl;
}
else
{
index = i;
break;
}
}
}
cout<<i<<endl;
return 0;
}
Because the inner for loop has a condition to loop while j is less than pattern.size() but you are also incrementing i inside the body. When i goes out of bounds of s.size() then index also goes out of bounds and you'd get an OutOfBounds error.
The brute force method has to test the pattern with every possible subsequence. The main condition is the length, which has to be the same. All subsequence from s are:
['NOB', 'OBO', 'BOD', 'ODY', 'DY_', 'Y_N', 'NO', 'NOT', 'OTI', 'TIC',
'ICE', 'CED', 'ED', 'D_H', '_HI', 'HIM']
There are many ways to do it, you can do it char by char, or by using string operations like taking a substring. Both are nice excercises for learning.
Starting at zero in the s string you take the first three chars, compare to the pattern, and if equal you give the answer. Otherwise you move on to the char starting at one, etc.

Getting Word Frequency From Vector In c++

I have googled this question and couldn't find an answer that worked with my code so i wrote this to get the frequency of the words the only issue is that i am getting the wrong number of occurrences of words apart form one that i think is a fluke. Also i am checking to see if a word has already been entered into the vector so i don't count the same word twice.
fileSize = textFile.size();
vector<wordFrequency> words (fileSize);
int index = 0;
for(int i = 0; i <= fileSize - 1; i++)
{
for(int j = 0; j < fileSize - 1; j++)
{
if(string::npos != textFile[i].find(textFile[j]) && words[i].Word != textFile[j])
{
words[j].Word = textFile[i];
words[j].Times = index++;
}
}
index = 0;
}
Any help would be appreciated.
Consider using a std::map<std::string,int> instead. The map class will handle ensuring that you don't have any duplicates.
Using an associative container:
typedef std::unordered_map<std::string, unsigned> WordFrequencies;
WordFrequencies count(std::vector<std::string> const& words) {
WordFrequencies wf;
for (std::string const& word: words) {
wf[word] += 1;
}
return wf;
}
It is hard to get simpler...
Note: you can replace unordered_map with map if you want the worlds sorted alphabetically, and you can write custom comparisons operations to treat them case-insensitively.
try this code instead if you do not want to use a map container..
struct wordFreq{
string word;
int count;
wordFreq(string str, int c):word(str),count(c){}
};
vector<wordFreq> words;
int ffind(vector<wordFreq>::iterator i, vector<wordFreq>::iterator j, string s)
{
for(;i<j;i++){
if((*i).word == s)
return 1;
}
return 0;
}
Code for finding the no of occurrences in a textfile vector is then:
for(int i=0; i< textfile.size();i++){
if(ffind(words.begin(),words.end(),textfile[i])) // Check whether word already checked for, if so move to the next one, i.e. avoid repetitions
continue;
words.push_back(wordFreq(textfile[i],1)); // Add the word to vector as it was not checked before and set its count to 1
for(int j = i+1;j<textfile.size();j++){ // find possible duplicates of textfile[i]
if(file[j] == (*(words.end()-1)).word)
(*(words.end()-1)).count++;
}
}