Problem with adding strings to a vector<set<string>> - c++

Thank you for taking your time to read this! I have been practicing online and I came across this one problem which I am not able to solve.
Firstly, we enter a number and then enter some names. The number is the size of a vector<string> where we put the names. Afterwards, the elements of the said vector<string> are to be copied to a list<string>.
Afterwards, the program is supposed to copy the names to a vector<set<string>> where each set represents a team. The size of the teams is to be determined by a formula and I have no problems in calculating the sizes(for example, if the number of children is 10, and you wish to place them in three teams, then the sizes of the teams should be 4, 3, 3 respectively.)
Now here comes the tricky part for me. The copying is to be done as follows:
The first entered name is copied to the first set<string>. Afterwards, you take the number of letters in the name and iterate through the list<string> number of letters times. (If at one point you reach the end of the list, the iterator goes back to the beginning of the list)
The name you stop at is to be put into the current set until it is full. When you put the name in the corresponding set, it is then to be removed from the list.
I do not know how to do this. I get stuck right after I put the first name in the first set<string> and remove it from the list<string> I do not know how to return the iterator back at the beginning of the list if it reaches the end of the list and I do not know how to skip to the next set<string> if the current one is full.
Here is what I tried:
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <list>
using namespace std;
int LettersInWord(string s) { // a "letter" is an alphabetic character or a number
int counter = 0;
for(int i = 0; i < s.length(); i++) {
if((s[i] >= 65 && s[i] <= 90) || (s[i] >= 97 && s[i] <= 122) ||
(s[i] >= 48 && s[i] <= 57))
counter++;
}
return counter;
}
int main() {
vector<set<string>> vss(3); // three teams
list<string> names = {{"Name1"}, {"Name2"}, {"Name3"}, {"Name4"}, {"Name5"},
{"Name6"}, {"Name7"}, {"Name8"}, {"Name9"}, {"Name10"}};
vector<int> size_teams = {4, 3, 3};
auto it = names.begin();
string s = *it;
vss[0].insert(*it); // put the first name in the first set
it = names.erase(it); // erase it
int number_of_iterations = LettersInWord(s);
int counter_of_insertions = 0; // this counter keeps track of
// how many strings are inserted in a set, so
// as not to overflow the size
for(int i = 0; i < vss.size(); i++) { // iterate through the vector of sets
int counter_of_iterations = 0; // we compare this to counter_of_insertions
for(auto it = names.begin(); it != names.end(); it++) { // iterate through the list
if(it == names.end())
it = names.begin(); // if iterator is at the end of list, return it to
// beginning
counter_of_iterations = 0;
if(counter_of_iterations == number_of_iterations) {
vss[i].insert(*it); // insert word
counter_of_insertions++;
if(counter_of_insertions == size_teams[i]) i++;
counter_of_insertions = 0;
it = names.erase(it);
number_of_iterations = LettersInWord(*it); // get no of letters in next word
}
}
}
return 0;
}
What this does is it just copies the first name to the first set and does absolutely nothing else.
Whatever I try I simply cannot fix this. Would anyone be kind to make a modification to the code above? I am sorry for any bad phrasing, mistakes or errors.
Note: It is mandatory to use list<string> and <vector<set<string>>
Thanks to anyone who is willing to help in any way!

if(counter_of_iterations == number_of_iterations) {
This line can never be true.
It's easy to see in godbolt, because there's a huge chunk of code that doesn't get colored (meaning that it didn't have any machine code generated for it):
https://godbolt.org/z/_wm8ff
Also, line 39 can never run either, since that's the termination case for the for loop it's in.

Related

C++ moving characters from one vector to another

