Realize "-" operator overloading as a friend function of class - c++

I try to realize difference of sets with "-". For example:
Set a = 1 2 3 4;
Set b = 3 4 5 6;
Set c = a - b; // (1 2);
How i should overload operator? I tried to use frienldy function, but it can't work with variable "size". Visual Studio show error "c2597" at 28th line (size++;)
I can't understand, how to overloading "-" for using it with two sets. When I overload method of class, i can use only one argument. When i use friend-function, i can use twi arguments (Set a, Set b), but i can't work with variable "size".
#include <iostream>
#include <locale.h>
#include <conio.h>
#include <vector>
using namespace std;
class Set {
private:
int size;
vector <int> vect;
public:
Set() { size = 0; }
~Set() { vect.clear(); }
void Enter();
void Show();
friend Set operator-(Set a, Set b)
{
size = 0;
vect.clear();
int i, j, n = 0;
for (i = 0; i < a.size; i++) {
int cnt = 0;
for (j = 0; j < b.size; j++)
{
if (a.vect[i] == b.vect[j]) cnt++;
}
if (cnt == 0) {
size++;
vect.push_back(a.vect[i]);
}
}
return a;
}
void add()
{
int element;
cout << "Введите новый элемент " << endl;
cin >> element;
size = size + 1;
vect.push_back(element);
}
};
void Set::Enter() {
cout << "Введите размер " << endl;
cin >> size;
vect.resize(size);
cout << "Введите элементы :" << endl;
for (int i = 0; i < size; i++)
{
cin >> vect[i];
}
}
void Set::Show() {
cout << "Множество: " << endl;
for (int i = 0; i < size; i++)
cout << vect[i] << " ";
cout << endl;
}
int main() {
setlocale(LC_ALL, "RUS");
Set a;
a.Enter();
Set b;
b.Enter();
Set c;
c = a - b;
c.Show();
c.add();
c.Show();
_getch();
return 0;
}
UPD:
I made it through method:
Set operator-(const Set& b)
{
Set a = *this;
Set tmp;
tmp.size = 0;
vect.clear();
int i, j, n = 0;
for (i = 0; i < a.size; i++) {
int cnt = 0;
for (j = 0; j < b.size; j++)
{
if (a.vect[i] == b.vect[j]) cnt++;
}
if (cnt == 0) {
tmp.size++;
tmp.vect.push_back(a.vect[i]);
}
}
return tmp;
}

friend functions are not member methods, so you have to remove/replace usage of (implicit) this as size = 0, you might add extra object:
friend Set operator-(Set a, Set b)
{
Set res;
for (int i = 0; i < a.size; i++) {
int cnt = 0;
for (int j = 0; j < b.size; j++)
{
if (a.vect[i] == b.vect[j]) cnt++;
}
if (cnt == 0) {
res.size++;
res.vect.push_back(a.vect[i]);
}
}
return res;
}

Related

DFS n-queens problem. Why my code is so slow?

