#include <array>
#include <ctime>
#include <vector>
#include <cstdlib>
#include <iostream>
// #include "solution.h"
using namespace std;
#define rep(i, j) for (int i = 0; i < 4; i++)\
for (int j = 0; j < 4; j++)
typedef array<array<int, 4>, 4> board;
board flip(board a, bool z = 1) {
board b;
rep(i, j) {
if (z) b[i][j] = a[j][i];
else b[i][j] = a[3 - j][3 - i];
}
return b;
}
board dir(board a, char c) {
if (c == 'U') return a;
if (c == 'L') return flip(a);
if (c == 'R') return flip(a, 0);
return flip(flip(a, 0));
}
board move(board a, char c) {
a = dir(a, c);
rep(j, i) {
if (a[i][j] == 0) continue;
for (int k = i + 1; k < 4; k++) {
if (a[k][j] == 0) continue;
if (a[i][j] == a[k][j]) {
a[i][j] *= -2;
a[k][j] = 0;
}
break;
}
}
rep(i, j) if (a[i][j] < 0) a[i][j] = -a[i][j];
rep(j, i) {
if (a[i][j] > 0) continue;
for (int k = i + 1; k < 4; k++) {
if (a[k][j] > 0) {
a[i][j] = a[k][j];
a[k][j] = 0;
break;
}
}
}
a = dir(a, c);
return a;
}
board put(board a) {
vector<pair<int, int>> zeros;
rep(i, j) if (a[i][j] == 0) zeros.push_back({i, j});
int p = rand() % 100;
int k = rand() % zeros.size();
int i = zeros[k].first;
int j = zeros[k].second;
int val = (p < 10) ? 4 : 2;
a[i][j] = val;
return a;
}
// BEGIN
// Энд функц заралж ашиглаж болно
board flip1(board a, bool z = 1) {
board b;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (z)
b[i][j] = a[j][i];
else
b[i][j] = a[3 - j][3 - i];
}
}
return b;
}
board dir1(board a, char c) {
if (c == 'U')
return a;
if (c == 'L')
return flip1(a);
if (c == 'R')
return flip1(a, 0);
return flip1(flip1(a, 0));
}
board move1(board a, char c) {
a = dir1(a, c);
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
if (a[i][j] == 0) continue;
for (int k = i + 1; k < 4; k++) {
if (a[k][j] == 0) continue;
if (a[i][j] == a[k][j]) {
a[i][j] *= -2;
a[k][j] = 0;
}
break;
}
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (a[i][j] < 0) a[i][j] = -a[i][j];
}
}
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
if (a[i][j] > 0) continue;
for (int k = i + 1; k < 4; k++) {
if (a[k][j] > 0) {
a[i][j] = a[k][j];
a[k][j] = 0;
break;
}
}
}
}
a = dir1(a, c);
return a;
}
bool over(const board& a, char move) {
board b = move1(a, move);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (b[i][j] == 0) {
return false;
}
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if ((i < 3 && b[i][j] == b[i + 1][j]) || (j < 3 && b[i][j] == b[i][j + 1])) {
return false;
}
}
}
return true;
}
int find_sum(board a){
int s=0;
for (int i = 0; i < 4; i++){
for (int j =0; j < 4; j++){
if (a[i][j]==0){
s++;
}
}
}
return s;
}
char play(board a) {
char up = 'U';
char down = 'D';
char left = 'L';
char right = 'R';
int sum_up,sum_down,sum_left,sum_right;
board b;
b = move1(a, up);
sum_up=find_sum(b);
if(over(a,up)){
sum_up=0;
}
b = move1(a, down);
sum_down=find_sum(b);
if(over(a,down)){
sum_down=0;
}
b = move1(a, right);
sum_right=find_sum(b);
if(over(a,right)){
sum_right=0;
}
b = move1(a, left);
sum_left=find_sum(b);
if(over(a,left)){
sum_left=0;
}
if(sum_right==sum_left && sum_up==sum_down){
return up;
}
if(sum_right>sum_left && sum_right>sum_up && sum_right>sum_down){
return right;
}
if(sum_left>sum_right && sum_left>sum_up && sum_left>sum_down){
return left;
}
if(sum_down>sum_up && sum_down>sum_left && sum_down>sum_right){
return down;
}
return up;
}
// Энд бичсэн хэсгээ л сервэрт илгээнэ
// END
int main(int argc, char **argv) {
string token;
if (argc == 2) token = argv[1];
srand(247);
srand(time(0));
board a; rep(i, j) a[i][j] = 0;
int itr = 0;
clock_t begin = clock();
while (true) {
char c = play(a);
rep(i, j) cout << a[i][j] << " \n"[j == 3];
cout << c << "\n";
if (c != 'U' && c != 'R' && c != 'D' && c != 'L') break;
board b = move(a, c);
if (itr > 0 && b == a) break;
a = put(b);
double timer = double(clock() - begin) / CLOCKS_PER_SEC;
if (timer > 10) break;
itr++;
}
int score = 0;
rep(i, j) score += a[i][j];
cout << "Score: " << score << endl;
cout << "Last state:\n";
rep(i, j) cout << a[i][j] << " \n"[j == 3];
double timer = double(clock() - begin) / CLOCKS_PER_SEC;
cout << "Time: " << (int)timer <<"sec\n";
return 0;
}