I'm new to C++. I am trying to create a program that reads a file named symbols.txt, fill a vector with the symbols, then take chars that are in the range [d;p] and move them to the second vector while erasing them from the first vector.
int main(){
vector<char> sym1;
vector<char> sym2;
int p = 100, d = 80;
char x;
ifstream symbols("symbols.txt");
while (symbols >> x )
{
sym1.push_back(x);
}
for(int i = 0; i < sym1.size(); i++){
if (sym1[i] < p && sym1[i] > d){
sym2.push_back(sym1[i]);
sym1.erase(sym1.begin()+i);
}
}
}
When I do this, the program works if there are no characters the same, otherwise it only moves half of the characters and leaves the other half untouched.
In your implementation, the first thing you need to notice is that in your for loop, sym1.size() changes if you call sym1.erase(). Second, since your variable i increments every time, you skip some elements in the vector.
For example, the element at index 5 is erased, then the element at index 6 will move down to replace it. In the mean time, your loops does i++, so you skip the element that moved to index 5.
I think you should use iterators with C++ containers, below is an example:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<char> sym1;
vector<char> sym2;
int p = 100, d = 80;
char x;
// ifstream symbols("symbols.txt");
// while (symbols >> x)
// {
// sym1.push_back(x);
// }
for(int i = 0; i < 200; i++) {
sym1.push_back(i);
}
int size = sym1.size();
for(vector<char>::iterator it = sym1.begin(); it != sym1.end(); ){
if (*it < p && *it > d){
sym2.push_back(*it);
it = sym1.erase(it);
}
else
it++;
}
for(vector<char>::iterator it = sym2.begin(); it != sym2.end(); it++) {
cout << (int)*it << " ";
}
}
std::vector is good for a lot of things. However, it's terribly inefficient when it comes to insertion or erasing at any other position than the end.
When an element is inserted somewhere (not at end), then the following happens:
The internally managed size is increased by 1. (This may cause a re-allocation of the internal buffer.)
The last element is moved to next position, the second last element is moved to the now "free" position, and so on until the element at insertion index is moved.
Similar happens when an element is erased:
The successor of the element to erase is moved to its previous position, the next is moved to its previous position, and so on until the last element is moved.
Finally, the internally managed size is decreased by 1. (No re-allocation. – The buffer is kept as reserved.)
In OPs case, it's the repeated erasing which makes me concerns. And, when I had this problem in production I used a way to reduce all the moves to the absolutely minimal required.
For this, I use two indices:
one to read and check the characters
one to write the characters which have to be kept in the vector (sym1 in OPs sample).
While the read index is simply incremented for each loop iteration (as usual) the write index is incremented only after an element has been moved (because it should be kept).
As long as nothing is erased, both indices will have identical values. In this case, it's a bit annoying that elements are moved to the position where they already are. However, I consider this as the lesser evil. (Checking whether indices are still identical will probably buy nothing if the move is simple enough.) As soon as something is erased the write index starts to lag behind the read index.
So finally, for a vector of length N there are exactly N write operations to perform (and this for granted). This sounds reliable and not too terrible.
(Erasing elements individually one by one could be in worst case result in
N - 1 + N - 2 + … + 1 moves of elements which are roughly N * (N - 1) / 2 or (N² - N) / 2.)
For the demonstration, the modified sample of OP:
#include <fstream>
#include <iostream>
#include <vector>
int main()
{
std::vector<char> sym1, sym2;
const char p = 'z', d = 'a';
// read sample data
std::ifstream symbols("symbols.txt");
for (char x; symbols >> x;) sym1.push_back(x);
// move all characters in [d, p] to sym2
size_t iWrite = 0;
for (size_t iRead = 0, n = sym1.size(); iRead < n; ++iRead) {
const char c = sym1[iRead];
if (c >= d && c <= p) sym2.push_back(c);
else sym1[iWrite++] = sym1[iRead];
}
// The difference between iWrite - iRead is the number of obsolete elements.
// (It must be equal to sym2.size().)
sym1.resize(iWrite);
// could've been altermatively: sym1.erase(sym1.begin() + iWrite, sym1.end());
// show results:
std::cout << "sym1: '";
for (const char c : sym1) std::cout << c;
std::cout << "'\nsym2: '";
for (const char c : sym2) std::cout << c;
std::cout << "'\n";
}
Input:
I used the above source code as input (as the OP didn't expose the symbols.txt file).
Output:
sym1: '#<>#<>#<>(){::<>1,2;='',='';//::(".");(;>>;)1._();//[,]2_W=0;(_R=0,=1.();R<;++R){=1[R];(>=&&<=)2._();1[W++]=1[R];}//TW-R.//(I2.().)1.(1.()+W,1.());//:::<<"1:'";(:1)::<<;::<<"'\2:'";(:2)::<<;::<<"'\";}'
sym2: 'includefstreamincludeiostreamincludevectorintmainstdvectorcharsymsymconstcharpadzreadsampledatastdifstreamsymbolssymbolstxtforcharxsymbolsxsympushbackxmoveallcharactersindptosymsizetiriteforsizetieadnsymsizeieadnieadconstcharcsymieadifcpcdsympushbackcelsesymiritesymieadhedifferencebetweeniriteieadisthenumberofobsoleteelementstmustbeequaltosymsizesymerasesymbeginiritesymendshowresultsstdcoutsymforconstcharcsymstdcoutcstdcoutnsymforconstcharcsymstdcoutcstdcoutn'
Live Demo on coliru
So, for the range ['a', 'z'], (I used in my demo for better illustration) sym2 ends up containing all lower case characters while sym1 keeps everything else (except the white spaces).
Concerning the missing white spaces I wondered a bit until I realized that the white spaces are filtered out by the read loop:
for (char x; symbols >> x;) sym1.push_back(x);
which used formatted input.
This could be changed using symbols.get(x) instead of symbols >> x but the filtering of white space might be even intended.
Nitpicking:
OP described the range [d;p] (for the characters to move) as requirement.
AFAIK, it's usual that square brackets (or angle brackets) describe ranges with closed ends (i.e. with inclusive border values) while for open ends (exclusive border values) round brackets are used.
Thus, either the requirement has to be (d;p)
or the implementation of the range check
if (sym1[i] < p && sym1[i] > d){ // check for range (d;p)
is not according to the requirement but should be
if (sym1[i] <= p && sym1[i] >= d){ // check for range [d;p]

R G B element array swap

I'm trying to create this c++ program to perform the description below. I am pretty certain the issue is in the recursive, but uncertain how to fix it. I'm guessing it just keeps iterating through to infinity and crashes. I do not even get an output. I figured I could just compare the previous and current pointer and perform a 3-piece temp swap based on lexicography. I would use a pointer to iterate through the array and decrement it after each swap, then recursively call with that ptr as the parameter. Didn't work, I'm here, help me please :). If there is a simpler solution that would work too, but prefer to understand where I went wrong with this code.
#include <string>
#include <iostream>
using namespace std;
// Given an array of strictly the characters 'R', 'G', and
// 'B', segregate the values of the array so that all the
// Rs come first, the Gs come second, and the Bs come last.
// You can only swap elements of the array.
char* RGBorder(char* c_a)
{
size_t sz = sizeof(c_a)/sizeof(*c_a);
char* ptr_ca = c_a;
char* prv_ptr = ptr_ca;
ptr_ca++;
char temp;
while(*ptr_ca)
{
switch(*ptr_ca)
{
case 'R' :
if( *prv_ptr < *ptr_ca ) {
temp = *prv_ptr; *prv_ptr = *ptr_ca; *ptr_ca = temp;
} else if( *prv_ptr == *ptr_ca ) {
continue;
} else { ptr_ca--; RGBorder(ptr_ca); }
case 'G' :
if( *prv_ptr < *ptr_ca ) {
temp = *prv_ptr; *prv_ptr = *ptr_ca; *ptr_ca = temp;
} else if( *prv_ptr == *ptr_ca ) {
continue;
} else { ptr_ca--; RGBorder(ptr_ca); }
default:
ptr_ca++;
continue;
}
ptr_ca++;
cout << *ptr_ca;
}
return c_a;
}
int main()
{
char ca[] = {'G', 'B', 'R', 'R', 'B', 'R', 'G'};
char *oca =RGBorder(ca);
char *pca = oca;
while(*pca)
{
cout << *pca << endl;
pca++;
}
}
There are many issues with your code.
1) You call the function RGBorder with a character pointer, and then attempt to get the number of characters using this:
size_t sz = sizeof(c_a)/sizeof(*c_a);
This will not get you the number of characters. Instead this will simply get you the
sizeof(char *) / sizeof(char)
which is usually 4 or 8. The only way to call your function using a char array is either provide a null-terminated array (thus you can use strlen), or you have to pass the number of characters in the array as a separate argument:
char *RGBorder(char *c_a, int size)
2) I didn't go through your code, but there are easier ways to do a 3-way partition in an array. One popular algorithm to do this is one based on the Dutch National Flag problem.
Since you want the array in RGB order, you know that the series of G will always come in the middle (somewhere) of the sequence, with R on the left of the sequence, and B always on the right of the sequence.
So the goal is to simply swap R to the left of the middle, and B to the right of the middle. So basically you want a loop that incrementally changes the "middle" when needed, while swapping R's and B's to their appropriate position when they're detected.
The following code illustrates this:
#include <algorithm>
char *RGBorder(char *c_a, int num)
{
int middle = 0; // assume we only want the middle element
int low = 0; // before the G's
int high = num - 1; // after the G's
while (middle <= high)
{
if ( c_a[middle] == 'R' ) // if we see an 'R' in the middle, it needs to go before the middle
{
std::swap(c_a[middle], c_a[low]); // swap it to a place before middle
++middle; // middle has creeped up one spot
++low; // so has the point where we will swap when we do this again
}
else
if (c_a[middle] == 'B') // if we see a 'B' as the middle element, it needs to go after the middle
{
std::swap(c_a[middle], c_a[high]); // place it as far back as you can
--high; // decrease the back position for next swap that comes here
}
else
++middle; // it is a 'G', do nothing
}
return c_a;
}
Live Example
Here is another solution that uses std::partition.
#include <algorithm>
#include <iostream>
char *RGBorder(char *c_a, int num)
{
auto iter = std::partition(c_a, c_a + num, [](char ch) {return ch == 'R';});
std::partition(iter, c_a + num, [](char ch) {return ch == 'G';});
return c_a;
}
Live Example
Basically, the first call to std::partition places the R's to the front of the array. Since std::partition returns an iterator (in this case, a char *) to the end of where the partition occurs, we use that as a starting position in the second call to std::partition, where we partition the G values.
Note that std::partition also accomplishes its goal by swapping.
Given this solution, we can generalize this for an n-way partition by using a loop. Assume we want to place things in RGBA order (4 values instead of 3).
#include <algorithm>
#include <iostream>
#include <cstring>
char *RGBorder(char *c_a, int num, char *order, int num2)
{
auto iter = c_a;
for (int i = 0; i < num2 - 1; ++i)
iter = std::partition(iter, c_a + num, [&](char ch) {return ch == order[i];});
return c_a;
}
int main()
{
char ca[] = "AGBRRBARGGARRBGAGRARAA";
std::cout << RGBorder(ca, strlen(ca), "RGBA", 4);
}
Output:
RRRRRRRGGGGGBBBAAAAAAA
Sorry to put it blunt, but that code is a mess. And I don't mean the mistakes, those are forgivable for beginners. I mean the formatting. Multiple statements in one line make it super hard to read and debug the code. Short variable names that carry no immediate intrinsic meaning make it hard to understand what the code is supposed to do. using namespace std; is very bad practise as well, but I can imagine you were taught to do this by whoever gives that course.
1st problem
Your cases don't break, thus you execute all cases for R, and both G and default for G. Also your code will never reach the last 2 lines of your loop, as you continue out before in every case.
2nd problem
You have an endless loop. In both cases you have two situations where you'll end up in an endless loop:
In the else if( *prv_ptr == *ptr_ca ) branch you simply continue; without changing the pointer.
In the else branch you do ptr_ca--;, but then in default you call ptr_ca++; again.(Note that even with breaks you would still call ptr_ca++; at the end of the loop.)
In both cases the pointer doesn't change, so once you end up in any of those conditions your loop will never exit.
Possible 3rd problem
I can only guess, because it is not apparent from the name, but it seems that prv_ptr is supposed to hold whatever was the last pointer in the loop? If so, it seems wrong that you don't update that pointer, ever. Either way, proper variable names would've made it more clear what the purpose of this pointer is exactly. (On a side note, consistent usage of const can help identify such issues. If you have a variable that is not const, but never gets updated, you either forgot to add const or forgot to update it.)
How to fix
Format your code:
Don't use using namespace std;.
One statement per line.
Give your variables proper names, so it's easy to identify what is what. (This is not 1993, really, I'd rather have a thisIsThePointerHoldingTheCharacterThatDoesTheThing than ptr_xy.)
Fix the aforementioned issues (add breaks, make sure your loop actually exits).
Then debug your code. With a debugger. While it runs. With breakpoints and stepping through line by line, inspecting the values of your pointers as the code executes. Fancy stuff.
Good luck!
just count the number of 'R', 'G' and 'B' letters and fill the array from scratch.
much easier, no recursions.

