diff --git a/the-uxuhul-voting-system/Makefile b/the-uxuhul-voting-system/Makefile new file mode 100644 index 0000000..7022988 --- /dev/null +++ b/the-uxuhul-voting-system/Makefile @@ -0,0 +1,16 @@ +EXE=a.out +CC=g++ +CFLAGS=-g -lm -O2 -std=gnu++17 -Wall -Wextra -Weffc++ +OBJ=main.cpp + +.PHONY: run +run: $(EXE) + ./$(EXE) +#include + +int prefs[100][8]; +int choice[100][8]; + + +void print_result(int res) +{ + int d3 = (res>>2); + int d2 = (res>>1)&1; + int d1 = (res)&1; + + char c3 = 'Y'*(d3 == 1) + 'N'*(d3 == 0); + char c2 = 'Y'*(d2 == 1) + 'N'*(d2 == 0); + char c1 = 'Y'*(d1 == 1) + 'N'*(d1 == 0); + printf("%c%c%c\n", c3, c2, c1); +} + +void round(int n_pr) +{ + // Get preferences + for (int i{0}; i < n_pr; ++i) { + scanf("%d %d %d %d %d %d %d %d\n", + &prefs[i][0], &prefs[i][1], &prefs[i][2], &prefs[i][3], + &prefs[i][4], &prefs[i][5], &prefs[i][6], &prefs[i][7] + ); + } + + for (int pr{n_pr-1}; 0 <= pr; --pr) + { + // For each possible state (states=[0, 7]) before a stone is turned + // see which of the 3 outcome states would be most prefered by the + // current priest and set that as the priests choice in the array + if (pr < n_pr-1) { + for (int c{0}; c < 8; ++c) + { + // Min value == highest preference + int min_i = c^1; + int min = prefs[pr][ choice[pr+1][c^1] ]; + + if (prefs[pr][ choice[pr+1][c^2] ] < min) { + min_i = c^2; + min = prefs[pr][ choice[pr+1][c^2] ]; + } + if (prefs[pr][ choice[pr+1][c^4] ] < min) { + min_i = c^4; + min = prefs[pr][ choice[pr+1][c^4] ]; + } + choice[pr][c] = choice[pr+1][min_i]; + } + } else { + for (int c{0}; c < 8; ++c) + { + int min_i = c^1; + int min = prefs[pr][c^1]; + + if (prefs[pr][c^2] < min) { + min_i = c^2; + min = prefs[pr][c^2]; + } + + if (prefs[pr][c^4] < min) { + min_i = c^4; + min = prefs[pr][c^4]; + } + choice[pr][c] = min_i; + } + } + } + + // Last priest gets to choose which one of 1,2,4 that he likes best + print_result(choice[0][0]); +} + + + + +int main() +{ + int n_rounds, n_priests; + scanf("%d\n", &n_rounds); + while (0 < n_rounds--) + { + scanf("%d\n", &n_priests); + round(n_priests); + } +} diff --git a/whac-a-mole/Makefile b/whac-a-mole/Makefile new file mode 100644 index 0000000..754aff8 --- /dev/null +++ b/whac-a-mole/Makefile @@ -0,0 +1,18 @@ +EXE=whac-a-moler +CC=g++ +CFLAGS=-g -O2 -std=gnu++17 +LFLAGS=-lm +WFLAGS=-Wall -Wextra -Weffc++ -Wpedantic +OBJ=main.cpp + + +.PHONY: clean test +test: $(EXE) + ./$(EXE) +#include +#include + +#include +using std::string; + +#include +using std::cout; + +#include +using std::vector; +#include + +void debug_indent(int lvl) {for (int i{0}; i < lvl; ++i) {cout << " ";}} + + +struct Mole +{ + int x; + int y; + int t; + + bool operator<(const Mole& other) { + return this->t > other.t; + } +}; + +struct Move +{ + int x; + int y; + + bool operator<(const Move& other) { + if ( (this->x < other.x) || + (this->x == other.x && this->y < other.y) + ) { + return true; + } else { + return false; + } + } +}; + +vector generate_moves(const int d) +{ + vector moves; + for (int i{-d}; i <= d; ++i) { + for (int j{-d}; j <= d; ++j) { + if ( (i*i + j*j) <= d*d) { + moves.push_back( {i,j} ); + }}} + + return moves; +} + + +struct Matrix +{ + bool *m; + size_t width; + int max_movement; + + Matrix( + size_t _width, + int _max_movement) : + m(nullptr), + width(_width), + max_movement(_max_movement) + { + m = (bool*) malloc( (width*width) * sizeof(bool) ); + for (size_t i{0}; i < width*width; ++i) { + *(m+i) = false; + } + }; + ~Matrix() { + delete m; + } + + + void set(int x, int y, bool val) { + size_t index = (x+max_movement)*width + (y+max_movement); + m[index] = val; + } + + bool get(int x, int y) const { + size_t index = (x+max_movement)*width + (y+max_movement); + return m[index]; + } + + void reinit( + const int t, + vector::const_iterator new_moles, + const vector::const_iterator end_iter) + { + // Zero existing matrix + for (size_t i{0}; i < width*width; ++i) { + *(m+i) = false; + } + if (t != new_moles->t) { return; } // Exit after board clear if no moles are on board + + int current_time = new_moles->t; + while (new_moles != end_iter && new_moles->t == current_time) + { + this->set(new_moles->x, new_moles->y, true); + ++new_moles; + } + } + + void print() + { + for (size_t j{0}; j < width; ++j) { + for (size_t i{0}; i < width; ++i) { + printf("(%2lu,%2lu)=%d ", i, j, *((m+i*width)+j)); + } + puts(""); + } + } +}; + +const int MAX_T = 10; +const int MAX_W = 20; +const int MAX_MV = 5; + + +struct Memo +{ + int max_hits[MAX_T][MAX_W + 2*MAX_MV][MAX_W + 2*MAX_MV]; + const int max_time; + const int board_width; + const int max_movement; + + Memo( + int _max_time, + int _board_width, + int _max_movement) : + max_time(_max_time), + board_width(_board_width), + max_movement(_max_movement) + { + for (int i{0}; i < max_time; ++i) { + for (int j{0}; j < board_width+2*max_movement; ++j) { + for (int k{0}; k < board_width+2*max_movement; ++k) { + max_hits[i][j][k] = 0; + } + } + } + } + + bool is_inside(int t, int x, int y) const { + bool inside = (1 <= t && t <= max_time); + inside &= (-max_movement <= x && x < board_width+max_movement); + inside &= (-max_movement <= y && y < board_width+max_movement); + + return inside; + } + + void set(int t, int x, int y, int val) { + assert( this->is_inside(t, x, y) ); + max_hits[t-1][x+max_movement][y+max_movement] = val; + } + + int get(int t, int x, int y) const { + assert( this->is_inside(t, x, y) ); + return max_hits[t-1][x+max_movement][y+max_movement]; + } + + void print() + { + for (int i{0}; i < max_time; ++i) { + printf("T-%d:\n", i+1); + printf(" : "); + for(int k{0}; k < board_width+2*max_movement; ++k) { + printf("%3d|", k-max_movement); + } + puts(""); + for (int j{0}; j < board_width+2*max_movement; ++j) { + + printf("%3d: ", j-max_movement); + for (int k{0}; k < board_width+2*max_movement; ++k) { + printf("%3d ", max_hits[i][j][k]); + } + puts("\n"); + } + puts(""); + } + } +}; + +int max(int a, int b) { + return (a < b) ? b : a; +} + +int max_hits_from_position( + const int t, + const int max_t, + const int x, + const int y, + const Memo& max_hits, + const Matrix& active_moles, + const vector& moves) +{ + int current_max = 0; + for (const auto& move : moves) + { + int hits = 0; + + const int new_x = x + move.x; + const int new_y = y + move.y; + if ( !max_hits.is_inside(t, new_x, new_y) ) { + continue; // Check new move if current moves whac way off board + } + + // Check current pos + if ( active_moles.get(x, y) ) { + ++hits; + } + + if ( !(move.x == 0 && move.y == 0) ) + { + // Yes I know, it is lazy + if ( (move.x%4 == 0 && move.y == 0) || + (move.y%4 == 0 && move.x == 0)) + { + const int it_x = (move.x/4); + const int it_y = (move.y/4); + + if ( active_moles.get( (x + 1*it_x), (y + 1*it_y) ) ) { + ++hits; + } + if ( active_moles.get( (x + 2*it_x), (y + 2*it_y) ) ) { + ++hits; + } + if ( active_moles.get( (x + 3*it_x), (y + 3*it_y) ) ) { + ++hits; + } + } + else if (move.x%2 == 0 && move.y%2 == 0) + { + const int it_x = (move.x/2); + const int it_y = (move.y/2); + + if ( active_moles.get( (x + 1*it_x), (y + 1*it_y) ) ) { + ++hits; + } + } + else if (move.x%3 == 0 && move.y%3 == 0) + { + const int it_x = (move.x/3); + const int it_y = (move.y/3); + + if ( active_moles.get( (x + 1*it_x), (y + 1*it_y) ) ) { + ++hits; + } + if ( active_moles.get( (x + 2*it_x), (y + 2*it_y) ) ) { + ++hits; + } + } + else if ( (move.x%5 == 0 && move.y == 0) || + (move.y%5 == 0 && move.x == 0)) + { + const int it_x = (move.x/5); + const int it_y = (move.y/5); + + if ( active_moles.get( (x + 1*it_x), (y + 1*it_y) ) ) { + ++hits; + } + if ( active_moles.get( (x + 2*it_x), (y + 2*it_y) ) ) { + ++hits; + } + if ( active_moles.get( (x + 3*it_x), (y + 3*it_y) ) ) { + ++hits; + } + if ( active_moles.get( (x + 4*it_x), (y + 4*it_y) ) ) { + ++hits; + } + } + + // Check pos at end of line: new_x and new_y + if ( active_moles.get(new_x, new_y) ) { + ++hits; + } + } + + // Add destination if not at last timestep + if (t < max_t) { + hits += max_hits.get(t+1, new_x, new_y); + } + + current_max = max(hits, current_max); + } + + return current_max; +} + +void test_case( + const int n, // Width of board + const int d, // Max distance of a move + const int n_moles) +{ + int b_width = n + 2*d; + Matrix active_moles(b_width, d); + + vector moles; + { + int x, y, t; + for (int i{0}; i < n_moles; ++i) { + scanf("%d %d %d\n", &x, &y, &t); + moles.push_back( {x, y, t} ); + } + } + std::sort(moles.begin(), moles.end()); + + int timestamp_last_mole = moles.begin()->t; + + + Memo max_hits(timestamp_last_mole, n, d); + + // Generate all valid moves for this test case + vector moves = generate_moves(d); + + // Iterator to beginning of sequence of moles for the current timestamp + vector::const_iterator current_moles = moles.begin(); + + int first_t = 1; + for (int t{timestamp_last_mole}; 1 <= t; --t) + { + // Iterate to moles on this timestep or earlier one (backwards iteration through time) + while ( (current_moles != moles.end()) && + (current_moles->t) > t) + { + ++current_moles; + } + + // Break out early if mole list is emptied + if (current_moles == moles.end()) + { + first_t = t+1; + break; + } + + // Re-initialize active_moles: zero and set new moles + active_moles.reinit(t, current_moles, moles.end()); + + // 2D iteration over all possible start positions in (and outside) the board + for (int i{-d}; i < n+d; ++i) { + for (int j{-d}; j < n+d; ++j) { + + int max_val = max_hits_from_position( + t, timestamp_last_mole, + i, j, + max_hits, + active_moles, + moves); + max_hits.set(t, i, j, max_val); + } + } + + } + + int max_val = 0; + for (int i{-d}; i < n+d; ++i) { + for (int j{-d}; j < n+d; ++j) { + int val = max_hits.get(first_t, i, j); + if (max_val < val) { + max_val = val; + } + } + } + printf("%d\n", max_val); +} + +int main() +{ + int n, d, m; + + while(1) + { + scanf("%d %d %d\n", &n, &d, &m); + if (n+d+m == 0) { break; } // All zeroes (no negative values in file) + + test_case(n, d, m); + } +} +