Advertisement
Guest User

Untitled

a guest
Dec 16th, 2019
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.96 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <thread>
  4. #include <vector>
  5. #include <chrono>
  6. #include <sstream>
  7. #include <math.h>
  8. #include <cassert>
  9. #include <mutex>
  10. #include <condition_variable>
  11. #include <array>
  12.  
  13. using namespace std;
  14.  
  15. class Tile {
  16. bool was;
  17. bool is;
  18. int step;
  19. public:
  20. Tile(bool what) : was(false), is(what), step(0) {};
  21.  
  22. void newState(bool state) {
  23. this->was = this->is;
  24. this->is = state;
  25. this->step++;
  26. }
  27.  
  28. void update() {
  29. this->was = this->is;
  30. this->step++;
  31. }
  32.  
  33. int getStep() {
  34. return this->step;
  35. }
  36.  
  37. bool getWas() {
  38. return this->was;
  39. }
  40.  
  41. bool getIs() {
  42. return this->is;
  43. }
  44. };
  45.  
  46. int N, T, S, height, width;
  47. vector<Tile> field;
  48. vector<int> stepcounter;
  49. vector<bool> alarmclock;
  50. mutex Mutex;
  51. condition_variable cv;
  52.  
  53. ifstream fin("C:\\clionfolder\\prog5\\input.txt");
  54. ofstream fout("C:\\clionfolder\\prog5\\output.txt");
  55.  
  56. void input() {
  57. int temp;
  58. fin >> N >> T >> S;
  59. for (int i = 0; i < N * N; i++) {
  60. fin >> temp;
  61. field.emplace_back(temp);
  62. }
  63. }
  64.  
  65. int moveInField(int horiz, int vertic, int id, int direction) {
  66. int x = id / horiz;
  67. int y = id % horiz;
  68. switch (direction) {
  69. case (0): { //up
  70. x--;
  71. if (x < 0) {
  72. x = vertic - 1;
  73. }
  74. break;
  75. }
  76. case (1): { //right
  77. y++;
  78. if (y == horiz) {
  79. y = 0;
  80. }
  81. break;
  82. }
  83. case (2): { //down
  84. x++;
  85. if (x == vertic) {
  86. x = 0;
  87. }
  88. break;
  89. }
  90. case (3): { //left
  91. y--;
  92. if (y < 0) {
  93. y = horiz - 1;
  94. }
  95. break;
  96. }
  97. }
  98. return x * horiz + y;
  99. }
  100.  
  101. int defineThreadCoverage() {
  102. //Каждый тред покрывает прямоугольник i x (N*N/T/i) для оптимизации числа соседей.
  103. int temp = N * N / T; //число клеток на один тред
  104. if (N % T == 0) { //Если получится разбить на "полосы", то у каждой зоны всего две соседних
  105. return N / T;
  106. } else {
  107. for (int i = (int) sqrt(temp); i > 0; i--) {
  108. if (temp % i == 0) {
  109. if (N % i == 0 && N % (temp / i) == 0) {
  110. return i;
  111. }
  112. }
  113. }
  114. }
  115. throw ("Error");
  116. }
  117.  
  118. int zoneId(int TileId) {
  119. int x = TileId / N;
  120. int y = TileId % N;
  121. x = x / height;
  122. y = y / width;
  123. return x * (N / width) + y;
  124. }
  125.  
  126. bool goodToGo(int id, array<int, 8> &neighbours) {
  127. //id-ый тред покрывает клетки с [(id / horiz) * vertic][(id % horiz) * horiz] по [(id / horiz) * vertic + height - 1][(id % horiz) * horiz + width - 1]
  128. int curstep = stepcounter[id];
  129. bool result = true;
  130. Mutex.lock();
  131. for (int i:neighbours) {
  132. if (stepcounter[i] < curstep) {
  133. result = false;
  134. }
  135. }
  136. Mutex.unlock();
  137. return result;
  138. }
  139.  
  140. void lookForNeighbours(int tileNumber, array<int, 8> &neighbours,int horiz, int vertic) {
  141. for (int i = 0; i < 8; i++) {
  142. neighbours[i] = moveInField(horiz, vertic, tileNumber, i % 4);
  143. }
  144. for (int i = 0; i < 4; i++) {
  145. neighbours[i] = moveInField(horiz, vertic, neighbours[i], (i + 1) % 4);
  146. }
  147. }
  148.  
  149. int neighboursAlive(int tileNumber) {
  150. int alive = 0;
  151. int curstep = stepcounter[zoneId(tileNumber)];
  152. array<int, 8> neighbours;
  153. lookForNeighbours(tileNumber,neighbours,N,N);
  154. for (int i:neighbours) {
  155. Mutex.lock();
  156. assert(field[i].getStep() == curstep || field[i].getStep() == curstep + 1);
  157. if (field[i].getStep() == curstep) {
  158. if (field[i].getIs()) {
  159. alive++;
  160. }
  161. } else {
  162. if (field[i].getWas()) {
  163. alive++;
  164. }
  165. }
  166. Mutex.unlock();
  167. }
  168. return alive;
  169. }
  170.  
  171. void ThreadBody(int id) {
  172. array<int, 8> neighbours;
  173. int horiz = N / width;
  174. int vertic = N / height;
  175. lookForNeighbours(id, neighbours,horiz,vertic);
  176. for (int COUNTER = 0; COUNTER < S; COUNTER++) {
  177. while (!goodToGo(id, neighbours)) {
  178. std::unique_lock<std::mutex> lk(Mutex);
  179. alarmclock[id] = false;
  180. cv.wait(lk, [id] { return alarmclock[id]; });
  181. lk.unlock();
  182. }
  183. int tileNumber, aliveNeighbours;
  184. //Здесь всё просто, для каждой клетки проверяем условие по соседям и шенаниганы из условия выполняем
  185. for (int i = (id / horiz) * height; i < (id / horiz + 1) * height; i++) {
  186. for (int j = (id % horiz) * width; j < (id % horiz + 1) * width; j++) {
  187. tileNumber = i * N + j;
  188. bool state = field[tileNumber].getIs();
  189. aliveNeighbours = neighboursAlive(tileNumber);
  190. Mutex.lock();
  191. if (state && (aliveNeighbours < 2 || aliveNeighbours > 3)) {
  192. field[tileNumber].newState(false);
  193. } else if (!state && aliveNeighbours == 3) {
  194. field[tileNumber].newState(true);
  195. } else {
  196. field[tileNumber].update();
  197. }
  198. Mutex.unlock();
  199. }
  200. }
  201. stepcounter[id]++;
  202. Mutex.lock();
  203. for(int i : neighbours){
  204. alarmclock[i] = true;
  205. }
  206. Mutex.unlock();
  207. cv.notify_one();
  208. /*ostringstream out;
  209. out << "Thread with id " << id << " started\n";
  210. cout << out.str();
  211.  
  212. out.str("");
  213. out << "Thread with id " << id << " finished\n";
  214. cout << out.str(); */
  215. }
  216.  
  217. }
  218.  
  219. void output() {
  220. for (int i = 0; i < N; i++) {
  221. for (int j = 0; j < N; j++) {
  222. if (field[i * N + j].getIs()) {
  223. cout << "1 ";
  224. } else {
  225. cout << "0 ";
  226. }
  227. }
  228. cout << endl;
  229. }
  230. }
  231.  
  232. int main() {
  233. input();
  234. output();
  235. cout << endl;
  236. this_thread::sleep_for(1ms);
  237. vector<thread> ThreadPile;
  238. height = defineThreadCoverage(); //высота покрываемой зоны
  239. width = N * N / T / height; //ширина покрываемой зоны
  240. for (int i = 0; i < T; i++) {
  241. stepcounter.push_back(0);
  242. alarmclock.push_back(false);
  243. }
  244. for (int i = 0; i < T; i++) {
  245. ThreadPile.emplace_back(ThreadBody, i);
  246. }
  247. for (int i = 0; i < T; i++) {
  248. if (ThreadPile[i].joinable()) {
  249. ThreadPile[i].join();
  250. }
  251. }
  252. output();
  253. return 0;
  254. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement