#include "vision.h"

#include <algorithm>
#include <cassert>
#include <vector>
#include <numeric>
#include <iostream>

template<class T> using vec = std::vector<T>;
using ll = long long;

vec<int> getVisionPattern1d() {
  return { 1, 2, 2, 1, 1, 2 };
}

int getMove1d( vec<int> v ) {
  assert( (int)v.size() % 2 == 1 );
  int k = (int)v.size() / 2;
  assert( v[k] == k );

  if( k == 1 ){
    if( v[0] > 1 ) return 0;
    if( v[2] > 1 ) return 2;
  }

  vec<vec<int>> pat2 = {
    { 2, 1, 2, 2, 1 },
    { 1, 2, 2, 1, 1 },
    { 1, 1, 2, 1, 2 }
  };

  if( std::find( pat2.begin(), pat2.end(), v ) != pat2.end() ) return 4;

  std::reverse( v.begin(), v.end() );
  assert( std::find( pat2.begin(), pat2.end(), v ) != pat2.end() );
  return 0;
}

vec<vec<int>> getVisionPattern2d() {
  vec<int> d1 = getVisionPattern1d();
  vec<vec<int>> ret(12, vec<int>(12, 1));
  for( int i = 0; i < 12; i++ )
    for( int j = 0; j < 12; j += 4 )
      ret[(i + j) % 12][i] = d1[i % 6];

  if( false ){
    vec<vec<bool>> blind(12, vec<bool>(12, false));
    for( int i = 0; i < 12; i++ )
      for( int j = 0; j < 12; j++ ){
	if( ret[i][j] > 1 ) continue;
	bool good = false;
	for( int di = -1; di <= +1; di++ )
	  for( int dj = -1; dj <= +1; dj++ )
	    good |= (ret[(i + di + 12) % 12][(j + dj + 12) % 12] > 1);
	blind[i][j] = !good;
      }
    std::cerr << "blind:" << std::endl;
    for( int i = 0; i < 12; i++ ){
      for( int j = 0; j < 12; j++ )
	std::cerr << blind[i][j] << ' ';
      std::cerr << std::endl;
    }
  }
  
  return ret;
}

std::pair<int, int> getMove2d( vec<vec<int>> v ) {
  assert( (int)v.size() % 2 == 1 );
  int k = (int)v.size() / 2;
  assert( v[k][k] == k );

  if( k == 1 ){
    for( int i = 0; i < 3; i++ )
      for( int j = 0; j < 3; j++ )
	if( v[i][j] > 1 ) return { i, j };
    return { 0, 1 }; // foarte important in pizda matii chiar nu glumesc
  }

  assert( k == 2 );
  vec<int> diag1(5), diag2(5);
  for( int i = 0; i < 5; i++ )
    diag1[i] = v[i][i];
  for( int i = 0; i < 5; i++ )
    diag2[i] = v[i][4 - i];

  if( std::reduce( diag1.begin(), diag1.end() ) < std::reduce( diag2.begin(), diag2.end() ) ){
    int ret = getMove1d( diag1 );
    return { ret, ret };
  }else{
    int ret = getMove1d( diag2 );
    return { ret, 4 - ret };
  }
 
}
