#include <bits/stdc++.h>
namespace std {
template <typename _Key, typename _Hash = std::hash<_Key>>
using hash_set = std::unordered_set<_Key, _Hash>;
template <typename _Key, typename _Hash = std::hash<_Key>>
using hash_mset = std::unordered_multiset<_Key, _Hash>;
template <typename _Key, typename _Val, typename _Hash = std::hash<_Key>>
using hash_map = std::unordered_map<_Key, _Val, _Hash>;
template <typename _Key, typename _Hash = std::hash<_Key>>
using hash_mmap = std::unordered_multimap<_Key, _Hash>;
template <typename _Key, typename _Cmp = std::less<_Key>>
using mset = std::multiset<_Key, _Cmp>;
template <typename _Key, typename _Val, typename _Cmp = std::less<_Key>>
using mmap = std::multimap<_Key, _Val, _Cmp>;
template <typename _Key>
using rset = std::set<_Key, std::greater<_Key>>;
template <typename _Key>
using rmset = std::multiset<_Key, std::greater<_Key>>;
template <typename _Key, typename _Val>
using rmap = std::map<_Key, std::greater<_Key>>;
template <typename _Key, typename _Val>
using rmmap = std::multimap<_Key, _Val, std::greater<_Key>>;
static std::ostream& fdeb = cerr;
struct NullOstream {};
template <typename T>
NullOstream& operator<<(NullOstream& out, const T&) {
  return out;
}
NullOstream& operator<<(NullOstream& out, std::ostream& (*)(std::ostream&)) {
  return out;
}
static NullOstream deb;
static NullOstream debl;
template <int _Ind, typename... _Args>
struct __TuplePrinter {
  static void print(ostream& out, const tuple<_Args...>& t) {
    __TuplePrinter<_Ind - 1, _Args...>::print(out, t);
    out << ' ' << get<_Ind>(t);
  }
};
template <typename... _Args>
struct __TuplePrinter<0, _Args...> {
  static void print(ostream& out, const tuple<_Args...>& t) {
    out << '(' << get<0>(t);
  }
};
template <typename... _Args>
ostream& operator<<(ostream& out, const tuple<_Args...>& t) {
  __TuplePrinter<sizeof...(_Args) - 1, _Args...>::print(out, t);
  out << ')';
  return out;
}
template <typename _T1, typename _T2>
ostream& operator<<(ostream& out, const pair<_T1, _T2>& p) {
  return out << '(' << p.first << ' ' << p.second << ')';
}
using uchar = unsigned char;
using ushort = unsigned short;
using uint = unsigned int;
using lld = long long;
using ulld = unsigned long long;
static const int MOD = 1e9 + 7;
static const int INF = MOD;
static const lld HASHP = 37;
}  // namespace std
using namespace std;
using LineInfo = std::array<int, 3>;
int main() {
  int n, m;
  std::cin >> n >> m;
  std::cin >> std::ws;
  std::vector<std::vector<std::pair<int, int>>> hh(3);
  for (int i = 0; i < n; ++i) {
    std::string line;
    std::getline(std::cin, line);
    LineInfo linfo;
    linfo[0] = INF;
    linfo[1] = INF;
    linfo[2] = INF;
    for (int j = 0; j < m; ++j) {
      int dist = std::min(j, m - j);
      int ind = -1;
      if (line[j] >= '0' && line[j] <= '9') {
        ind = 0;
      } else if (line[j] >= 'a' && line[j] <= 'z') {
        ind = 1;
      } else {
        ind = 2;
      }
      linfo[ind] = std::min(linfo[ind], dist);
    }
    for (int j = 0; j < 3; ++j) {
      hh[j].push_back(std::make_pair(linfo[j], i));
    }
  }
  for (auto& vv : hh) {
    std::sort(vv.begin(), vv.end());
    vv.resize(std::min(unsigned(vv.size()), unsigned(3U)));
  }
  int result = INF;
  for (const auto& v1 : hh[0]) {
    debl;
    debl << v1;
    for (const auto& v2 : hh[1]) {
      if (v1.second == v2.second) {
        continue;
      }
      debl << v2;
      for (const auto& v3 : hh[2]) {
        if (v1.second == v3.second || v2.second == v3.second) {
          continue;
        }
        deb << v3;
        result = std::min(1LL * result, 1LL * v1.first + v2.first + v3.first);
      }
    }
  }
  std::cout << result << std::endl;
  return 0;
}
