C++ Can someone explain what these for loops are saying? - c++

So this code is the base outline for a boggle game from online that I copied over.
SOURCE: http://www.codingfriends.com/index.php/2010/06/10/boggle/
bool findUsersWord(string findThis, Grid<char> &theBoard, Vector<cell> &theRoute, string alreadyFound, int placeY, int placeX)
{
// need to find the findThis base case
if (findThis == alreadyFound)
return true;
// need to find the first letter within the board and then progress around that.
if (alreadyFound.empty())
{
for (int rows = 0; rows < theBoard.numRows(); rows++)
for (int cols = 0; cols < theBoard.numCols(); cols++)
// find the each character within the
if (theBoard[rows][cols] == findThis[0])
{
alreadyFound = findThis[0];
cell newR;
newR.row = rows;
newR.col = cols;
theRoute.add(newR);
if (findUsersWord(findThis, theBoard, theRoute, alreadyFound, rows, cols))
return true;
else
// clear out the found Board
theRoute.clear();
}
}
else
{
// try and find the next letters within the area around the base letter
// spin around the letter 3 * 3 grid
for (int y= (placeY > 0 ? placeY-1: placeY); y <=(placeY == (theBoard.numRows()-1) ? placeY : placeY+1);y++)
for (int x=(placeX > 0 ? placeX-1: placeX); x<=(placeX == (theBoard.numCols()-1) ? placeX : placeX+1); x++)
if ((theBoard[y][x] == findThis[alreadyFound.length()]) && (!(y==placeY && x ==placeX)))
// already used letter
if (!placeAlreadyUsed(y,x,theRoute))
{
alreadyFound += findThis[alreadyFound.length()];
cell newR;
newR.row = y;
newR.col = x;
theRoute.add(newR);
if (findUsersWord(findThis, theBoard,theRoute, alreadyFound, y, x))
return true;
else
{
if (alreadyFound.length() > 1)
alreadyFound = alreadyFound.substr(0, alreadyFound.length()-1);
theRoute.removeAt(theRoute.size()-1);
}
}
return false;
}
return false;
}
The code below is the code in question which is part of the code above.
for (int y= (placeY > 0 ? placeY-1: placeY); y <=(placeY == (theBoard.numRows()-1) ? placeY : placeY+1);y++)
for (int x=(placeX > 0 ? placeX-1: placeX); x<=(placeX == (theBoard.numCols()-1) ? placeX : placeX+1)
I am wondering if someone could turn this code into more simple code that doesn't involve the using of ? and that. I do know the simple parts of it such as the "?" means return and ":" means next line, but I am lost in the fact that it is being used in a for loop and the fact that it would just look like
if(placeY > 0)
return playceY-1
placeY;
Where have I gone wrong?

The ? : block is just a strange looking if statement. It's an inline if, if you will.
Here's the format
argument ? result evaluated to if true : result evaluated to if false
Here's an example
1<2 ? "Hurray" : "boo"
Will evaluate to "Hurray" because 1<2 is true. However, if we switch it to 1>2 it will evaluate to "boo".

I do know the simple parts of it such as the "?" means return and ":" means next line
Um, no. That's not what it means at all. ?: is one operator with three operand expressions, one of which appears between the ? and the :.
placeY > 0 ? placeY-1 : placeY
is an expression that means: "If placeY > 0 then evaluate placeY-1; otherwise evaluate placeY".
The idea of the code is that we want, for some reason, to iterate over all positions of the board that are next to (placeX,placeY). Those positions form a rectangle, and the ?: operators are used to compute the left, right, top and bottom limits of that rectangle. For example the expression quoted above is for the top coordinate. It is usually placeY-1, except that if placeY is already 0, there is no row on the board above it, and in that case placeY itself is the top row.

Related

g++ error: stray '\177' in program

I was trying to code for following program
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.
Example 1:
Given intervals [1,3],[6,9] insert and merge [2,5] would result in [1,5],[6,9].
Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] would result in [1,2],[3,10],[12,16].
This is the relevant part of my program
here. I want to erase the few positions from the vector
then I am getting the following error
error: stray '\177' in program
intervals.erase(intervals.begin()+(p+1),intervals.begin()+(q+1));
vector<Interval> Solution::insert(vector<Interval> &intervals, Interval newInterval) {
int n = intervals.size();
int p=-1,q=-1,a,b;
for(int i=0;i<n;++i){
if(intervals[i].start <= newInterval.start <= intervals[i+1].end)
p = i;
else if(intervals[i].end < newInterval.start < intervals[i+1].start)
a = i;
if(intervals[i].start <= newInterval.end <= intervals[i+1].end)
q = i;
else if(intervals[i].end < newInterval.end < intervals[i+1].start)
b = i;
}
int x,z;
if(p != -1 && q != -1)
x = q-p;
if(x > 0){
z=intervals[q].end;
intervals.erase(intervals.begin()+(p+1),intervals.begin()+(q+1));
intervals[p].end = z;
}
return vector
}
Did you copy that code from a website?
I managed to reproduce your result with this snippet:
const char* msg = "You can't copy this";
When copied and put on coliru here you'll get the same error code.
What I used for the above snippet in HTML code was:
<code>const char* msg = </code><code>"You can't copy this";
</code>
Note the  character I put in there.
To fix that, you can use a decent editor like Notepad++ that will make the stray characters visible:

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.

