#include <algorithm>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <istream>
#include <iterator>
#include <map>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#define DBG(x) { cout << left << setw(40) << #x << (x) << endl; }

template<int Base, int Exp>
class Power{
public:
	static const int value = Power<Base,Exp-1>::value * Base;
};

template<int Base>
class Power<Base,0>{
public:
	static const int value = 1;
};

template<template <int,int,int> class Func, template<int> class ArgGetter, int Times>
class Apply{
public:
	template<typename T>
	static void exec(T& t){
		typedef ArgGetter<Times> Arg;
		Func<Arg::type::x, Arg::type::y, Arg::type::value>::exec(t);
		Apply<Func,ArgGetter,Times-1>::exec(t);
	}
	template<typename T>
	static void exec(T const& t){
		typedef ArgGetter<Times> Arg;
		Func<Arg::type::x, Arg::type::y, Arg::type::value>::exec(t);
		Apply<Func,ArgGetter,Times-1>::exec(t);
	}
	template<typename T, typename U>
	static void exec(T& t, U& u){
		typedef ArgGetter<Times> Arg;
		Func<Arg::type::x, Arg::type::y, Arg::type::value>::exec(t, u);
		Apply<Func,ArgGetter,Times-1>::exec(t, u);
	}
	template<typename T, typename U>
	static void exec(T const& t, U& u){
		typedef ArgGetter<Times> Arg;
		Func<Arg::type::x, Arg::type::y, Arg::type::value>::exec(t, u);
		Apply<Func,ArgGetter,Times-1>::exec(t, u);
	}
	template<typename T, typename U>
	static void exec(T& t, U const& u){
		typedef ArgGetter<Times> Arg;
		Func<Arg::type::x, Arg::type::y, Arg::type::value>::exec(t, u);
		Apply<Func,ArgGetter,Times-1>::exec(t, u);
	}
	template<typename T, typename U>
	static void exec(T const& t, U const& u){
		typedef ArgGetter<Times> Arg;
		Func<Arg::type::x, Arg::type::y, Arg::type::value>::exec(t, u);
		Apply<Func,ArgGetter,Times-1>::exec(t, u);
	}
};

template<template <int,int,int> class Func, template<int> class ArgGetter>
class Apply<Func,ArgGetter,0>{
public:
	template<typename T>
	static void exec(T&){}
	template<typename T>
	static void exec(T const&){}
	template<typename T, typename U>
	static void exec(T&, U&){}
	template<typename T, typename U>
	static void exec(T const&, U&){}
	template<typename T, typename U>
	static void exec(T&, U const&){}
	template<typename T, typename U>
	static void exec(T const&, U const&){}
};

template<template<int,int> class Iterator, int Size, int X, int Y, int N>
class IfCellTraversed{
public:
	typedef Iterator<Size,N> Current;
	static const bool value = (Current::x == X && Current::y == Y) || IfCellTraversed<Iterator,Size,X,Y,N-1>::value;
};

template<template<int,int> class Iterator, int Size, int X, int Y>
class IfCellTraversed<Iterator,Size,X,Y,0>{
public:
	typedef Iterator<Size,1> Current;
	static const bool value = (Current::x == X && Current::y == Y);
};

template<int Size, int N>
class MagicSquareIterator{
public:
	typedef MagicSquareIterator<Size,N-1> Prev;
	typedef IfCellTraversed< ::MagicSquareIterator,Size, (Prev::x+1)%Size, (Prev::y-1+Size)%Size, N-1> SkipTest;
	static const int x = SkipTest::value ? Prev::x : (Prev::x+1)%Size;
	static const int y = SkipTest::value ? (Prev::y + 1)%Size : (Prev::y-1+Size)%Size;
	static const int value = Prev::value + 1;
};

template<int Size>
class MagicSquareIterator<Size,1>{
public:
	static const int x = Size/2;
	static const int y = 0;
	static const int value = 1;
};

