I'm working on a project which takes a string input from the user of coordinates.
example of input:
"Polygons = [(1, 1), (4, 1), (4, 5), (3,5), (1, 5); (5,3), (3, 4), (6, 4), (6, 12), (3, 12)]"
One of the functions that I am making is checking the minimum/maximum X, which is clearly any number after a "(", however the problem that's bugging me is converting what's after the ( into a float to use it in calculations and number comparisons.
#include <iostream>
#include "string"
#include <stdlib.h>
#include <cstdlib>
using namespace std;
//Using a constant string for testing
string Polygon_Input = "Polygons = [(1, 1), (4, 1), (4, 5), (3,5), (1, 5); (5,3), (3, 4), (6, 4), (6, 12), (3, 12)]";
string Operation;
float Min_X = 9999;
int main()
{
getline(cin, Operation);
if (Operation == "Minimum_X")
{
for (int i; i <= Polygon_Input.length(); i++)
{
if (Polygon_Input[i] == '(')
{
float X = Polygon_Input[i + 1];
if (X < Min_X)
{
Min_X = X;
}
}
}
cout << Min_X;
}
That's not working, it always prints out 49 as Min_X
I also tried the same code with one modification, but still doesn't work.
if (Polygon_Input[i] == '(')
{
string X_As_String = Polygon_Input.substr(i + 1, i + 1);
float X = atof(X_As_String.c_str());
if (X < Min_X)
{
Min_X = X;
}
First of all, there are several problems in your code.
float Min_X = 9999;
The minimum value must be in the list. Initialize the first element as the minimum value and compare it with the rest.
if (X < Min_X)
The value X is int whereas Min_X is float. Don't compare int with float. Declare both as float and then cast if you would like an integer number.
for (int i=0; i <= Polygon_Input.length(); i++)
Pay attention to <=. It should be <.
Now the solution for your problem is
//#include <limits> // no need for this
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdlib>
using namespace std;
//Using a constant string for testing
string Polygon_Input = "Polygons = [(1, 1), (4, 1), (4, 5), (3,5), (1, 5); (5,3), (3, 4), (6, 4), (6, 12), (3, 12)]";
string Operation("Minimum_X");
//float Min_X = 9999; ?????? Why
float Min_X;
bool flag(true);
int main()
{
//getline(cin, Operation); // commented out for test
if (Operation == "Minimum_X")
{
for (int i=0; i < Polygon_Input.size(); i++)
{
if ( Polygon_Input[i] == '(' )
{
// extract X values (i.e. the first co-ordinate of a point )
std::string temp = Polygon_Input.substr(i+1, Polygon_Input.find_first_of(",",i)-i-1 );
// convert strig to float
float X = std::stof(temp);
// store first element and compare it with the rest
if(flag){
Min_X = X;
flag=false;
}
// int X = Polygon_Input[i + 1] - '0'; ????? What is this?
if (X < Min_X)
{
Min_X = X;
}
}
}
cout << Min_X << endl;
}
return 0;
}
The output is
1
which the minimum X value in the list. This code handles float values as well (i.e. (3.45, 4)). Try different values for checking.
Related
I'm testing some programms for my lectures. I'm creating classes and use a paramterlist to initalize a field but the second variable doesn't change.
#include <iostream>
using namespace std;
class Punkt {
int x;
int y;
public:
Punkt(int a = 0, int b = 0)
{
x = a;
y = b;
}
void printXY()
{
cout << "x= " << x << " y= " << y << endl;
}
};
int main() {
Punkt pFeld[] = { (1, 1), (2, 2), (3, 3) };
for (int i = 0; i < 3; i++)
pFeld[i].printXY();
cin.get();
};
No error messages. Expected result was that x and y change, while actual result is that only x changes and y stays 0.
This
(1, 1)
is an expression with the comma operator.
In fact this initialization
Punkt pFeld[] = { (1, 1), (2, 2), (3, 3) };
is equivalent to
Punkt pFeld[] = { 1, 2, 3 };
So the constructor with the second default argument equal to 0 is called three times.
Use instead
{ 1, 1 }
Here is your updated code
#include <iostream>
using namespace std;
class Punkt {
int x;
int y;
public:
Punkt(int a = 0, int b = 0)
{
x = a;
y = b;
}
void printXY()
{
cout << "x= " << x << " y= " << y << endl;
}
};
int main() {
Punkt pFeld[] = { {1, 1}, {2, 2}, {3, 3} };
for (int i = 0; i < 3; i++)
pFeld[i].printXY();
cin.get();
}
Its output is
x= 1 y= 1
x= 2 y= 2
x= 3 y= 3
Pay attention to that the semicolon after the function main is redundant.
Passing (1, 1) to the constructor of Punkt, the comma operator will return the 2nd operand as the result (the 1st operand is discarded), so you're only passing one int with value 1 to the constructor. That's why y is always initialized as 0.
What you want should be
Punkt pFeld[] = { {1, 1}, {2, 2}, {3, 3} }; // list initialization since C++11
or
Punkt pFeld[] = { Punkt(1, 1), Punkt(2, 2), Punkt(3, 3) };
Like the question says, I have a 10X11 array and I need each tile to be a 3x3 instead of 1x1 and Im not sure how to do that. I also am having trouble pulling the correct x value for my finish point. Any help would be much appreciated. here is my code so far:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
int main()
{
//establishing constant variables;
const char Walls = '#';
const char Mazes = '-';
const int row = 10;
const int col = 11;
//defining strings to pull from text file
std::string arraysize_sx;
std::string arraysize_sy;
std::string start_sx;
std::string start_sy;
std::string finish_sx;
std::string finish_sy;
std::string walls_s;
std::ifstream openfile ("input.txt");
std::ofstream outputfile ("output.txt",std::ios::app);
//gets points from text file, using , and . as delimiters
std::getline(openfile, arraysize_sx , ',');
std::getline(openfile, arraysize_sy, '.');
std::getline(openfile, start_sx, ',');
std::getline(openfile, start_sy, '.');
std::getline(openfile, finish_sx , ',');
std::getline(openfile, finish_sy , '.');
std::getline(openfile,walls_s, '.');
int startx,starty;
int finishx,finishy;
//convert string to int
std::stringstream rowconv(arraysize_sx);
std::stringstream colconv(arraysize_sy);
std::stringstream startsx(start_sx);
std::stringstream startsy(start_sy);
std::stringstream finishsx(finish_sx);
std::stringstream finishsy(finish_sy);
// rowconv >> row;
// colconv >> col;
startsx >> startx;
startsy >> starty;
finishsx >> finishx;
finishsy >> finishy;
//defining the shape of the maze
char maze [col][row] = {
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
{'-','-','-','-','-','-','-','-','-','-'},
};
maze[startx][starty] = 's';
maze[finishx+3][finishy] = 'f';
outputfile << *maze;
openfile.close();
}
Here is my .txt input for refrence, each different point is marked by a period. i.e dimentions. start. finish. walls:
10, 11.
(0, 0).
(3, 10).
(0, 6), (0, 7), (0, 9),
(1, 1), (1, 2), (1, 4), (1, 7),
(2, 1), (2, 7), (2, 8), (2, 10),
(3, 1), (3, 2), (3, 3), (3, 4), (3, 7),
(4, 0), (4, 6), (4, 9), (4, 10),
(5, 2), (5, 3), (5, 4), (5, 5), (5, 7),
(6, 1), (6, 8), (6, 9),
(7, 1), (7, 2), (7, 3), (7, 6),
(8, 1), (8, 5), (8, 6), (8, 8), (8, 10),
(9, 3), (9, 7).
Update:
I updated my code so that instead of creating the array like I did above. I used for loops to create the start and finish. Im still working on adding the walls in and creating 3X3 squares for each point. I'm trying to find out if its possible to place a 3X3 array within one point on another array.
Updated code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
int main()
{
//establishing constant variables;
const int row = 10;
const int col = 11;
double p1x,p1y;
//defining strings to pull from text file
std::string arraysize_sx;
std::string arraysize_sy;
std::string start_sx;
std::string start_sy;
std::string finish_sx;
std::string finish_sy;
// std::string walls_sx;
// std::string walls_sy;
std::string walls_sf;
std::ifstream openfile ("input.txt");
std::ofstream outputfile ("output.txt",std::ios::app);
// int wx,wy;
int startx,starty;
int finishx,finishy;
//gets points from text file, using , and . as delimiters
std::getline(openfile, arraysize_sx , ',');
std::getline(openfile, arraysize_sy, '.');
std::getline(openfile, start_sx, ',');
std::getline(openfile, start_sy, '.');
std::getline(openfile, finish_sx , ',');
std::getline(openfile, finish_sy , '.');
// std::getline(openfile,walls_sx, ',');
// std::getline(openfile,walls_sy, ',');
std::getline(openfile,walls_sf, '.');
//convert string to int
std::stringstream rowconv(arraysize_sx);
std::stringstream colconv(arraysize_sy);
std::stringstream startsx(start_sx);
std::stringstream startsy(start_sy);
std::stringstream finishsx(finish_sx);
std::stringstream finishsy(finish_sy);
// std::stringstream wallx(walls_sx);
// std::stringstream wally(walls_sy);
startsx >> startx;
startsy >> starty;
finishsx >> finishx;
finishsy >> finishy;
// wallx >> wx;
// wally >> wy;
//defining the shape of the maze
char maze [col][row];
char s [3][3] = {
{'-','-','-'},
{'-','S','-'},
{'-','-','-'}
};
//defining the start point and endpoint using the points pulled from the text file
for (int x = 0; x < col; x++){
for (int y = 0; y < row; y++){
if (x == startx && y == starty){
maze[x][y] = 'S';
}
else if (y == finishx+3 && x == finishy){
maze[x][y] = 'F';
}
else{
maze [x][y] = '-';
}
}
}
std::cout << walls_sf << std::endl;
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))
I am doing this problem http://community.topcoder.com/stat?c=problem_statement&pm=2915&rd=5853, but my program gives wrong output, I tried more ways and it does not work properly. I do not get it, because other people do it like me and they are fine. Can you please check if I have properly implemented the BFS? Thanks in advance.
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
#define P push
#define PP pop();
#define T front();
int mo[][2] = { {-2, -1}, {-2, 1}, {2, -1}, {2, 1}, {-1, -2}, {1, -2}, {-1, 2}, {1, 2} };
int m[8][8];
int BFS(int sy, int sx, int fy, int fx)
{
queue<int> s;
m[sy][sx] = 1;
s.P(sy);
s.P(sx);
s.P(0);
while(!s.empty())
{
int d = s.T s.PP
int x = s.T s.PP
int y = s.T s.PP
for(int i=0;i < 8;i++)
{
int yy = y + mo[i][0];
int xx = x + mo[i][1];
if(yy < 0 || yy > 7 || xx < 0 || xx > 7) continue;
if(m[yy][xx] != -1) continue;
if(yy == fy && xx == fx) return d + 1;
m[yy][xx] = 0;
s.P(yy);
s.P(xx);
s.P(d+1);
}
}
return -1;
}
class CaptureThemAll {
public:
int fastKnight(string knight, string rook, string queen) {
vector<int> p{knight[0] - 'a', knight[1] - '1', rook[0] - 'a', rook[1] - '1', queen[0] - 'a', queen[1] - '1'};
memset(m, -1, sizeof(m));
int a = BFS(p[1], p[0], p[3], p[2]);
memset(m, -1, sizeof(m));
int b = BFS(p[1], p[0], p[5], p[4]);
memset(m, -1, sizeof(m));
int c = BFS(p[3], p[2], p[5], p[4]);
return min(a,b) + c;
}
};
I think the problem might be that you push y,x,d so your queue will be
Front y Middle x End d
But when you pop the front element you place it (y) into a variable called d.
It may work better if you change:
int d = s.T s.PP
int x = s.T s.PP
int y = s.T s.PP
to
int y = s.T s.PP
int x = s.T s.PP
int d = s.T s.PP
I am struggling to convert a 2D array of points in a 1D array of ints. I wrote a wrapper class to do that for me (Array3D), which does the mapping for me with filling the underlying buffer, but it looks like the indexing is totally wrong, since when I print my 2D array and in comparison the buffer, it gives me different outputs.
The 2D point array has dimensions steps × number_of_robots. Therefore, the 1D buffer has
a length of steps × number_of_robots × 2.
Idea is that
buffer[index(x,y,0)] corresponds to points[index(x,y)].x
buffer[index(x,y,1)] corresponds to points[index(x,y)].y
The output is wrong, since it should be identical when I print out the 2D point array and the 1D buffer. I read the row of points from a file, and therefore, they totally should be identical.
The points are derived from the input read by a file. How that is done seems unimportant. Fact is, that the output of main.cpp is:
(0, 4) (0, 5) (1, 5) (2, 5) (2, 4) (3, 4) (2, 4) (2, 3) (2, 2)
(4, 0) (4, -1) (4, 0) (4, 1) (3, 1) (4, 1) (4, 2) (3, 2) (2, 2)
(0, 2) (0, 3) (1, 2) (2, 2) (2, 2) (3, 3) (2, 2) (2, 2) (2, 2)
(1, 2) (2, 2) (2, 2) (3, 3) (2, 2) (2, 2) (2, 2) (3, 3) (2, 2)
point.cpp
Point::Point(int a, int b) {
x = a;
y = b;
}
Array3D.cpp
template<class T>
int Array3D<T>::index(int x,int y, int z) {
return (x * ydim + y) * zdim + z;
}
template<class T>
T Array3D<T>::get( int x, int y, int z) {
return buffer[index(x,y,z)];
}
template<class T>
void Array3D<T>::set( int x, int y, int z ,T n) {
buffer[index(x,y,z)] = n;
}
Harvester.cpp
int Harvester::index(int t, int n) {
return t*number_of_robots + n;
}
void Harvester::extract(Array3D<int> *array) {
Point p;
for(int t = 0; t < steps; t++ ) {
for(int n = 0; n < number_of_robots; n++) {
p = data[index(t,n)];
array->set(t,n,0,p.x);
array->set(t,n,1,p.x);
}
}
}
void Harvester::read_points(string filename) {
string line;
ifstream input;
input.open(filename.c_str());
input >> number_of_robots;
int x, y;
for(int n = 0; n < number_of_robots; n++) {
if(input >> x >> y) {
data[index(0,n)].x = x;
data[index(0,n)].y = y;
//cout << x << " " << y << endl;
} else {
cout << "Your file is bad, and you should feel bad!";
return;
}
}
}
void Harvester::print_harvest() {
for (int n = 0; n < number_of_robots; n++) {
for (int t = 0; t < steps; t++) {
data[index(t,n)].dump();
}
cout << endl;
}
cout << endl;
}
robots_002.txt
2
0 4
4 0
main.cpp
int main() {
int mission_time;
int number_of_robots;
Point goal;
string path;
bool print = true;
int choice = 2;
mission_time = 8;
number_of_robots = 2;
goal.x = 2;
goal.y = 2;
path = "robots_002.txt";
int steps = mission_time + 1;
Harvester h(mission_time, number_of_robots, goal);
h.read_points("fixtures/" + path);
h.run();
int *buffer = new int[steps * number_of_robots * 2];
Array3D<int> arr(steps, number_of_robots, 2, buffer);
h.extract(&arr);
h.print_harvest();
for (int n = 0; n < number_of_robots; n++) {
for (int t = 0; t < steps; t++) {
printf("(%d, %d)\t", arr.get(t, n, 0), arr.get(t, n, 1));
}
cout << endl;
}
return 0;
}
still looking through but quick observation. In Harverster::extract, you are setting both to p.x
void Harvester::extract(Array3D<int> *array) {
Point p;
for(int t = 0; t < steps; t++ ) {
for(int n = 0; n < number_of_robots; n++) {
p = data[index(t,n)];
array->set(t,n,0,p.x);
array->set(t,n,1,p.x); //<-- im thinking you want this to be p.y
}
}
}