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.
Related
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.
I am new to the game maker. I created a list and I want to compare all the data in the list with a specific value. I used the following code:
for(var i=0;i<ds_list_size(lst);i++;)
{
if ds_list_find_value(lst,i)>tmp
ds_list_replace(lst,i,ds_list_find_value(lst,i)-1);
}
and I face the following error:
Push :: Execution Error - Variable Get -1.lst(100001, -1)
at
gml_Object_object0_RightButtonPressed_1 (line 21) - for(var i=0;i
where is my problem?
Thanks all.
if your first for loop i = 0; and when the first entry in the list is smaller than tmp it tries to replace the first place in the list with a not existing one. so you could either check if its the first entry of the list with
if ( i == 0 ) { }
or your could start the for loop from the second entry with
for(var i=1;i<ds_list_size(lst);i++;)
I think the ; at the end of i++; is unnecessary, you only need to use ; in a for-loop as seperator.
GML gives more freedom to common C# rules though (like how there are no brackets needed around an if-condition), so perhaps that's allowed.
Another possibility might be that the index is out of range at ds_list_replace()
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".
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?
I'm writing a program that will balance Chemistry Equations; I thought it'd be a good challenge and help reinforce the information I've recently learned.
My program is set up to use getline(cin, std::string) to receive the equation. From there it separates the equation into two halves: a left side and right side by making a substring when it encounters a =.
I'm having issues which only concerns the left side of my string, which is called std::string leftSide. My program then goes into a for loop that iterates over the length of leftSide. The first condition checks to see if the character is uppercase, because chemical formulas are written with the element symbols and a symbol consists of either one upper case letter, or an upper case and one lower case letter. After it checks to see if the current character is uppercase, it checks to see if the next character is lower case; if it's lower case then I create a temporary string, combine leftSide[index] with leftSide[index+1] in the temp string then push the string to my vector.
My problem lies on the first iteration; I've been using CuFe3 = 8 (right side doesn't matter right now) to test it out. The only thing stored in std::string temp is C. I'm not sure why this happening; also, I'm still getting numbers in my final answer and I don't understand why. Some help fixing these two issues, along with an explanation, would be greatly appreciated.
[CODE]
int index = 0;
for (it = leftSide.begin(); it!=leftSide.end(); ++it, index++)
{
bool UPPER_LETTER = isupper(leftSide[index]);
bool NEXT_LOWER_LETTER = islower(leftSide[index+1]);
if (UPPER_LETTER)// if the character is an uppercase letter
{
if (NEXT_LOWER_LETTER)
{
string temp = leftSide.substr(index, (index+1));//add THIS capital and next lowercase
elementSymbol.push_back(temp); // add temp to vector
temp.clear(); //used to try and fix problem initially
}
else if (UPPER_LETTER && !NEXT_LOWER_LETTER) //used to try and prevent number from getting in
{
string temp = leftSide.substr(index, index);
elementSymbol.push_back(temp);
}
}
else if (isdigit(leftSide[index])) // if it's a number
num++;
}
[EDIT] When I entered in only ASDF, *** ***S ***DF ***F was the output.
string temp = leftSide.substr(index, (index+1));
substr takes the first index and then a length, rather than first and last indices. You want substr(index, 2). Since in your example index is 0 you're doing: substr(index, 1) which creates a string of length 1, which is "C".
string temp = leftSide.substr(index, index);
Since index is 0 this is substr(index, 0), which creates a string of length 0, that is, an empty string.
When you're processing parts of the string with a higher index, such as Fe in "CuFe3" the value you pass in as the length parameter is higher and so you're creating strings that are longer. F is at index 2 and you call substr(index, 3), which creates the string "Fe3".
Also the standard library usually uses half open ranges, so even if substr took two indices (which, again, it doesn't) you would do substr(index, index+2) to get a two character string.
bool NEXT_LOWER_LETTER = islower(leftSide[index+1]);
You might want to check that index+1 is a valid index. If you don't want to do that manually you might at least switch to using the bounds checked function at() instead of operator[].