244 lines
5.3 KiB
C++
244 lines
5.3 KiB
C++
/*
|
|
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
|
VIM: let b:cf5run="{OUT}"
|
|
*/
|
|
#include <iostream>
|
|
#include <exception>
|
|
#include <chrono>
|
|
#include <vector>
|
|
|
|
void print(const std::vector<int>& row)
|
|
{
|
|
for (auto i : row){
|
|
std::cout << i << ',';
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
|
|
void print(const std::vector<std::vector<int>>& board)
|
|
{
|
|
for (const auto& row : board){
|
|
for (auto i : row){
|
|
std::cout << i << ',';
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
}
|
|
|
|
struct OneDimVec
|
|
{
|
|
using board_t = std::vector<int>;
|
|
using iterator_t = int *;
|
|
enum {dimentions=1};
|
|
static iterator_t begin(board_t& b, int n){
|
|
return b.data();
|
|
}
|
|
static iterator_t end(board_t& b, int n){
|
|
return b.data()+b.size();
|
|
}
|
|
static iterator_t next(iterator_t it){
|
|
return it+1;
|
|
}
|
|
};
|
|
|
|
struct OneDimVecReverse
|
|
{
|
|
using board_t = std::vector<int>;
|
|
using iterator_t = board_t::reverse_iterator;
|
|
enum {dimentions=1};
|
|
static iterator_t begin(board_t& b, int n){
|
|
return b.rbegin();
|
|
}
|
|
static iterator_t end(board_t& b, int n){
|
|
return b.rend();
|
|
}
|
|
static iterator_t next(iterator_t it){
|
|
return it+1;
|
|
}
|
|
};
|
|
|
|
|
|
template <typename Traits>
|
|
void push(typename Traits::board_t& board, int n)
|
|
{
|
|
auto q = Traits::begin(board, n);
|
|
auto pe = Traits::end(board, n);
|
|
for (auto p = Traits::next(q); p != pe; p=Traits::next(p)){
|
|
if (*p==0){
|
|
continue;
|
|
}
|
|
else if (*q == 0){
|
|
*q+=*p;
|
|
*p = 0;
|
|
}
|
|
else if (*q == *p){
|
|
*q+=*p;
|
|
*p = 0;
|
|
q = Traits::next(q);
|
|
}
|
|
else {
|
|
q = Traits::next(q);
|
|
*q = *p;
|
|
if (q != p){
|
|
*p = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void test(typename T::board_t v){
|
|
std::cout << "--------------" << std::endl;
|
|
print(v);
|
|
if constexpr (T::dimentions == 1){
|
|
push<T>(v,0);
|
|
} else {
|
|
for (int i = 0; i < T::dim_size(v); ++i){
|
|
push<T>(v,i);
|
|
}
|
|
}
|
|
std::cout << "-" << std::endl;
|
|
print(v);
|
|
}
|
|
|
|
struct BoardTraits
|
|
{
|
|
using board_t=std::vector<std::vector<int>>;
|
|
enum {dimentions=2};
|
|
struct iterator_t {
|
|
board_t& b;
|
|
int i;
|
|
int j;
|
|
int& operator*(){
|
|
return b[i][j];
|
|
}
|
|
bool operator != (const iterator_t& it){
|
|
return i != it.i;
|
|
}
|
|
iterator_t& operator = (const iterator_t& it){
|
|
i=it.i;
|
|
j=it.j;
|
|
return *this;
|
|
}
|
|
};
|
|
};
|
|
|
|
struct Up : public BoardTraits
|
|
{
|
|
static int dim_size(const board_t& b){
|
|
return b[0].size();
|
|
}
|
|
static iterator_t begin(board_t& b, int n){
|
|
return {b, 0, n};
|
|
}
|
|
static iterator_t end(board_t& b, int n){
|
|
return {b, int(b.size()), n};
|
|
}
|
|
static iterator_t next(const iterator_t& it){
|
|
return {it.b, it.i+1, it.j};
|
|
}
|
|
};
|
|
|
|
struct Down : public BoardTraits
|
|
{
|
|
static int dim_size(const board_t& b){
|
|
return b[0].size();
|
|
}
|
|
static iterator_t begin(board_t& b, int n){
|
|
return {b, int(b.size())-1, n};
|
|
}
|
|
static iterator_t end(board_t& b, int n){
|
|
return {b, -1, n};
|
|
}
|
|
static iterator_t next(const iterator_t& it){
|
|
return {it.b, it.i-1, it.j};
|
|
}
|
|
};
|
|
|
|
struct Left : public BoardTraits
|
|
{
|
|
using iterator_t = std::vector<int>::iterator;
|
|
static int dim_size(const board_t& b){
|
|
return b.size();
|
|
}
|
|
static iterator_t begin(board_t& b, int n){
|
|
return b[n].begin();
|
|
}
|
|
static iterator_t end(board_t& b, int n){
|
|
return b[n].end();
|
|
}
|
|
static iterator_t next(const iterator_t& it){
|
|
return it+1;
|
|
}
|
|
};
|
|
|
|
struct Right : public BoardTraits
|
|
{
|
|
using iterator_t = std::vector<int>::reverse_iterator;
|
|
static int dim_size(const board_t& b){
|
|
return b.size();
|
|
}
|
|
static iterator_t begin(board_t& b, int n){
|
|
return b[n].rbegin();
|
|
}
|
|
static iterator_t end(board_t& b, int n){
|
|
return b[n].rend();
|
|
}
|
|
static iterator_t next(const iterator_t& it){
|
|
return it+1;
|
|
}
|
|
};
|
|
|
|
|
|
int main ( void )
|
|
{try{
|
|
auto begin = std::chrono::high_resolution_clock::now();
|
|
|
|
test<OneDimVec>({4, 0, 4, 8});
|
|
test<OneDimVecReverse>({4, 0, 4, 8});
|
|
std::cout << "test" << std::endl;
|
|
//......
|
|
test<Left>({
|
|
{4, 0, 4, 8},
|
|
{2, 0, 2, 8},
|
|
{1, 1, 0, 0},
|
|
{4, 0, 4, 4}
|
|
});
|
|
test<Right>({
|
|
{4, 0, 4, 8},
|
|
{2, 0, 2, 8},
|
|
{1, 1, 0, 0},
|
|
{4, 0, 4, 4}
|
|
});
|
|
test<Up>({
|
|
{4, 0, 4, 8},
|
|
{2, 0, 2, 8},
|
|
{1, 1, 0, 0},
|
|
{4, 0, 4, 4}
|
|
});
|
|
test<Down>({
|
|
{4, 0, 4, 8},
|
|
{2, 0, 2, 8},
|
|
{1, 1, 0, 0},
|
|
{4, 0, 4, 4}
|
|
});
|
|
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
std::chrono::duration<double> seconds = end - begin;
|
|
std::cout << "Time: " << seconds.count() << std::endl;
|
|
return 0;
|
|
}
|
|
catch ( const std::exception& e )
|
|
{
|
|
std::cerr << std::endl
|
|
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
|
return 2;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
std::cerr << std::endl
|
|
<< "unknown exception." << std::endl;
|
|
return 1;
|
|
}}
|
|
|