Finding the shortest word ladder between two given words and a dictionary

I am trying to find shortest ladder from a dictionary between two given words. All the words including the given one and in the dictionary have same number of characters. In one pass, only one character may be changed and shortest path is required. Ex.: given: "hit" and "cil" Dic: ["hil", "hol", "hot", "lot", "lit", "lil"] So, the answer should be "hit"->"hil"->"cil"
I have tried to solve this problem using BFS; by finding next word in the dictionary and checking if that is adjacent to the popped item from the queue. This approach won't give me the shortest path though:
If, I try to replace each letter with 26 alphabets and if the resulting word is present in the dictionary, accept that: still this approach won't give me shortest path. Ex.: Here, it shall give me: hit->lit->lot->hot->hol->lil->cil
Probably, the better approach would be to construct a tree first and then find the shortest path in the tree from starting word to ending word.
I know, there are solutions to this problem on this forum but none of them explains the algorithm. I am new to BFS and so not much familiar.
I am interested in knowing how to find one of the shortest path and if several then all shortest paths.
What I suggest is to build a graph over the words in the dictionary, where a node represents a word and there is an edge from a <-> b if b can be transformed from a by changing only one character from a (and of course, the vice versa is also true). This process will take O(n*n) time where n is the no. of words in the dictionary. How to do this is as follows :
For each word build frequency array of characters, call it farr, which is 26 length long, and farr[i] tells how many times character i, in alphabetical order occurs in word, and then in a nested loop running n*n times you just need to compare the entries of frequency table for the words, they must differ by only one character in order to have an edge from word a to b.
Also Note that the edges are undirected(in both directions) in this graph.
After building the complete graph on words of dictionary, add the question word as well to graph. And then go ahead with the BFS searching for the target word from node of initial word, where the transformation required is initial word -> target word.
Now say you find target word at level 'i', while exploring from initial word then the shortest path is 'i' units long.
This approach is a bit brute force, but may be a good starting point.
If the target word is equal to the start word, or has Levenshtein distance 1 the result is [start, target] and you are done.
Otherwise you have to find all members of the dictionary with Levenshtein distance 1 from the start word. If one of them has Levenshtein distance 1 to the target word, the result is [start, word, target] and you're done. Otherwise, you recurse with every word in the chosen list as a start and the target as the target and prepend start to the shortest result.
pseudo code - a bit python like:
myDict = {"hil", "hol", "hot", "lot", "lit", "lil"}
used_wordlist = {}
shortestWordLadder(start, target):
if start == target or levenshtein(start, target) = 1:
return [start, target]
current_wordlist = [x for x in myDict
if x not in used_wordlist and
levenshtein(ladder[-1], x) = 1]
if current_wordlist.size = 0:
return null
for word in current_wordlist:
if levenshtein(word, target) == 1:
return [start, word, target]
used_wordlist.insert_all(current_wordlist)
min_ladder_size = MAX_INT
min_ladder = null
for word in currrent_wordlist:
ladder = shortestWordLadder(word, target)
if ladder is not null and ladder.size < min_ladder_size:
min_ladder_size = ladder.size
min_ladder = ladder.prepend(start)
return min_ladder
Possible optimization:
I considered to reuse the matrix, that levenshtein(start, target) would create internally, but I could not gain enough confidence, that it would work in all cases. The idea was to start at the bottom right of the matrix and chose the smallest neighbor, that would create a word from the dictionary. Then continue with that position. If no neighbor of the current cell creates a word from the dictionary, we'd have to backtrack until we find a way to a field with value 0. If backtracking brings us back to the bottom right cell, there is no solution.
I am not sure now, that there might not be solutions, that you'd maybe ignore that way. If it finds a solution, I am pretty confident, that it is one of the shortest.
At the moment I lack the time to think it through. If that proves to not be a complete solution, you could use it as an optimization step instead of the levenshtein(start, target) call in the first line of shortestWOrdLadder(), since the algorithm gives you the Levenshtein distance and, if possible, the shortest path.
I have worked out a solution by adopting the following approach:
1.) I have built a tree from the dictionary first, assuming the starting point to be the given word; and finding all words adjacent to this word and so on
2.) Next I have tried to construct all possible paths from given word to the end word using this tree.
Complexity: O(n*70 + 2^n-1 * lg(n)) = O(2^n-1*lg(n)) Here n is the number of words in the dictionary, 70 comes out as the range of ASCII values from 65 to 122 (A to a), I have taken a round figure here. Complexity is exponential as expected.
Even, after certain optimizations, worst case complexity won't change.
Here is the code I wrote (its tested by me and works. Any bugs or suggestions would be highly appreciated.):
#include <iostream>
#include <vector>
#include <cstring>
#include <deque>
#include <stack>
#include <algorithm>
using namespace std;
struct node {
string str;
vector<node *> children;
node(string s) {
str = s;
children.clear();
}
};
bool isAdjacent(string s1, string s2) {
int table1[70], table2 [70];
int ct = 0;
for (int i = 0; i < 70; i++) {
table1[i] = 0;
table2[i] = 0;
}
for (int i = 0; i < s1.length(); i++) {
table1[((int)s1[i])- 65] += 1;
table2[((int)s2[i])- 65] += 1;
}
for (int i = 0; i < 70; i++) {
if (table1[i] != table2[i])
ct++;
if (ct > 2)
return false;
}
if (ct == 2)
return true;
else
return false;
}
void construct_tree(node *root, vector<string> dict) {
deque<node *> q;
q.push_back(root);
while (!q.empty()) {
node *curr = q.front();
q.pop_front();
if (dict.size() == 0)
return;
for (int i = 0; i < dict.size(); i++) {
if (isAdjacent(dict[i], curr->str)) {
string n = dict[i];
dict.erase(dict.begin()+i);
i--;
node *nnode = new node(n);
q.push_back(nnode);
curr->children.push_back(nnode);
}
}
}
}
void construct_ladders(stack<node *> st, string e, vector<vector <string> > &ladders) {
node *top = st.top();
if (isAdjacent(top->str,e)) {
stack<node *> t = st;
vector<string> n;
while (!t.empty()) {
n.push_back(t.top()->str);
t.pop();
}
ladders.push_back(n);
}
for (int i = 0; i < top->children.size(); i++) {
st.push(top->children[i]);
construct_ladders(st,e,ladders);
st.pop();
}
}
void print(string s, string e, vector<vector<string> > ladders) {
for (int i = 0; i < ladders.size(); i++) {
for (int j = ladders[i].size()-1; j >= 0; j--) {
cout<<ladders[i][j]<<" ";
}
cout<<e<<endl;
}
}
int main() {
vector<string> dict;
string s = "hit";
string e = "cog";
dict.push_back("hot");
dict.push_back("dot");
dict.push_back("dog");
dict.push_back("lot");
dict.push_back("log");
node *root = new node(s);
stack<node *> st;
st.push(root);
construct_tree(root, dict);
vector<vector<string> > ladders;
construct_ladders(st, e, ladders);
print(s,e,ladders);
return 0;
}

iterating vector of strings C++

The code is to read instructions from text file and print out graphic patterns. One is my function is not working properly. The function is to read the vectors of strings I've got from the file into structs.
Below is my output, and my second, third, and sixth graphs are wrong. It seems like the 2nd and 3rd vectors are not putting the correct row and column numbers; and the last one skipped "e" in the alphabetical order.
I tried to debug many times and still can't find the problem.
typedef struct Pattern{
int rowNum;
int colNum;
char token;
bool isTriangular;
bool isOuter;
}Pattern;
void CommandProcessing(vector<string>& , Pattern& );
int main()
{
for (int i = 0; i < command.size(); i++)
{
Pattern characters;
CommandProcessing(command[i], characters);
}
system("pause");
return 0;
}
void CommandProcessing(vector<string>& c1, Pattern& a1)
{
reverse(c1.begin(), c1.end());
string str=" ";
for (int j = 0; j < c1.size(); j++)
{
bool foundAlpha = find(c1.begin(), c1.end(), "alphabetical") != c1.end();
bool foundAll = find(c1.begin(), c1.end(), "all") != c1.end();
a1.isTriangular = find(c1.begin(), c1.end(), "triangular") != c1.end() ? true : false;
a1.isOuter = find(c1.begin(), c1.end(), "outer") != c1.end() ? true : false;
if (foundAlpha ==false && foundAll == false){
a1.token = '*';
}
//if (c1[0] == "go"){
else if (c1[j] == "rows"){
str = c1[++j];
a1.rowNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "columns"){
str = c1[++j];
a1.colNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "alphabetical")
a1.token = 0;
else if (c1[j] == "all"){
str = c1[--j];
a1.token = *str.c_str();
j++;
}
}
}
Before debugging (or posting) your code, you should try to make it cleaner. It contains many strange / unnecessary parts, making your code harder to understand (and resulting in the buggy behaviour you just described).
For example, you have an if in the beginning:
if (foundAlpha ==false && foundAll == false){
If there is no alpha and all command, this will be always true, for the entire length of your loop, and the other commands are all placed in else if statements. They won't be executed.
Because of this, in your second and third example, no commands will be read, except the isTriangular and isOuter flags.
Instead of a mixed structure like this, consider the following changes:
add a default constructor to your Pattern struct, initializing its members. For example if you initialize token to *, you can remove that if, and even the two bool variables required for it.
Do the parsing in one way, consistently - the easiest would be moving your triangular and outer bool to the same if structure as the others. (or if you really want to keep this find lookup, move them before the for loop - you only have to set them once!)
Do not modify your loop variable ever, it's an error magnet! Okay, there are some rare exceptions for this rule, but this is not one of them.
Instead of str = c1[++j];, and decrementing later, you could just write str = c1[j+1]
Also, are you sure you need that reverse? That makes your relative +/-1 indexing unclear. For example, the c1[j+1 is j-1 in the original command string.
About the last one: that's probably a bug in your outer printing code, which you didn't post.

Selective Infinite Loop in Making a Tournament Tree

I want to write a program that randomly generates a tournament tree using only the number of challengers. I read into another such problem, but the answer described how ranks would take part and seeding the players, which went a little over head.
The problem I am facing is that my algorithm produces an infinite loop for values between 1 and 4 inclusively. For all values otherwise, the program runs as desired.
My approach was to take in an array of strings for the competitors' names. Then, I would iterate over each position and randomly select a competitor's name to take that spot. Because I am swapping the names, I have to check for duplicates in the array. I believe this is where my code is experiencing issues.
Here is the snippet that actually determines the tree
for(int i = 0; i < no_players;) {
int index = rand() % ((no_players - i) + i);
// randomly choose an element from the remainder
string temp = players[index];
bool unique = true;
// check all the elements before the current position
for(int j = 0; j < i; j++) {
// if the element is already there, it is not unique
if(players[j] == temp)
unique = false;
}
// only if the element is unique, perform the swap
if(unique) {
players[index] = players[i];
players[i] = temp;
i++;
}
}
Any help is much appreciated!