#include <bits/stdc++.h>
using namespace std;
struct node {
  int mini[4];
};
int cnt = 0, m;
int findLast(int flag, string &s) {
  int ans = -1;
  for (int i = 0; i < s.length(); i++) {
    if (flag == 0 && (s[i] >= 'a' && s[i] <= 'b'))
      ans = i;
    else if (flag == 1 && (s[i] >= '1' && s[i] <= '9'))
      ans = i;
    else if (flag == 2 && (s[i] == '*' || s[i] == '&' || s[i] == '#'))
      ans = i;
  }
  return ans;
}
int findfirst(int flag, string &s) {
  for (int i = 0; i < s.length(); i++) {
    if (flag == 0 && (s[i] >= 'a' && s[i] <= 'z'))
      return i;
    else if (flag == 1 && (s[i] >= '0' && s[i] <= '9'))
      return i;
    else if (flag == 2 && (s[i] == '*' || s[i] == '&' || s[i] == '#'))
      return i;
  }
  return -1;
}
int findMin(int location) {
  if (location == -1) return INT_MAX;
  return min(location, m - location);
}
node arr[(int)1e3];
int mat[6][3] = {{1, 2, 3}, {1, 3, 2}, {2, 1, 3},
                 {2, 3, 1}, {3, 1, 2}, {3, 2, 1}};
int calAns(int x, int y, int z) {
  int ans = INT_MAX;
  for (int i = 0; i < 6; i++) {
    if (arr[x].mini[mat[i][0]] == INT_MAX ||
        arr[y].mini[mat[i][1]] == INT_MAX || arr[z].mini[mat[i][2]] == INT_MAX)
      continue;
    ans = min(ans, arr[x].mini[mat[i][0]] + arr[y].mini[mat[i][1]] +
                       arr[z].mini[mat[i][2]]);
  }
  return ans;
}
int main() {
  int n;
  scanf("%d", &n);
  scanf("%d", &m);
  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    arr[cnt].mini[1] = min(findMin(findfirst(0, s)), findMin(findLast(0, s)));
    arr[cnt].mini[2] = min(findMin(findfirst(1, s)), findMin(findLast(1, s)));
    arr[cnt].mini[3] = min(findMin(findfirst(2, s)), findMin(findLast(2, s)));
    cnt++;
  }
  int ans = INT_MAX;
  for (int i = 0; i < cnt; i++) {
    for (int j = i + 1; j < cnt; j++) {
      for (int k = j + 1; k < cnt; k++) {
        ans = min(ans, calAns(i, j, k));
      }
    }
  }
  cout << ans;
  return 0;
}