Simple recursive function to determine if two elements are transitively true

newbie here. Even newer to recursion. I'm writing a function for my C++ program, and as you'll be able to tell, I'm a bit clueless when it comes to recursive algorithms. I'd appreciate it greatly if someone could fix my function so I can get it working and perhaps have a better idea how to handle recursion afterward.
My function takes a two-dimensional square array of booleans, and integer i, and an integer array_size as parameters. The function returns a boolean value.
The array is an adjacency matrix that I use to represent a set of conditionals. For example, if the value at [0][3] is true, then 0 -> 3 (if 0, then 3). If [3][7] is true, then 3 -> 7 (if 3, then 7). By the transitive property, 0 -> 7 (if 0, then 7).
The integer i is a particular element in the set of conditionals. The function will return true if this element is transitively connected to the last element in the array. The last element in the array is the integer (array_size - 1),
The integer array_size is the size of each dimension of the square array. If array_size is 20, then the array is 20x20.
The idea of this function is to determine if there is any logical "path" from the first integer element to the last integer element by the transitive property. When the path exists, the function returns true, otherwise, it returns false. The recursive call should allow it to traverse all possible paths, returning true once it finally reaches the last element and false if all paths fail.
For example, if i = 0 and array_size = 10, then the function will return whether or not 0 -> 9 is valid according to the conditionals provided by the matrix and the transitive property.
This is my code so far:
bool checkTransitivity(bool **relations, int i, int array_size){
bool isTransitive = false;
if (i == array_size - 1)
{
isTransitive = true;
}
else
{
for (int j = i; j < array_size; j++){
if (relations[i][j])
{
isTransitive = checkTransitivity(relations, j, array_size);
}
}
}
return isTransitive;
Currently, the function returns true for all input.
Any help at all is appreciated. Thanks in advance!
EDIT: This first part is unnecessary because of your if-else statement. Move on to END OF EDIT.
Let's start with what a base case in a recursive function is:
if (i == array_size - 1)
{
isTransitive = true;
}
Well you do have a base case, but nothing is being returned. You are just setting a flag to true. What you want to do is:
if (i == array_size - 1) {
return true;
}
Now the function will work its way up the recursive stack to return true. END OF EDIT.
But we still need to fix the recursive case:
else {
for (int j = i; j < array_size; j++) {
if (relations[i][j]) {
isTransitive = isTransitive || checkTransitivity(relations, j, array_size);
}
}
}
return isTransitive;
The || means binary OR. So you have the logic right. You want to check each possible path to see if it can get there, but by setting isTransitive to the result of each check, isTransitive is only going to be set to the last call. By doing isTransitive = isTransitive || recursive call, isTransitive will be true as long as one of the calls results in a true value.
The last thing I want to say is a caution: if relations[i][j] == true and relations[j][i] == true, your code will still be in an infinite loop. You must find a way to eliminate the potential backtracking. One way to do this is to create another array that stores which paths you have already checked so you do not infinitely loop.
More information can be found here: Depth First Search
I think all you need is a break condition to stop continuing the loop when you encounter a non-transitive item. See below (haven't tested)
bool checkTransitivity(bool **relations, int i, int array_size){
bool isTransitive = false;
if (i == array_size - 1)
{
isTransitive = true;
}
else
{
for (int j = i; j < array_size; j++){
isTransitive = relations[i][j] && checkTransitivity(relations, j, array_size);
if (!isTransitive)
break;
}
}
return isTransitive;
}

Recommended improved match-finding algorithm for Bejeweled game?

I'm trying to determine a sensible method of finding matches of 3, 4, or 5, for each rows and column. The player looks for areas (rows or columns) in the game board where the same "gem" will, after swapping two adjacent pieces (one swap each turn), repeat for 3-5 consecutive spots.
Here's an example scenario of a match-making move:
Board before player move (bolded is necessary swap):
A C B B C
D D B A D
D A A C C
A D B B A
D C D A A
Board after player move (bolded is resulting match):
A C B B C
D D B A D
D A A C C
D A B B A
D C D A A
In this example, there is a 4-match of "D" in the first column, after the first row. I'm trying to figure out how to find such matches after 1.) the board is created at the start of the game and the board randomizes a number of times to eliminate immediate matches, and 2.) after the player makes a move. If working correctly, the program will be able to detect a match after the correct swap is made by the program itself or the player.
Every algorithm I've attempted have caused the looping to go out of bounds and/or improperly find all resulting matches after a swap. By this, I mean that the program would sometimes try to search outside the array because I'm unsuccessfully telling the program how to "adjust" its array-searching based on where the current spot is. Even when it does not cause runtime errors, it still shows improper results. For instance, the player will see that the board has at least one complete match shown, which isn't good.
Here are explanations for two procedures I've attempted:
Following spaces. From the current spot, check ahead four spaces across in same row (or less if there's less than four spaces remaining in the row). First check for a match of five, including the current spot; if none, check for four (minus a spot); if none, check for three (minus a spot); if none, no match found. Repeat the same check for the below column.
Preceding spaces. From the current spot, check back four spaces across in same row (or less if there's less than four spaces in between the first spot in the row and the current spot). First check for a match of five, including the current spot; if none, check for four (minus a spot); if none, check for three (minus a spot); if none, no match found. Repeat the same check for the above column.
Here's the primary function where such working algorithm is needed. The use of my Gem class here (which is currectly broken) may not be important to the request, so I won't add it unless it's helpful.
bool Board::findMatches(bool scoringMove) // false if board is being setup before game
{
bool matchesFound = false;
// loops through entire board, where "size" is the width, not the number of spots
for (int i = 0; i < size.getSize()*size.getSize(); i++)
{
// loops for each type of Gem, six total (_not identical to given example_)
for (int k = 0; k < gems.getNumGems(); k++)
{
Gem traverseGems(k); // next Gem (in sequence)
char nextGem = traverseGems.getGem(); // next Gem set to a char
// ROWS check
// default match search for 3-match
if ((i < (size.getSize()*size.getSize())-4)
&& (board[i]->getGem() == nextGem)
&& (board[i+1]->getGem() == nextGem)
&& (board[i+2]->getGem() == nextGem))
{
// if the player is making a move
if (!scoringMove)
return true;
matchesFound = true;
// just adds points to score; irrelevant to algorithm
scoreMatches(3, 'R', i, 3);
// no 4-match, but a 3-match
if (board[i+3]->getGem() != nextGem)
scoreMatches(3, 'R', i, 3);
else
scoreMatches(4, 'R', i, 4);
// 5-match found
if (board[i+3]->getGem() == nextGem && board[i+4]->getGem() == nextGem)
scoreMatches(5, 'R', i, 5);
}
// COLUMNS check (comments for rows check apply here as well)
if ((i <= (size.getSize()-1))
&& (board[i]->getGem() == nextGem)
&& (board[i+size.getSize()]->getGem() == nextGem)
&& (board[i+(size.getSize()*2)]->getGem() == nextGem))
{
if (!scoringMove)
return true;
matchesFound = true;
scoreMatches(3, 'C', i, 3);
if (board[i+(size*3)]->getGem() != nextGem)
scoreMatches(3, 'C', i, 3);
else
scoreMatches(4, 'C', i, 4);
if (board[i+(size*3)]->getGem() == nextGem && board[i+(size*4)]->getGem() == nextGem)
scoreMatches(5, 'C', i, 5);
}
}
}
return matchesFound;
}
Board.h
#ifndef BOARD_H
#define BOARD_H
#include "Size.h"
#include "Score.h"
#include "Move.h"
#include "Gem.h"
#include <iostream>
#include <iomanip>
#include <ctime>
class Board
{
private:
Size size;
Score score;
Gem **board;
bool moreSwaps;
void swapGems(Move);
void swapGems(int, int);
void setNewRandGem(int);
void findMoreSwaps();
void scoreMatches(int, char, int, int);
bool findMatches(bool);
public:
Board();
Board(Size, Score&);
~Board();
void displayBoard() const;
bool isMatch(Move);
bool moreMovesFound() const;
};
#endif
Board Constructor
Board::Board(Size size, Score &score)
{
srand((unsigned int)time(NULL)); // I can always move this to main()
this->size = size;
this->score = score;
board = new Gem *[size.getSize()*size.getSize()];
for (int i = 0; i < size.getSize()*size.getSize(); i++)
board[i] = new Gem;
//This is the "pre-game" block.
//As long as the program finds a new match after performing its
//own swaps, it'll randomize the entire board and start over again.
//This is incredibly unefficient, but I will try to fix it later.
do
{
for (int i = 0; i < size.getSize()*size.getSize(); i++)
setNewRandGem(i);
} while (findMatches(false));
}
Having reread the updated question, I think your goal is to test whether, for a given 5x5 board, there is any possible swap of two adjacent symbols that will produce a board with 3 or more identical symbols in a row or column.
If the previous attempts produced out-of-bounds errors, that would imply a bug in the implementation, not a bug in the algorithm. So using a different algorithm would do nothing to solve that problem, you still need to implement proper array boundary checks. There is no way around that, but on the plus side it is not particularly hard. Simply check each index on whether it is smaller than zero or larger than the array dimension size, before accessing the array. If it is, trace back the steps your program used to get to that value, and find the bug that must be there.
Of course, if the program produces the wrong results in addition to out-of-bounds errors, then your algorithm might also be wrong.
Having said that, I am still not sure I understand the algorithms you describe, but they seem too complex for this problem. Unless you need to evaluate thousands of boards per second, a simple brute force algorithm will suffice. Just try out all possible swaps, and for each swap check if the board contains 3 or more identical symbols in a row or column.
Here is a description in pseudocode:
function is_there_a_valid_move(board)
// returns true if there is a valid bejewelled move
// test all horizontal swaps
for (x = 0; x++; x< board-width - 1):
for (y = 0; y++; y < board-height):
make a copy of the board: board2
swap board2[x,y] and board2[x+1,y]
check_matches(board2, 3)
if match found: return true
// test all vertical swaps
for (x = 0; x++; x< board-width):
for (y = 0; y++; y < board-height - 1):
make a copy of the board: board2
swap board2[x,y] and board2[x,y+1]
check_matches(board2, 3)
if match found: return true
return false
function check_matches(board, num_matches)
// returns true if there are num_matches or more of the same symbol in a row or column
// check rows
for (y = 0; y++; y < board-height):
consecutive_symbols = 0
for (x = 0; x++; x< board-width - 1):
if board[x,y] == board[x+1,y]: consecutive_symbols++
else: consecutive_symbols = 0
if consecutive_symbols >=num_matches: return true
// check columns
for (x = 0; x++; x< board-width):
consecutive_symbols = 0
for (y = 0; y++; y < board-height - 1):
if board[x,y] == board[x,y+1]: consecutive_symbols++
else: consecutive_symbols = 0
if consecutive_symbols >=num_matches: return true
return false
This is certainly not the fastest method, but for a 5x5 board everything else is overkill.

input string validation without external libraries for c++

I need to validate one input string from a user. Eventually it will need to break down into two coordinates. ie a4 c3. And once they are coordinates they need to be broken out into 4 separate ints. a=0 b=1, etc. They must also follow the following stipulations:
If an end-of-input signal is reached the program quits.
Otherwise, all non-alphanumeric characters are discarded from the input.
If what remains is the single letter 'Q'
Then the program quits.
If what remains consists of 4 characters, with one letter and one digit among the first two characters and one letter and one digit among the last two characters, and if each letter-digit pair is in the legal range for our grid
Then input is acceptable.
I have completely over-thought and ruined my function. Please let me know where I can make some corrections.
I am mainly having trouble going from one string, to four chars if and only if the data is valid. Everything else I can handle.
Here is what I have so far.
void Grid::playerMove()
{
string rawMove;
string pair1 = " ";
string pair2 = " ";
bool goodInput = false;
char maxChar = 'a';
char chary1, chary2;
int x11,x22,y11,y22;
for (int i =0; i<size; i++)
{
maxChar++;
}
while(!goodInput)
{
cout<<"What two dots would you like to connect? (Q to quit) ";
cin>>rawMove;
rawMove = reduceWords(rawMove);
if (rawMove == "Q")
{
cout<<"end game";
goodInput = false;
}
else if (rawMove.size() == 4)
{
for(int j=0;j<2;j++)
{
if (pair1[j] >='a' && pair1[j] <=maxChar)
{
chary1 = pair1[j];
}
else if(pair1[j] >=0 && pairl[j]<=size+1)
{
x1 = pair1[j];
}
}
for(int k=0;k<2;k++)
{
if (pair2[k] >='a' && pair2[k] <=maxChar)
{
chary2 = pair2[k];
}
else if(pair2[k] >=0 && pair2[k]<=size+1)
{
x2 = pair2[k];
}
}
}
if(char1 != NULL && char2 != NULL && x1 !=NULL && x2 != NULL)
{
for (int m = 0; m <= size m++)
{
if (char1 == m;)
{
x1 = m;
}
}
for (int n = 0; n <= size n++)
{
if (char2 == n)
{
x2 = n;
}
}
}
}
The end goal would be to have x1, x2, y1, and y2 with their respective values.
Keep in mind I am not allowed to have any external libraries.
It's not clear what exactly you want to achieve, but here are some pointers to get you started:
The while loop will never end because you're setting goodInput to false on quit which lets the loop continue.
The code probably does not even compile? You are missing a curly closing brace..
You are initializing pair1 and pair2 to empty strings but never change them again, so they will never contain any real information about your moves
maybe what you really want is to split up rawMove into the pair1 and pair2 substrings first?
Since this is a homework - and you're supposed to learn from those (right?) - I'm not going to give you the complete answer, but rather something like a recipe:
Use std::istream::getline(char*, std::streamsize s) to read a whole line from std::cin. Make sure you allocate a buffer large enough to hold the expected input (including the terminating null character) plus some more for invalid characters. After the call, check the failbit (input was too long) and the eofbit (hit the end-of-input) of the std::cin stream and handle those cases. Construct a std::string from the buffer if there was no error or EOF has not been reached.
Write a character-classification function (e.g. call it isAlNum(char c)) that returns true if the char argument is alpha-numeric, and false otherwise.
Combine std::string::erase(), std::remove_if(), std::not1(), std::ptr_fun() and your function isAlNum() to sanitise the input string.
Write a function that validates and parses the coordinates from the sanitised input string and call it with the sanitised input string.
Wrap the whole thing in an appropriate while() loop.
This should get you started in the right direction. Of course, if you're allowed to use C++11 features and you know how to write good regular expressions, by all means, use the <regex> header instead of doing the parsing manually.