Recently got an assignment on solving the n-queens problem using BFS/DFS.
My BFS stops at N=7 and I think it's understandable but DFS has a problem with N=8 and goes on for a few minutes.
Do you have any suggestions on how to speed it up?
Also, can you recommend what should I learn to speed up my code in general?
Here's my code:
#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <chrono>
#include <stack>
using namespace std;
const int N = 6;
int states_generated = 1;
void tree(vector<int> data) {
string arr[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
arr[i][j] = " -";
}
}
for (int i = 0; i < data.size(); i++) {
arr[data[i] - 1][i] = " *";
}
cout << endl;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cout << arr[i][j];
}
cout << endl;
}
}
vector<int>* gen_v_variants(vector<int> parent) {
if (parent.size() == N) return nullptr;
vector<int>* vector_box = new vector<int>[N];
for (size_t i = 0; i < N; i++) {
vector_box[i] = parent;
vector_box[i].push_back(i + 1);
states_generated++;
}
return vector_box;
}
struct Node {
vector<int> queens;
bool checked = false;
queue<vector<int>> kids;
Node(vector<int> queens) {
this->queens = queens;
vector<int>* vector_box = gen_v_variants(queens);
if (vector_box != nullptr) {
for (int i = 0; i < N; i++) {
kids.push(vector_box[i]);
}
}
delete[] vector_box;
}
bool check() {
checked = (this->kids.size() == 0) ? true : false;
return checked;
}
~Node() {
}
};
bool validator(vector<int> data) {
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (data[i] == data[j] || abs(i - j) == abs(data[i] - data[j])) return false;
}
}
tree(data);
return true;
}
class DFS {
public:
int N;
stack<Node> st;
int states_checked = 0;
int n_queens_solved = 0;
DFS(int N, Node data) {
this->N = N;
this->st.push(data);
}
void begin() {
while (this->st.size() > 0) {
if (this->st.top().queens.size() < N && !this->st.top().check()) {
add_to_stack();
}
else if (this->st.top().queens.size() == N) {
if (validator(st.top().queens)) {
this->n_queens_solved++;
this->states_checked++;
}
else {
this->states_checked++;
}
this->st.top().checked = true;
st.pop();
}
else if (this->st.top().check()) {
st.pop();
}
}
result();
}
void add_to_stack() {
Node* parent = &this->st.top();
st.push(parent->kids.front());
parent->kids.pop();
parent = nullptr;
}
void result() {
cout << endl << "States: " << states_generated << "\nStates checked for n-queen problem: " << this->states_checked
<< "\nN-Queens problems solved: " << this->n_queens_solved << endl;
}
~DFS() {}
};
int main() {
using chrono::high_resolution_clock;
using chrono::duration_cast;
using chrono::duration;
using chrono::milliseconds;
auto t1 = high_resolution_clock::now();
vector<int> start;
Node a(start);
DFS test(N, a);
test.begin();
auto t2 = high_resolution_clock::now();
duration<double, milli> ms_double = t2 - t1;
cout << ms_double.count() / 1000 << "s";
}

Dijkstra's alghoritm with OpenMP

There is a fully working Dijkstra algorithm that takes values ​​from a file (or writes a new one) and writes data to a matrix. How can you improve the program using OpenMP so that its speed is significantly increased? New to openMP, had little experience with common matrices, mostly parallelization "for".
I attach all the code below:
#include <iostream>
#include <fstream>
#include <string>
#include <climits>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iomanip>
#include <locale.h>
#include <chrono>
using namespace std;
class Timer
{
private:
using clock_t = std::chrono::high_resolution_clock;
using second_t = std::chrono::duration<double, std::ratio<1> >;
chrono::time_point<clock_t> m_beg;
public:
Timer() : m_beg(clock_t::now())
{
}
double elapsed() const
{
return std::chrono::duration_cast<second_t>(clock_t::now() - m_beg).count();
}
};
void fillingArray(int** arr, int c, string filename) {
ofstream fout(filename);
srand(static_cast<unsigned int>(time(0)));
for (int i = 0; i < c; i++){
for (int j = 0; j < c; j++) {
arr[i][j] = arr[j][i] = rand() % 10 + 1;
}
}
for (int i = 0; i < c; i++) {
fout << endl;
for (int j = 0; j < c; j++) {
fout << setw(5) << arr[i][j];
}
}
}
void read(int** arr, int c, string filename) {
char answer;
ifstream file;
file.open(filename);
if (!file) {
fillingArray(arr, c, filename);
}
else {
cout << "File found\nWant to overwrite it? (y / n)\n";
cin >> answer;
if (answer == 'y' || answer == 'Y') {
fillingArray(arr, c, filename);
}
else {
for (int i = 0; i < c; i++) {
for (int j = 0; j < c; j++) {
file >> arr[i][j];
}
}
}
}
file.close();
}
void Dijkstra(int** arr, int c, int st)
{
Timer t;
int count, index, i, u, m = st + 1;
int* distance = (int*)malloc(c * sizeof(int*));
bool* visited = new bool[c];
for (i = 0; i < c; i++)
{
distance[i] = INT_MAX; visited[i] = false;
}
distance[st] = 0;
for (count = 0; count < c - 1; count++)
{
int min = INT_MAX;
for (i = 0; i < c; i++)
if (!visited[i] && distance[i] <= min)
{
min = distance[i]; index = i;
}
u = index;
visited[u] = true;
for (i = 0; i < c; i++)
if (!visited[i] && arr[u][i] && distance[u] != INT_MAX &&
distance[u] + arr[u][i] < distance[i])
distance[i] = distance[u] + arr[u][i];
}
double time = t.elapsed();
cout << "Cost of the path from the initial peak to the rest:\t\n";
for (i = 0; i < c; i++) if (distance[i] != INT_MAX)
cout << m << " > " << i + 1 << " = " << distance[i] << endl;
else cout << m << " > " << i + 1 << " = " << "route not available" << endl;
cout << "Time passed: " << time << "с\n";
delete[] visited;
delete[] distance;
}
int main()
{
string filename, rash;
filename = "arr";
rash = ".dat";
int c;
cout << "Enter the number of ribs:\n";
cin >> c;
int** arr = (int**)malloc(c * sizeof(int*));
for (int i = 0; i < c; i++) {
arr[i] = (int*)malloc(c * sizeof(int));
}
filename += to_string(c) + rash;
read(arr, c, filename);
Dijkstra(arr, c, 0);
delete[] arr;
}

