Skip to content

Instantly share code, notes, and snippets.

@samchon
Created April 25, 2018 04:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samchon/e76ced99bc908aca7d8ae87b6fe4b9a0 to your computer and use it in GitHub Desktop.
Save samchon/e76ced99bc908aca7d8ae87b6fe4b9a0 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <array>
using namespace std;
/* ----------------------------------------------------------------
DEFINITIONS
---------------------------------------------------------------- */
template <size_t N> using Row = array<int, N>;
template <size_t N> using Matrix = array<Row<N>, N>;
enum Direction : int
{
RIGHT = 0,
DOWN = 1,
LEFT = 2,
UP = 3
};
template <size_t N, size_t R = 0, size_t C = 0,
int Direct = Direction::RIGHT,
size_t Step = 0,
size_t Size = N,
size_t Turn = 0,
int K = 1>
void snail(Matrix<N> &matrix);
template <size_t N, size_t R, size_t C,
int Direct, size_t Step, size_t Size, size_t Turn,
int K>
void advance(Matrix<N> &matrix);
template <size_t N, size_t R, size_t C,
int Direct, size_t Step, size_t Size, size_t Turn,
int K>
void turn(Matrix<N> &matrix);
/* ----------------------------------------------------------------
IMPLEMENTATIONS
---------------------------------------------------------------- */
template <size_t N, size_t R, size_t C,
int Direct, size_t Step, size_t Size, size_t Turn,
int K>
void snail(Matrix<N> &matrix)
{
if constexpr (Size != 0)
{
matrix[R][C] = K;
if constexpr (Step + 1 == Size)
{
if constexpr (Direct == Direction::UP)
turn<N, R, C, Direction::RIGHT, Step+1, Size, Turn, K>(matrix);
else
turn<N, R, C, Direct+1, Step+1, Size, Turn, K>(matrix);
}
else
advance<N, R, C, Direct, Step+1, Size, Turn, K>(matrix);
}
}
template <size_t N, size_t R, size_t C,
int Direct, size_t Step, size_t Size, size_t Turn,
int K>
void advance(Matrix<N> &matrix)
{
if constexpr (Direct == Direction::RIGHT)
snail<N, R, C+1, Direct, Step, Size, Turn, K+1>(matrix);
else if constexpr (Direct == Direction::DOWN)
snail<N, R+1, C, Direct, Step, Size, Turn, K+1>(matrix);
else if constexpr (Direct == Direction::LEFT)
snail<N, R, C-1, Direct, Step, Size, Turn, K+1>(matrix);
else
snail<N, R-1, C, Direct, Step, Size, Turn, K+1>(matrix);
}
template <size_t N, size_t R, size_t C,
int Direct, size_t Step, size_t Size, size_t Turn,
int K>
void turn(Matrix<N> &matrix)
{
if constexpr (Turn % 2 == 0)
advance<N, R, C, Direct, 0, Size-1, Turn + 1, K>(matrix);
else
advance<N, R, C, Direct, 0, Size, Turn + 1, K>(matrix);
}
/* ----------------------------------------------------------------
THE MAIN FUNCTION
---------------------------------------------------------------- */
template <size_t N, size_t R = 0, size_t C = 0>
void print(const Matrix<N> &matrix)
{
cout << matrix[R][C] << '\t';
if constexpr (C + 1 < N)
print<N, R, C + 1>(matrix);
else if constexpr (R + 1 < N)
{
cout << endl;
print<N, R + 1, 0>(matrix);
}
};
int main()
{
Matrix<5> matrix;
snail(matrix);
print(matrix);
return 0;
}
@samchon
Copy link
Author

samchon commented Apr 26, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment