How to map char values to int using enum - c++

I am trying to map some chars in a string to some integer values using enum. Please tell where am I going wrong?
enum moves{U,R,D,L};
class Solution {
public:
bool judgeCircle(string moves) {
// moves is a string having values like ULLDDRR, ULRD, UULLDDRR
int X[] = {0,1,0,-1};
int Y[] = {1,0,-1,0};
// while iterating the string if I get a 'U' , I want to use it as an index
//with U representing the 0th index, R as index=1 and so on.. as specified
//in the enum
int x=0 , y=0;
enum moves ind;
for( int i = 0 ; i < moves.length() ; i++ ) {
ind = moves[i]; // but this line here gives error
x += X[ind];
y += Y[ind];
}
if(!x && !y)
return true;
else
return false;
}
};

I would drop the idea with an enum because I feel it has no use for the actual problem – to map characters to navigation moves. For this, I would use a std::map or a std::unordered_map. (Considering, that there are 4 entries only, the performance difference is probably hard to measure.)
While I was preparing a sample code, πάντα ῥεῖ gave a similar hint. Though, I would even recommend to bundle x and y of moves together:
#include <map>
#include <iomanip>
#include <iostream>
// bundle x and y for a move (which needs both of them)
struct Move {
int dx, dy;
};
// a type to map chars to moves
using MoveMap = std::map<char, Move>;
// a pre-defined move map
static const MoveMap mapMoves = {
{ 'U', { 0, 1 } },
{ 'R', { 1, 0 } },
{ 'D', { 0, -1 } },
{ 'L', { -1, 0 } }
};
/* a function to use move map
*
* id ... one of U R D L
* x, y ... coordinates (update)
* return: true if successful, (false e.g. for wrong id)
*/
bool move(char id, int &x, int &y)
{
const MoveMap::const_iterator iter = mapMoves.find(id);
return iter != mapMoves.end()
? x += iter->second.dx, y += iter->second.dy, true
: false;
}
// check it out:
int main()
{
int x = 0, y = 0;
const char test[] = "ULLDDRR, ULRD, UULLDDRR";
for (char id : test) {
std::cout << "(" << x << ", " << y << "): "
<< "Move '" << id << "' -> ";
if (move(id, x, y)) {
std::cout << "(" << x << ", " << y << ")\n";
} else std::cout << "failed\n";
}
return 0;
}
Output:
(0, 0): Move 'U' -> (0, 1)
(0, 1): Move 'L' -> (-1, 1)
(-1, 1): Move 'L' -> (-2, 1)
(-2, 1): Move 'D' -> (-2, 0)
(-2, 0): Move 'D' -> (-2, -1)
(-2, -1): Move 'R' -> (-1, -1)
(-1, -1): Move 'R' -> (0, -1)
(0, -1): Move ',' -> failed
(0, -1): Move ' ' -> failed
(0, -1): Move 'U' -> (0, 0)
(0, 0): Move 'L' -> (-1, 0)
(-1, 0): Move 'R' -> (0, 0)
(0, 0): Move 'D' -> (0, -1)
(0, -1): Move ',' -> failed
(0, -1): Move ' ' -> failed
(0, -1): Move 'U' -> (0, 0)
(0, 0): Move 'U' -> (0, 1)
(0, 1): Move 'L' -> (-1, 1)
(-1, 1): Move 'L' -> (-2, 1)
(-2, 1): Move 'D' -> (-2, 0)
(-2, 0): Move 'D' -> (-2, -1)
(-2, -1): Move 'R' -> (-1, -1)
(-1, -1): Move 'R' -> (0, -1)
(0, -1): Move '' -> failed
Live Demo on coliru

Related

How do I make it go in diagonal directions?