template<int Size>
class IteratorForSize{
public:
	template<int N>
	class Template{
	public:
		typedef MagicSquareIterator<Size,N> type;
	};
};

template<int X, int Y, int Value>
class FillSquare{
public:
	template<typename T>
	static void exec(T& t){
		t(X,Y) = Value;
	}
};



template<int N>
class Copy{
public:
	template<int X, int Y, int>
	class Regular{
	public:
		template<typename T, typename U>
		static void exec(T const& from, U& to){
			to(X,Y) = from(X,Y);
		}
	};

	template<int X, int Y, int>
	class FromRawToSquare{
	public:
		template<typename T, typename U>
		static void exec(T const& from, U& to){
			to(X,Y) = from[Y*N + X];
		}
	};
};





template<int X, int Y, int>
class AddValue{
public:
	template<typename T, typename U>
	static void exec(T& to, U const& what){
		to(X,Y) += what;
	}
};

template<int X, int Y, int>
class AddValueFrom{
public:
	template<typename T, typename U>
	static void exec(T& to, U const& what){
		to(X,Y) += what(X,Y);
	}
};


template<int N>
class MagicSquare;

template<int N>
istream& operator>> (istream& s, MagicSquare<N> & sq);

template<int N>
class MagicSquare{

public:

	template<template <int,int,int> class Func>
	class SquareApply{
	public:
		typedef Apply<Func, IteratorForSize<N>::template Template,Power<N,2>::value> type;
	};

	MagicSquare(){
		SquareApply<FillSquare>::type::exec(*this);
	}

	MagicSquare(MagicSquare const& o){
		SquareApply<Copy<N>::template Regular>::type::exec(o, *this);
	}

	MagicSquare(istream& s){
		s >> *this;
	}

	MagicSquare(int added){
		SquareApply<FillSquare>::type::exec(*this);
		SquareApply<AddValue>::type::exec(*this,added);

	}

	~MagicSquare(){}

	MagicSquare& operator=(MagicSquare const& o){
		SquareApply<Copy<N>::template Regular>::type::exec(o, *this);
	}

	MagicSquare operator+(MagicSquare const& o){
		MagicSquare sq;
		SquareApply<Copy<N>::template Regular>::type::exec(o, sq);
		SquareApply<AddValueFrom>::type::exec(sq, *this);
		return sq;
	}

	int operator()(int x, int y) const {
		return data[y][x];
	}

	int& operator()(int x, int y){
		return data[y][x];
	}


private:
	int data[N][N];
	int property1, property2, property3;
};

template<int N>
ostream& operator<< (ostream& o, MagicSquare<N> const& sq){
	o << "Magic Square " << N << "x" << N << ":" << endl;
	for(int y = 0; y < N; y++){
		for(int x = 0; x < N; x++){
			o << setw(4) << right << sq(x,y);
		}
		o << endl;
	}
	return o;
}

template<int N>
istream& operator>> (istream& s, MagicSquare<N> & sq){
	std::vector<int> values(Power<N,2>::value);
	for(int i = 0; i < Power<N,2>::value; i++){
		s >> values[i];
	}

	MagicSquare<N>::template SquareApply<Copy<N>::template FromRawToSquare>::type::exec(values, sq);
	return s;
}

int main()
{
	MagicSquare<5> sq;

	stringstream str("17 23 4 10 11 24 5 6 12 18 1 7 13 19 25 8 14 20 21 2 15 16 22 3 9");

	MagicSquare<5> sq2(str);

	DBG(sq);
	DBG(sq2);
	DBG(sq+sq2);

	MagicSquare<1> m1;
	MagicSquare<3> m3;
	MagicSquare<5> m5;
	MagicSquare<7> m7;
	MagicSquare<9> m9;
	MagicSquare<11> m11;

	DBG(m1);
	DBG(m3);
	DBG(m5);
	DBG(m7);
	DBG(m9);
	DBG(m11);
}