How to limit a matrix class to get only 'X' 'O' or '.'

I have a board class that makes N*N board of chars.
class Cell
{
public:
int row; int col;
};
class Board {
private:
int size;
char** matrix = nullptr;
//many other class functions.
char & operator[](const Cell& cellToChange) {
if (cellToChange.row < size && cellToChange.col < size) {
return matrix[cellToChange.row][cellToChange.col];
}
else {
cout << "ERROR!" << endl;
}
}
now when I use in the main this
"board1[{1, 4}] = 'X';"
It is changing this place in the matrix to 'X' and any other char.
I need to limit this matrix to only 'X' 'O' or '.'
I"m not allowed to chain the main! I may only change the classes.
My goal I can not achieve right not is to make the program print "error" when I"m trying to do
"board1[{1, 4}] = 'z'".
And I have wasted hours on hours trying to achieve it and I really need your help here.
This is the whole class I wrote:
#include <iostream>
using namespace std;
class Cell
{
public:
int row; int col;
};
class Board {
private:
int size;
char** matrix = nullptr;
public:
Board(int sizeToSet) { //constructor with size
size = sizeToSet;
matrix = new char*[size]; //creates a matrix
for (int i = 0; i < size; i++)
matrix[i] = new char[size];
for (int i = 0; i < size; i++) { //makes every cell in matix '.'
for (int j = 0; j < size; j++) {
matrix[i][j] = '.';
}
}
}
void printSize() { //matrix size print
cout << size << endl;
}
~Board() { //destructor
for (int i = 0; i < size; i++)
delete[] matrix[i];
delete[] matrix;
}
Board(const Board& other) { //copy constructor
if (this != &other) {
size = other.size;
matrix = new char*[size];
for (int i = 0; i < size; i++)
matrix[i] = new char[size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
matrix[i][j] = other.matrix[i][j];
}
}
}
}
Board(Board&& other) { //move constructor
size = other.size;
matrix = other.matrix;
other.matrix = nullptr;
}
friend ostream& operator<<(ostream& os, const Board& boardToPrint) { //prints matrix
for (int i = 0; i < boardToPrint.size; i++) {
for (int j = 0; j < boardToPrint.size; j++) {
os << boardToPrint.matrix[i][j] << " ";
}
os << endl;
}
os << endl;
return os;
}
char & operator[](const Cell& cellToChange) {
if (cellToChange.row < size && cellToChange.col < size) {
return matrix[cellToChange.row][cellToChange.col];
}
else {
cout << "ERROR!" << endl;
}
}
void operator=(char charToAdd) {
if (charToAdd == 'X' || charToAdd == 'O' || charToAdd == '.') {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
matrix[i][j] = charToAdd;
}
}
}
else {
cout << "ERROR!" << endl;
}
}
const Board& operator=(const Board& other) {
if (this != &other) {
size = other.size;
matrix = new char*[size];
for (int i = 0; i < size; i++)
matrix[i] = new char[size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
matrix[i][j] = other.matrix[i][j];
}
}
}
return *this;
}
};
and this is the whole main I"m not allowed to change:
#include "Board.h"
#include <iostream>
using namespace std;
int main() {
Board board1{4}; // Initializes a 4x4 board
cout << board1 << endl; /* Shows an empty board:
....
....
....
....
*/
cout << board1[{1,2}] << endl; // .
board1[{1,1}]='X';
board1[{1,2}]='O';
char c = board1[{1,2}]; cout << c << endl; // O
cout << board1 << endl; /* Shows the following board:
....
.XO.
....
....
*/
// This should raise an exception
// "Illegal"
board1 = '.'; // Fill the entire board with "."
cout << board1 << endl; /* Shows an empty board, as above */
board1 = 'a'; // This should raise exception
// "Illegal"
board1[{0,1}] = 'x'; // This should raise an exception
// "Illegal"
Board board2 = board1;
board2[{0,0}] = 'X';
cout << board1 << endl; /* Shows an empty board, as above */
cout << board2 << endl; /* Shows a board with an X at top-left */
board1 = board2;
board1[{3,3}] = 'O';
cout << board2 << endl; /* Shows a board with an X at top-left */
cout << board1 << endl; /* Shows a board with an X at top-left and O at bottom-right */
cout << "Good bye!" << endl;
return 0;
}
THANKS!
What you need is another layer of abstraction. Since you can't control the right hand side of the assignment, you need to control the assignment operator. To do that, you need a proxy object. You'll return that object from the operator[] and then you do your logic in it's assignment operator. That would look like
class Proxy
{
char& val;
Proxy(char& val) : val(val) {}
Proxy& operator=(char new_val)
{
if (new_val == 'X' || new_val == 'O' || new_val == '.')
{
val = new_val;
return *this;
}
throw std::invalid_argument("Invalid Assignment. Use X, O, or .");
}
// allows this class to implicitly convertible to a char
operator char() { return val; }
};
and
Proxy operator[](const Cell& cellToChange) {
if (cellToChange.row < size && cellToChange.col < size) {
return {matrix[cellToChange.row][cellToChange.col]};
}
throw std::out_of_range("invalid index");
}