I have code that I already have four basic directions (Up, Down, Left, Right). However, I want to have them go in diagonal directions as well, so it will add up to eight directions. How would I do that? What I see from it, I basically have to have two directions change at the same time, but I don't know how to do that.
Code:
// problem with backtracking using stack
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;
#define N 4
#define M 5
class node {
public:
int x, y;
int dir;
node(int i, int j)
{
x = i;
y = j;
// Initially direction
// set to 0
dir = 0;
}
};
// maze of n*m matrix
int n = N, m = M;
// Coordinates of food
int fx, fy;
bool visited[N][M];
bool isReachable(int maze[N][M])
{
// Initially starting at (0, 0).
int i = 0, j = 0;
cout << '[' << i << ':' << j << ']';
stack<node> s;
node temp(i, j);
s.push(temp);
while (!s.empty()) {
// Pop the top node and move to the
// left, right, top, down or retract
// back according the value of node's
// dir variable.
temp = s.top();
int d = temp.dir;
i = temp.x, j = temp.y;
// Increment the direction and
// push the node in the stack again.
temp.dir++;
s.pop();
s.push(temp);
// If we reach the Food coordinates
// return true
if (i == fx and j == fy) {
return true;
}
// Checking the Up direction.
if (d == 0) {
if (i - 1 >= 0 and maze[i - 1][j] == 1 and
!visited[i - 1][j]) {
cout <<'['<< i - 1 << ':'<<j << ']' ;
node temp1(i - 1, j);
visited[i - 1][j] = true;
s.push(temp1);
}
}
// Checking the left direction
else if (d == 1) {
if (j - 1 >= 0 and maze[i][j - 1] == 1 and
!visited[i][j - 1]) {
cout << '[' << i << ':' << j-1 << ']' ;
node temp1(i, j - 1);
visited[i][j - 1] = true;
s.push(temp1);
}
}
// Checking the down direction
else if (d == 2) {
if (i + 1 < n and maze[i + 1][j] == 1 and
!visited[i + 1][j]) {
cout << '[' << i + 1 << ':' << j << ']' ;
node temp1(i + 1, j);
visited[i + 1][j] = true;
s.push(temp1);
}
}
// Checking the right direction
else if (d == 3) {
if (j + 1 < m and maze[i][j + 1] == 1 and
!visited[i][j + 1]) {
cout << '[' << i << ':' << j + 1<< ']' ;
node temp1(i, j + 1);
visited[i][j + 1] = true;
s.push(temp1);
}
}
// If none of the direction can take
// the rat to the Food, retract back
// to the path where the rat came from.
else {
visited[temp.x][temp.y] = false;
s.pop();
}
//system("pause");
}
// If the stack is empty and
// no path is found return false.
return false;
}
// Driver code
int main()
{
// Initially setting the visited
// array to true (unvisited)
memset(visited, false, sizeof(visited));
// Maze matrix
int maze[N][M] = {
{ 1, 0, 1, 1, 0 },
{ 1, 1, 1, 0, 1 },
{ 0, 1, 0, 1, 1 },
{ 1, 1, 1, 1, 1 }
};
// Food coordinates
fx = 2;
fy = 3;
if (isReachable(maze)) {
cout << "Path Found!" << '\n';
}
else
cout << "No Path Found!" << '\n';
return 0;
}```
By combining the conditions you already have... You have the following for checking the second dimension:
if (j + 1 < m and maze[i][j + 1] == 1 and !visited[i][j + 1])
If you want to increment both at once you would do something like:
if (i + 1 < n and j + 1 < m and maze[i + 1][j + 1] == 1 and !visited[i + 1][j + 1])
Since you have 4 diagonals, you would do similar checkings for the other 3 diagonals. Be careful with copy and paste not to forget to increment/decrement both i and j.
Let's assume a board, with row 0 and column 0 in the upper left corner.
Also, assume the present position is at <row, column>.
There are 8 locations relative to the present position (unless you are near the edge of the board).
+---------------------+---------------------+--------------------+
| row - 1, column - 1 | row - 1, column + 0 | row - 1, column + 1|
+---------------------+---------------------+--------------------+
| row + 0, column - 1 | row, column | row + 0, column + 1|
+---------------------+---------------------+--------------------+
| row + 1, column - 1 | row + 1, column + 0 | row + 1, column + 1|
+---------------------+---------------------+--------------------+
Before making a move, check the validity of the next move.
The next move would be based on the above table.

How to check all neighbors of a character in a string vector

Game of conway. Trying to access all neighbors of a each "cell" that i read in from a file.
If a cell is alive, it stays alive for the next generation if it has exactly two or three neighbors.
If a cell is dead, then it becomes alive for the next generation if it has exactly three neighbors.
E has exactly 8 neighbors in both situations.
Im having issues with the top line of the next generation:
......... F......DE
...ABC... I......GH
...DEF... .........
...GHI... .........
......... C......AB
file is read into currentgen, a string vector
nextgen is a copy of currentgen, that I change as needed
//find neighbors
for (size_t i=0; i < currentgen.size(); i++){
for(size_t j = 0; j < currentgen[0].length(); j++){
//neighbor count
int neighborcount = 0;
//south neighbor
if(currentgen[(i+1) % currentgen.size()][j] == 'O'){
neighborcount++;
}
//north
if(currentgen[(i-1) % currentgen.size()][j] == 'O'){
neighborcount++;
}
//left
if(currentgen[i][(j-1) % currentgen[i].length()] == 'O'){
neighborcount++;
}
//right
if(currentgen[i][(j+1) % currentgen[i].length()] == 'O'){
neighborcount++;
}
//south right
if(currentgen[(i+1) % currentgen.size()]
[(j+1) % currentgen[i].length()] == 'O'){
neighborcount++;
}
//south left
if(currentgen[(i+1) % currentgen.size()]
[(j-1) % currentgen[i].length()] == 'O'){
neighborcount++;
}
//north right
if(currentgen[(i-1) % currentgen.size()]
[(j+1) % currentgen[i].length()] == 'O'){
neighborcount++;
}
//north left
if(currentgen[(i-1) % currentgen.size()]
[(j-1) % currentgen[i].length()] == 'O'){
neighborcount++;
}
//if cell is alive
if(currentgen[i][j] == 'O'){
nextgen[i][j] = '.';
if(neighborcount == 2){
nextgen[i][j]= 'O';
}
if(neighborcount == 3){
nextgen[i][j]= 'O';
}
}
//if cell is dead
if(currentgen[i][j] == '.'){
if(neighborcount == 3){
nextgen[i][j]= 'O';
}
}
The issue with your code is that you're relying on % having the usual meaning of remainder. However, in c++, doing % on negative values will give you a remainder towards 0.
So the following expression is:
-1 % 5 // -1 not 4
To do the remainder correctly, you can add the value you're using as the modulus, and then you're guaranteed to have a positive number, and the calculation will work:
(-1 + 5) % 5 // 4 yay!!
Also, all those if conditions to check the neighbors is very verbose. You could simplify that to:
for (size_t i=0; i < currentgen.size(); i++) {
for(size_t j = 0; j < currentgen[0].length(); j++) {
//neighbor count
int neighborcount = 0;
for (int i_offset : {-1, 0, 1})
for (int j_offset : {-1, 0, 1})
if (i && j && currentgen[(i + i_offset + currentgen.size())
% currentgen.size()]
[(j + j_offset + currentgen[i].size())
% currentgen[i].size()] == 'O')
neighborcount++;
//if cell is alive
// ... etc
Here is a small piece of advice on how to avoid hard-coding the coordinates (south, north, left, right, etc.). You can use 2 arrays, namely dx and dy, which indicates the delta of x and y coordinates.
For example, start with a north neighbour and go clockwise (see the picture attached):
dx and dy description
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {-1, -1, 0, 1, 1, 1, 0, -1};
Now, in order to cycle through the neighbours of a cell (x, y), just add the corresponding dx and dy entries.
As pointed out by #cigien, you should not compute a remainder operator for negative values. The easiest thing to do is to add n and take modulo n, where n is a size of the field. It will save you from having negative value before modulo operation while preserving the same result, since n % n = 0.
Here is how you can cycle through the neighbours of (x, y):
int x;
int y;
// fill x and y
for(int d = 0; d < 8; ++d)
{
int nx = x + dx[d];
int ny = y + dy[d];
nx = (nx + n) % n;
ny = (ny + n) % n;
// horray!
}
Something like this:
#include <iostream>
#include <utility>
int main() {
char field[5][5]{
'.', '.', '.', '.', '.',
'.', '.', 'O', '.', '.',
'.', 'O', '.', 'O', '.',
'.', '.', 'O', '.', '.',
'.', '.', '.', '.', '.'
};
int posX = 2, posY = 2, count = 0;
for (int y = -1; y <= 1; ++y)
for (int x = -1; x <= 1; ++x) {
const char symbol = field[(posY + y + 5) % 5][(posX + x + 5) % 5];
count += static_cast<int>((y != 0 || x != 0) && symbol == 'O');
}
std::cout << count << '\n';
}
or
const char symbol = field[(posY + y + HEIGHT) & (HEIGHT - 1)][(posX + x + WIDTH) & (WIDTH - 1)];
if your field size is a power of 2 in x/y direction

Rat in maze problems, how to display coordinates where rat stepped in random generated matrix?

I started coding and searched a lot codes on internet but couldn't find the solution for my problem. I'm gonna paste there my current code. I already coded that if there is perfect path for rat or no (rat can only step on number one, "0" and "2" are walls.) But I cant display the coordinates of each "number one". For an example:
1,0,1,
1,2,2,
1,1,1,
Then the path is, (0,0) -> (1,0) -> (2,0) -> (1,2) -> (2,2)
if the matrix is
1,0,2,
0,2,1,
1,0,1,
Then no path for the rat.
Please edit my code and paste it there please or if you have already solved program for my problem please share it with me... I'm really new in c++.
// CPP program to solve Rat in a maze
// problem with backtracking using stack
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;
#define N 4
#define M 5
void mtxkeres(int (&mat)[N][M]);
class node {
public:
int x, y;
int dir;
node(int i, int j)
{
x = i;
y = j;
// Initially direction
// set to 0
dir = 0;
}
};
// maze of n*m matrix
int n = N, m = M;
// Coordinates of food
int fx, fy;
bool visited[N][M];
bool isReachable(int maze[N][M])
{
// Initially starting at (0, 0).
int i = 0, j = 0;
stack<node> s;
node temp(i, j);
s.push(temp);
while (!s.empty()) {
// Pop the top node and move to the
// left, right, top, down or retract
// back according the value of node's
// dir variable.
temp = s.top();
int d = temp.dir;
i = temp.x, j = temp.y;
// Increment the direction and
// push the node in the stack again.
temp.dir++;
s.pop();
s.push(temp);
// If we reach the Food coordinates
// return true
if (i == fx and j == fy) {
return true;
}
// Checking the Up direction.
if (d == 0) {
if (i - 1 >= 0 and maze[i - 1][j] and
visited[i - 1][j]) {
node temp1(i - 1, j);
visited[i - 1][j] = false;
s.push(temp1);
}
}
// Checking the left direction
else if (d == 1) {
if (j - 1 >= 0 and maze[i][j - 1] and
visited[i][j - 1]) {
node temp1(i, j - 1);
visited[i][j - 1] = false;
s.push(temp1);
}
}
// Checking the down direction
else if (d == 2) {
if (i + 1 < n and maze[i + 1][j] and
visited[i + 1][j]) {
node temp1(i + 1, j);
visited[i + 1][j] = false;
s.push(temp1);
}
}
// Checking the right direction
else if (d == 3) {
if (j + 1 < m and maze[i][j + 1] and
visited[i][j + 1]) {
node temp1(i, j + 1);
visited[i][j + 1] = false;
s.push(temp1);
}
}
// If none of the direction can take
// the rat to the Food, retract back
// to the path where the rat came from.
else {
visited[temp.x][temp.y] = true;
s.pop();
}
}
// If the stack is empty and
// no path is found return false.
return false;
}
// Driver code
int main()
{
// Initially setting the visited
// array to true (unvisited)
memset(visited, true, sizeof(visited));
// Maze matrix
int maze[N][M] = {
{ 1, 0, 1, 1, 0 },
{ 1, 1, 1, 0, 1 },
{ 0, 1, 0, 1, 1 },
{ 1, 1, 1, 1, 1 }
};
// Food coordinates
fx = 2;
fy = 3;
if (isReachable(maze)) {
cout << "Path Found!" << '\n';
}
else
cout << "No Path Found!" << '\n';
return 0;
}

Stuck in a maze loop

The problem
I'm new to this sort of programming, and my C++ maze solver is stuck in a loop.
The maze is a simple char 2-D matrix with an asterisk (*) for a valid path square, and a slash (/) for a wall square.
Why doesn't the program stop when it finds a '/'?
# include < iostream >
using namespace std;
char lab[6][6] =
{ { '/','/','/','/','/' },
{ '/','*','/','/','/' },
{ '/','*','*','*','/' },
{ '/','/','*','/','/' },
{ '/','/','*','/','/' },
{ '/','/','*','*','*' } };
int x, y;
void run(char lab[][6], int, int);
bool movU() // Move Up
{
if (lab[x][y - 1] == '*')
return true;
else
return false;
}
bool movR() // Move right
{
if (lab[x + 1][y] == '*')
return true;
else
return false;
}
bool movD() // Move Down
{
if (lab[x][y + 1] == '*')
return true;
else
return false;
}
bool movL() // Move Left
{
if (lab[x - 1][y] == '*')
return true;
else
return false;
}
void run(char lab[][6], int x, int y)
{
if (movU() == true) // I'm getting stuck right here
run(lab, x, y - 1); // Getting negative numbers here
else if (movR() == true)
run(lab, x + 1, y);
else if (movD() == true)
run(lab, x, y + 1);
else if (movL() == true)
run(lab, x - 1, y);
else
cout << "Error" << endl;
}
int main()
{
x = 1, y = 2; // Start position
run(lab, x, y);
return 0;
}
Besides the global scoping problem with x and y, you haven't done anything to keep the subscripts from running over the edge of the maze into random memory locations. As a result, y continues to decrement, and you back up through memory looking for an asterisk. Since you also recur, you continue this until you blow all your stack space.
Also, you don't seem to be comfortable with boolean values yet: you do a lot of extra work to deal with constants true and false, rather than simply using the value of a boolean expression.
I've fixed these items in your code:
# include <iostream>
using namespace std;
char lab[6][6] =
{
{ '/','/','/','/','/' },
{ '/','*','/','/','/' },
{ '/','*','*','*','/' },
{ '/','/','*','/','/' },
{ '/','/','*','/','/' },
{ '/','/','*','*','*' }
};
void run(char lab[][6], int, int);
bool movU(int x, int y) // Move Up
{
return x >= 0 && y >= 1 &&
x < 6 && y < 6 &&
lab[x][y - 1] == '*';
}
bool movR(int x, int y) // Move right
{
return x >= 0 && y >= 0 &&
x < 5 && y < 6 &&
lab[x+1][y] == '*';
}
bool movD(int x, int y) // Move Down
{
return x >= 0 && y >= 0 &&
x < 6 && y < 5 &&
lab[x][y + 1] == '*';
}
bool movL(int x, int y) // Move Left
{
return x >= 1 && y >= 0 &&
x < 6 && y < 6 &&
lab[x-1][y] == '*';
}
void run(char lab[][6], int x, int y)
{
cout << "ENTER run; x = " << x << "\ty = " << y << endl;
if (movU(x, y)) // I'm getting stuck right here
run(lab, x, y - 1); // Getting negative numbers here
else if (movR(x, y))
run(lab, x + 1, y);
else if (movD(x, y))
run(lab, x, y + 1);
else if (movL(x, y))
run(lab, x - 1, y);
else
cout << "Error" << endl;
}
int main()
{
// x = 1, y = 2; // Start position
run(lab, 1, 2);
return 0;
}
This stays within bounds ... and loops until it runs out of stack space. You need to add code to avoid rechecking ground you've already visited. For instance, you can mark the location with another character, such as an underscore.
You also need to recognize when you're done. What marks the maze exit? You'll need a check in your run routine for that.

How to initialize static member array with a result of a function?

I'm translating such fragment of this Python file to C++:
SIDE = 3
LINES = []
for y in range(SIDE):
row = tuple((x, y) for x in range(SIDE))
LINES.append(row)
for x in range(SIDE):
col = tuple((x, y) for y in range(SIDE))
LINES.append(col)
LINES.append(tuple((x, x) for x in range(SIDE)))
LINES.append(tuple((SIDE - x - 1, x) for x in range(SIDE)))
LINES holds (x, y) coordinates of possible lines in Tic Tac Toe game. So for SIDE = 3 it holds:
[((0, 0), (1, 0), (2, 0)),
((0, 1), (1, 1), (2, 1)),
((0, 2), (1, 2), (2, 2)),
((0, 0), (0, 1), (0, 2)),
((1, 0), (1, 1), (1, 2)),
((2, 0), (2, 1), (2, 2)),
((0, 0), (1, 1), (2, 2)),
((2, 0), (1, 1), (0, 2))]
SIDE value can change.
What I've tried
Performance is crucial (that's why I reached for C++), so I would like to calculate LINES only once. Thus, I've chosen to implement LINES as a static member of the class TicTacToeState.
I started with such code:
static char init_lines() {
return 'a';
}
class TicTacToeState {
static char LINES;
};
char TicTacToeState::LINES = init_lines();
It works. How to change LINES to an array? Maybe vector will be better? With pairs?
Maybe static member is not the best choice, maybe there is an easier way?
How would you translate it to C++?
We know the size of LINES, it's always 2 * SIDE + 2.
Special requirement
All C++ code must be in one .cpp file, no headers. Why? Because this is fragment of a library for bot competitions and it's typical that you can submit only one file.
In C++ you can initialize static array members using group initialization
static int a[10] = {5}; //this will initialize first position item with 5 and rest with 0s
static char b[2] = {'b', 'b'};
static int c[2][2] = { {1,1}, {1,2} };
int main()
{
cout<< a[0] << endl; //output: 5
cout<< a[1] << endl; //output: 0
cout<< b[0] << endl; //output: b
cout<< c[0][1] << endl; //output: 1
}
Although the fact is you need to know size of the array not like in Python's list that are dynamically
If you need to insert to the table values calculated dynamically the best way to do this is to create factory method
static int** fact(int width, int height)
{
int** a;
a = new int*[width]; //we can do it when it is DYNAMIC array!
a[0] = new int[height];
a[1] = new int[height];
for(int i = 0; i < width; i++)
for(int k = 0; k < height; k++)
a[i][k] = i*k;
return a;
}
static int** c = fact(2, 2); //you can call it with your SIDE var
int main()
{
cout<< c[1][1] << endl; //output: 1
}
Of course you can process it in loops
The same approach will be proper when you will decide to use std Vector class which is equvalent of Python's dynamic list
I suppose you could do this using a lambda function like this:
#include <vector>
#include <iostream>
const auto SIDE = 3U;
struct coord
{
unsigned x;
unsigned y;
coord(unsigned x, unsigned y): x(x), y(y) {}
};
static const auto lines = [] // lambda function
{
// returned data structure
std::vector<std::vector<coord>> lines;
for(auto y = 0U; y < SIDE; ++y)
{
lines.emplace_back(); // add a new line to back()
for(auto x = 0U; x < SIDE; ++x)
lines.back().emplace_back(x, y); // add a new coord to that line
}
for(auto x = 0U; x < SIDE; ++x)
{
lines.emplace_back();
for(auto y = 0U; y < SIDE; ++y)
lines.back().emplace_back(x, y);
}
lines.emplace_back();
for(auto i = 0U; i < SIDE; ++i)
lines.back().emplace_back(i, i);
lines.emplace_back();
for(auto i = 0U; i < SIDE; ++i)
lines.back().emplace_back(SIDE - i - 1, i);
return lines;
}(); // NOTE: () is important to run the lambda function
int main()
{
for(auto const& line: lines)
{
std::cout << "(";
for(auto const& coord: line)
std::cout << "(" << coord.x << ", " << coord.y << ")";
std::cout << ")\n";
}
}
Output:
((0, 0)(1, 0)(2, 0))
((0, 1)(1, 1)(2, 1))
((0, 2)(1, 2)(2, 2))
((0, 0)(0, 1)(0, 2))
((1, 0)(1, 1)(1, 2))
((2, 0)(2, 1)(2, 2))
((0, 0)(1, 1)(2, 2))
((2, 0)(1, 1)(0, 2))