Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
- static constexpr int MEMORY_SIZE = 10;
- enum class Direction { AWAY = 0, LEFT = 1, RIGHT = 2, UP = 3, DOWN = 4, SAME = 5 };
- using std::cin;
- using std::cerr;
- using std::cout;
- using std::endl;
- using std::vector;
- using std::sort;
- struct Position
- {
- int x{}, y{};
- };
- struct CopterState
- {
- Direction dir{Direction::AWAY};
- unsigned char mem[MEMORY_SIZE]{};
- };
- unsigned get_value(unsigned char *mem)
- {
- return mem[0] | (mem[1] << 8) | (mem[2] << 16) | (mem[3] << 24);
- }
- void random_bytes(unsigned char *mem, size_t size)
- {
- static int fd = -1;
- if (fd < 0) {
- fd = open("/dev/urandom", O_RDONLY, 0);
- if (fd < 0) {
- cerr << "cannot open /dev/urandom" << endl;
- abort();
- }
- }
- ssize_t sz = read(fd, mem, size);
- if (sz < 0) {
- cerr << "read error from /dev/urandom" << endl;
- abort();
- }
- if (!sz) {
- cerr << "EOF from /dev/urandom" << endl;
- abort();
- }
- if (sz != (ssize_t) size) {
- cerr << "invalid read from /dev/urandom" << endl;
- abort();
- }
- }
- int main()
- {
- int copter_count;
- cin >> copter_count;
- if (copter_count <= 0 || copter_count > 1000) {
- cerr << "invalid copter count" << endl;
- abort();
- }
- vector<Position> targets(copter_count);
- for (int i = 0; i < copter_count; ++i) {
- int x, y;
- cin >> x >> y;
- targets[i] = {x, y};
- }
- CopterState self{};
- for (int i = 0; i < MEMORY_SIZE; ++i) {
- int m;
- cin >> m;
- if (m < 0 || m > 255) {
- cerr << "invalid memory value" << endl;
- abort();
- }
- self.mem[i] = m;
- }
- int neighbour_count;
- cin >> neighbour_count;
- if (neighbour_count < 0 || neighbour_count >= copter_count) {
- cerr << "invalid neighbour count " << neighbour_count << endl;
- abort();
- }
- vector<CopterState> neighbours(neighbour_count);
- for (int i = 0; i < neighbour_count; ++i) {
- int dir;
- cin >> dir;
- if (dir < int(Direction::LEFT) || dir > int(Direction::SAME)) {
- cerr << "invalid direction for neighbour " << i << endl;
- abort();
- }
- neighbours[i].dir = Direction(dir);
- for (int j = 0; j < MEMORY_SIZE; ++j) {
- int m;
- cin >> m;
- if (m < 0 || m > 255) {
- cerr << "invalid memory value" << endl;
- abort();
- }
- neighbours[i].mem[j] = m;
- }
- }
- if (self.mem[0] == 0) {
- // initial state
- self.mem[0] = 1;
- random_bytes(self.mem + 1, 4);
- self.dir = Direction::SAME;
- self.mem[5] = int(Direction::AWAY);
- memcpy(&self.mem[6], &self.mem[1], 4);
- } else if (self.mem[0] >= 1 && self.mem[0] < copter_count) {
- // propagation state
- unsigned cur = get_value(self.mem + 6);
- int max_ind = -1;
- unsigned max_val = cur;
- for (int i = 0; i < neighbour_count; ++i) {
- unsigned n = get_value(neighbours[i].mem + 6);
- if (n > max_val) {
- max_val = n;
- max_ind = i;
- }
- }
- if (max_ind >= 0) {
- memcpy(self.mem + 6, neighbours[max_ind].mem + 6, 4);
- self.mem[5] = int(neighbours[max_ind].dir);
- }
- ++self.mem[0];
- self.dir = Direction::SAME;
- } else if (self.mem[0] >= copter_count && self.mem[0] <= copter_count * 2) {
- // movement state
- int new_dir = int(Direction::SAME);
- if (self.mem[5] == int(Direction::LEFT)
- || self.mem[5] == int(Direction::RIGHT)
- || self.mem[5] == int(Direction::UP)
- || self.mem[5] == int(Direction::DOWN)) {
- int i;
- for (i = 0; i < neighbour_count; ++i) {
- if (int(neighbours[i].dir) == self.mem[5]) {
- new_dir = int(neighbours[i].mem[5]);
- break;
- }
- }
- if (i >= neighbour_count) {
- cerr << "no neighbour in the given direction" << endl;
- abort();
- }
- self.dir = Direction(self.mem[5]);
- self.mem[5] = new_dir;
- } else {
- self.dir = Direction::SAME;
- }
- ++self.mem[0];
- } else if (self.mem[0] == copter_count * 2 + 1) {
- // ensure, that all copters are at the same point
- if (neighbour_count + 1 != copter_count) {
- cerr << "not all copters at the same point" << endl;
- abort();
- }
- // sort random numbers and assign serial to each copter
- vector<unsigned> copter_ids(copter_count);
- for (int i = 0; i < neighbour_count; ++i) {
- copter_ids[i] = get_value(neighbours[i].mem + 1);
- }
- unsigned self_id = get_value(self.mem + 1);
- copter_ids[neighbour_count] = self_id;
- sort(copter_ids.begin(), copter_ids.end());
- memset(self.mem + 5, 0, 5);
- int i;
- for (i = 0; i < int(copter_ids.size()); ++i) {
- if (self_id == copter_ids[i]) {
- break;
- }
- }
- if (i >= int(copter_ids.size())) {
- cerr << "copter_id not found" << endl;
- abort();
- }
- self.mem[5] = i + 1;
- // assign target from the list
- // assume all copters are not at the first target point
- int diff_x = targets[i].x - targets[0].x;
- int diff_y = targets[i].y - targets[0].y;
- if ((short) diff_x != diff_x) {
- cerr << "target figure is too big" << endl;
- abort();
- }
- if ((short) diff_y != diff_y) {
- cerr << "target figure is too big" << endl;
- abort();
- }
- self.mem[6] = diff_x;
- self.mem[7] = diff_x >> 8;
- self.mem[8] = diff_y;
- self.mem[9] = diff_y >> 8;
- ++self.mem[0];
- self.dir = Direction::SAME;
- } else {
- // extract direction
- int diff_x = (short)(self.mem[6] | self.mem[7] << 8);
- int diff_y = (short)(self.mem[8] | self.mem[9] << 8);
- if (diff_x < 0) {
- self.dir = Direction::LEFT;
- ++diff_x;
- } else if (diff_x > 0) {
- self.dir = Direction::RIGHT;
- --diff_x;
- } else if (diff_y < 0) {
- self.dir = Direction::DOWN;
- ++diff_y;
- } else if (diff_y > 0) {
- self.dir = Direction::UP;
- --diff_y;
- } else {
- self.dir = Direction::SAME;
- }
- self.mem[6] = diff_x;
- self.mem[7] = diff_x >> 8;
- self.mem[8] = diff_y;
- self.mem[9] = diff_y >> 8;
- }
- if (self.dir == Direction(0)) {
- cerr << "copter does not make a turn" << endl;
- abort();
- }
- std::cout << int(self.dir);
- for (int i = 0; i < 10; ++i) {
- std::cout << " " << int(self.mem[i]);
- }
- cout << endl;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement