n,m = map(int,raw_input().split())
t = []
ts = []
tsign = []
smin = 51
dmin = 51
lmin = 51
for x in range(0,n,+1):
    tsign.append([51,51,51])
for z in range(0,n,+1):
    s = str(raw_input())
    for x in range(0,m,+1):
        #print s[x],ord(s[x])
        if s[x].isdigit() == True:
            if tsign[z][0]==51:
                tsign[z][0] = x
        elif ord(s[x])-97 >= 0 and ord(s[x])-97<= 26 and tsign[z][1] == 51:
            tsign[z][1] = x
        elif (s[x] == '#' or s[x] == '*' or s[x]== '&') and tsign[z][2] == 51:
            tsign[z][2] = x
    ts.append(s[0])
    t.append(s)
for x in tsign:
    if x[0]<dmin:
        dmin = x[0]
    if x[1]<lmin:
        lmin = x[1]
    if x[2]<smin:
        smin = x[2]
print dmin+lmin+smin


n,m = map(int,raw_input().split())
t = []
ts = []
tsign = []
smin = 51
dmin = 51
lmin = 51
for x in range(0,n,+1):
    tsign.append([51,51,51,False])
for z in range(0,n,+1):
    smin = 51
    dmin = 51
    lmin = 51
    s = str(raw_input())
    for x in range(0,m,+1):
        if s[x].isdigit() == True:
            if x<dmin:
                dmin = x
            if m-x<dmin:
                dmin = m-x
            tsign[z][0] = dmin
        elif ord(s[x])-97 >= 0 and ord(s[x])-97<= 25:
            if x<lmin:
                lmin = x
            if m-x<lmin:
                lmin = m-x
            tsign[z][1] = lmin
        elif (s[x] == '#' or s[x] == '*' or s[x]== '&'):
            if x<smin:
                smin = x
            if m-x < smin:
                smin = m-x
            tsign[z][2] = smin
    ts.append(s[0])
    t.append(s)
smin = 51
dmin = 51
lmin = 51
poz_lmin = poz_smin = poz_dmin = -1
xx=0
for x in tsign:
    if x[0]<dmin and x[3] == False:
        dmin = x[0]
        x[3] = True
        if poz_dmin != -1:
            tsign[poz_dmin][3] = False
        poz_dmin = xx
    xx += 1
xx=0
for x in tsign:
    if x[1]<lmin and x[3] == False:
        lmin = x[1]
        x[3] = True
        if poz_lmin != -1:
            tsign[poz_lmin][3] = False
        poz_lmin = xx
    xx += 1
xx=0
for x in tsign:
    if x[2]<smin and x[3] == False:
        smin = x[2]
        x[3] = True
        if poz_smin != -1:
            tsign[poz_smin][3] = False
        poz_smin = xx
    xx += 1
print lmin+dmin+smin


n,m = map(int,raw_input().split())
t = []
ts = []
tsign = []
smin = 51
dmin = 51
lmin = 51
for x in range(0,n,+1):
    tsign.append([51,51,51])
for z in range(0,n,+1):
    s = str(raw_input())
    for x in range(0,m,+1):
        #print s[x],ord(s[x])
        if s[x].isdigit() == True:
            if x<dmin:
                dmin = x
            #if tsign[z][0]==51:
                #tsign[z][0] = x
        elif ord(s[x])-97 >= 0 and ord(s[x])-97<= 25:
            #tsign[z][1] = x
            if x<lmin:
                lmin = x
        elif s[x] == '#' or s[x] == '*' or s[x]== '&':
            if x<smin:
                smin = x
    ts.append(s[0])
    t.append(s)
'''
for x in tsign:
    if x[0]<dmin:
        dmin = x[0]
    if x[1]<lmin:
        lmin = x[1]
    if x[2]<smin:
        smin = x[2]
'''
print dmin+lmin+smin


#include <stdio.h>
#include <math.h>
int main (void)
{
	int n,m;
	char s[60][60];
	int chr[60],abc[60],dig[60];
	scanf("%d%d",&n,&m);
	if (m==1)
	{
		printf("0\n");
		return 0;
	}
	int mid=m/2;
	for (int i=1;i<=n;i++)
	{
		getchar();
		s[i][0]=getchar();
		for (int t=1;t<=mid;t++)
			s[i][t]=getchar();
		if (m%2==0)
			s[i][-mid]=s[i][mid];
		else
			s[i][-mid]=getchar();
		for (int t=-mid+1;t<0;t++)
			s[i][t]=getchar();
	}
	for (int i=1;i<=n;i++)
	{
		chr[i]=abc[i]=dig[i]=50;
		for (int t=-mid;t<=mid;t++)
		{
			if (s[i][t]>='0' && s[i][t]<='9')
			{
				if (fabs(t)<dig[i])
					dig[i]=fabs(t);
			}
			else if (s[i][t]>='a' && s[i][t]<='z')
			{
				if (fabs(t)<abc[i])
					abc[i]=fabs(t);
			}
			else
			{
				if (fabs(t)<chr[i])
					chr[i]=fabs(t);
			}
		}
	}
	int min=150;
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=n;j++)
			if (j!=i)
			{
				for (int k=1;k<=n;k++)
					if (k!=i && k!=j)
					{
						int t=chr[i]+abc[j]+dig[k];
						if (t < min)
							min=t;
					}
			}
	}
	printf("%d\n",min);
	return 0;
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using static Template;
using static System.Console;
using static System.Convert;
using static System.Math;
using Pi = Pair<int, int>;

class Solver
{
    public void Solve(Scanner sc)
    {
        int N, M;
        sc.Make(out N, out M);
        var dp = Create(N + 1, () => Create(2, () => Create(2, () => Create(2,()=>int.MaxValue/2))));
        dp[0][0][0][0] = 0;//num,le,cha
        for(var i = 1; i <= N; i++)
        {
            var s = ReadLine();
            for(var j=0;j<M;j++)
            {
                if ('0' <= s[j] && s[j] <= '9')
                {
                    for (var k = 0; k < 2; k++)
                        for (var f = 0; f < 2; f++)
                            for (var w = 0; w < 2; w++)
                                chmin(ref dp[i][1][f][w],dp[i - 1][k][f][w]+Min(j,M-j));
                }
                if (s[j] == '#' || s[j] == '*' || s[j] == '&')
                {
                    for (var k = 0; k < 2; k++)
                        for (var f = 0; f < 2; f++)
                            for (var w = 0; w < 2; w++)
                                chmin(ref dp[i][k][1][w],dp[i - 1][k][f][w]+Min(j,M-j));
                }
                if ('a' <= s[j] && s[j] <= 'z')
                {
                    for (var k = 0; k < 2; k++)
                        for (var f = 0; f < 2; f++)
                            for (var w = 0; w < 2; w++)
                                chmin(ref dp[i][k][f][1],dp[i - 1][k][f][w]+Min(j,M-j));
                }
            }
        }
        var min = int.MaxValue / 2;
        for (var i = 0; i <= N; i++)
            chmin(ref min, dp[i][1][1][1]);
        WriteLine(min);
    }
}

#region Template
public static class Template
{
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver().Solve(new Scanner());
        Console.Out.Flush();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) == 1) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) == -1) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static T[] Copy<T>(this T[] A) => Create(A.Length, i => A[i]);
    public static T Unify<T>(this T[] A, Func<T, T, T> f, T init = default(T)) { for (var i = 0; i < A.Length; i++) init = f(init, A[i]);return init; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}

public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    //public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    //public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    //public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}
public class Pair<T1, T2> : IComparable<Pair<T1, T2>>
{
    public T1 v1;
    public T2 v2;
    public Pair() { }
    public Pair(T1 v1, T2 v2)
    { this.v1 = v1; this.v2 = v2; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2> p)
    {
        var c = Comparer<T1>.Default.Compare(v1, p.v1);
        if (c == 0)
            c = Comparer<T2>.Default.Compare(v2, p.v2);
        return c;
    }
    public override string ToString() => $"{v1.ToString()} {v2.ToString()}";
    public void Deconstruct(out T1 a, out T2 b) { a = v1; b = v2; }
}

public class Pair<T1, T2, T3> : Pair<T1, T2>, IComparable<Pair<T1, T2, T3>>
{
    public T3 v3;
    public Pair() : base() { }
    public Pair(T1 v1, T2 v2, T3 v3) : base(v1, v2)
    { this.v3 = v3; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2, T3> p)
    {
        var c = base.CompareTo(p);
        if (c == 0)
            c = Comparer<T3>.Default.Compare(v3, p.v3);
        return c;
    }
    public override string ToString() => $"{base.ToString()} {v3.ToString()}";
    public void Deconstruct(out T1 a, out T2 b, out T3 c) { Deconstruct(out a, out b); c = v3; }
}
#endregion


use std::cmp::*;
fn main() {
    let (n, m) = {
        let r = getvec::<usize>();
        (r[0], r[1])
    };
    let inf = 10000;
    let mut nu = (inf, 0);
    let mut al = (inf, 0);
    let mut sy = (inf, 0);
    let mut nu2 = nu;
    let mut al2 = al;
    let mut sy2 = sy;
    for k in 0..n {
        let mut num = inf;
        let mut alp = inf;
        let mut sym = inf;
        let _s = getnum::<String>();
        let s = _s.as_bytes();
        for i in 0..m {
            let j = min(i, m - i);
            match s[i] as char {
                x if x.is_digit(10) => num = min(num, j),
                x if x.is_digit(36) => alp = min(alp, j),
                '#' | '*' | '&' => sym = min(sym, j),
                _ => {}
            }
        }
        if (num, k) < nu {
            nu2 = nu;
            nu = (num, k);
        } else {
            nu2 = min(nu2, (num, k));
        }
        if (alp, k) < al {
            al2 = al;
            al = (alp, k);
        } else {
            al2 = min(al2, (alp, k));
        }
        if (sym, k) < sy {
            sy2 = sy;
            sy = (sym, k);
        } else {
            sy2 = min(sy2, (sym, k));
        }
    }
    let mut res = nu.0 + sy.0 + al.0;
    if nu.1 == sy.1 || nu.1 == al.1 || al.1 == sy.1 {
        if nu.1 == sy.1 {
            let a = nu2.0 - nu.0;
            let b = sy2.0 - sy.0;
            res += min(a, b);
        } else if nu.1 == al.1 {
            let a = nu2.0 - nu.0;
            let b = al2.0 - al.0;
            res += min(a, b);
        } else {
            let a = al2.0 - al.0;
            let b = sy2.0 - sy.0;
            res += min(a, b);
        }
    }
    println!("{}", res);
}
#[allow(dead_code)]
fn next_line() -> String {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).unwrap();
    input
}

#[allow(dead_code)]
fn getnum<T: std::str::FromStr>() -> T {
    let res = next_line();
    res.trim().parse::<T>().ok().unwrap()
}

#[allow(dead_code)]
fn getvec<T: std::str::FromStr>() -> Vec<T> {
    let res = next_line();
    res.split_whitespace().map(|x| x.parse::<T>().ok().unwrap()).collect()
}


#![allow(unused_imports)]
use std::io::{ self, Write };
use std::str::FromStr;
use std::cmp::{ min, max };
use std::collections::{ BinaryHeap, VecDeque };

macro_rules! trace {
    ($var:expr) => ({
        let _ = writeln!(&mut std::io::stderr(), ">>> {} = {:?}", stringify!($var), $var);
    })
}
macro_rules! swap { ($a:expr, $b:expr) => ({ let t = $b; $b = $a; $a = t; }) }

fn find_digit(cs: &Vec<char>) -> usize {
    let n = cs.len();
    let mut r = n;
    for i in 0..n {
        let c = cs[i];
        if c >= '0' && c <= '9' { r = min(r, i); r = min(r, n-i); }
    }
    r
}

fn find_alpha(cs: &Vec<char>) -> usize {
    let n = cs.len();
    let mut r = n;
    for i in 0..n {
        let c = cs[i];
        if c >= 'a' && c <= 'z' { r = min(r, i); r = min(r, n-i); }
    }
    r
}

fn find_symbol(cs: &Vec<char>) -> usize {
    let n = cs.len();
    let mut r = n;
    for i in 0..n {
        let c = cs[i];
        if c == '*' || c == '#' || c == '&' { r = min(r, i); r = min(r, n-i); }
    }
    r
}

fn main() {
    let mut sc = Scanner::new();
    let n: usize = sc.cin();
    let _: i32 = sc.cin();

    let mut ss = vec![];
    for _ in 0..n {
        let s: String = sc.cin();
        let cs: Vec<char> = s.chars().collect();
        // trace!(cs);
        ss.push(cs);
    }

    let mut ans = 50 * 50;

    for i in 0..n {
        for j in 0..n {
            if i == j { continue; }
            for k in 0..n {
                if i == k { continue; }
                if j == k { continue; }
                let x = find_digit(&ss[i]);
                let y = find_alpha(&ss[j]);
                let z = find_symbol(&ss[k]);
                // trace!(((i,j,k), (x,y,z)));
                ans = min(ans, x + y + z);
            }
        }
    }

    println!("{}", ans);

}

#[allow(dead_code)]
struct Scanner { stdin: io::Stdin, buffer: VecDeque<String>, }
#[allow(dead_code)]
impl Scanner {
    fn new() -> Scanner { Scanner { stdin: io::stdin(), buffer: VecDeque::new() } }
    fn reserve(&mut self) {
        while self.buffer.len() == 0 {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
    }
    fn cin<T: FromStr>(&mut self) -> T {
        self.reserve();
        match self.buffer.pop_front().unwrap().parse::<T>() {
            Ok(a) => a,
            Err(_) => panic!("parse err")
        }
    }
    fn get_char(&mut self) -> char {
        self.reserve();
        let head = self.buffer[0].chars().nth(0).unwrap();
        let tail = String::from( &self.buffer[0][1..] );
        if tail.len()>0 { self.buffer[0]=tail } else { self.buffer.pop_front(); }
        head
    }
}


#![allow(unused_imports)]
use std::io::{ self, Write };
use std::str::FromStr;
use std::cmp::{ min, max };
use std::collections::{ BinaryHeap, VecDeque };

macro_rules! trace {
    ($var:expr) => ({
        let _ = writeln!(&mut std::io::stderr(), ">>> {} = {:?}", stringify!($var), $var);
    })
}
macro_rules! swap { ($a:expr, $b:expr) => ({ let t = $b; $b = $a; $a = t; }) }

fn find_digit(n: usize, cs: &Vec<char>) -> usize {
    let mut r = n;
    for i in 0..n {
        let c = cs[i];
        if c >= '0' && c <= '9' { r = min(r, i); r = min(r, n-i); break; }
    }
    r
}

fn find_alpha(n: usize, cs: &Vec<char>) -> usize {
    let mut r = n;
    for i in 0..n {
        let c = cs[i];
        if c >= 'a' && c <= 'z' { r = min(r, i); r = min(r, n-i); break; }
    }
    r
}

fn find_symbol(n: usize, cs: &Vec<char>) -> usize {
    let mut r = n;
    for i in 0..n {
        let c = cs[i];
        if c == '*' || c == '#' || c == '&' { r = min(r, i); r = min(r, n-i); break; }
    }
    r
}

fn main() {
    let mut sc = Scanner::new();
    let n: usize = sc.cin();
    let _: i32 = sc.cin();

    let mut ss = vec![];
    for _ in 0..n {
        let s: String = sc.cin();
        let cs: Vec<char> = s.chars().collect();
        ss.push(cs);
    }

    let mut ans = 50 * 50;

    for i in 0..n {
        for j in 0..n {
            if i == j { continue; }
            for k in 0..n {
                if i == k { continue; }
                if j == k { continue; }
                let x = find_digit(n, &ss[i]);
                let y = find_alpha(n, &ss[j]);
                let z = find_symbol(n, &ss[k]);
                // trace!(((i,j,k), (x,y,z)));
                ans = min(ans, x + y + z);
            }
        }
    }

    println!("{}", ans);

}

#[allow(dead_code)]
struct Scanner { stdin: io::Stdin, buffer: VecDeque<String>, }
#[allow(dead_code)]
impl Scanner {
    fn new() -> Scanner { Scanner { stdin: io::stdin(), buffer: VecDeque::new() } }
    fn reserve(&mut self) {
        while self.buffer.len() == 0 {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
    }
    fn cin<T: FromStr>(&mut self) -> T {
        self.reserve();
        match self.buffer.pop_front().unwrap().parse::<T>() {
            Ok(a) => a,
            Err(_) => panic!("parse err")
        }
    }
    fn get_char(&mut self) -> char {
        self.reserve();
        let head = self.buffer[0].chars().nth(0).unwrap();
        let tail = String::from( &self.buffer[0][1..] );
        if tail.len()>0 { self.buffer[0]=tail } else { self.buffer.pop_front(); }
        head
    }
}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
char Map[55][55];
int vis[55];
struct Node{
    int no,step;
}dig[55],low[55],sym[55];
int cmp(Node &x,Node &y){
    return x.step<y.step;
}
int main()
{
    int n,m,i,j,k,ans,minn;
    scanf ("%d %d",&n,&m);
    getchar();
    for (i=1;i<=n;i++){
        for (j=1;j<=m;j++) scanf ("%c",&Map[i][j]);
        dig[i].no=i; low[i].no=i; sym[i].no=i;
        dig[i].step=100000000; low[i].step=100000000; sym[i].step=100000000;
        getchar();
    }
    for (i=1;i<=n;i++){
        for (j=1;j<=m;j++)
            if (Map[i][j]>='0' && Map[i][j]<='9'){dig[i].step=j-1; break;}
        for (j=1;j<=m;j++)
            if (Map[i][j]>='a' && Map[i][j]<='z'){low[i].step=j-1; break;}
        for (j=1;j<=m;j++)
            if (Map[i][j]=='#' || Map[i][j]=='*' || Map[i][j]=='&'){sym[i].step=j-1; break;}
        for (j=m;j>=1;j--)
            if (Map[i][j]>='0' && Map[i][j]<='9' && m-j+1<dig[i].step){dig[i].step=m-j+1; break;}
        for (j=m;j>=1;j--)
            if (Map[i][j]>='a' && Map[i][j]<='z' && m-j+1<low[i].step){low[i].step=m-j+1; break;}
        for (j=m;j>=1;j--)
            if ((Map[i][j]=='#' || Map[i][j]=='*' || Map[i][j]=='&') && m-j+1<sym[i].step){sym[i].step=m-j+1; break;}
    }
    //for (i=1;i<=n;i++) cout<<dig[i].step<<' '<<low[i].step<<' '<<sym[i].step<<endl;
    sort(dig+1,dig+n+1,cmp);
    sort(low+1,low+n+1,cmp);
    sort(sym+1,sym+n+1,cmp);
    //for (i=1;i<=n;i++) cout<<dig[i].step<<' '<<low[i].step<<' '<<sym[i].step<<endl;
    ans=0; minn=1000000000;
    for (i=1;i<=3;i++){
        vis[dig[i].no]=1;
        ans+=dig[i].step;
        for (j=1;j<=3;j++){
            if (vis[low[j].no]==1) continue;
            vis[low[j].no]=1;
            ans+=low[j].step;
            for (k=1;k<=3;k++){
                if (vis[sym[k].no]==1) continue;
                ans+=sym[k].step;
                if (ans<minn) minn=ans;
                ans-=sym[k].step;
                //cout<<"ans="<<ans<<endl;
            }
            vis[low[j].no]=0;
            ans-=low[j].step;
        }
        vis[dig[i].no]=0;
        ans-=dig[i].step;
    }
    printf ("%d\n",minn);
    return 0;
}


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
char Map[55][55];
int vis[55];
struct Node{
    int no,step;
}dig[55],low[55],sym[55];
int cmp(Node &x,Node &y){
    return x.step<y.step;
}
int main()
{
    int n,m,i,j,k,ans,minn;
    scanf ("%d %d",&n,&m);
    getchar();
    for (i=1;i<=n;i++){
        for (j=1;j<=m;j++) scanf ("%c",&Map[i][j]);
        dig[i].no=i; low[i].no=i; sym[i].no=i;
        dig[i].step=1000000000; low[i].step=1000000000; sym[i].step=1000000000;
        getchar();
    }
    for (i=1;i<=n;i++){
        for (j=1;j<=m;j++)
            if (Map[i][j]>='0' && Map[i][j]<='9'){dig[i].step=j-1; break;}
        for (j=1;j<=m;j++)
            if (Map[i][j]>='a' && Map[i][j]<='z'){low[i].step=j-1; break;}
        for (j=1;j<=m;j++)
            if (Map[i][j]=='#' || Map[i][j]=='*' || Map[i][j]=='&'){sym[i].step=j-1; break;}
        for (j=m;j>=1;j--)
            if (Map[i][j]>='0' && Map[i][j]<='9' && m-j+1<dig[i].step){dig[i].step=m-j+1; break;}
        for (j=m;j>=1;j--)
            if (Map[i][j]>='a' && Map[i][j]<='z' && m-j+1<low[i].step){low[i].step=m-j+1; break;}
        for (j=m;j>=1;j--)
            if ((Map[i][j]=='#' || Map[i][j]=='*' || Map[i][j]=='&') && m-j+1<sym[i].step){sym[i].step=m-j+1; break;}
    }
    sort(dig+1,dig+n+1,cmp);
    sort(low+1,low+n+1,cmp);
    sort(sym+1,sym+n+1,cmp);
    ans=0; minn=1000000000;
    for (i=1;i<=3;i++){
        vis[dig[i].no]=1;
        ans+=dig[i].step;
        for (j=1;j<=3;j++){
            if (vis[low[j].no]==1) continue;
            vis[low[j].no]=1;
            ans+=low[j].step;
            for (k=1;k<=3;k++){
                if (vis[sym[k].no]==1) continue;
                ans+=sym[k].step;
                if (ans<minn) minn=ans;
                ans-=sym[k].step;
            }
            vis[low[j].no]=0;
            ans-=low[j].step;
        }
        vis[dig[i].no]=0;
        ans-=dig[i].step;
    }
    printf ("%d\n",minn);
    return 0;
}


package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"reflect"
	"unicode"
)

func main() {
	var n, m int
	fmt.Fscan(reader, &n, &m)
	pointers := make([]string, n)
	for i := range pointers {
		fmt.Fscan(reader, &pointers[i])
	}
	digit, letter, special := getAllInfo(pointers)
	//fmt.Println(digit)
	//fmt.Println(letter)
	//fmt.Println(special)
	ans := int(1e6)
	for d := 0; d < n; d++ {
		for l := 0; l < n; l++ {
			if d != l {
				for s := 0; s < n; s++ {
					if s != d && s != l {
						if max(digit[d], max(letter[l], special[s])) < m {
							ans = min(ans, digit[d]+letter[l]+special[s])
							//fmt.Println(d, l, s, ans)
						}
					}
				}
			}
		}
	}
	fmt.Fprintln(writer, ans)
	writer.Flush()
}

func getAllInfo(pointers []string) (digit, letter, special []int) {
	for _, pointer := range pointers {
		d, l, s := getInfo(pointer)
		digit = append(digit, d)
		letter = append(letter, l)
		special = append(special, s)
	}
	return
}

func getInfo(pointer string) (digit, letter, special int) {
	digit, letter, special = len(pointer), len(pointer), len(pointer)
	for i, char := range pointer {
		if unicode.IsDigit(char) {
			digit = min(digit, min(i, len(pointer)-i))
		} else if unicode.IsLetter(char) {
			letter = min(letter, min(i, len(pointer)-i))
		} else {
			special = min(special, min(i, len(pointer)-i))
		}
	}
	return
}

func found(k, s []int, l int) bool {
	s = decrease(s, 0, l)
	for i := range k {
		tempK := decrease(k, i, l)
		if reflect.DeepEqual(s, tempK) {
			return true
		}
	}
	return false
}

func decrease(values []int, pos, l int) []int {
	ans := make([]int, len(values))
	for i := range ans {
		ans[(i-pos+len(ans))%len(ans)] = (values[i] - values[pos] + l) % l
	}
	return ans
}

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func abs64(a int64) int64 {
	if a < 0 {
		return -a
	}
	return a
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func max64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func min64(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

var (
	reader = bufio.NewReaderSize(os.Stdin, 1<<13)
	writer = bufio.NewWriterSize(os.Stdout, 1<<13)
)

func readi() int {
	return int(readi64())
}

func read2i() (int, int) {
	return readi(), readi()
}

func readis(n int) []int {
	res := make([]int, n)
	for i := range res {
		res[i] = readi()
	}
	return res
}

func readi64() int64 {
	b, err := reader.ReadByte()
	for !isValid(b, err) {
		b, err = reader.ReadByte()
	}
	sign, res := int64(1), int64(0)
	if b == '-' {
		sign *= -1
		b, err = reader.ReadByte()
	}
	for isValid(b, err) {
		res = res*10 + int64(b-'0')
		b, err = reader.ReadByte()
	}
	return res * sign
}

func readline() string {
	res := new(bytes.Buffer)
	for {
		line, isPrefix, err := reader.ReadLine()
		if err != nil {
			panic(err)
		}
		res.Write(line)
		if !isPrefix {
			break
		}
	}
	return res.String()
}

func isValid(b byte, err error) bool {
	return err == nil && (('0' <= b && b <= '9') || b == '-')
}


package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"reflect"
	"unicode"
)

func main() {
	var n, m int
	fmt.Fscan(reader, &n, &m)
	pointers := make([]string, n)
	for i := range pointers {
		fmt.Fscan(reader, &pointers[i])
	}
	digit, letter, special := getAllInfo(pointers)
	//fmt.Println(digit)
	//fmt.Println(letter)
	//fmt.Println(special)
	ans := int(1e6)
	for d := 0; d < n; d++ {
		for l := 0; l < n; l++ {
			if d != l {
				for s := 0; s < n; s++ {
					if s != d && s != l {
						if max(digit[d], max(letter[l], special[s])) < m {
							ans = min(ans, n-3+digit[d]+letter[l]+special[s])
						}
					}
				}
			}
		}
	}
	fmt.Fprintln(writer, ans)
	writer.Flush()
}

func getAllInfo(pointers []string) (digit, letter, special []int) {
	for _, pointer := range pointers {
		d, l, s := getInfo(pointer)
		digit = append(digit, d)
		letter = append(letter, l)
		special = append(special, s)
	}
	return
}

func getInfo(pointer string) (digit, letter, special int) {
	digit, letter, special = len(pointer), len(pointer), len(pointer)
	for i, char := range pointer {
		if unicode.IsDigit(char) {
			digit = min(digit, min(i, len(pointer)-i))
		} else if unicode.IsLetter(char) {
			letter = min(letter, min(i, len(pointer)-i))
		} else {
			special = min(special, min(i, len(pointer)-i))
		}
	}
	return
}

func found(k, s []int, l int) bool {
	s = decrease(s, 0, l)
	for i := range k {
		tempK := decrease(k, i, l)
		if reflect.DeepEqual(s, tempK) {
			return true
		}
	}
	return false
}

func decrease(values []int, pos, l int) []int {
	ans := make([]int, len(values))
	for i := range ans {
		ans[(i-pos+len(ans))%len(ans)] = (values[i] - values[pos] + l) % l
	}
	return ans
}

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func abs64(a int64) int64 {
	if a < 0 {
		return -a
	}
	return a
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func max64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func min64(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

var (
	reader = bufio.NewReaderSize(os.Stdin, 1<<13)
	writer = bufio.NewWriterSize(os.Stdout, 1<<13)
)

func readi() int {
	return int(readi64())
}

func read2i() (int, int) {
	return readi(), readi()
}

func readis(n int) []int {
	res := make([]int, n)
	for i := range res {
		res[i] = readi()
	}
	return res
}

func readi64() int64 {
	b, err := reader.ReadByte()
	for !isValid(b, err) {
		b, err = reader.ReadByte()
	}
	sign, res := int64(1), int64(0)
	if b == '-' {
		sign *= -1
		b, err = reader.ReadByte()
	}
	for isValid(b, err) {
		res = res*10 + int64(b-'0')
		b, err = reader.ReadByte()
	}
	return res * sign
}

func readline() string {
	res := new(bytes.Buffer)
	for {
		line, isPrefix, err := reader.ReadLine()
		if err != nil {
			panic(err)
		}
		res.Write(line)
		if !isPrefix {
			break
		}
	}
	return res.String()
}

func isValid(b byte, err error) bool {
	return err == nil && (('0' <= b && b <= '9') || b == '-')
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

func I(i ...interface{}) error {
	_, err := fmt.Fscan(r, i...)
	return err
}

func O(o ...interface{}) {
	fmt.Fprint(w, o...)
}

var (
	r *bufio.Reader
	w *bufio.Writer
)

func init() {
	if f, err := os.Open("in.goC"); err == nil {
		r = bufio.NewReader(f)
	} else {
		r = bufio.NewReader(os.Stdin)
	}
	w = bufio.NewWriter(os.Stdout)
}

type Int int64

func main() {
	defer w.Flush()
	var n, m Int
	for I(&n, &m) == nil {
		solve(n, m)
	}
}

func solve(n, m Int) {
	t := make([]string, n)
	for i := Int(0); i < n; i++ {
		I(&t[i])
	}
	o := make([][3]Int, n)
	for i := Int(0); i < n; i++ {
		o[i] = [3]Int{1e4, 1e4, 1e4}
	}
	for i := Int(0); i < n; i++ {
		for j := Int(0); j < m; j++ {
			min(&o[i][c(t[i][j])], j)
			min(&o[i][c(t[i][j])], m-j)
		}
	}
	ans := Int(1e13)
	for i := Int(0); i < n; i++ {
		for j := Int(0); j < n; j++ {
			for p := Int(0); p < n; p++ {
				if i != j && j != p && i != p {
					min(&ans, o[i][0]+o[j][1]+o[p][2])
				}
			}
		}
	}
	O(ans, "\n")
}

func min(a *Int, b Int) {
	if *a > b {
		*a = b
	}
}

func c(a byte) Int {
	if a >= 'a' && a <= 'z' {
		return 0
	} else if a >= '0' && a <= '9' {
		return 1
	}
	return 2
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var best = 100000

func solve() {
	n := readInt()
	m := readInt()
	a := make([]string, n)
	for i := 0; i < n; i++ {
		a[i] = readString()
		a[i] += a[i]
	}
	res := make([][]int, n)
	for k, v := range a {
		res[k] = make([]int, 3)
		minL := 10000
		minS := 10000
		minN := 10000
		for i := 0; i < len(v); i++ {
			ch := v[i]
			if ch >= '0' && ch <= '9' {
				minN = min(minN, abs(i-m))
			} else if ch == '#' || ch == '&' || ch == '*' {
				minS = min(minS, abs(i-m))
			} else {
				minL = min(minL, abs(i-m))
			}
		}
		res[k][0] = minL
		res[k][1] = minS
		res[k][2] = minN
	}
	visited := make([]bool, n)
	dfs(res, 0, visited, 0)
	fmt.Println(best)
}

func dfs(cost [][]int, column int, visited []bool, res int) {
	if column == 3 {
		best = min(best, res)
		return
	}
	for i := 0; i < len(visited); i++ {
		if !visited[i] && cost[i][column] != 10000 {
			visited[i] = true
			dfs(cost, column+1, visited, res+cost[i][column])
			visited[i] = false
		}
	}
}

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

var scanner *bufio.Scanner

func main() {
	scanner = bufio.NewScanner(os.Stdin)
	const MaxTokenLength = 1024 * 1024
	scanner.Buffer(make([]byte, 0, MaxTokenLength), MaxTokenLength)
	scanner.Split(bufio.ScanWords)
	solve()
}

// IO

func readString() string {
	scanner.Scan()
	return scanner.Text()
}

func readInt() int {
	val, _ := strconv.Atoi(readString())
	return val
}

func readInt64() int64 {
	v, _ := strconv.ParseInt(readString(), 10, 64)
	return v
}

func readIntArray(sz int) []int {
	a := make([]int, sz)
	for i := 0; i < sz; i++ {
		a[i] = readInt()
	}
	return a
}

func readInt64Array(n int) []int64 {
	res := make([]int64, n)
	for i := 0; i < n; i++ {
		res[i] = readInt64()
	}
	return res
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}


package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

const INF int = 5555

func Solve(io *FastIO) {
	bit := make(map[rune]uint)
	for c := '0'; c <= '9'; c++ {
		bit[c] = 0
	}
	for c := 'a'; c <= 'z'; c++ {
		bit[c] = 1
	}
	bit['#'] = 2
	bit['*'] = 2
	bit['&'] = 2

	N := io.NextInt()
	M := io.NextInt()

	dp := make([]int, 8)
	FillArray(dp, INF)
	dp[0] = 0

	for i := 0; i < N; i++ {
		S := io.NextLine()

		next := make([]int, 8)
		copy(next, dp)

		for j, c := range S {
			dist := Min(j, M - j)
			mask := 1 << bit[c]
			for k, v := range dp {
				nextMask := k | mask
				next[nextMask] = Min(next[nextMask], v + dist)
			}
		}

		copy(dp, next)
	}
	io.Println(dp[7])
}

func Min(args ...int) int {
	min := args[0]
	for i := 1; i < len(args); i++ {
		if args[i] < min {
			min = args[i]
		}
	}
	return min
}

func FillArray(arr []int, val int) {
	for i := range arr {
		arr[i] = val
	}
}

type FastIO struct {
	reader *bufio.Reader
	writer *bufio.Writer
}

func (io *FastIO) NextChar() byte {
	c, _ := io.reader.ReadByte()
	return c
}

func (io *FastIO) NextInt() int {
	c := io.NextChar()
	for IsSpaceChar(c) {
		c = io.NextChar()
	}
	sgn := 1
	if c == '-' {
		sgn = -1
		c = io.NextChar()
	}
	res := 0
	for !IsSpaceChar(c) {
		res = (res * 10) + int(c - '0')
		c = io.NextChar()
	}
	return sgn * res
}

func (io *FastIO) NextLong() int64 {
	c := io.NextChar()
	for IsSpaceChar(c) {
		c = io.NextChar()
	}
	sgn := int64(1)
	if c == '-' {
		sgn = -1
		c = io.NextChar()
	}
	res := int64(0)
	for !IsSpaceChar(c) {
		res = (res * 10) + int64(c - '0')
		c = io.NextChar()
	}
	return sgn * res
}

func (io *FastIO) NextIntArray(size int) []int {
	return io.NextIntArrayOffset(size, 0)
}

func (io *FastIO) NextIntArrayOffset(size, offset int) []int {
	arr := make([]int, size + offset)
	for i := 0; i < size; i++ {
		arr[i + offset] = io.NextInt()
	}
	return arr
}

func (io *FastIO) NextLongArray(size int) []int64 {
	return io.NextLongArrayOffset(size, 0)
}

func (io *FastIO) NextLongArrayOffset(size, offset int) []int64 {
	arr := make([]int64, size + offset)
	for i := 0; i < size; i++ {
		arr[i + offset] = io.NextLong()
	}
	return arr
}

func (io *FastIO) NextString() string {
	c := io.NextChar()
	for (IsSpaceChar(c)) {
		c = io.NextChar()
	}
	var sb bytes.Buffer
	for !IsSpaceChar(c) {
		sb.WriteByte(c)
		c = io.NextChar()
	}
	return sb.String()
}

func (io *FastIO) NextLine() string {
	c := io.NextChar()
	for (IsSpaceChar(c)) {
		c = io.NextChar()
	}
	var sb bytes.Buffer
	for !IsLineBreakChar(c) {
		sb.WriteByte(c)
		c = io.NextChar()
	}
	return sb.String()
}

func (io *FastIO) Println(args ...interface{}) {
	io.writer.WriteString(fmt.Sprintln(args...))
}

func (io *FastIO) Printf(format string, args ...interface{}) {
	io.writer.WriteString(fmt.Sprintf(format, args...))
}

func (io *FastIO) FlushOutput() {
	io.writer.Flush()
}

func IsSpaceChar(c byte) bool {
	switch c {
	case 0, '\t', '\n', '\r', ' ':
		return true
	default:
		return false
	}
}

func IsLineBreakChar(c byte) bool {
	switch c {
		case 0, '\n', '\r':
			return true
		default:
			return false
	}
}

func main() {
	io := FastIO{reader: bufio.NewReader(os.Stdin), writer: bufio.NewWriter(os.Stdout)}
	Solve(&io)
	io.FlushOutput()
}


<?php

list($n, $m) = array_map('intval', explode(' ', readline()));
$strings = array();
$dp = array();
for ($i=0;$i<$n;$i++){
    array_push($strings, readline());
}

for($j=0;$j<3;$j++){
    $dp[$j] = array_fill(0, $n, -1);
}

function type($char){
    if(is_numeric($char)){
        return 0;
    }elseif($char == '#' ||$char == '*' ||$char == '&' ){
        return 1;
    }else{
        return 2;
    }
}

function steps($i, $m){
    if($i > (int)($m/2)){
        return $m - $i;
    }
    return $i;
}

foreach ($strings as $key => $string){
    for($i=0;$i<$m;$i++){
        $steps = steps($i, $m);
        $type = type($string[$i]);
        if($dp[$type][$key] > $steps || $dp[$type][$key] == -1){
            $dp[$type][$key] = $steps;
        }
    }
}
$min = PHP_INT_MAX;

for ($i=0; $i<$n;$i++){
    for ($j=0; $j<$n;$j++){
        for ($k=0; $k<$n;$k++){
            if($i != $j && $i != $k && $j != $k){
                $cur = $dp[0][$i] + $dp[1][$j] + $dp[2][$k];
                if($min > $cur){
                    $min = $cur;
                }
            }
        }
    }
}

echo $min;


<?php

list($n, $m) = array_map('intval', explode(' ', readline()));
$strings = array();
$dp = array();
for ($i=0;$i<$n;$i++){
    array_push($strings, readline());
}

for($j=0;$j<3;$j++){
    $dp[$j] = array_fill(0, $n, PHP_INT_MAX);
}

function type($char){
    if(is_numeric($char)){
        return 0;
    }elseif($char == '#' ||$char == '*' ||$char == '&' ){
        return 1;
    }else{
        return 2;
    }
}

function steps($i, $m){
    if($i > (int)($m/2)){
        return $m - $i;
    }
    return $i;
}

foreach ($strings as $key => $string){
    for($i=0;$i<$m;$i++){
        $steps = steps($i, $m);
        $type = type($string[$i]);
        if($dp[$type][$key] > $steps){
            $dp[$type][$key] = $steps;
        }
    }
}
$min = PHP_INT_MAX;

for ($i=0; $i<$n;$i++){
    for ($j=0; $j<$n;$j++){
        for ($k=0; $k<$n;$k++){
            if($i != $j && $i != $k && $j != $k){
                $cur = $dp[0][$i] + $dp[1][$j] + $dp[2][$k];
                if($min > $cur){
                    $min = $cur;
                }
            }
        }
    }
}

echo $min;


import time, string
def f():
    M = 10**9
    s0 = string.ascii_lowercase
    s1 = string.digits
    st = time.clock()
    n, m = map(int,raw_input().split())
    C = [[M]*3 for i in xrange(n)]
    for i in xrange(n):
        s = raw_input().strip()
        ss = [0 if c in s0 else 1 if c in s1 else 2 for c in s]
        for k in xrange(3):
            for j in xrange(m):
                if ss[j] == k: C[i][k] = min(C[i][k], j)
                if ss[m-1-j] == k: C[i][k] = min(C[i][k], j+1)
    #for i in xrange(n): print C[i]
    res = min(C[i][0]+C[j][1]+C[k][2] for i in xrange(n) for j in xrange(n) for k in xrange(n) if i != j and j !=k and i != k)
    print res
f()


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * n
char = [10 ** 5] * n
integer = [10 ** 5] * n

for _ in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[i] = min(symbol[i], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[i] = min(char[i], j, m-j)
        else :
            integer[i] = min(integer[i],j, m-j)
print min(symbol) + min(char) + min(integer)


n, m = map(int, raw_input().split())
t = []
for i in xrange(n) :
    t.append(list(raw_input()))

s = [10 ** 5] * n
d = [10 ** 5] * n
c = [10 ** 5] * n

for i in xrange(n) :
    for j in xrange(m) :
        if t[i][j] == '*' or t[i][j] == '&' or t[i][j] == '#' :
            s[i] = min(s[i], min(j, m - j))
        elif ord('a') <= ord(t[i][j]) <= ord('a') + 26 :
            d[i] = min(d[i], min(j, m - j))
        else :
            c[i] = min(c[i], min(j, m - j))

ans = 10 ** 5
for i in xrange(n) :
    for j in xrange(n) :
        for k in xrange(n) :
            if i != j and j != k and k != i :
                ans = min(ans, c[i] + d[j] + s[k])

print ans


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * m
char = [10 ** 5] * m
integer = [10 ** 5] * m

for _ in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[j] = min(symbol[j], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[j] = min(char[j], j, m-j)
        else :
            integer[j] = min(integer[j],j, m-j)
print min(symbol) + min(char) + min(integer)


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * n
char = [10 ** 5] * n
integer = [10 ** 5] * n

for i in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[i] = min(symbol[i], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[i] = min(char[i], j, m-j)
        else :
            integer[i] = min(integer[i],j, m-j)

ans = 10 ** 5

for i in xrange(n):
    for j in xrange(n) :
        for k in xrange(n) :
            if (i ^ j and i ^ k and k ^ j) :
                ans = min(ans, symbol[i] + char[j] + integer[k])
print ans


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * m
char = [10 ** 5] * m
integer = [10 ** 5] * m

for _ in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[i] = min(symbol[i], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[i] = min(char[i], j, m-j)
        else :
            integer[i] = min(integer[i],j, m-j)
print min(symbol) + min(char) + min(integer)


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * n
char = [10 ** 5] * n
integer = [10 ** 5] * n

for i in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[i] = min(symbol[i], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[i] = min(char[i], j, m-j)
        else :
            integer[i] = min(integer[i],j, m-j)
print min(symbol) + min(char) + min(integer)


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * n
char = [10 ** 5] * n
integer = [10 ** 5] * n

for i in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[i] = min(symbol[i], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[i] = min(char[i], j, m-j)
        else :
            integer[i] = min(integer[i],j, m-j)

ans = 10 ** 5

for i in xrange(n):
    for j in xrange(n) :
        for k in xrange(n) :
            if not (i ^ j or i ^ k or k ^ j) :
                ans = min(ans, symbol[i] + char[j] + integer[k])
print ans


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * n
char = [10 ** 5] * n
integer = [10 ** 5] * n

for i in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[i] = min(symbol[i], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[i] = min(char[i], j, m-j)
        else :
            integer[i] = min(integer[i],j, m-j)

ans = 10 ** 5

for i in xrange(n):
    for j in xrange(n) :
        for k in xrange(n) :
            if not (i ^ j or i ^ k ork ^ j) :
                ans = min(ans, symbol[i] + char[i] + integer[i])
print ans


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * n
char = [10 ** 5] * n
integer = [10 ** 5] * n

for i in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[i] = min(symbol[i], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[i] = min(char[i], j, m-j)
        else :
            integer[i] = min(integer[i],j, m-j)

ans = 10 ** 5

for i in xrange(n):
    for j in xrange(n) :
        for k in xrange(n) :
            if not (i ^ j or i ^ k or k ^ j) :
                ans = min(ans, symbol[i] + char[i] + integer[i])
print ans


n, m = map(int, raw_input().split())
symbol = [10 ** 5] * n
char = [10 ** 5] * n
integer = [10 ** 5] * n

for i in xrange(n) :
    s = raw_input()

    for j, c in enumerate(s) :
        if c in "*&#" :
            symbol[i] = min(symbol[i], j, m-j)
        elif ord('a') <= ord(c) <= ord('a') + 26 :
            char[i] = min(char[i], j, m-j)
        else :
            integer[i] = min(integer[i],j, m-j)

ans = 10 ** 5

for i in xrange(n):
    for j in xrange(n) :
        for k in xrange(n) :
            if (i ^ j or i ^ k or k ^ j) :
                ans = min(ans, symbol[i] + char[j] + integer[k])
print ans


import string

n, m = map(int, raw_input().split())
dists = [3*[m] for i in range(n)]
for i, dist in enumerate(dists):
    s = raw_input().strip()
    for j in range(3):
        for k, ch in enumerate(s):
            if ch in string.digits:
                dist[0] = min(dist[0], k, m-k)
            elif ch in string.ascii_lowercase:
                dist[1] = min(dist[1], k, m-k)
            else:
                dist[2] = min(dist[2], k, m-k)
    #print(dist)

used = n*[False]

def solve(ix):
    if ix == 3:
        return 0
    best = n*m
    for i in range(n):
        if used[i]:
            continue
        used[i] = True
        cost = dists[i][ix] + solve(ix+1)
        best = min(best, cost)
        used[i] = False
    return best

result = solve(0)
print(result)


r, c = (int(x) for x in raw_input().split())
dp = [1e9] * 8
dp[0] = 0

alpha = [
	"1234567890",
	"qwertyuiopasdfghjklzxcvbnm",
	"#*&"
]

for _ in xrange(r):
	s = raw_input()
	next = [1e9] * 8
	for i in xrange(c):
		for j in xrange(len(dp)):
			for k in xrange(3):
				if s[i] in alpha[k]:
					next[j | (2**k)] = min(next[j | (2**k)], dp[j] + min(i, c-i))
	for i in xrange(8):
		dp[i] = next[i]
print dp[7]


n,m = map(int,raw_input().split())
arr = []
for i in range(n):
  temp = [9999,9999,9999]
  cur = list(raw_input())
  for j in range(m):
    if cur[j] >= '0' and cur[j] <= '9':
      temp[0] = min(j,temp[0],m-j)
    elif cur[j] >= 'a' and cur[j] <= 'z':
      temp[1] = min(j,temp[1],m-j)
    else:
      temp[2] = min(j,temp[2],m-j)
  arr.append(temp)
ans = 9999
for i in range(n):
  for j in range(n):
    for k in range(n):
      if i==j or j==k or i==k:
        continue
      ans = min(arr[i][0]+arr[j][1]+arr[k][2],ans)
print ans


n,m=map(int,raw_input().split())
lst=[]
ans=[]
d1=[]
d2=[]
d3=[]
for i in  range(0,10):
  d1.append(str(i))
for i in  range(0,26):
  d2.append(chr(97+i))
d3=["#","*","&"]
ans1=[]
ans2=[]
ans3=[]
for _ in range(0,n):
  st=str(raw_input())
  lst.append(st)
  l=100000
  r=100000
  for j in range(0,len(st)):
    if st[j] in d1:
      l=j
      break
  for j in range(len(st)-1,-1,-1):
    if st[j] in d1:
      r=len(st)-j
      break
  ans1.append(min(l,r))
  l=100000
  r=100000
  for j in range(0,len(st)):
    if st[j] in d2:
      #print "yee"
      l=j
      break
  for j in range(len(st)-1,-1,-1):
    if st[j] in d2:
      r=len(st)-j
      break
  ans2.append(min(l,r))
  l=100000
  r=100000
  for j in range(0,len(st)):
    if st[j] in d3:
      l=j
      break
  for j in range(len(st)-1,-1,-1):
    if st[j] in d3:
      r=len(st)-j
      break
  ans3.append(min(l,r))
lk=[]
for i in range(0,len(ans1)):
  for j in range(0,len(ans2)):
    for k in range(0,len(ans3)):
      if i!=j and j!=k and i!=k:
        lk.append(ans1[i]+ans2[j]+ans3[k])
print min(lk)


from sys import stdin, stdout
rr = lambda: stdin.readline().strip()
rrM = lambda: map(int, rr().split())
R, C = rrM()
A = [rr() for _ in xrange(R)]

def solve(R, C, A):
    def type_of(val):
        if val.isalpha():
            type_ = 0
        elif val.isdigit():
            type_ = 1
        elif val == '#':
            type_ = 2
        elif val == '*':
            type_ = 3
        elif val == '&':
            type_ = 4
        else:
            type_ = -1
        return type_
    #For each row, record the minimum distance to
    # a letter, number, hash, star, and ampersand.
    INF = float('inf')
    mindist = [ [INF]*5 for _ in xrange(R) ]
    for r, row in enumerate(A):
        for c, val in enumerate(row):
            type_ = type_of(val)
            if type_ == -1: continue
            delta = min(c, C - c)
            mindist[r][type_] = min(mindist[r][type_], delta)

    memo = {}
    def dp(k, mask):
        #What is the minimum cost to fulfill
        # the given mask of categories with
        # A[:1+k]?
        if (k,mask) in memo:
            return memo[k,mask]

        if k == -1:
            return INF if mask else 0

        ans = dp(k - 1, mask)
        for category, dist in enumerate(mindist[k]):
            bit = 1 << category
            for submask in xrange( 1<< 5):
                if submask | bit == mask:
                    ans = min(ans, dist + dp(k-1, submask))

        memo[k, mask] = ans
        return ans

    ans = min( dp(len(A) - 1, int('00111',2)),
                dp(len(A) - 1, int('01011',2)),
                dp(len(A) - 1, int('10011',2)) )
    return ans

print solve(R, C, A)


from sys import stdin, stdout
rr = lambda: stdin.readline().strip()
rrM = lambda: map(int, rr().split())
R, C = rrM()
A = [rr() for _ in xrange(R)]

def solve(R, C, A):
    def type_of(val):
        if val.isalpha():
            type_ = 0
        elif val.isdigit():
            type_ = 1
        elif val == '#':
            type_ = 2
        elif val == '*':
            type_ = 3
        elif val == '&':
            type_ = 4
        else:
            type_ = -1
        return type_
    #For each row, record the minimum distance to
    # a letter, number, hash, star, and ampersand.
    INF = float('inf')
    mindist = [ [INF]*5 for _ in xrange(R) ]
    for r, row in enumerate(A):
        for c, val in enumerate(row):
            type_ = type_of(val)
            if type_ == -1: continue
            delta = min(c, C - c)
            mindist[r][type_] = min(mindist[r][type_], delta)

    memo = {}
    def dp(k, mask):
        #What is the minimum cost to fulfill
        # the given mask of categories with
        # A[:1+k]?
        if k == -1:
            return INF if mask else 0

        ans = dp(k - 1, mask)
        for category, dist in enumerate(mindist[k]):
            bit = 1 << category
            for submask in xrange( 1<< 5):
                if submask | bit == mask:
                    ans = min(ans, dist + dp(k-1, submask))

        memo[k, mask] = ans
        return ans

    ans = min( dp(len(A) - 1, int('00111',2)),
                dp(len(A) - 1, int('01011',2)),
                dp(len(A) - 1, int('10011',2)) )
    return ans

print solve(R, C, A)


from sys import stdin, stdout
rr = lambda: stdin.readline().strip()
rrM = lambda: map(int, rr().split())
R, C = rrM()
A = [rr() for _ in xrange(R)]

def solve(R, C, A):
    def type_of(val):
        if val.isalpha():
            type_ = 0
        elif val.isdigit():
            type_ = 1
        elif val == '#':
            type_ = 2
        elif val == '*':
            type_ = 3
        elif val == '&':
            type_ = 4
        else:
            type_ = -1
        return type_
    #For each row, record the minimum distance to
    # a letter, number, hash, star, and ampersand.
    INF = float('inf')
    mindist = [ [INF]*5 for _ in xrange(R) ]
    for r, row in enumerate(A):
        for c, val in enumerate(row):
            type_ = type_of(val)
            if type_ == -1: continue
            delta = min(c, C - c)
            mindist[r][type_] = min(mindist[r][type_], delta)

    memo = {}
    def dp(k, mask):
        #What is the minimum cost to fulfill
        # the given mask of categories with
        # A[:1+k]?
        if k,mask in memo:
            return memo[k,mask]

        if k == -1:
            return INF if mask else 0

        ans = dp(k - 1, mask)
        for category, dist in enumerate(mindist[k]):
            bit = 1 << category
            for submask in xrange( 1<< 5):
                if submask | bit == mask:
                    ans = min(ans, dist + dp(k-1, submask))

        memo[k, mask] = ans
        return ans

    ans = min( dp(len(A) - 1, int('00111',2)),
                dp(len(A) - 1, int('01011',2)),
                dp(len(A) - 1, int('10011',2)) )
    return ans

print solve(R, C, A)


n, m = map(int, raw_input().split())
cs = [raw_input() for _ in xrange(n)]
ds = []
for c in cs:
    alphas = []
    nums = []
    raros = []
    for i in xrange(m):
        if c[i].isalpha():
            alphas.append(i)
        elif c[i].isdigit():
            nums.append(i)
        else :
            raros.append(i)
    res = [float("inf"), float("inf"), float("inf")]
    for a in alphas:
        res[0] = min(res[0], a, m-a)
    for a in nums:
        res[1] = min(res[1], a, m-a)
    for a in raros:
        res[2] = min(res[2], a, m-a)
    ds.append(res)
l1 = []
l2 = []
l3 = []
for d in ds:
    l1.append(d[0])
    l2.append(d[1])
    l3.append(d[2])
from collections import defaultdict
tomado = defaultdict(bool)
ls = [l1,l2,l3]
ls.sort(key=lambda x: x.count(float("inf")), reverse = True)
total = 0
for i in xrange(3):
    li = ls[i]
    eli = list(enumerate(li))
    eli.sort(key = lambda x: x[1])
    id = 0
    while tomado[eli[id][0]]:
        id += 1
    tomado[eli[id][0]] = True
    total += eli[id][1]

print total


import itertools
from fractions import gcd
from math import sqrt
from bisect import bisect_left
import heapq
from collections import deque
from itertools import combinations as C

def Ls():
	return list(raw_input())
def get(a):
	return map(a , raw_input().split())
def Int():
	return int(raw_input())
def Str():
	return raw_input()
#Aj to aram se bina paper ke ^_^
from collections import defaultdict
#late 25 min , lets see kitni girti he aaj
n , m = get(int)
cost = []
st = []
for i in xrange(n):
	a = list(raw_input())
	st.append(a)
	fa = False
	fex = False
	fd = False
	idx = 0
	for j in a:
		#if (idx+1 == m-1):put = 1
		if j.isalpha():
			cost.append((min(m-idx , idx) ,i , 1))
			fa = True
		elif j.isdigit():
			cost.append((min(m-idx , idx)  ,i , 2))
		elif (j == '#' or j == '&' or j == '*'):
			cost.append((min(m-idx , idx) , i , 3))
		idx += 1
cost.sort()
ans = 10**9
for ix in C(cost , 3):
	a , b, c = ix
	ls1 = [a[2] , b[2] , c[2]]
	ls2 = [a[1] , b[1] , c[1]]
	if len(set(ls1)) == len(set(ls2)) and len(set(ls1)) == 3:
		#print a , b , c
		ans = min(ans , a[0]+b[0]+c[0])

print ans


import itertools
from fractions import gcd
from math import sqrt
from bisect import bisect_left
import heapq
from collections import deque
from itertools import combinations as C

def Ls():
	return list(raw_input())
def get(a):
	return map(a , raw_input().split())
def Int():
	return int(raw_input())
def Str():
	return raw_input()
#Aj to aram se bina paper ke ^_^
from collections import defaultdict
#late 25 min , lets see kitni girti he aaj
n , m = get(int)
cost = []
st = []
for i in xrange(n):
	a = list(raw_input())
	st.append(a)
	fa = False
	fex = False
	fd = False
	idx = 0
	st_1 = []
	st_2 = []
	st_3 = []
	for j in a:
		#if (idx+1 == m-1):put = 1
		if j.isalpha():
			#cost.append((min(m-idx , idx) ,i , 1))
			st_1.append((min(m-idx , idx) ,i , 1))
			fa = True
		elif j.isdigit():
			st_2.append((min(m-idx , idx) ,i , 2))
		elif (j == '#' or j == '&' or j == '*'):
			st_3.append((min(m-idx , idx) ,i , 3))
		idx += 1
	st_1.sort()
	st_2.sort()
	st_3.sort()
	if len(st_1):
		cost.append(st_1[0])
	if len(st_2):cost.append(st_2[0])
	if len(st_3):cost.append(st_3[0])
#not optimal
#cost.sort()
ans = 10**9
for ix in C(cost , 3):
	a , b, c = ix
	ls1 = [a[2] , b[2] , c[2]]
	ls2 = [a[1] , b[1] , c[1]]
	if len(set(ls1)) == len(set(ls2)) and len(set(ls1)) == 3:
		#print a , b , c
		ans = min(ans , a[0]+b[0]+c[0])

print ans


def f(sl, sr, func):
	n = len(sl)
	res = int(1e9)
	for i in xrange(n):
		if func(sl[i]) or func(sr[i]):
			res = min(res, i)
			break
	return res

n, m = map(int, raw_input().split())
a = [raw_input() for i in xrange(n)]
b = [(s[0:1] + s[-1:-m:-1]) for s in a]

res = int(1e9)
for i1 in xrange(n):
	for j1 in xrange(n):
		if i1 == j1:
			continue
		for k1 in xrange(n):
			if k1 == i1 or k1 == j1:
				continue
			res1 = f(a[i1], b[i1], lambda c: ord('0') <= ord(c) and ord(c) <= ord('9'))
			res2 = f(a[j1], b[j1], lambda c: ord('a') <= ord(c) and ord(c) <= ord('z'))
			res3 = f(a[k1], b[k1], lambda c: c == '*' or c == '#' or c == '&')
			res = min(res, res1 + res2 + res3)

print res


from collections import defaultdict
def go():
	n,m = [int(i) for i in raw_input().split(" ")]
	a=[]
	for i in range(n):
		a.append(raw_input())

	def diffs(s):
		char=10e9
		num=10e9
		spec=10e9
		for i in range(m):
			if s[i] >= 'a' and s[i]<='z':
				char = min(i,m-i,char)
			elif s[i]>= '0' and s[i]<='9':
				num = min(i,m-i,num)
			else :
				spec = min(i,m-i,spec)

		return char,num,spec

	d = []
	for s in a:
		d.append(diffs(s))
	best = 30e9
	for i in range(n):
		for j in range(n):
			if i==j:
				continue
			for k in range(n):
				if i==k or j==k:
					continue
				best = min(best, d[i][0]+d[j][1]+d[k][2])
	return best

print go()


n, m = map(int, input().split())
words = [input() for _ in range(n)]
arr = [[10**19 for _ in range(3)] for _ in range(n)]

def ind(c):
    if c.isdigit():
        return 0
    if c.isalpha():
        return 1
    return 2

for i, w in enumerate(words):
    for j in range(len(w)):
        k = ind(w[j])
        arr[i][k] = min(arr[i][k], min(j, m - j))

ans = 10 ** 19

for i in range(n):
    for j in range(n):
        for k in range(n):
            if i == j or j == k or i == k:
                continue

            c = ind(words[i][0])
            ans = min(ans, arr[j][(c - 1) % 3] + arr[k][(c + 1) % 3])
            ans = min(ans, arr[j][(c + 1) % 3] + arr[k][(c - 1) % 3])

print(ans)


def lol():
    ans = INF
    for i in range(n):
        for j in range(n):
            for k in range(n):
                if i == j or j == k or k == i:
                    continue

                a, b, c = INF, INF, INF
                for i1 in range(m):
                    if 48 <= ord(s[i][i1]) <= 57 or 48 <= ord(s[i][-i1]) <= 57:
                        a = min(a, i1)

                    if 97 <= ord(s[j][i1]) <= 122 or 97 <= ord(s[j][-i1]) <= 122:
                        b = min(b, i1)

                    if s[k][i1] in sim or s[k][-i1] in sim:
                        c = min(c, i1)

                    if a < INF and b < INF and c < INF:
                        break

                ans = min(ans, a + b + c)
    return ans

n, m = map(int, input().split())

INF = 10 ** 9
s = [0] * n
sim = ['*', '&', '#']
for i in range(n):
    new = input()
    s[i] = new + new

ans = lol()

if ans >= INF:
    print(-1)
else:
    print(ans)


n,leng=map(int,input().split())
a=leng
d=leng
c=leng
from re import search
e=[[],[],[],[]]
for i in range(n):
    s=input()
    sr=s[::-1]
    let=search('[a-z]',s)
    dig=search('\d', s)
    sig=search('\*|#|&', s)
    if let:
        let=min(let.start(),search('[a-z]',sr).start()+1)
        e[1].append([let, i])
    if dig:
        dig = min(dig.start(), search('\d', sr).start() + 1)
        e[2].append([dig, i])
    if sig:
        sig = min(sig.start(), search('\*|#|&', sr).start() + 1)
        e[3].append([sig, i])
    if len(e[1])>3:
        e[1].sort()
        e[1].pop()
    if len(e[2])>3:
        e[2].sort()
        e[2].pop()
    if len(e[3])>3:
        e[3].sort()
        e[3].pop()
ans=leng*3
e.pop(0)
def rec(se,ind):
    if len(se)==3:
        global ans
        ans=min(ans,sum(se))
    else:
        for el,i in e[len(se)]:
            if i not in ind:
                rec(se+[el],ind|{i})
rec([],set())
print(ans)


n,leng=map(int,input().split())
a=leng
d=leng
c=leng
from re import search
e=[[],[],[],[]]
for i in range(n):
    s=input()
    sr=s[::-1]
    let=search('[a-z]',s)
    dig=search('\d', sr)
    sig=search('\*|#|&', s)
    if let:
        let=min(let.start(),search('\w',sr).start()+1)
        e[1].append([let, i])
    if dig:
        dig = min(dig.start(), search('\d', sr).start() + 1)
        e[2].append([dig, i])
    if sig:
        sig = min(sig.start(), search('\*|#|&', sr).start() + 1)
        e[3].append([sig, i])

    if len(e[1])>3:
        e[1].sort()
        e[1].pop()
    if len(e[2])>3:
        e[2].sort()
        e[2].pop()
    if len(e[3])>3:
        e[3].sort()
        e[3].pop()
ans=leng*3
e.pop(0)
def rec(se,ind):
    if len(se)==3:
        global ans
        ans=min(ans,sum(se))
    else:
        for el,i in e[len(se)]:
            if i not in ind:
                rec(se+[el],ind|{i})
rec([],set())
print(ans)


n,leng=map(int,input().split())
a=leng
d=leng
c=leng
from re import search
e=[[],[],[],[]]
for i in range(n):
    s=input()
    sr=s[::-1]
    let=search('[a-z]',s)
    dig=search('\d', s)
    sig=search('\*|#|&', s)
    if let:
        let=min(let.start(),search('[a-z]',sr).start()+1)
        e[1].append([let, i])
    if dig:
        dig = min(dig.start(), search('\d', sr).start() + 1)
        e[2].append([dig, i])
    if sig:
        sig = min(sig.start(), search('\*|#|&', sr).start() + 1)
        e[3].append([sig, i])

    if len(e[1])>3:
        e[1].sort()
        e[1].pop()
    if len(e[2])>3:
        e[2].sort()
        e[2].pop()
    if len(e[3])>3:
        e[3].sort()
        e[3].pop()
ans=leng*3
e.pop(0)
def rec(se,ind):
    if len(se)==3:
        global ans
        ans=min(ans,sum(se))
    else:
        for el,i in e[len(se)]:
            if i not in ind:
                rec(se+[el],ind|{i})
print(e)
rec([],set())
print(ans)


n, m = map(int, input().strip().split())
arr = []
for i in range(n): arr.append(list(input()))

dp = [[float('inf') for i in range(3)] for i in range(n)]
for i in range(n):
    for j in range(m):
        if ord('a') <= ord(arr[i][j]) <= ord('z'):
            dp[i][0] = min(dp[i][0], j, m-j)
        elif arr[i][j] in '&#*':
            dp[i][1] = min(dp[i][1], j, m-j)
        else:
            dp[i][2] = min(dp[i][2], j, m-j)

ans = float('inf')
for i in range(n):
    for j in range(n):
        for k in range(n):
            if len(set([i, j, k])) == 3:
                print(i, j, k, 'check')
                ans = min(dp[i][0] + dp[j][1] + dp[k][2], ans)

# for i in dp:
#     print(i)

print(ans)


n, m = map(int, input().strip().split())
arr = []
for i in range(n): arr.append(list(input()))

dp = [[float('inf') for i in range(3)] for i in range(n)]
for i in range(n):
    for j in range(m):
        if ord('a') <= ord(arr[i][j]) <= ord('z'):
            dp[i][0] = min(dp[i][0], j, n-j)
        elif arr[i][j] in '&#*':
            dp[i][1] = min(dp[i][1], j, n-j)
        else:
            dp[i][2] = min(dp[i][2], j, n-j)

ans = float('inf')
for i in range(n):
    for j in range(n):
        for k in range(n):
            if i != j != k:
                ans = min(dp[i][0] + dp[j][1] + dp[k][2], ans)

# for i in dp:
#     print(i)

print(ans)


n, m = map(int, input().strip().split())
arr = []
for i in range(n): arr.append(list(input()))

dp = [[float('inf') for i in range(3)] for i in range(n)]
for i in range(n):
    for j in range(m):
        if ord('a') <= ord(arr[i][j]) <= ord('z'):
            dp[i][0] = min(dp[i][0], j, m-j)
        elif arr[i][j] in '&#*':
            dp[i][1] = min(dp[i][1], j, m-j)
        else:
            dp[i][2] = min(dp[i][2], j, m-j)

ans = float('inf')
for i in range(n):
    for j in range(n):
        for k in range(n):
            if i != j != k:
                ans = min(dp[i][0] + dp[j][1] + dp[k][2], ans)

# for i in dp:
#     print(i)

print(ans)


n, m = map(int, input().strip().split())
arr = []
for i in range(n): arr.append(list(input()))

dp = [[float('inf') for i in range(3)] for i in range(n)]
for i in range(n):
    for j in range(m):
        if ord('a') <= ord(arr[i][j]) <= ord('z'):
            dp[i][0] = min(dp[i][0], j, n-j)
        elif arr[i][j] in '&#*':
            dp[i][1] = min(dp[i][1], j, n-j)
        else:
            dp[i][2] = min(dp[i][2], j, n-j)

ans = float('inf')
for i in range(n):
    for j in range(n):
        for k in range(n):
            if i != j != k:
                ans = min(dp[i][0] + dp[i][1] + dp[i][2], ans)

print(ans)


n, m = map(int, input().strip().split())
arr = []
for i in range(n): arr.append(list(input()))

dp = [[float('inf') for i in range(3)] for i in range(n)]
for i in range(n):
    for j in range(m):
        if ord('a') <= ord(arr[i][j]) <= ord('z'):
            dp[i][0] = min(dp[i][0], j, m-j)
        elif arr[i][j] in '&#*':
            dp[i][1] = min(dp[i][1], j, m-j)
        else:
            dp[i][2] = min(dp[i][2], j, m-j)

ans = float('inf')
for i in range(n):
    for j in range(n):
        for k in range(n):
            if len(set([i, j, k])) == 3:
                # print(i, j, k, 'check')
                ans = min(dp[i][0] + dp[j][1] + dp[k][2], ans)

# for i in dp:
#     print(i)

print(ans)


n,m = list(map(int, input().split(" ")))
strings = []
for i in range(n):
	strings.append(input())

spec = set('#*&')
dig = set('0123456789')
alpha = set('abcdefghijklmnopqrstuvwxyz')

def num(checkset, checkstring):
	m = len(checkstring)+1
	for i, c in enumerate(checkstring):
		if c in checkset:
			m = min(m, i)
			m = min(m, len(checkstring)-i)
	if m < len(checkstring)+1:
		return m
	return -1

ret = float('inf')

for i in range(n):
	for j in range(n):
		for k in range(n):
			if i==j or i==k or j==k:
				continue
			else:
				s1 = num(spec, strings[i])
				s2 = num(dig, strings[j])
				s3 = num(alpha, strings[k])
				if s1 >= 0 and s2 >= 0 and s3 >= 0:
					ret = min(ret, s1+s2+s3)

print(str(int(ret)))


"""
Code of Ayush Tiwari
Codeforces: servermonk
Codechef: ayush572000

"""
# import sys
# input = sys.stdin.buffer.readline

def solution():
    n,m=map(int,input().split())
    num=[100000]*100
    char=[100000]*100
    special=[100000]*100
    for i in range(n):
        s=input()
        for j in range(m):
            if s[j]>='0' and s[j]<='9':
                num[i]=min(num[i],min(j,m-j))
            if s[j]>='a' and s[j]<='z':
                char[i]=min(char[i],min(j,m-j))
            if s[j]=='*' or s[j]=='#' or s[j]=='&':
                special[i]=min(special[i],min(j,m-j))
    ans=100000
    for i in range(n):
        for j in range(n):
            for k in range(n):
                if i==k or j==k or i==j:
                   continue
                ans=min(ans,num[i]+char[j]+special[k])
    print(ans)

solution()


import sys
from copy import deepcopy

N, M = map(int, input().split())
str = []
for i in range(N):
    str.append(input())

def is_int(n):
    try:
        int(n)
        return True
    except ValueError:
        return False

def rec(c, cur):
    if cur >= 3:
        return 0

    c = sorted(c, key=lambda a: a[cur])
    best = sys.maxsize

    for d in c:
        if d[cur] != sys.maxsize:
            c2 = deepcopy(c)
            c2.remove(d)
            sub = rec(c2, cur+1)
            if sub != sys.maxsize:
                best = min(best, d[cur] + sub)

    return best

def main():
    c = [[sys.maxsize] * 3 for _ in range(N)]
    for i in range(N):
        for j in range(M):
            dist = min(j, M-j)
            if str[i][j] in ['*', '#', '&']:
                c[i][0] = min(c[i][0], dist)
            elif is_int(str[i][j]):
                c[i][1] = min(c[i][1], dist)
            elif 'a' <= str[i][j] <= 'z':
                c[i][2] = min(c[i][2], dist)
            else:
                raise RuntimeError("Invalid input")

    print(rec(c, 0))

if __name__ == '__main__':
    main()


N, M = map(int, input().split())
str = []
for i in range(N):
    str.append(input())

class Row:
    def __init__(self, ):
        self.ch = int(1e9)
        self.az = int(1e9)
        self.num = int(1e9)
        self.used = False

def is_int(n):
    try:
        int(n)
        return True
    except ValueError:
        return False

def rec(c, param):
    c = sorted(c, key=lambda a: getattr(a, param))
    best = int(1e9)

    if param == "ch":
        next_param = "az"
    elif param == "az":
        next_param = "num"
    else:
        next_param = None

    if next_param is not None:
        for row in c:
            if not row.used:
                row.used = True
                best = min(best, getattr(row, param) + rec(c, next_param))
                row.used = False
    else:
        for row in c:
            if not row.used:
                best = min(best, getattr(row, param))

    return best

def main():
    c = [Row() for _ in range(N)]
    for i in range(N):
        for j in range(M):
            dist = min(j, M-j)
            if 'a' <= str[i][j] <= 'z':
                c[i].az = min(c[i].az, dist)
            elif is_int(str[i][j]):
                c[i].num = min(c[i].num, dist)
            else:
                c[i].ch = min(c[i].ch, dist)

    print(rec(c, "ch"))

if __name__ == '__main__':
    main()


package com.company;
import java.io.*;
import java.util.*;
import java.math.*;

public class Main {

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        tuple[] pts = new tuple[n];
        for(int i = 0; i < n; i++){
            pts[i] = new tuple(sc.nextInt(),sc.nextInt(),i+1);
        }
        Arrays.sort(pts);
        for(int i = 1; i < n; i++){
            if(pts[i-1].R >= pts[i].R){
                System.out.println(pts[i].idx + " " + pts[i-1].idx);
                return;
            }
        }
        System.out.println("-1 -1");
    }
    public  static class tuple implements Comparable <tuple>{
        int L, R, idx;
        tuple(int l, int r, int i){
            L = l;
            R = r;
            idx = i;
        }
        public int compareTo(tuple o){
            if(L != o.L)return o.R-R;
            return L - o.L;
        }
    }
    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

        public Scanner(FileReader s) throws FileNotFoundException {	br = new BufferedReader(s);}

        public String next() throws IOException
        {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {return Integer.parseInt(next());}

        public long nextLong() throws IOException {return Long.parseLong(next());}

        public String nextLine() throws IOException {return br.readLine();}

        public double nextDouble() throws IOException { return Double.parseDouble(next()); }

        public boolean ready() throws IOException {return br.ready();}
    }
}


import java.io.*;
import java.util.*;
public class abc
{
    public static class seg
    {
        int a;
        int b;
        seg(int x,int y)
        {
            a=x;
            b=y;
        }
    }
    public static void main(String[] args)throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(br.readLine());
        seg[] seq=new seg[n];
        for(int i=0;i<n;i++)
        {
            String t1=br.readLine();
            String[] t2=t1.split(" ");
            seg s=new seg(Integer.parseInt(t2[0]),Integer.parseInt(t2[1]));
            seq[i]=s;
        }
        Arrays.sort(seq,new Comparator<seg>()
            {
                public int compare(seg s1,seg s2)
                {
                    if(s1.a==s2.a)
                    {
                        return (int)(s2.b-s1.b);
                    }
                    else
                    {
                        return (int)(s1.a-s2.a);
                    }
                }
            });

        for(int k=0;k<n;k++)
        {
            System.out.println(seq[k].a+" "+seq[k].b);
        }

        int flag=1;
        for(int j=0;j<n;j++)
        {
            int ll=seq[j].a;
            int ul=seq[j].b;
            int low=j+1;
            int high=n-1;
            while(low<=high)
            {
                int mid=(low+high)/2;
                if(seq[mid].a>=ll&&seq[mid].b<=ul)
                {
                    System.out.println((mid+1)+" "+(j+1));
                    flag=-1;
                    break;
                }
                else if(seq[mid].a>ul||seq[mid].b>ul)
                {
                    high=mid-1;
                }
            }
            if(flag==-1)
            {
                break;
            }
        }
        if(flag==1)
        {
            System.out.println(-1+" "+-1);
        }
    }
}


import java.io.*;
import java.util.*;
public class ECR433
{
    public static class seg
    {
        int a;
        int b;
        int ind;
        seg(int x,int y,int z)
        {
            a=x;
            b=y;
            ind=z;
        }
    }
    public static void main(String[] args)throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(br.readLine());
        seg[] seq=new seg[n];
        for(int i=0;i<n;i++)
        {
            String t1=br.readLine();
            String[] t2=t1.split(" ");
            seg s=new seg(Integer.parseInt(t2[0]),Integer.parseInt(t2[1]),i+1);
            seq[i]=s;
        }
        Arrays.sort(seq,new Comparator<seg>()
            {
                public int compare(seg s1,seg s2)
                {
                    if(s1.a==s2.a)
                    {
                        return (int)(s2.b-s1.b);
                    }
                    else
                    {
                        return (int)(s1.a-s2.a);
                    }
                }
            });
            int ax=-1;
            int ay=-1;
        for(int j=0;j<n-1;j++)
        {
            if(seq[j].b>=seq[j+1].b)
            {
                ax=seq[j+1].ind;
                ay=seq[j].ind;
                break;
            }
        }
        System.out.println(ax+" "+ay);
        /*
        for(int k=0;k<n;k++)
        {
        System.out.println(seq[k].a+" "+seq[k].b);
        }
         */
        /*
        int flag=1;
        for(int j=0;j<n;j++)
        {
            int ll=seq[j].a;
            int ul=seq[j].b;
            int low=j+1;
            int high=n-1;
            while(low<=high)
            {
                int mid=(low+high)/2;
                if(seq[mid].a>=ll&&seq[mid].b<=ul)
                {
                    System.out.println((mid+1)+" "+(j+1));
                    flag=-1;
                    break;
                }
                else if(seq[mid].a>ul||seq[mid].b>ul)
                {
                    high=mid-1;
                }
            }
            if(flag==-1)
            {
                break;
            }
        }
        if(flag==1)
        {
            System.out.println(-1+" "+-1);
        }
        */
    }
}


import java.io.*;
import java.util.*;
public class abc
{
    public static class seg
    {
        int a;
        int b;
        seg(int x,int y)
        {
            a=x;
            b=y;
        }
    }
    public static void main(String[] args)throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(br.readLine());
        seg[] seq=new seg[n];
        for(int i=0;i<n;i++)
        {
            String t1=br.readLine();
            String[] t2=t1.split(" ");
            seg s=new seg(Integer.parseInt(t2[0]),Integer.parseInt(t2[1]));
            seq[i]=s;
        }
        Arrays.sort(seq,new Comparator<seg>()
            {
                public int compare(seg s1,seg s2)
                {
                    if(s1.a==s2.a)
                    {
                        return (int)(s2.b-s1.b);
                    }
                    else
                    {
                        return (int)(s1.a-s2.a);
                    }
                }
            });
        /*
        for(int k=0;k<n;k++)
        {
        System.out.println(seq[k].a+" "+seq[k].b);
        }
         */

        int flag=1;
        for(int j=0;j<n;j++)
        {
            int ll=seq[j].a;
            int ul=seq[j].b;
            int low=j+1;
            int high=n-1;
            while(low<=high)
            {
                int mid=(low+high)/2;
                if(seq[mid].a>=ll&&seq[mid].b<=ul)
                {
                    System.out.println((mid+1)+" "+(j+1));
                    flag=-1;
                    break;
                }
                else if(seq[mid].a>ul||seq[mid].b>ul)
                {
                    high=mid-1;
                }
            }
            if(flag==-1)
            {
                break;
            }
        }
        if(flag==1)
        {
            System.out.println(-1+" "+-1);
        }
    }
}


import java.io.*;
import java.util.*;
public class abc
{
    public static class seg
    {
        int a;
        int b;
        seg(int x,int y)
        {
            a=x;
            b=y;
        }
    }
    public static void main(String[] args)throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        int n=Integer.parseInt(br.readLine());
        seg[] seq=new seg[n];
        for(int i=0;i<n;i++)
        {
            String t1=br.readLine();
            String[] t2=t1.split(" ");
            seg s=new seg(Integer.parseInt(t2[0]),Integer.parseInt(t2[1]));
            seq[i]=s;
        }
        Arrays.sort(seq,new Comparator<seg>()
        {
            public int compare(seg s1,seg s2)
            {
                if(s1.a==s2.a)
                {
                    return (int)(s1.b-s2.b);
                }
                else
                {
                    return (int)(s1.a-s2.a);
                }
            }
        });
        /*
        for(int k=0;k<n;k++)
        {
            System.out.println(seq[k].a+" "+seq[k].b);
        }
        */
       int flag=1;
        for(int j=0;j<n;j++)
        {
            int ll=seq[j].a;
            int ul=seq[j].b;
            int low=j+1;
            int high=n-1;
            while(low<=high)
            {
                int mid=(low+high)/2;
                if(seq[mid].a>=ll&&seq[mid].b<=ul)
                {
                    System.out.println((mid+1)+" "+(j+1));
                    flag=-1;
                    break;
                }
                else if(seq[mid].a>ul||seq[mid].b>ul)
                {
                    high=mid-1;
                }
            }
            if(flag==-1)
            {
                break;
            }
        }
        if(flag==1)
        {
            System.out.println(-1+" "+-1);
        }
    }
}


 import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class A  {

	public static void main(String[] args) throws NumberFormatException, IOException {

		Scanner in = new Scanner(System.in);

		int n = Integer.parseInt(in.nextLine());

		List<Point> pnts = new ArrayList<>();

		for(int i=0; i<n; i++) {
			String[] inp = in.nextLine().split("\\s+");

			int l = Integer.parseInt(inp[0]);
			int r = Integer.parseInt(inp[1]);

			pnts.add(new Point(l, r, i+1));
		}

		Collections.sort(pnts, new Comparator<Point>() {
			@Override
			public int compare(Point o1, Point o2) {
				if(o1.x == o2.x) {
					return Integer.compare(o2.y, o1.y);
				}
				else {
					return Integer.compare(o1.x, o2.x);
				}
			}
		});

		int max = -100;
		int ind = -1;

		for(int i=0; i<n; i++) {
			Point cur = pnts.get(i);

			if(cur.y <= max) {
				System.out.println(i+1 + " " + (ind));
				return;
			}

			if(cur.y > max) {
				max = cur.y;
				ind = i+1;
			}
		}

		System.out.println(-1 + " " + -1);

	}

}

class  Point {
	int x,y,z;

	Point(int xx,int yy,int zz) {
		x = xx;
		y= yy;
		z= zz;
	}
}


 import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class A  {

	public static void main(String[] args) throws NumberFormatException, IOException {

		Scanner in = new Scanner(System.in);

		int n = Integer.parseInt(in.nextLine());

		List<Point> pnts = new ArrayList<>();

		for(int i=0; i<n; i++) {
			String[] inp = in.nextLine().split("\\s+");

			int l = Integer.parseInt(inp[0]);
			int r = Integer.parseInt(inp[1]);

			pnts.add(new Point(l, r, i+1));
		}

		Collections.sort(pnts, new Comparator<Point>() {
			@Override
			public int compare(Point o1, Point o2) {
				if(o1.x == o2.x) {
					return Integer.compare(o2.y, o1.y);
				}
				else {
					return Integer.compare(o1.x, o2.x);
				}
			}
		});

		int max = -100;
		int ind = -1;

		for(int i=0; i<n; i++) {
			Point cur = pnts.get(i);

			if(cur.y <= max) {
				System.out.println(ind + " " + (i+1));
				return;
			}

			if(cur.y > max) {
				max = cur.y;
				ind = i+1;
			}
		}

		System.out.println(-1 + " " + -1);

	}

}

class  Point {
	int x,y,z;

	Point(int xx,int yy,int zz) {
		x = xx;
		y= yy;
		z= zz;
	}
}


 import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class A  {

	public static void main(String[] args) throws NumberFormatException, IOException {

		Scanner in = new Scanner(System.in);

		int n = Integer.parseInt(in.nextLine());

		List<Point> pnts = new ArrayList<>();

		for(int i=0; i<n; i++) {
			String[] inp = in.nextLine().split("\\s+");

			int l = Integer.parseInt(inp[0]);
			int r = Integer.parseInt(inp[1]);

			pnts.add(new Point(l, r, i+1));
		}

		Collections.sort(pnts, new Comparator<Point>() {
			@Override
			public int compare(Point o1, Point o2) {
				if(o1.x == o2.x) {
					return Integer.compare(o2.y, o1.y);
				}
				else {
					return Integer.compare(o1.x, o2.x);
				}
			}
		});

		int max = -100;
		int ind = -1;

		for(int i=0; i<n; i++) {
			Point cur = pnts.get(i);

			if(cur.y <= max) {
				System.out.println(cur.z + " " + (ind));
				return;
			}

			if(cur.y > max) {
				max = cur.y;
				ind = cur.z;
			}
		}

		System.out.println(-1 + " " + -1);

	}

}

class  Point {
	int x,y,z;

	Point(int xx,int yy,int zz) {
		x = xx;
		y= yy;
		z= zz;
	}
}


import java.io.*;
import java.util.*;

public class C {
    public static void main(String[] args)throws Exception {
        InputReader in = new InputReader(System.in);

        int n = in.nextInt();

        HashSet<Integer> set = new HashSet<>();

        HashMap<Integer,Data> dataMap = new HashMap<>();

        int ansI,ansJ;
        for (int i = 0; i < n; i++) {
                int ai = in.nextInt();
                int aj = in.nextInt();

                if(set.contains(ai)){
                    if(dataMap.get(ai).end > aj){
                        ansI = dataMap.get(ai).index;
                        ansJ = i+1;
                        System.out.println(ansJ+" "+ansI);
                        return;
                    } else {
                        ansJ = dataMap.get(ai).index;
                        ansI = i+1;
                        System.out.println(ansJ+" "+ansI);
                        return;
                    }
                } else {
                    set.add(ai);
                    Data data = new Data();
                    data.begin = ai;
                    data.end = aj;
                    data.index = i+1;
                    dataMap.put(ai,data);
                }
        }

        int prevNum = 0;

        Integer[] arr = new Integer[set.size()];
        arr = set.toArray(arr);
        Arrays.sort(arr);

        for (Integer num: arr){
            if(prevNum!=0){
                if(dataMap.get(num).end<= dataMap.get(prevNum).end){
                    ansI = dataMap.get(prevNum).index;
                    ansJ = dataMap.get(num).index;
                    System.out.println(ansJ+" "+ansI);
                    return;
                } else {
                    prevNum = num;
                }
            } else {
                prevNum = num;
            }
        }
        System.out.println("-1 -1");
    }

    private static class Data {
        public int begin;
        public int end;
        public int index;
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }

}


import java.util.*;

public class C {
    public static void main(String[] args)throws Exception {
        Scanner in = new Scanner(System.in);

        int n = in.nextInt();

        TreeSet<Integer> treeSet = new TreeSet<>();

        HashMap<Integer,Data> dataMap = new HashMap<>();

        int ansI,ansJ;
        boolean solved = false;

        for (int i = 0; i < n; i++) {
            if(!solved){
                int ai = in.nextInt();
                int aj = in.nextInt();

                if(treeSet.contains(ai)){
                    if(dataMap.get(ai).end > aj){
                        ansI = dataMap.get(ai).index;
                        ansJ = i+1;
                        System.out.println(ansJ+" "+ansI);
                        return;
                    } else {
                        ansJ = dataMap.get(ai).index;
                        ansI = i+1;
                        System.out.println(ansJ+" "+ansI);
                        return;
                    }
                } else {
                    treeSet.add(ai);
                    Data data = new Data();
                    data.begin = ai;
                    data.end = aj;
                    data.index = i+1;
                    dataMap.put(ai,data);
                }
            }
        }

        int prevNum = 0;

        for (Integer num: treeSet){
            if(prevNum!=0){
                if(dataMap.get(num).end<= dataMap.get(prevNum).end){
                    ansI = dataMap.get(prevNum).index;
                    ansJ = dataMap.get(num).index;
                    System.out.println(ansJ+" "+ansI);
                    return;
                } else {
                    prevNum = num;
                }
            } else {
                prevNum = num;
            }
        }
        System.out.println("-1 -1");
    }

    private static class Data {
        public int begin;
        public int end;
        public int index;
    }
}


import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class C {
    public static void main(String[] args)throws Exception {
        FastScanner in = new FastScanner();

        int n = in.nextInt();

        HashSet<Integer> set = new HashSet<>();

        HashMap<Integer,Data> dataMap = new HashMap<>();

        int ansI,ansJ;
        for (int i = 0; i < n; i++) {
                int ai = in.nextInt();
                int aj = in.nextInt();

                if(set.contains(ai)){
                    if(dataMap.get(ai).end > aj){
                        ansI = dataMap.get(ai).index;
                        ansJ = i+1;
                        System.out.println(ansJ+" "+ansI);
                        return;
                    } else {
                        ansJ = dataMap.get(ai).index;
                        ansI = i+1;
                        System.out.println(ansJ+" "+ansI);
                        return;
                    }
                } else {
                    set.add(ai);
                    Data data = new Data();
                    data.begin = ai;
                    data.end = aj;
                    data.index = i+1;
                    dataMap.put(ai,data);
                }
        }

        int prevNum = 0;

        Integer[] arr = new Integer[set.size()];
        arr = set.toArray(arr);
        Arrays.sort(arr);

        for (Integer num: arr){
            if(prevNum!=0){
                if(dataMap.get(num).end<= dataMap.get(prevNum).end){
                    ansI = dataMap.get(prevNum).index;
                    ansJ = dataMap.get(num).index;
                    System.out.println(ansJ+" "+ansI);
                    return;
                } else {
                    prevNum = num;
                }
            } else {
                prevNum = num;
            }
        }
        System.out.println("-1 -1");
    }

    private static class Data {
        public int begin;
        public int end;
        public int index;
    }

    static class FastScanner {

        private InputStream mIs;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;

        public FastScanner() {
            this(System.in);
        }

        public FastScanner(InputStream is) {
            mIs = is;
        }

        public int read() {
            if (numChars == -1)
                throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = mIs.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public String nextLine() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isEndOfLine(c));
            return res.toString();
        }

        public String nextString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        public long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;

        }

    }

}


import java.util.*;

public class C {
    public static void main(String[] args)throws Exception {
        Scanner in = new Scanner(System.in);

        int n = in.nextInt();

        Set<Integer> set = new HashSet<>();

        HashMap<Integer,Data> dataMap = new HashMap<>();

        int ansI,ansJ;
        for (int i = 0; i < n; i++) {
                int ai = in.nextInt();
                int aj = in.nextInt();

                if(set.contains(ai)){
                    if(dataMap.get(ai).end > aj){
                        ansI = dataMap.get(ai).index;
                        ansJ = i+1;
                        System.out.println(ansJ+" "+ansI);
                        return;
                    } else {
                        ansJ = dataMap.get(ai).index;
                        ansI = i+1;
                        System.out.println(ansJ+" "+ansI);
                        return;
                    }
                } else {
                    set.add(ai);
                    Data data = new Data();
                    data.begin = ai;
                    data.end = aj;
                    data.index = i+1;
                    dataMap.put(ai,data);
                }
        }

        int prevNum = 0;

        List<Integer> list = new ArrayList<>(set);
        Collections.sort(list);

        for (Integer num: list){
            if(prevNum!=0){
                if(dataMap.get(num).end<= dataMap.get(prevNum).end){
                    ansI = dataMap.get(prevNum).index;
                    ansJ = dataMap.get(num).index;
                    System.out.println(ansJ+" "+ansI);
                    return;
                } else {
                    prevNum = num;
                }
            } else {
                prevNum = num;
            }
        }
        System.out.println("-1 -1");
    }

    private static class Data {
        public int begin;
        public int end;
        public int index;
    }
}


import java.util.*;

public class C {
    public static void main(String[] args)throws Exception {
        Scanner in = new Scanner(System.in);

        int n = in.nextInt();

        List<Data> data = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            data.add(new Data(in.nextInt(),in.nextInt(),i+1));
        }

        data.sort(new Comparator<Data>() {
            @Override
            public int compare(Data o1, Data o2) {
                if(o1.begin.compareTo(o2.begin) == 0){
                    return o1.end.compareTo(o2.end);
                } else {
                    return o1.begin.compareTo(o2.begin);
                }
            }
        });

        Data[] d = new Data[n];
        d = data.toArray(d);

        for (int i = 0; i < n; i++) {
            for (int j = i; d[i].end >= d[j].begin&& j<n; j++) {
                if(d[i].begin<=d[j].begin && d[i].end>=d[j].end && i!=j){
                    System.out.println(d[j].index+" "+d[i].index);
                    return;
                }
                try {
                    Data k = d[j+1];
                } catch (ArrayIndexOutOfBoundsException e){
                    break;
                }
            }
        }

        System.out.println("-1 -1");
    }

    private static class Data implements Comparable<Data>{
        public Integer begin;
        public Integer end;
        public int index;

        public Data(int begin, int end, int index) {
            this.begin = begin;
            this.end = end;
            this.index = index;
        }

        @Override
        public int compareTo(Data o) {
            return this.begin.compareTo(o.begin);
        }

        @Override
        public String toString() {
            return this.begin+" "+this.end+" "+this.index;
        }
    }
}


import java.io.*;
import java.util.*;

public class C {
    public static void main(String[] args)throws Exception {
        InputReader in = new InputReader(System.in);
        OutputWriter out = new OutputWriter(System.out);

        int n = in.nextInt();

        TreeSet<Integer> set = new TreeSet<>();

        HashMap<Integer,Data> dataMap = new HashMap<>();

        int ansI,ansJ;
        for (int i = 0; i < n; i++) {
                int ai = in.nextInt();
                int aj = in.nextInt();

                if(set.contains(ai)){
                    if(dataMap.get(ai).end > aj){
                        ansI = dataMap.get(ai).index;
                        ansJ = i+1;
                        out.printLine(ansJ+" "+ansI);
                        out.flush();
                        return;
                    } else {
                        ansJ = dataMap.get(ai).index;
                        ansI = i+1;
                        out.printLine(ansJ+" "+ansI);
                        out.flush();
                        return;
                    }
                } else {
                    set.add(ai);
                    Data data = new Data();
                    data.begin = ai;
                    data.end = aj;
                    data.index = i+1;
                    dataMap.put(ai,data);
                }
        }

        int prevNum = 0;

        for (Integer num: set){
            if(prevNum!=0){
                if(dataMap.get(num).end<= dataMap.get(prevNum).end){
                    ansI = dataMap.get(prevNum).index;
                    ansJ = dataMap.get(num).index;
                    out.printLine(ansJ+" "+ansI);
                    out.flush();
                    return;
                } else {
                    prevNum = num;
                }
            } else {
                prevNum = num;
            }
        }
        out.printLine("-1 -1");
        out.flush();
    }

    private static class Data {
        public int begin;
        public int end;
        public int index;
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void print(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0)
                    writer.print(' ');
                writer.print(objects[i]);
            }
        }

        public void printLine(Object... objects) {
            print(objects);
            writer.println();
        }

        public void close() {
            writer.close();
        }

        public void flush() {
            writer.flush();
        }

    }

}