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";
}
Related
i have assigment to create c++ program which will multiple 2 uknown size matrix using fork and shared memory, I have write this code but at the end for multiplication result i get all zeros. Sorry for mess code im new in this.
`
`#include<iostream>
#include<math.h>
#include<vector>
#include<signal.h>
#include<unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<sys/wait.h>
using namespace std;
int l, m, n, job_numb;
key_t id_shared_mem;
int **B, **C, **A;
int **generateMatrix(int **matrix, int iterator, int vel){
for (int i = 0; i < iterator; i++)
{
matrix[i] = new int[vel];
for (int j = 0; j < vel; j++)
{
matrix[i][j] = (rand() % 9);
}
}
return matrix;
}
int **generateMatrixC(int **matrix, int iterator, int vel)
{
for (int i = 0; i < iterator; i++)
{
matrix[i] = new int[vel];
}
return matrix;
}
void *writeMatrixResult(int **matrix, int stupac, int red)
{
for (int i = 0; i < stupac; i++)
{
for (int j = 0; j < red; j++)
{
cout << matrix[i][j] << " ";
}
cout << endl;
}
return NULL;
}
void write()
{
cout << "Mnozenik = " << endl;
writeMatrixResult(A, l, m);
cout << "Mnozitelj = " << endl;
writeMatrixResult(B, m, l);
cout << "Umnozak = " << endl;
writeMatrixResult(C, l, l);
}
void abort(int sig) {
if (sig == SIGINT) {
for (int i = 0; i < job_numb; i++) wait(NULL);
shmdt(A);
shmdt(B);
shmctl(id_shared_mem, IPC_RMID, NULL);
} else {
write();
shmdt(A);
shmdt(B);
shmctl(id_shared_mem, IPC_RMID, NULL);
}
exit(0);
}
void proces(int procesId)
{
while (job_numb > procesId)
{
int i = 0;
while (i < l)
{
int j = 0;
C[procesId][i] = 0;
while (m > j)
{
C[procesId][i] = C[procesId][i] + A[procesId][j] * B[j][i];
j++;
}
i++;
}
procesId++;
}
}
int main(int argc, char ** argv) {
if (argc != 4) {
cout << " unesite 3 argumenta!" << endl;
return 0;
}
l = atoi(argv[1]);
m = atoi(argv[2]);
n = atoi(argv[3]);
job_numb = l / n;
if (l % n) {
job_numb++;
}
id_shared_mem = shmget(IPC_PRIVATE, sizeof(int) * 10, 0600);
sigset(SIGINT, abort);
A = (int **)shmat(id_shared_mem, NULL, 0);
B = A + l;
C = B + l * m*m;
A = new int *[l];
B = new int *[m];
C = new int *[l];
srand(time(NULL));
A = generateMatrix(A,l, m );
B = generateMatrix(B,m,l);
C = generateMatrixC(C,l,l);
for (int i = 0; i < n; i++)
{
switch (fork()) {
case 0: { //dijete
proces(i);
exit(0);
}
case -1: { //greska
cout << "Fatalna pogreska!" << endl;
exit(1);
}
}
}
for (int i = 0; i < job_numb; i++) wait(NULL);
abort(0);
}`
`
i have try to assign only one value to matrix C like c[1][1] = 2 in proces function to see if it will write any, but still im getting all zeros on printl.
I'm getting an error message in Codeblocks C++ 'Program received signal SIGSEGV, Segmentation fault' in comparison between a vector element and a size of vector of vectors inside for loop (line 133 if (parz_przestrzenie[i] != parz_dystanse[i].size())).
Could anyone tell me why?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int bloki_parz[100000], bloki_nieparz[100000];
int silnia(int n)
{
int liczba = 1;
for (int i = 1; i <= n; i++)
{
liczba *= i;
}
return liczba;
}
int main()
{
int n, czapka, wolne_miejsca = 0, wynik = 1;
vector<int> parz, nieparz, parz_przestrzenie, nieparz_przestrzenie, parz_przestrzenie2, nieparz_przestrzenie2;
vector<vector<int>> parz_dystanse;
vector<vector<int>> nieparz_dystanse;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> czapka;
if (i % 2 == 0)
{
parz.push_back(czapka);
}
else
{
nieparz.push_back(czapka);
}
}
int parz_size = parz.size(), nieparz_size = nieparz.size();
// sprawdzamy czy dane nie sÂą sprzeczne ; gdy zabraknie nam miejsc do rozmieszczania
vector<int> parz_duplicate = parz;
vector<int> nieparz_duplicate = nieparz;
parz_duplicate.erase(unique(parz_duplicate.begin(), parz_duplicate.end()), parz_duplicate.end());
nieparz_duplicate.erase(unique(nieparz_duplicate.begin(), nieparz_duplicate.end()), nieparz_duplicate.end());
int parz_dupl_size = parz_duplicate.size(), nieparz_dupl_size = nieparz_duplicate.size();
if (parz_size < nieparz_dupl_size)
{
cout << 0 << endl;
return 0;
}
if (nieparz_size < parz_dupl_size)
{
cout << 0 << endl;
return 0;
}
for (int i = 0; i < parz_size - 1; i++)
{
if (parz[i] == parz[i + 1])
{
bloki_parz[i + 1] = 1;
}
}
for (int i = 0; i < nieparz_size - 1; i++)
{
if (nieparz[i] == nieparz[i + 1])
{
bloki_nieparz[i] = 1;
}
}
for (int i = 0; i < parz_size; i++)
{
vector<int> bloczek;
for (int j = i; j < parz_size; j++)
{
if (parz[j] != parz[j + 1])
{
bloczek.push_back(parz[j]);
}
else
{
i += 1;
break;
}
}
if (bloczek.size() != 0)
{
parz_dystanse.push_back(bloczek);
}
}
int parz_dyst_size = parz_dystanse.size();
if (parz[parz_size - 1] != parz[parz_size - 2])
{
parz_dystanse[parz_dyst_size - 1].push_back(parz[parz_size - 1]);
}
for (int i = 0; i < nieparz_size; i++)
{
vector<int> bloczek;
for (int j = i; j < nieparz_size; j++)
{
if (nieparz[j] != nieparz[j + 1])
{
bloczek.push_back(nieparz[j]);
}
else
{
i += 1;
break;
}
}
if (bloczek.size() != 0)
{
nieparz_dystanse.push_back(bloczek);
}
}
int nieparz_dyst_size = nieparz_dystanse.size();
int current_wynik = 0;
for (int i = 0; i < nieparz_size; i++)
{
if (bloki_parz[i] == 0)
{
current_wynik++;
}
else
{
if (current_wynik != 0)
{
parz_przestrzenie.push_back(current_wynik);
}
current_wynik = 0;
}
}
parz_przestrzenie.push_back(current_wynik);
current_wynik = 0;
for (int i = 0; i < parz_size; i++)
{
if (bloki_nieparz[i] == 0)
{
current_wynik++;
}
else
{
if (current_wynik != 0)
{
nieparz_przestrzenie.push_back(current_wynik);
}
current_wynik = 0;
}
}
nieparz_przestrzenie.push_back(current_wynik);
int parz_przest_size = parz_przestrzenie.size(), nieparz_przest_size = nieparz_przestrzenie.size();
for (int i = 0; i < 1; i++)
{
if (parz_przestrzenie[i] != parz_dystanse[i].size())
{
wynik *= parz_przestrzenie[i];
wolne_miejsca++;
}
}
for (int i = 0; i < nieparz_przest_size; i++)
{
if (nieparz_przestrzenie[i] != nieparz_dystanse[i].size())
{
wynik *= nieparz_przestrzenie[i];
wolne_miejsca++;
}
}
cout << wynik * silnia(wolne_miejsca) << endl;
}
parz_dystanse is a vector of a vector. In this case the return value of parz_dystanse.size() is a long unsigned int, whereas an element of parz_przestrzenie is an int.
You need to make explicit that parz_dystanse.size() returns an int in order to make comparitions between integer expressions of different signedness.
This will fix that problem:
if (parz_przestrzenie[i] != (int)parz_dystanse[i].size())
So I'm trying to write a function called "splitoList" to take 3 arguments, a string, another string that defines where to split the first string, and a class List to append the data to. Here's what I have so far.
split.h
#include <iostream>
#include <sstream>
using namespace std;
string splitoList(string s, string spechar, List <string> lst) {
size_t pos = 0;
string token;
int i = 0;
if (spechar == "") {
for (char i : s) {
string n(1,i);
lst.append(n);
}
return s;
} else {
while ((pos = s.find(spechar)) != std::string::npos) {
token = s.substr(0, pos);
lst.append(token);
s.erase(0, pos + spechar.length());
}
//cout << s;
lst.append(s);
lst.print();
return s;
}
}
lists.h
#include <iostream>
#include <cstdarg>
using namespace std;
template <class T>
class List {
public:
int size;
T* list;
List() {
size = 0;
list = new T[100];
}
void append(T data) {
list[size] = data;
size++;
}
int select(int pos) {
return list[pos];
}
void clear() {
for (int i = 0; i <= size; i++) {
list[i] = list[i - 1];
}
size = 0;
}
void sort(bool reverse) {
int temp;
if (reverse == true) {
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (list[i] > list[j]) {
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
}
else {
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (list[i] < list[j]) {
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
}
}
void remove() {
if (size == 0) {
cout << "[ ]\n";
return;
}
else {
for (int i = 0; i < size - 1; i++) {
list[i] = list[i + 1];
}
size--;
}
}
void reverse() {
int temp;
for (int i = size - 1; i > 0; i--) {
temp = list[i];
list[i] = list[size-i-1];
list[size-i-1] = temp;
}
}
void count(int item) {
int cnt = 0;
for (int i = 0; i < size; i++) {
if (list[i] == item) {
cnt++;
}
}
cout << cnt << endl;
}
void print() {
if (size == 0) {
cout << "[ ]\n";
return;
}
cout << "[";
for (int i = 0; i < size; i++) {
if (i == size - 1) {
cout << list[i];
}
else {
cout << list[i] << ", ";
}
}
cout << "]\n";
}
List operator+(List l2) {
List l3;
for (int i = 0; i < this->size; i++) {
l3.append(this->list[i]);
}
for (int i = 0; i < l2.size; i++) {
l3.append(l2.list[i]);
}
return l3;
}
};
and main.cpp
#include <iostream>
#include <sstream>
#include "lists.h"
#include "split.h"
using namespace std;
int main() {
List <string> l1;
l1.append("Hello!"); l1.append("World!");
l1.print();
l1.clear();
string n = "Hello World";
splitoList(n, " ", l1);
l1.print();
return 0;
}
I've deduced that it's not an issue with my "lists.h" file, but that the function outputs the list as intended but isn't appending to my list "l1" defined in main. So when lst.print(); is called in the function, it outputs "[Hello, World]" and when l1.print(); is called in main nothing is printed. I'm kinda stuck on this as I know it revolves around pointing to the inputted list class but I'm not sure what to do from here.
You need to change your function's prototype, with a reference argument, then the print statement works as you expected
string splitoList(string s, string spechar, List <string>& lst)
When passing lst as value, the instance in function splitoList is a copy of the one in your main function; as a reference, they are the same instance.
FAQs on reference:
https://isocpp.org/wiki/faq/references
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;
}
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;
}