#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
//#include <bits/stdc++.h>
#include <map>
using namespace std;
int n, k;
string v[20];
unordered_map<string, bool> mapa;

bool check(vector<string> & v) {
    int res = 0;
    for(int i = 0; i < n; i++) {
        string word = "";
        for(int j = 0; j < n; j++) {
            word += v[i][j];
        }
        if(mapa[word]) {
            res++;
        }
        if(res >= 2 * n) {
            return true;
        }
        
        word = "";
        for(int j = n - 1; j >= 0; j--) {
            word += v[i][j];
        }
        if(mapa[word]) {
            res++;
        }
        if(res >= 2 * n) {
            return true;
        }
        word = "";
        for(int j = 0; j < n; j++) {
            word += v[j][i];
        }
        if(mapa[word]) {
            res++;
        }
        if(res >= 2 * n) {
            return true;
        }
        
        word = "";
        for(int j = n - 1; j >= 0; j--) {
            word += v[j][i];
        }
        if(mapa[word]) {
            res++;
        }
        if(res >= 2 * n) {
            return true;
        }
    }
    return false;
}
int main() {
    ios_base::sync_with_stdio(false);
    cin >> n >> k;
    
    unordered_map<string, bool> mapa;
    map<vector<string>, bool> crossword_visited;
    for(int i = 0; i < k; i++) {
        cin >> v[i];
        mapa[v[i]] = true;
    }
    
    string tmp = "";
    for(int i = 0; i < n; i++) {
        tmp += ".";
    }
    vector<string> c(n, tmp);
    
    queue<vector<string>> q;
    q.push(c);
    
    queue<vector<bool>> q_visited;
    vector<bool> visited(k, false);
    q_visited.push(visited);
    int res = 0;
    while(!q.empty()) {
        c = q.front();
        q.pop();
        
        visited = q_visited.front();
        q_visited.pop();
        
        for(int i = 0; i < n; i++) {
            for(int j= 0; j < n; j++) {
                cout << c[i][j];
            }
            cout << endl;
        }
        cout << endl;
        
        
        if(check(c)) {
            res++;
            continue;
        }
        for(int a = 0; a < k; a++) {
            if(!visited[a]) {
                for(int i = 0; i < n; i++) {
                    bool ok = true;
                    for(int j = 0; j < n; j++) {
                        if(v[a][j] != c[i][j] and c[i][j] != '.') {
                            ok = false;
                            break;
                        }
                    }
                    if(ok) {
                        vector<string> t = c;
                        for(int j = 0; j < n; j++) {
                            t[i][j] = v[a][j];
                        }
                        if(!crossword_visited[t]) {
                            q.push(t);
                            visited[a] = true;
                            q_visited.push(visited);
                            visited[a] = false;
                            
                            crossword_visited[t] = true;
                        }
                    }
                    ok = true;
                    for(int j = n  - 1; j >= 0; j--) {
                        if(v[a][j] != c[i][j] and c[i][j] != '.') {
                            ok = false;
                            break;
                        }
                    }
                    if(ok) {
                        vector<string> t = c;
                        for(int j = n - 1; j >= 0; j--) {
                            t[i][j] = v[a][j];
                        }
                        if(!crossword_visited[t]) {
                            q.push(t);
                            visited[a] = true;
                            q_visited.push(visited);
                            visited[a] = false;
                            crossword_visited[t] = true;

                        }
                    }
                    
                    ok = true;
                    for(int j = 0; j < n; j++) {
                        if(v[a][j] != c[j][i] and c[j][i] != '.') {
                            ok = false;
                            break;
                        }
                    }
                    if(ok) {
                        vector<string> t = c;
                        for(int j = 0; j < n; j++) {
                            t[j][i] = v[a][j];
                        }
                        if(!crossword_visited[t]) {
                            q.push(t);
                            visited[a] = true;
                            q_visited.push(visited);
                            visited[a] = false;
                            crossword_visited[t] = true;

                        }
                    }
                    ok = true;
                    for(int j = n - 1; j>= 0; j--) {
                        if(v[a][j] != c[j][i] and c[j][i] != '.') {
                            ok = false;
                            break;
                        }
                    }
                    if(ok) {
                        vector<string> t = c;
                        for(int j = n - 1; j >= 0; j--) {
                            t[j][i] = v[a][j];
                        }
                        if(!crossword_visited[t]) {
                            q.push(t);
                            visited[a] = true;
                            q_visited.push(visited);
                            visited[a] = false;
                            crossword_visited[t] = true;

                        }
                    }
                    
                }
            }
        }
        
        
        
    }
    cout << res << endl;
    return 0;
}