HackerRank says ~no response on stdout~. C++

I wrote this solution for the absolute permutation problem on HackerRank. It works fine on dev-C++ but doesn't work on Hackerrank. I've found that the code produces output when I remove the abs_perm(). What's the problem here?
#include <iostream>
using namespace std;
int arr[100000];
int check(int n, int k)
{
if ( (2*k == n) || (k == 0) || (n - 4*k == 0) )
return 1;
else if (k < n/2)
return check(n - 4*k, k);
else
return 0;
}
void swap(int &a, int &b)
{
int c = b;
b = a;
a = c;
}
void ini(int n)
{
for (int i = 0; i < n; i++)
{
arr[i] = i+1;
}
}
void abs_perm(int n, int k)
{
for (int i = 0; i < k; i++)
{
swap(arr[i], arr[k+i]);
}
if (2*k == n)
return;
for (int i = n - 1; i > n - k - 1; i--)
{
swap(arr[i], arr[i-k]);
}
if (n - 4*k == 0)
return;
abs_perm(n - 4*k, k);
}
int main()
{
int T;
cin >> T;
int N[T], K[T];
for (int i = 0; i < T; i++)
{
cin >> N[i] >> K[i];
}
for (int i = 0; i < T; i++)
{
cout << N[i] << " " << K[i] << "\n";
}
for (int i = 0; i < T; i++)
{
if ( !check(N[i], K[i]) )
cout << "-1\n";
else
{
ini(N[i]);
abs_perm(N[i], K[i]);
for (int j = 0; j < N[i]; j++)
{
cout << arr[j] << " ";
}
cout << "\n";
}
}
return 0;
}
Array is a structure to use when you know at compile time the dimension of your structure. What you wrote at the begin in abs_perm() is not correct for standard compilers (in fact you don't know the dimension of your array). You can use a std::vector or a std::list which allocate memory dynamically or (bad solution) you can allocate an array with dimension that certainly contains all elements you will put inside.

Visual Studio Gives Ambiguous Error for No Real Reason

It gives the following error:
error C2872: 'count' : ambiguous symbol
Count variable has been declared as a global variable and the code compiles and runs in Sublime Text. Don't understand why Visual Studio is crying over it.
#include <iostream>
#include <fstream>
using namespace std;
int** am; // Adjacency matrix
int* ar, * ar2; // Arrays to work with
int n; // Number of nodes
int node1, node2, k; // For reading input from the console
int count;
bool checkReachability(int, int, int);
void fillArray(int);
void updateArray(int,int);
void freeMemory();
int main() {
ifstream in;
in.open("Input2.txt");
int a, b;
if(in.is_open()) {
in >> n;
// Allocate memory on the heap dynamically for the adjacency matrix:
am = new int*[n];
ar = new int[n];
ar2 = new int[n];
for (int i = 0; i < n; i++) {
am[i] = new int[n];
}
// Initialize the values of the adjacency matrix with 0s and the principle diagonal with 1s initially:
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
am[i][j] = 1;
} else {
am[i][j] = 0;
}
}
}
while(!in.eof()) {
in >> a >> b;
am[a-1][b-1] = 1;
}
cout << "The adjacency matrix input is as follows: \n\n";
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << am[i][j] << " ";
}
cout << endl << endl;
}
in.close();
} else {
cout << "\nError reading the input file\n\n";
}
char c;
do {
cout << "\nPlease enter the input (node1, node2, k): \n";
cin >> node1 >> node2 >> k;
fillArray(node1-1);
count = 0;
if(checkReachability(node1-1,node2-1,k)) {
cout << "\nReachable within " << k << " steps";
if (count < k) {
cout << " (actually " << count << ")";
}
cout << endl << endl;
} else {
cout << "\nNot reachable within " << k << " steps \n";
}
cout << "\nDo you want to continue? Y/N \n\n";
cin >> c;
} while (c == 'Y' || c == 'y');
freeMemory();
system("pause");
return 0;
}
bool checkReachability(int n1, int n2, int k) {
if (n1 == n2) return true;
count++;
if (count <= k) {
if (ar[n2] != 0) return true;
int x;
for (int i = 0; i < n; i++) {
if (ar[i] != 0 && i != n1) {
ar[i]++;
x = ar[i];
}
}
for(int i = 0; i < n; i++) {
ar2[i] = ar[i];
}
for(int i = 0; i < n; i++) {
if (ar2[i] == x) {
fillArray(i);
updateArray(x,i);
if (checkReachability(ar2[i], n2, k)) return true;
}
}
}
return false;
}
void fillArray(int x) {
// To fill the array with the adjacencies of a particular node
for(int i = 0; i < n; i++) {
ar[i] = am[x][i];
}
}
void updateArray(int x, int y) {
for(int i = 0; i < n; i++) {
if (ar[i] == 1 && i != y) {
ar[i] = x;
}
}
}
void freeMemory() {
// To free the dynamically allocated memory on the heap
for (int i = 0; i < n; i++) {
delete [] am[i];
}
delete [] ar;
delete [] ar2;
}
using namespace std is your problem.
Looks like the Microsoft implementation of either the iostream or fstream headers themselves include algorithm. This is causing the name clash with std::count().
So, as #Retiredninja suggested, if I choose to replace while(!in.eof()) with while(in >> a >> b) in:
while(!in.eof()) {
in >> a >> b;
am[a-1][b-1] = 1;
}
Does the rest of the code in the while loop remain the same or does it mean, the input has already been read into a and b when the condition is checked in while(in >> a >> b)?
And become the following:
while(in >> a >> b) {
am[a-1][b-1] = 1;
}
or does it remain:
while(in >> a >> b) {
in >> a >> b;
am[a-1][b-1] = 1;
}