Given an arbitrary matrix, how do I find the co-ordinates that surrounds each city accurately?
E.g. City 1 has surrounding matrix of (0, 0), (0, 3), (1, 0), (1, 3), (2,0), (2, 1), (2, 2), (2, 3).
I have tried using a hardcoded method. Which is loop through each city's co-ordinate, however there are still inaccuracy in this method.
E.g. (0, 1) and from there check all 8 directions, up, down, left, right, upper left, upper right, bottom left, bottom right.
And if the char value is ' ', it is not a city which means it is part of a surrounding.
Is there any way which is much more efficient and more accurate in finding the surrounding?
void surroundings(int x, int y) {
// Initiate the first city struct information
citySummInfo.cityId = cityLocList[0].cityId;
citySummInfo.cityName = cityLocList[0].cityName;
citySummInfoList.push_back(citySummInfo);
// Add unique cityID & cityName into vector
for (size_t i = 0; i < cityLocList.size(); i++) {
for (size_t j = 0; j < citySummInfoList.size(); j++) {
if (cityLocList[i].cityId == citySummInfoList[j].cityId && cityLocList[i].cityName == citySummInfoList[j].cityName) {
break;
}
else if (j == citySummInfoList.size() - 1) {
citySummInfo.cityId = cityLocList[i].cityId;
citySummInfo.cityName = cityLocList[i].cityName;
citySummInfoList.push_back(citySummInfo);
}
}
}
// To populate the entire matrix with city ID
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
for (size_t k = 0; k < cityLocList.size(); k++) {
if (cityLocList[k].xGrid == i && cityLocList[k].yGrid == j)
mapPtr[j][i] = cityLocList[k].cityId + '0';
}
}
}
// Main process of getting the surrounding
for (size_t i = 0; i < citySummInfoList.size(); i++) {
for (size_t j = 0; j < cityLocList.size(); j++) {
if (citySummInfoList[i].cityId == cityLocList[j].cityId)
citySummInfoList[i].coOrdinates.push_back(to_string(cityLocList[j].xGrid) + "." + to_string(cityLocList[j].yGrid));
}
}
for (size_t i = 0; i < citySummInfoList.size(); i++) {
vector<string> temp;
for (size_t j = 0; j < citySummInfoList[i].coOrdinates.size(); j++) {
char cityId = citySummInfoList[i].cityId + '0';
char delim[] = { '.' };
vector<string> tempAxis = tokenizer(citySummInfoList[i].coOrdinates[j], delim, 1);
int xAxis = stoi(tempAxis[0]);
int yAxis = stoi(tempAxis[1]);
if (xAxis - 1 < 0 || yAxis - 1 < 0) {
continue;
}
if (mapPtr[xAxis - 1][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis - 1][yAxis] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis - 1][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
}
citySummInfoList[i].coOrdinates.reserve(temp.size());
citySummInfoList[i].coOrdinates.insert(citySummInfoList[i].coOrdinates.end(), temp.begin(), temp.end());
}
}
Also, is there a possibility that my print function may cause such unreliability?
void print(int x, int y) {
for (int i = 0; i <= x + 2; i++) {
if (i == 0 || i >= x + 1) // Indentation for 1st and last row of non city locations
cout << setw(4) << " ";
for (int j = 0; j <= y + 2; j++) {
if ((i == 0 || i == x + 1) && j <= y + 1) { // Layout for first and last row
cout << "# ";
}
else if ((j == 0 && (i != 0 || i <= x))) { // Numbering for each row
if (x - i >= 0) {
cout << setw(3) << left << x - i << " ";
}
else {
cout << " "; // Indentation for last row of #s
}
}
else if (j == 1 && i < x + 2) { // Layout for first column
cout << "#";
}
else if (j == y + 2 && i != 0 && i < x + 1) { // Layout for last column
cout << " #";
}
else if (i == x + 2 && j < y + 1) { // Numbering for each column
cout << j - 1 << " ";
}
else if ((i != 0 && i != x + 2 && j != y + 2)) {
cout << " " << mapPtr[x - i][j - 2]; // Plot map value
}
}
cout << endl;
}
cout << endl;
}
This is an O(n) answer for your problem. The idea behind it is to find all points that are edges (a point is an edge if it is adjacent to anything which is not its own city).
After finding all edge points, loop through each of them and add all points adjacent to them which are whitespace characters.
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int, int> point;
string m[] = {
" ",
" 555 ",
" 555 ",
" 222 555 ",
" 222 ",
" 222 ",
" 222 ",
" ",
"11 33 ",
"11 44",
" 44"
};
//hash function for pairs
struct hash_pair {
template <class T1, class T2>
size_t operator()(const pair<T1, T2>& p) const {
auto hash1 = hash<T1>{}(p.first);
auto hash2 = hash<T2>{}(p.second);
return hash1 ^ hash2;
}
};
bool insideBounds(int x, int y, point &size){
if(x < 0 || x >= size.x || y < 0 || y >= size.y) return false;
return true;
}
bool isEdge(int x, int y, point &size){
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
if(!insideBounds(x + j, y + i, size)) return true;
if(m[y + i][x + j] == ' ') return true;
}
}
return false;
}
void FindSurrounding(int x, int y){
//size of map
point size = make_pair(11, 11);
//current city id
char city = m[y][x];
//finding a point in edge of the city
point edge = make_pair(x, y);
for(int i = x - 1; i >= 0; --i)
if(m[y][i] == city) edge = make_pair(i, y);
//find all edge points
unordered_set<point, hash_pair> visited;
stack<point> toVisit;
toVisit.push(edge);
while(toVisit.size()){
point current = toVisit.top();
visited.insert(current);
toVisit.pop();
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
point p = make_pair(current.x + j, current.y + i);
if(!insideBounds(p.x, p.y, size) || m[p.y][p.x] != city) continue;
if(visited.find(p) == visited.end() && isEdge(p.x, p.y, size)){
toVisit.push(p);
}
}
}
}
//find surrounding slots
unordered_set<point, hash_pair> surrounding;
for (const auto& p: visited) {
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
point curr = make_pair(p.x + j, p.y + i);
if(insideBounds(curr.x, curr.y, size) && m[curr.y][curr.x] == ' '){
surrounding.insert(curr);
}
}
}
}
//print answer
for (const auto& p: surrounding) {
cout<<"("<<p.x<<", "<<p.y<<"), ";
}
}
int main()
{
FindSurrounding(0, 8);
return 0;
}
OUTPUT: (2, 10), (1, 10), (2, 9), (0, 10), (2, 8), (2, 7), (1, 7), (0, 7),
I'm trying to write a piece of code, which goes over a loop of 8^12 iterations, and in each iteration when some conditions are met I push_back to a vector (each thread has its own vector to push_back, which I combine after the loop). But it seems that my the execution is more time consuming the more threads are active. Here' the function (method of an object) passed to each thread:
void HamiltonianKH::mapping_kernel(ull_int start, ull_int stop, std::vector<ull_int>* map_threaded, int _id) {
int n = 1;
out << "A new thread joined tha party! from " << start << " to " << stop << endl;
for (ull_int j = start; j < stop; j++) {
int bSz = 0, fSz = 0, N_e = 0;
std::tie(bSz, fSz, N_e) = calculateSpinElements(this->L, j);
if ((bSz + fSz == this->Sz) && N_e == this->num_of_electrons)
map_threaded->push_back(j);
if (show_system_size_parameters == true && (j - start) % ull_int((stop - start) * n / 4) == 0 && j > 0) {
out << n << "-th quarter of " << _id << endl;
n++;
}
}
}
, here is the caulculate_spinelements function:
std::tuple<int, int, int> calculateSpinElements(int L, ull_int& j) {
int bSz = 0; //bosonic total spin - spin of upper orbital locked to n=1 filling
int fSz = 0; //fermionic total spin
int N_e = 0; // numer of electrons in given state
std::vector<int> temp = int_to_binary(j, L);
for (int k = 0; k < L; k++) {
if (temp[k] < 4) bSz += 1;
else bSz -= 1;
if (temp[k] % 4 == 1) {
fSz += 1;
N_e += 1;
}
else if (temp[k] % 4 == 2) {
fSz -= 1;
N_e += 1;
}
else if (temp[k] % 4 == 3)
N_e += 2;
}
return std::make_tuple(bSz, fSz, N_e);
}
and her is the separation to threads:
void HamiltonianKH::generate_mapping() {
ull_int start = 0, stop = std::pow(8, L);
//mapping_kernel(start, stop, mapping, L, Sz, num_of_electrons);
//Threaded
std::vector<std::vector<ull_int>*> map_threaded(num_of_threads);
std::vector<std::thread> threads;
threads.reserve(num_of_threads);
for (int t = 0; t < num_of_threads; t++) {
start = t * (ull_int)std::pow(8, L) / num_of_threads;
stop = ((t + 1) == num_of_threads ? (ull_int)std::pow(8, L) : (ull_int)std::pow(8, L) * (t + 1) / num_of_threads);
map_threaded[t] = new std::vector<ull_int>();
threads.emplace_back(&HamiltonianKH::mapping_kernel, this, start, stop, map_threaded[t], t);
}
for (auto& t : threads) t.join();
for (auto& t : threads) t.~thread();
ull_int size = 0;
for (auto& t : map_threaded) {
size += t->size();
}
out << "size = " << size << endl;
for (auto & t : map_threaded)
mapping->insert(mapping->end(), t->begin(), t->end());
//sort(mapping->begin(), mapping->end());
if (show_system_size_parameters == true) {
out << "Mapping generated with " << mapping->size() << " elements" << endl;
out << "Last element = " << mapping->at(mapping->size() - 1) << endl;
}
//out << mapping[0] << " " << mapping[mapping.size() - 1] << endl;
assert(mapping->size() > 0 && "Not possible number of electrons - no. of states < 1");
}
The variables: mapping, L, num_of_electrons and Sz are public fields in the object. The whole code has over 2000 lines, but the execution after the generate_mapping() call is irrelevant to the problem.
Do any of you guys have an idea, why this piece of code executes longer on more threads?
Thank you very much in advance.
I would like some help understanding why my program is printing a grid of
....................
....................
....................
....................
....................
...............OOOOO
OOOOOOOOOOOOO.......
....................
....................
....................
The correct output would be so:
....................
....................
....................
....................
....................
....................
....................
.............O.O....
..............OO....
..............O.....
The way I wrote it is to create a copy of the old state and manipulate it using the rules of the game. After I check every cell, I store count of the number of neighbors alive for that cell. IF the count is greater than 3 or less than two, the cell will die.
If a cell has a count of 2 or 3 neighbors, it remains alive.
If a dead cell has a count of 3, it becomes alive.
These rules are directly applied to the copy version instead of the old and then print the copy.
I've tried using a debugger but I'm still unsure of how to use it properly. I haven't notice any red flags as of yet.
Here's my code:
#include <iostream>
#include <vector>
using std::vector;
using std::cout;
vector<vector<bool> > world = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
void generate(const vector<vector<bool> >&g,vector<vector<bool> >&newworld)
{
int count = 0;
newworld = g;
for(size_t i = 0; i < g.size();i++) {
for(size_t j = 0; j < g[i].size();j++) {
int x = g.size(); //I rows
int y = g[i].size(); //J columns
//wrap the edges with formula (x+n)%n where n = NumOfRows or NumOfCol
if(g[(((i+1)+x)%x)][(((j-1)+y)%y)]==true){//top left
count++;
}
else if(g[(((i+1)+x)%x)][j]==true){//top middle
count++;
}
else if(g[(((i+1)+x)%x)][(((j+1)+y)%y)]==true){//top right
count++;
}
else if(g[i][(((j-1)+y)%y)]==true){//left cell
count++;
}
else if(g[i][(((j+1)+y)%y)]==true){//right cell
count++;
}
else if(g[(((i-1)+x)%x)][(((j-1)+y)%y)]==true){ //bottom left
count++;
}
else if(g[(((i-1)+x)%x)][j]==true){//bottom middle
count++;
}
else if(g[(((i-1)+x)%x)][(((j+1)+y)%y)]==true){//bottom right
count++;
}
if (g[i][j]) {
if(count > 3 || count < 2) {//if alive cell has more than 3 or less than 2, die
newworld[i][j] = false;
}
else if (count == 2 || count == 3) { //remain the same
newworld[i][j] = g[i][j];
}
}
else if (g[i][j] == false) {//dead come alive
if(count == 3) {
newworld[i][j] = true;
}
}
}
}
}
void display(vector<vector<bool> >&a)
{
for(size_t row = 0; row <a.size(); row++) {
for(size_t column = 0; column <a[row].size(); column++){
if (a[row][column]) {
cout << 'O';
}
else {
cout << '.';
}
}
cout << '\n';
}
}
int main()
{
vector<vector<bool> > newworld;
generate(world,newworld);
display(newworld);
return 0;
}
The function generate has (at least) two problem.
count is initialized outside the nested loops, so it's never reset to zero (as it should, for every cell) and keeps growing.
All the conditions are mutually exclusive, so whenever one it's met, the others are skipped. There shouldn't be any else if, but only ifs.
Keeping the data structure you chose, you can rewrite that function as
using gof_t = std::vector<std::vector<bool>>;
void generate(gof_t& g, gof_t& newworld)
{
for(size_t i = 0, x = g.size(); i < x; i++)
{
for(size_t j = 0, y = g[i].size(); j < y; j++)
{
size_t i_prev = (i + x - 1) % x;
size_t i_next = (i + 1) % x;
size_t j_prev = (j + y - 1) % y;
size_t j_next = (j + 1) % y;
int count = g[i_prev][j_prev] + g[i_prev][j] + g[i_prev][j_next]
+ g[i ][j_prev] + g[i ][j_next]
+ g[i_next][j_prev] + g[i_next][j] + g[i_next][j_next];
newworld[i][j] = g[i][j] ? (count == 2 || count == 3) : (count == 3);
}
}
std::swap(g, newworld); // <-- Passing by non const reference, we can swap without copying
}
Live (pun intended), here.
So I try implementing a BFS algorithm and really understand how it works (creating some kind of "my version", out of scratch, just looking at graphs and some pseudocodes) and here is what I ended up with:
#include<iostream>
#include<string>
#include<fstream>
#include<queue>
using namespace std;
void main(int argc, char *argv[])
{
// Deklaracja uchwytu do pliku (tylko do odczytu pliku)
ifstream plik(argv[1]);
// Tablica stringow - przechowujaca wartosci pol 12x12
string labirynt[12];
pair <int, int> start;
pair <int, int> koniec;
// Wektor par - działa jak tablica, przechowuje pary współrzędnych pól
queue <pair<int, int>> kolejka;
// Tablica odwiedzin - sprawdza czy pole zostalo odwiedzone, 0 jesli nie, 1 jesli tak
bool odwiedzone[12][12] = { 0 };
// Zmienna pomocnicza - bo getline sluzy do umieszczania danych w stringu, nie w tablicy znakow
int i = 0;
// Pętla wczytująca tekst z pliku do tablicy labirynt
while (getline(plik, labirynt[i]))
{
i++;
}
// Wyszukanie początku i końca w labiryncie (A i B)
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 12; j++)
{
if (labirynt[i][j] == 'A')
{
start.first = i;
start.second = j;
}
if (labirynt[i][j] == 'B')
{
koniec.first = i;
koniec.second = j;
}
}
}
// Ustawiamy pole startowe jako odwiedzone - żadne pole nie może być odwiedzone więcej niż 1 raz
odwiedzone[start.first][start.second] = true;
// Wiersz i kolumna bieżącego wierzchołka
int w, k;
kolejka.push(start);
// Dopóki kolejka nie jest pusta
while (!kolejka.empty())
{
// Pobieramy z kolejki wiersz i kolumnę bieżącego wierzchołka
w = kolejka.front().first;
k = kolejka.front().second;
// Usuwamy parę z kolejki
kolejka.pop();
// Sprawdzamy czy dotarliśmy do wyjścia
if (w == koniec.first && k == koniec.second)
break;
// Przeglądamy sąsiadów bieżącego wierzchołka
for (i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
{
if ((i != j) && (!i || !j))
if (labirynt[w + i][k + j] == ' ' && !odwiedzone[w + i][k + j])
{
odwiedzone[w + i][k + j] = true;
pair <int, int> para;
para.first = w + i;
para.second = k + j;
kolejka.push(para);
cout << kolejka.front().first << endl;
cout << kolejka.front().second << endl;
}
}
}
system("PAUSE");
}
Here is the example maze I use (program reads from file that is dropped on .exe)
xxxxxxxxxxxx
xxA xxxxxxx
xx x xxxxxx
x x xxxxxx
xx x xxxx
xx xxx xxxxx
x xxxxxxxx
x x xxxxxxx
x xxx xxxxxx
x xxxxxxx
xxx Bxxx
xxxxxxxxxxxx
It works (shows coordinates of every field in a maze it goes through and finds B), but I don't know how to count moves needed to go through shortest path.
instead of using odwiedzone[w + i][k + j] = true; for checking the coordinate have been stepped before, use something like odwiedzone[w + i][k + j] = now + 1 to count the number of step from start to that position:
// first, declare all odwiedzone[][]=-1
...
odwiedzone[start.first][start.second] = 0;
// first position needs 0 step
...
for (i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
{
if ((i != j) && (!i || !j))
if (labirynt[w + i][k + j] == ' ' && odwiedzone[w + i][k + j]==-1)
{
odwiedzone[w + i][k + j] = odwiedzone[w][k]+1;
//next position = now position + 1
pair <int, int> para;
para.first = w + i;
para.second = k + j;
kolejka.push(para);
cout << kolejka.front().first << endl;
cout << kolejka.front().second << endl;
}
}
I see 2 ways of achieving what you want:
Use a separate queue for storing the associated distance with each cell, e.g. start will have 0, each neighbour of start will have 1 and so on. Each time you add a new neighbor, his value will be distance to current cell + 1. The value for destination in the second queue will give you the path length.
When adding a neighbor in the queue, record his parent. So when you find the source you can reconstruct the path and count the number of steps.