loop until a certain condition is met - c++

From this site https://www.geeksforgeeks.org/lca-for-general-or-n-ary-trees-sparse-matrix-dp-approach-onlogn-ologn/
I have a problem with this while loop part:
// runs till path 1 & path 2 mathches
int i = 0;
while (path[1][i] == path[2][i])
i++;
I want to increment i until two array elements are equal and I expected this loop to be like:
// runs till path 1 & path 2 mathches
int i = 0;
while (path[1][i] != path[2][i])
i++;
because I want to increment "i" when values are not equal but it does not seem so. Why equality is checked instead of inequality? This while loop confuses my mind. (Note: I run the whole code and it is working.)

By the line which follows (in your reference) where the last matching is returned, I see it that the error is in the comment. It should say something like "runs as long as the paths match" not "till".

Related

-nan Error when trying to return the index of a class object

So in my intro to CS class, we're learning about classes and I'm having a lot of trouble right now.
This is project 2 part 2:
https://github.com/CSCI1300-StartingComputing/CSCI1300-Spring2022/blob/main/project/project2/project2pt2.md#question0
project 2 part 1 (part 2 builds on a lot of this stuff:https://github.com/CSCI1300-StartingComputing/CSCI1300-Spring2022/blob/main/project/project2/project2pt1.md#question4
I am specifically on number 6 for part 2.
I believe the problem lies in the below snippet of code:
while (k < numbMovies){temp = movies[k].getTitle(); //store movie title into temp arr
//convert temp to lowercase for case insensitivity
while (b < temp.length()){temp[b] = tolower(temp[b]);
b++;
}
//if the title we're searching is found in the movies array
if (temp == title)
{
movieIdx = k; //the kth movie will be our match, so save k as our index
numMatches++; //increment number of matches. if the title is found, this should be one at most
}
k++;
}
There is an issue somewhere with the line temp = movies[k].getTitle();, I think.
What this line is supposed to do is reference an array from the Movie class developed in part 1, store a title found at 'k' from the movies array into a string so that I can compare it to the string being passed into the function (this comparison is done in the line containing if(temp == title).
I then wish to save the value of k when temp == title as movieIdx, so that this can be used further in this function.
I think that the problem is with my referencing of the movies[] array, but I'm not sure what it might be.
Since there are a lot of things going on in this project, I'd be happy to send my files over to anyone who'd be willing to take a look.
Thanks in advance.
FURTHER CONTEXT:
I was attempting to test edge cases by returning 'movieIdx' immediately after setting movieIdx = k, just to see what was going wrong. Example of what I mean:
{
movieIdx = k; //the kth movie will be our match, so save k as our index
numMatches++; //increment number of matches. if the title is found, this should be one at most
return movieIdx;
}
-nan was returned consistently, although if I returned k outside of the first while loop (that contains the other while loops), I'd get the value that was expected (50, in this case, which equals numbMovies). If I returned movieIdx outside of the loop, I got 0.
This told me that there was some issue with the condition if(temp == title). I then did a test where I replaced 'temp' with a hardcoded value that I knew would be passed, "the prestige".
Doing this returned the expected value. I then knew that there must be some issue with 'temp' itself, and I have assumed that the issue therein would probably have to do with how I'm referencing the movies[] array.

Why is this code fragment returning unexpected results?

I am currently learning C++ at my school, and am making a word sleuth as part of a project that I have to submit. For this, I have already made the grid of alphabets and other necessary things (clues, rules, etc.). I am taking the input in the form of coordinates in an integer array whereby the user enters 4 values in the array, signifying the initial row and column number and the final row and column number, corresponding to which are the first and last alphabets of a particular word.
After doing this, I am now comparing the array input by the user with the array I have already defined that has the coordinates of that particular word. This is shown here :
cout<<"Enter the coordinates of starting and final characters : row1 col1 row2 col2 "<<endl;
for (z = 0; z < 4; z++) //first for loop
cin>>p[z]; //taking the input as an array 'p'
for (b = 0; b < 4; b++) //second for loop
{
if (p[b] == messi[b])
b+=0;
}
if (b == 4)
cout<<"Great!!!! You have answered the question correctly"<<"\n\n";
else
cout<<"You got this one wrong mate! Try again :)"<<"\n\n";
Here, messi[b] is the array which has the coordinates corresponding to the word 'MESSI' in the grid. Now, to my mind, the 'if' statement after the second for loop must contain the condition to check if b = 3. However, when I do that, the output always comes out to be what the 'else' statement says i.e. "You got this..." for every input. However, when I impose the condition to check if b = 4, the output comes out to be what the 'if' statement says i.e. "Great!!..." for every input.
What wrong am I doing? I hope I am clear enough in explaining the problem to you. I am using CodeBlocks 16.01.
It's a bit unclear what you are doing, as the program stands, b will always be equal to 4 after the second for-loop since the last time to condition was true, b < 4. So after the increment, it will be 4.
Inside the second for-loop you also have the NOP code b += 0; which does absolutely nothing to the code. What is the intention here?

Beginner difficulty with vectors and while-loops in C++

Update:
So it turns out there were two issues:
The first is that I checked the [k-1] index before I checked k == 0. This was a crash, although mostly fixable, and not the primary issue I posted about.
The primary issue is that the code seems to execute only after I press ctrl+z. Not sure why that would be.
Original:
So, learning from Stroustrup's text in C++ programming, I got to an example on vectors and tried implementing it myself. The gist is that the program user enters a bunch of words, and the program alphabetizes them, and then prints them without repeats. I managed to get working code using a for statement, but one of my initial attempts confuses me as to why this one doesn't work.
To be clear, I'm not asking to improve this code. I already have better, working code. I'm wondering here why the code below doesn't work.
The "error" I get is that the code compiles and runs fine, but when I input words, nothing happens and I'm prompted to input more.
I'm certain there's an obvious mistake, but I've been looking everywhere for the last 8 hours (no exaggeration) just devoted to finding the error on my own. But I can't.
int main() {
vector<string> warray; string wentry; int k = 0;
cout << "Enter words and I'll alphabetize and delete repeats:\n\n";
while (cin >> wentry) warray.push_back(wentry);
sort(warray.begin(), warray.end());
while (k < warray.size()) {
if (warray[k - 1] != warray[k] || k == 0) cout << warray[k] << "\n";
++k;
}
}
My reasoning for why this should work is this: I initialize my array of words, my word entry per input, and a variable to index word output.
Then I have a while statement so that every input is stacked at the end of the array.
Then I sort my array.
Then I use my index which starts at 0 to output the 0th item of the array.
Then so long as there are words in the array not yet reached by the index, the index will check that the word is not a repeat of the prior index position, and then print if not.
No matter what whappens, the index is incremented by one, and the check begins again.
Words are printed until the index runs through and checks all the words in the array.
Then we wait for new entries, although this gets kind of screwy with the above code, since the sorting is done before the checking. This is explicitly not my concern, however. I only intend for this to work once.
To end the cycle of input you need to insert EOF character which is ctrl+d. However, there are other problems in your code. You have k = 0 to start with so the moment you will try warray[k - 1] your code will crash.
At the point where you take
warray[k - 1]
for the first time, k is zero, so you want to get the warray value at index -1, which is not necessarily defined in memory (and even if, I wouldn't do this anyway). So as it compiles, I guess the address is defined in your case by accident.
I would try simply reversing the OR combination in your if-condition:
if (k == 0 || warray[k - 1] != warray[k])
thus for the first iteration (k == 0) it won't check the second condition because the first condition is then already fulfilled.
Does it work then?
You're stuck in the while loop because you don't have a way of breaking out of it. That being said, you can use Ctrl + d (or use Ctrl + z if executing on windows in the command prompt) to break out of the loop and continue executing the code.
As for while loop at the bottom which prints out the sorted vector of values, your program is going to crash as user902384 suggested because your program will first check for warray[k - 1].
Ideally, you want to change the last part of your program to:
while (k < warray.size())
{
if (k == 0 || warray[k - 1] != warray[k])
cout << warray[k] << "\n";
++k;
}
This way, the k == 0 check passes and your program will skip checking warray[k - 1] != warray[k] (which would equal warray[-1] != warray[0] when k=0).
You just needed to reverse:
if (warray[k - 1] != warray[k] || k == 0)
to
if (k == 0 || warray[k - 1] != warray[k] )
for terminating this condition if k = 0.
An alternative.
Although it can termed as a bit off topic, considering you want to work with std::vector<>, but std::set<> is an excellent container which satisfies your current two conditions:
Sort the strings in alphabetical order.
Delete all the repetitions.
Include <set> in your .cpp file, and create a set object, insert all the std::string and iterate through the set to get your ordered, duplicate-free strings!
The code:
int main() {
//Define a set container.
set<string> s;
//A temporary string variable.
string temp;
//Inserting strings into the set.
while (cin >> temp) s.insert(temp);
//Create a set<int> iterator.
set<string>::iterator it;
//Scanning the set
for(it = s.begin(); it != s.end(); ++it)
{
//To access the element pointed by the iterator,
//use *it.
cout<<*it<<endl;
}
return 0;
}
I just recommended this container, because you will study set in Stroustrup's text, and it is very easy and convenient instead of laboring over a vector.

for loop stops when if statement is satisfied

I am trying to count how many times the unique words in a LinkedList appear using this code:
for(int i2 = 0; i2 < a.size(); i2++)
{
word2 = a.get(i2);
for(int j2 = 0; j2 < a.size(); j2++)
{
if(word2 == a.get(j2))
{
counter++;
}
}
System.out.println(word2 + " : " + counter);
counter = 0;
}
But the counter prints out:
Alphabet : 1
Alright : 1
Apple : 1
Alphabet : 1
Alright : 1
Apple : 1
Alphabet : 1
Alright : 1
Apple : 1
There is obviously more than one of the words, but the counter never gets higher then one. I think that the inner for loop is stopping when the if statement is satisfied, but I don't want it to. Any suggestions?
You should use
word2.equals(a.get(j2))
Using "==" you compare the references to those String which are not equal.
And by the way you will print the counter multiple times for the same word if you have repetitions. Let's say you have the word Apple on 2 positions in your list. When you will reach these 2 positions the counter will go up to 2 and you will print (Apple: 2) 2 times
This seems like java to me. You can't compare string with (==) operator.
if(word2.equals(a.get(j2)))
Just a new addition!!!
As suggested by #user3412998 its better to use Sets so that you can avoid duplication.
Now if you need to use ArrayList only then you need to take one element and check if there are multiple copies of that element using loop.The condition can be checked by .equals method if you are using string or my contains method incase you are inserting objects(dont forget to override your equals method in the corresponding class). This is a very tedious process and I do not recommend it.
I believe that the easiest way will to not to add duplicate elements in your array list. to accomplish that look at the code below..
if(!a.contains(word)){
a.add(word);
}
Note word is a String object.
Here I am checking weather the string is already contained in the ArrayList, before insertion.
make a bit of modifications so that you can use it, for arrays, or for directly inputting data etc..
I hope this helps..

C++ - solve a sudoku game

I'm new to C++ and have to do a home assignment (sudoku). I'm stuck on a problem.
Problem is that to implement a search function which to solve a sudoku.
Instruction:
In order to find a solution recursive search is used as follows. Suppose that there is a
not yet assigned field with digits (d1....dn) (n > 1). Then we first try to
assign the field to d1, perform propagation, and then continue with search
recursively.
What can happen is that propagation results in failure (a field becomes
empty). In that case search fails and needs to try different digits for one of
the fields. As search is recursive, a next digit for the field considered last
is tried. If none of the digits lead to a solution, search fails again. This in
turn will lead to trying a different digit from the previous field, and so on.
Before a digit d is tried by assigning a field to
it, you have to create a new board being a copy of the current board (use
the copy constructor and allocate the board from the heap with new). Only
then perform the assignment on the copy. If the recursive call to search
returns unsuccessfully, a new board can be created for the next digit to be
tried.
I've tried:
// Search for a solution, returns NULL if no solution found
Board* Board::search(void) {
// create a copy of the cur. board
Board *copyBoard = new Board(*this);
Board b = *copyBoard;
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
// if the field has not been assigned, assign it with a digit
if(!b.fs[i][j].assigned()){
digit d = 1;
// try another digit if failed to assign (1 to 9)
while (d <=9 && b.assign(i, j, d) == false){
d++;
// if no digit matches, here is the problem, how to
// get back to the previous field and try another digit?
// and return null if there's no pervious field
if(d == 10){
...
return NULL;
}
}
}
}
return copyBoard;
}
Another problem is where to use the recursive call? Any tips? thx!
Complete instruction can been found here: http://www.kth.se/polopoly_fs/1.136980!/Menu/general/column-content/attachment/2-2.pdf
Code: http://www.kth.se/polopoly_fs/1.136981!/Menu/general/column-content/attachment/2-2.zip
There is no recursion in your code. You can't just visit each field once and try to assign a value to it. The problem is that you may be able to assign, say, 5 to field (3,4) and it may only be when you get to field (6,4) that it turns out there can't be a 5 at (3, 4). Eventually you need to back out of recursion until you come back to (3,4) and try another value there.
With recursion you might not use nested for loops to visit fields, but visit the next field with a recursive call. Either you manage to reach the last field, or you try all possibilities and then leave the function to get back to the previous field you visited.
Sidenote: definitely don't allocate dynamic memory for this task:
//Board *copyBoard = new Board(*this);
Board copyBoard(*this); //if you need a copy in the first place
Basically what you can try is something like this (pseudocode'ish)
bool searchSolution(Board board)
{
Square sq = getEmptySquare(board)
if(sq == null)
return true; // no more empty squares means we solved the puzzle
// otherwise brute force by trying all valid numbers
foreach (valid nr for sq)
{
board.doMove(nr)
// recurse
if(searchSolution(board))
return true
board.undoMove(nr) // backtrack if no solution found
}
// if we reach this point, no valid solution was found and the puzzle is unsolvable
return false;
}
The getEmptySquare(...) function could return a random empty square or the square with the least number of options left.
Using the latter will make the algorithm converge much faster.