#include <iostream>
#include <bits/stdc++.h>
#include <set>
using namespace std;

#define ll int
#define endl '\n'
#define pll pair<ll, ll>
#define ppll pair<ll, pair<ll, ll>>
#define mp make_pair
#define pb push_back
#define mset multiset<ll, greater<ll>>
#define sz(x) (ll)x.size()
#define fr(i,a,b) for(ll i=a;i<=b;i++)
#define repr(i,n) for(ll i=0ll;i<n;i++)
#define fir first
#define sec second
#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10
#define N 1000005

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

ll lr[1005][1005];
ll tb[1005][1005];

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;
    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;
    ll s=min(l,min(r,min(t,b)));
    if(s>0){
        size[x][y]=s;

        lr[x-s][y]++;
        lr[x+s+1][y]--;

        tb[x][y-s]++;
        tb[x][y+s+1]--;
    }
}
int main(){
    fast_io;
    accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }

    fr(y,1,m){
        fr(x,1,n){
            lr[x][y] += lr[x-1][y];
        }
    }

    fr(x,1,n){
        fr(y,1,m){
            tb[x][y] += tb[x][y-1];
        }
    }
    // fr(x,1,n){
    //     fr(y,1,m){
    //         if(size[x][y])cout<<size[x][y]<<" "<<x<<" "<<y<<endl;
    //     }
    // }
    fr(x,1,n){
        fr(y,1,m){
            v[x][y] = lr[x][y] || tb[x][y];
        }
    }
    ll count=0;
    fr(x, 1, n){
        fr(y, 1, m){
            if( a[x][y] != v[x][y] ){
                cout<<-1<<endl;
                return 0;
            }
            if(size[x][y]) count++;
        }
    }
    cout<<count<<endl;

    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<endl;
        }
    }

}


#include <iostream>
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define fr(i,a,b) for(ll i=a;i <= b;i++)
#define repr(i,n) for(ll i=0;i < n;i++)

#define sz(x) x.size()
#define pll pair<ll,ll>
#define mp make_pair

#define pb push_back
#define N 100005
#define ppll pair<ll,pll>

#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

ll lr[1005][1005];
ll tb[1005][1005];

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;
    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;
    ll s=min(l,min(r,min(t,b)));
    if(s>0){
        size[x][y]=s;

        lr[x-s][y]++;
        lr[x+s+1][y]--;

        tb[x][y-s]++;
        tb[x][y+s+1]--;
    }
}
int main(){
    fast_io;
    accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }

    ll count=0;
    fr(x,1,n){
        fr(y,1,m){
            lr[x][y] += lr[x-1][y];
            tb[x][y] += tb[x][y-1];
            v[x][y] = lr[x][y] || tb[x][y];
            if( a[x][y] != v[x][y] ){
                cout<<-1<<"\n";
                return 0;
            }
            if(size[x][y]) count++;

        }
    }

    cout<<count<<"\n";
    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<"\n";
        }
    }

}


#include <iostream>
#include <bits/stdc++.h>
#include <set>
using namespace std;

#define ll long long
#define endl '\n'
#define pll pair<ll, ll>
#define ppll pair<ll, pair<ll, ll>>
#define mp make_pair
#define pb push_back
#define mset multiset<ll, greater<ll>>
#define sz(x) (ll)x.size()
#define fr(i,a,b) for(ll i=a;i<=b;i++)
#define repr(i,n) for(ll i=0ll;i<n;i++)
#define fir first
#define sec second
#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10
#define N 1000005

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

ll lr[1005][1005];
ll tb[1005][1005];

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;
    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;
    ll s=min(l,min(r,min(t,b)));
    if(s>0){
        size[x][y]=s;

        lr[x-s][y]++;
        lr[x+s+1][y]--;

        tb[x][y-s]++;
        tb[x][y+s+1]--;
    }
}
int main(){
    fast_io;
    accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }

    fr(y,1,m){
        fr(x,1,n){
            lr[x][y] += lr[x-1][y];
        }
    }

    fr(x,1,n){
        fr(y,1,m){
            tb[x][y] += tb[x][y-1];
        }
    }
    // fr(x,1,n){
    //     fr(y,1,m){
    //         if(size[x][y])cout<<size[x][y]<<" "<<x<<" "<<y<<endl;
    //     }
    // }
    fr(x,1,n){
        fr(y,1,m){
            v[x][y] = lr[x][y] || tb[x][y];
        }
    }
    ll count=0;
    fr(x, 1, n){
        fr(y, 1, m){
            if( a[x][y] != v[x][y] ){
                cout<<-1<<endl;
                return 0;
            }
            if(size[x][y]) count++;
        }
    }
    cout<<count<<endl;

    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<endl;
        }
    }

}


#include <iostream>
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define fr(i,a,b) for(ll i=a;i <= b;i++)
#define repr(i,n) for(ll i=0;i < n;i++)

#define sz(x) x.size()
#define pll pair<ll,ll>
#define mp make_pair

#define pb push_back
#define N 100005
#define ppll pair<ll,pll>

#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;

    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;
    ll s=min(l,min(r,min(t,b)));
    if(s>0) size[x][y]=s;
    while(s>0) {
        v[x+s][y] = 1;
        v[x-s][y] = 1;
        v[x][y+s] = 1;
        v[x][y-s] = 1;
        v[x][y] = 1;
        s--;
    }
}
int main(){
    fast_io;
    accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }
    ll count=0;
    fr(x, 1, n){
        fr(y, 1, m){
            if( a[x][y] != v[x][y] ){
                cout<<-1<<endl;
                return 0;
            }
            if(size[x][y]) count++;
        }
    }
    cout<<count<<endl;

    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<endl;
        }
    }

}


#include <iostream>
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define fr(i,a,b) for(ll i=a;i <= b;i++)
#define repr(i,n) for(ll i=0;i < n;i++)

#define sz(x) x.size()
#define pll pair<ll,ll>
#define mp make_pair

#define pb push_back
#define N 100005
#define ppll pair<ll,pll>

#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

ll lr[1005][1005];
ll tb[1005][1005];

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;
    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;
    ll s=min(l,min(r,min(t,b)));
    if(s>0){
        size[x][y]=s;

        lr[x-s][y]++;
        lr[x+s+1][y]--;

        tb[x][y-s]++;
        tb[x][y+s+1]--;
    }
}
int main(){
    fast_io;
    accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }

    ll count=0;
    fr(x,1,n){
        fr(y,1,m){
            lr[x][y] += lr[x-1][y];
            tb[x][y] += tb[x][y-1];
            v[x][y] = lr[x][y] || tb[x][y];
            if( a[x][y] != v[x][y] ){
                cout<<-1<<endl;
                return 0;
            }
            if(size[x][y]) count++;

        }
    }

    cout<<count<<endl;
    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<endl;
        }
    }

}


#include <iostream>
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define fr(i,a,b) for(ll i=a;i <= b;i++)
#define repr(i,n) for(ll i=0;i < n;i++)

#define endl "\n"
#define sz(x) x.size()
#define pll pair<ll,ll>
#define mp make_pair

#define pb push_back
#define N 100005
#define ppll pair<ll,pll>

#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

ll lr[1005][1005];
ll tb[1005][1005];

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;
    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;
    ll s=min(l,min(r,min(t,b)));
    if(s>0){
        size[x][y]=s;

        lr[x-s][y]++;
        lr[x+s+1][y]--;

        tb[x][y-s]++;
        tb[x][y+s+1]--;
    }
}
int main(){
    fast_io;
    // accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }

    ll count=0;
    fr(x,1,n){
        fr(y,1,m){
            lr[x][y] += lr[x-1][y];
            tb[x][y] += tb[x][y-1];
            v[x][y] = lr[x][y] || tb[x][y];
            if( a[x][y] != v[x][y] ){
                cout<<-1<<endl;
                return 0;
            }
            if(size[x][y]) count++;

        }
    }

    cout<<count<<endl;
    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<endl;
        }
    }

}


#include <iostream>
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define fr(i,a,b) for(ll i=a;i <= b;i++)
#define repr(i,n) for(ll i=0;i < n;i++)

#define sz(x) x.size()
#define pll pair<ll,ll>
#define mp make_pair

#define pb push_back
#define N 100005
#define ppll pair<ll,pll>

#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

ll lr[1005][1005];
ll tb[1005][1005];

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;
    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;
    ll s=min(l,min(r,min(t,b)));
    if(s>0){
        size[x][y]=s;

        lr[x-s][y]++;
        lr[x+s+1][y]--;

        tb[x][y-s]++;
        tb[x][y+s+1]--;
    }
}
int main(){
    fast_io;
    accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }

    fr(y,1,m){
        fr(x,1,n){
            lr[x][y] += lr[x-1][y];
        }
    }

    fr(x,1,n){
        fr(y,1,m){
            tb[x][y] += tb[x][y-1];
        }
    }
    // fr(x,1,n){
    //     fr(y,1,m){
    //         if(size[x][y])cout<<size[x][y]<<" "<<x<<" "<<y<<endl;
    //     }
    // }
    fr(x,1,n){
        fr(y,1,m){
            v[x][y] = lr[x][y] || tb[x][y];
        }
    }
    ll count=0;
    fr(x, 1, n){
        fr(y, 1, m){
            if( a[x][y] != v[x][y] ){
                cout<<-1<<endl;
                return 0;
            }
            if(size[x][y]) count++;
        }
    }
    cout<<count<<endl;

    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<endl;
        }
    }

}


#include <iostream>
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define fr(i,a,b) for(ll i=a;i <= b;i++)
#define repr(i,n) for(ll i=0;i < n;i++)

#define sz(x) x.size()
#define pll pair<ll,ll>
#define mp make_pair

#define pb push_back
#define N 100005
#define ppll pair<ll,pll>

#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;

    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;

    // m=x;
    // n=y;
    // while(a[m][n]){
    //     l++;
    //     m--;
    // }
    // m=x;
    // n=y;

    // while(a[m][n]){
    //     r++;
    //     m++;
    // }
    // m=x;
    // n=y;

    // while(a[m][n]){
    //     t++;
    //     n--;
    // }
    // m=x;
    // n=y;
    // while(a[m][n]){
    //     b++;
    //     n++;
    // }
    // cout<<l<<r<<t<<b<<endl;
    ll s=min(l,min(r,min(t,b)));
    if(s>0) size[x][y]=s;
    while(s>0) {
        v[x+s][y] = 1;
        v[x-s][y] = 1;
        v[x][y+s] = 1;
        v[x][y-s] = 1;
        v[x][y] = 1;
        s--;
    }
}
int main(){
    fast_io;
    accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }
    ll all = 1;
    fr(x, 1, n){
        fr(y, 1, m){
            if( a[x][y] != v[x][y] ){
                cout<<-1<<endl;
                return 0;
            }
        }
    }
    ll count=0;
    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) count++;
        }
    }
    cout<<count<<endl;
    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<endl;
        }
    }

}


#include <iostream>
#include <bits/stdc++.h>
#include <set>
using namespace std;

#define ll long long

#define endl '\n'
#define pll pair<ll, ll>
#define ppll pair<ll, pair<ll, ll>>
#define mp make_pair
#define pb push_back
#define mset multiset<ll, greater<ll>>
#define sz(x) (ll)x.size()
#define fr(i,a,b) for(ll i=a;i<=b;i++)
#define repr(i,n) for(ll i=0ll;i<n;i++)
#define fir first
#define sec second
#define fast_io ios_base::sync_with_stdio(false)
#define accuracy long long int precision = numeric_limits<double>::digits10
#define N 1000005

ll n,m;
ll a[1005][1005];
ll v[1005][1005];
ll size[1005][1005];

ll span[1005][1005][4];

ll left(ll x,ll y){
    ll direction=0;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + left(x-1,y);
}

ll right(ll x,ll y){
    ll direction=1;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + right(x+1,y);
}

ll top(ll x,ll y){
    ll direction=2;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + top(x,y-1);
}

ll bottom(ll x,ll y){
    ll direction=3;
    if(a[x][y] == 0) return 0;
    if(span[x][y][direction]) return span[x][y][direction];
    return span[x][y][direction] = 1 + bottom(x,y+1);
}

ll lr[1005][1005];
ll tb[1005][1005];

void pre(ll x, ll y){
    ll m,n;
    if(a[x][y] == 0) return;
    ll l=left(x,y)-1,r=right(x,y)-1,t=top(x,y)-1,b=bottom(x,y)-1;
    ll s=min(l,min(r,min(t,b)));
    if(s>0){
        size[x][y]=s;

        lr[x-s][y]++;
        lr[x+s+1][y]--;

        tb[x][y-s]++;
        tb[x][y+s+1]--;
    }
}
int main(){
    fast_io;
    accuracy;

    cin>>n>>m;;

    fr(i,1,n){
        fr(j,1,m){
            char temp;
            cin>>temp;
            if(temp == '*'){
                a[i][j] = 1;
            }
        }
    }

    fr(i,1,n){
        fr(j,1,m){
            pre(i,j);
        }
    }

    fr(y,1,m){
        fr(x,1,n){
            lr[x][y] += lr[x-1][y];
        }
    }

    fr(x,1,n){
        fr(y,1,m){
            tb[x][y] += tb[x][y-1];
        }
    }
    // fr(x,1,n){
    //     fr(y,1,m){
    //         if(size[x][y])cout<<size[x][y]<<" "<<x<<" "<<y<<endl;
    //     }
    // }
    fr(x,1,n){
        fr(y,1,m){
            v[x][y] = lr[x][y] || tb[x][y];
        }
    }
    ll count=0;
    fr(x, 1, n){
        fr(y, 1, m){
            if( a[x][y] != v[x][y] ){
                cout<<-1<<endl;
                return 0;
            }
            if(size[x][y]) count++;
        }
    }
    cout<<count<<endl;

    fr(x, 1, n){
        fr(y, 1, m){
            if(size[x][y]) cout<<x<<" "<<y<<" "<<size[x][y]<<endl;
        }
    }

}


#include <bits/stdc++.h>
using namespace std;
#define M 1000000007
#define U 998244353
#define N 1000005
#define int long long
#define sz(c) (int)c.size()
#define fr first
#define ll long long
#define sc second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(),(a).end()
#define rep(i,a,n) for(int i=a ; i<n ; i++)
#define r0 return 0;
#define endl '\n'
#define INF (int)1e15
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	std::cerr << name << " : " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');std::cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
int n,m;
bool bound(int i,int j){
    if(i>=0 && i<n && j>=0 && j<m) return 1;
    return 0;
}
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
const int dxo[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
const int dyo[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
const int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
signed main()
{
	ios_base::sync_with_stdio(0);
	int TESTS=1;
	// cin>>TESTS;
	while(TESTS--)
	{
		cin >> n >> m;
		string s[n];
		rep(i,0,n) cin >> s[i];
		vector<vector<int>> ans;
		int used[n][m];
		rep(i,0,n) rep(j,0,m) used[i][j] = 0;
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='.') continue;
				int cur = 0;
				while(1){
					bool f = 1;
					int dis = cur+1;
					rep(k,0,4)
						if(!bound(i+dis*dx[k], j+dis*dy[k]) || s[i+dis*dx[k]][j+dis*dy[k]]=='.')
							f = 0;
                    bool g=1;
rep(k,0,4)
						if(bound(i+dis*dx[k], j+dis*dy[k]))
							g &= used[i+dis*dx[k]][j+dis*dy[k]];
					if(!f || g) break;
					cur++;
				}
				// trace(i,j,cur);
				rep(l,0,cur){
					used[i][j] = 1;
					int dis = l+1;
					// trace(dis);
					rep(k,0,4)
						used[i+dis*dx[k]][j+dis*dy[k]] = 1;
				}
				if(cur) ans.pb({i,j,cur});
			}
		}
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='*' and used[i][j]==0){
					// trace(i,j);
					cout << -1;
					r0;
				}
			}
		}
		cout << sz(ans) << endl;
		for(auto j:ans){
			cout << j[0]+1<<" "<<j[1]+1<<" "<<j[2]<<endl;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 1000000007
#define U 998244353
#define N 1000005
#define int long long
#define sz(c) (int)c.size()
#define fr first
#define ll long long
#define sc second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(),(a).end()
#define rep(i,a,n) for(int i=a ; i<n ; i++)
#define r0 return 0;
#define endl '\n'
#define INF (int)1e15
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	std::cerr << name << " : " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');std::cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
int n,m;
bool bound(int i,int j){
    if(i>=0 && i<n && j>=0 && j<m) return 1;
    return 0;
}
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
const int dxo[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
const int dyo[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
const int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
signed main()
{
	ios_base::sync_with_stdio(0);
	int TESTS=1;
	// cin>>TESTS;
	while(TESTS--)
	{
		cin >> n >> m;
		string s[n];
		rep(i,0,n) cin >> s[i];
		vector<vector<int>> ans;
		int used[n][m];
		rep(i,0,n) rep(j,0,m) used[i][j] = 0;
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='.') continue;
				int cur = 0;
				while(1){
					bool f = 1;
					int dis = cur+1;
					rep(k,0,4)
						if(!bound(i+dis*dx[k], j+dis*dy[k]) || s[i+dis*dx[k]][j+dis*dy[k]]=='.')
							f = 0;
					if(!f) break;
					cur++;
				}
				// trace(i,j,cur);
				rep(l,0,cur){
					used[i][j] = 1;
					int dis = l+1;
					// trace(dis);
					rep(k,0,4)
						used[i+dis*dx[k]][j+dis*dy[k]] = 1;
				}
				if(cur) ans.pb({i,j,cur});
			}
		}
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='*' and used[i][j]==0){
					// trace(i,j);
					cout << -1;
					r0;
				}
			}
		}
		cout << sz(ans) << endl;
		for(auto j:ans){
			cout << j[0]+1<<" "<<j[1]+1<<" "<<j[2]<<endl;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 1000000007
#define U 998244353
#define N 1000005
#define int long long
#define sz(c) (int)c.size()
#define fr first
#define ll long long
#define sc second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(),(a).end()
#define rep(i,a,n) for(int i=a ; i<n ; i++)
#define r0 return 0;
#define endl '\n'
#define INF (int)1e15
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	std::cerr << name << " : " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');std::cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
int n,m;
bool bound(int i,int j){
    if(i>=0 && i<n && j>=0 && j<m) return 1;
    return 0;
}
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
const int dxo[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
const int dyo[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
const int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
signed main()
{
	ios_base::sync_with_stdio(0);
	int TESTS=1;
	// cin>>TESTS;
	while(TESTS--)
	{
		cin >> n >> m;
		string s[n];
		rep(i,0,n) cin >> s[i];
		vector<vector<int>> ans;
		int used[n][m];
		rep(i,0,n) rep(j,0,m) used[i][j] = 0;
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='.') continue;
				int cur = 0;
				while(1){
					bool f = 1;
					int dis = cur+1;
					rep(k,0,4)
						if(!bound(i+dis*dx[k], j+dis*dy[k]) || s[i+dis*dx[k]][j+dis*dy[k]]=='.')
							f = 0;
                    int g=1;
                  if(f) rep(k,0,4)
							g &= used[i+dis*dx[k]][j+dis*dy[k]];
					if(!f || g) break;
					cur++;
				}
				// trace(i,j,cur);
				rep(l,0,cur){
					used[i][j] = 1;
					int dis = l+1;
					// trace(dis);
					rep(k,0,4)
						used[i+dis*dx[k]][j+dis*dy[k]] = 1;
				}
				if(cur) ans.pb({i,j,cur});
			}
		}
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='*' and used[i][j]==0){
					// trace(i,j);
					cout << -1;
					r0;
				}
			}
		}
		cout << sz(ans) << endl;
		for(auto j:ans){
			cout << j[0]+1<<" "<<j[1]+1<<" "<<j[2]<<endl;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 1000000007
#define U 998244353
#define N 1000005
#define int long long
#define sz(c) (int)c.size()
#define fr first
#define ll long long
#define sc second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(),(a).end()
#define rep(i,a,n) for(int i=a ; i<n ; i++)
#define r0 return 0;
#define endl '\n'
#define INF (int)1e15
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	std::cerr << name << " : " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');std::cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
int n,m;
bool bound(int i,int j){
    if(i>=0 && i<n && j>=0 && j<m) return 1;
    return 0;
}
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
const int dxo[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
const int dyo[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
const int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
vector<vector<int>> a(1001, vector<int>(1001,0));

int val(int i, int j){
	if(i<0 || j<0) return 0;
	if(i>=n and j<m) return a[n-1][j];
	if(i<n and j>=m) return a[i][m-1];
	if(i>=n and j>=m) return a[n-1][m-1];
	return a[i][j];
}

bool check(int x, int i, int j){
	int ans = 0;
	ans = val(i,j) - val(i-x-1,j) - val(i,j-1) + val(i-x-1,j-1);
	// trace(ans);
	if(ans!=x+1) return false;
	ans = val(i,j) - val(i,j-x-1) - val(i-1,j) + val(i-1,j-x-1);
	// trace(ans);
	if(ans!=x+1) return false;
	ans = val(i+x,j) - val(i-1,j) - val(i+x,j-1) + val(i-1,j-1);
	// trace(ans);
	if(ans!=x+1) return false;
	ans = val(i,j+x) - val(i,j-1) - val(i-1,j+x) + val(i-1,j-1);
	// trace(ans);
	if(ans!=x+1) return false;
	return true;
}

signed main()
{
	ios_base::sync_with_stdio(0);
	int TESTS=1;
	// cin>>TESTS;
	while(TESTS--)
	{
		cin >> n >> m;
		string s[n];
		rep(i,0,n) cin >> s[i];
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j] == '*') a[i][j] = 1;
			}
		}
		// trace(1);
		rep(i,0,n){
			rep(j,0,m){
				if(i&&j){
					a[i][j] += a[i-1][j]+a[i][j-1]-a[i-1][j-1];
				}
				if(i==0 && j){
					a[i][j] += a[i][j-1];
				}
				if(j==0 && i){
					a[i][j] += a[i-1][j];
				}
			}
		}
		// trace(val(0,2));
		vector<vector<int>> ans;
		int used[n][m];
		rep(i,0,n) rep(j,0,m) used[i][j] = 0;
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='.') continue;
				int cur = 0;
				int lo = 0, hi = min({i,j,n-1-i,m-1-j});
				// trace(i,j,lo,hi);
				while(lo<=hi){
					int mid = (lo+hi)>>1;
					// trace(mid);
					if(check(mid,i,j)) lo = mid+1;
					else hi = mid-1;
				}
				cur = lo-1;
				// trace(i,j,cur);
				rep(l,0,cur){
					used[i][j] = 1;
					int dis = l+1;
					// trace(dis);
					rep(k,0,4)
						used[i+dis*dx[k]][j+dis*dy[k]] = 1;
				}
				if(cur) ans.pb({i,j,cur});
			}
		}
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='*' and used[i][j]==0){
					trace(i,j);
					cout << -1;
					r0;
				}
			}
		}
		cout << sz(ans) << endl;
		for(auto j:ans){
			cout << j[0]+1<<" "<<j[1]+1<<" "<<j[2]<<endl;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 1000000007
#define U 998244353
#define N 1000005
#define int long long
#define sz(c) (int)c.size()
#define fr first
#define ll long long
#define sc second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(),(a).end()
#define rep(i,a,n) for(int i=a ; i<n ; i++)
#define r0 return 0;
#define endl '\n'
#define INF (int)1e15
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	std::cerr << name << " : " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');std::cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
int n,m;
bool bound(int i,int j){
    if(i>=0 && i<n && j>=0 && j<m) return 1;
    return 0;
}
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
const int dxo[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
const int dyo[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
const int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
vector<vector<int>> a(1001, vector<int>(1001,0));

int val(int i, int j){
	if(i<0 || j<0) return 0;
	if(i>=n and j<m) return a[n-1][j];
	if(i<n and j>=m) return a[i][m-1];
	if(i>=n and j>=m) return a[n-1][m-1];
	return a[i][j];
}

bool check(int x, int i, int j){
	int ans = 0;
	ans = val(i,j) - val(i-x-1,j) - val(i,j-1) + val(i-x-1,j-1);
	if(ans!=x+1) return false;
	ans = val(i,j) - val(i,j-x-1) - val(i-1,j) + val(i-1,j-x-1);
	if(ans!=x+1) return false;
	ans = val(i+x,j) - val(i-1,j) - val(i+x,j-1) + val(i-1,j-1);
	if(ans!=x+1) return false;
	ans = val(i,j+x) - val(i,j-1) - val(i-1,j+x) + val(i-1,j-1);
	if(ans!=x+1) return false;
	return true;
}

signed main()
{
	ios_base::sync_with_stdio(0);
	int TESTS=1;
	// cin>>TESTS;
	while(TESTS--)
	{
		cin >> n >> m;
		string s[n];
		rep(i,0,n) cin >> s[i];
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j] == '*') a[i][j] = 1;
			}
		}
		// trace(1);
		rep(i,0,n){
			rep(j,0,m){
				if(i&&j){
					a[i][j] += a[i-1][j]+a[i][j-1]-a[i-1][j-1];
				}
			}
		}
		vector<vector<int>> ans;
		int used[n][m];
		rep(i,0,n) rep(j,0,m) used[i][j] = 0;
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='.') continue;
				int cur = 0;
				int lo = 0, hi = min({i,j,n-1-i,m-1-j});
				while(lo<=hi){
					int mid = (lo+hi)>>1;
					// trace(mid);
					if(check(mid,i,j)) lo = mid+1;
					else hi = mid-1;
				}
				cur = lo-1;
				// trace(i,j,cur);
				rep(l,0,cur){
					used[i][j] = 1;
					int dis = l+1;
					// trace(dis);
					rep(k,0,4)
						used[i+dis*dx[k]][j+dis*dy[k]] = 1;
				}
				if(cur) ans.pb({i,j,cur});
			}
		}
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='*' and used[i][j]==0){
					// trace(i,j);
					cout << -1;
					r0;
				}
			}
		}
		cout << sz(ans) << endl;
		for(auto j:ans){
			cout << j[0]+1<<" "<<j[1]+1<<" "<<j[2]<<endl;
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
#define M 1000000007
#define U 998244353
#define N 1000005
// #define int long long
#define sz(c) (int)c.size()
#define fr first
#define ll long long
#define sc second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(),(a).end()
#define rep(i,a,n) for(int i=a ; i<n ; i++)
#define r0 return 0;
#define endl '\n'
#define INF (int)1e15
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	std::cerr << name << " : " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');std::cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
int n,m;
bool bound(int i,int j){
    if(i>=0 && i<n && j>=0 && j<m) return 1;
    return 0;
}
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
const int dxo[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
const int dyo[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
const int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
vector<vector<int>> a(1001, vector<int>(1001,0));

int val(int i, int j){
	if(i<0 || j<0) return 0;
	if(i>=n and j<m) return a[n-1][j];
	if(i<n and j>=m) return a[i][m-1];
	if(i>=n and j>=m) return a[n-1][m-1];
	return a[i][j];
}

bool check(int x, int i, int j){
	int ans = 0;
	ans = val(i,j) - val(i-x-1,j) - val(i,j-1) + val(i-x-1,j-1);
	// trace(ans);
	if(ans!=x+1) return false;
	ans = val(i,j) - val(i,j-x-1) - val(i-1,j) + val(i-1,j-x-1);
	// trace(ans);
	if(ans!=x+1) return false;
	ans = val(i+x,j) - val(i-1,j) - val(i+x,j-1) + val(i-1,j-1);
	// trace(ans);
	if(ans!=x+1) return false;
	ans = val(i,j+x) - val(i,j-1) - val(i-1,j+x) + val(i-1,j-1);
	// trace(ans);
	if(ans!=x+1) return false;
	return true;
}

signed main()
{
	ios_base::sync_with_stdio(0);
	int TESTS=1;
	// cin>>TESTS;
	while(TESTS--)
	{
		cin >> n >> m;
		string s[n];
		rep(i,0,n) cin >> s[i];
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j] == '*') a[i][j] = 1;
			}
		}
		// trace(1);
		rep(i,0,n){
			rep(j,0,m){
				if(i&&j){
					a[i][j] += a[i-1][j]+a[i][j-1]-a[i-1][j-1];
				}
				if(i==0 && j){
					a[i][j] += a[i][j-1];
				}
				if(j==0 && i){
					a[i][j] += a[i-1][j];
				}
			}
		}
		// trace(val(0,2));
		vector<vector<int>> ans;
		int used[n][m];
		rep(i,0,n) rep(j,0,m) used[i][j] = 0;
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='.') continue;
				int cur = 0;
				int lo = 0, hi = min({i,j,n-1-i,m-1-j});
				// trace(i,j,lo,hi);
				while(lo<=hi){
					int mid = (lo+hi)>>1;
					// trace(mid);
					if(check(mid,i,j)) lo = mid+1;
					else hi = mid-1;
				}
				cur = lo-1;
				// trace(i,j,cur);
				rep(l,0,cur){
					used[i][j] = 1;
					int dis = l+1;
					// trace(dis);
					rep(k,0,4)
						used[i+dis*dx[k]][j+dis*dy[k]] = 1;
				}
				if(cur) ans.pb({i,j,cur});
			}
		}
		rep(i,0,n){
			rep(j,0,m){
				if(s[i][j]=='*' and used[i][j]==0){
					trace(i,j);
					cout << -1;
					r0;
				}
			}
		}
		cout << sz(ans) << endl;
		for(auto j:ans){
			cout << j[0]+1<<" "<<j[1]+1<<" "<<j[2]<<endl;
		}
	}
}


#include<iostream>
#include<stack>
#include<string>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<ctime>
#include<math.h>
#include<functional>
#include<cstring>
#include<iomanip>
#include<set>
#include<utility>
#include<limits.h>
#include<stdio.h>
#define lowbit(x) (x)&(-x)

typedef long long ll;
//
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 2e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 0x3ffffff;
const double eps = 1e-5;
/*ll gcd(ll a, ll b)//最大公约数
{
return b == 0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b)*b;
}
ll fast_pow(ll a, ll k)//快速幂
{
ll ans = 1;
a = a%mod;
while (k != 0)
{
if (k & 1) ans = (ans*a) % mod;
k >>= 1;
a = (a*a) % mod;
}
return ans;
}
ll C(ll n, ll m)//组合数的计算
{
ll ans = 1;
for (ll i = 1;i <= m;i++)
ans = (ans*(n - m + i) / i) % mod;
return ans%mod;
}

bool is_prime(ll x)//素数判断
{
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
ll temp = sqrt(1.0*x);
for (ll i = 5;i <= temp;i += 6)
if (x%i == 0 || x % (i + 2) == 0) return false;
return true;
}
int prime[maxm], pnum = 0;//素数表，pnum是索引
bool p[maxm] = { 0 };//如果被筛掉，就为true
void Find_Prime()//更快的筛选法，遇到一个素数，就把它的倍数全部筛掉
{
for (int i = 2;i < maxm;i++)
{
if (p[i] == false)//不用一个数一个数的判断素数了
{
prime[pnum++] = i;
for (int j = i + i;j < maxm;j += i)//筛掉素数的倍数
p[j] = true;
}
}
}

void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}//x是a在mod b下的逆元
ll CRT(int a[],int m[],int n)
{
ll M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];///M为除数乘积
}
for(int i=0; i<n; i++)
{
t=M/m[i];///除了mi以外的n-1个整数乘积
Exgcd(t,m[i],x,y);///求逆元，由扩展欧几里得转换成t*ti+m[i]*y=1来求ti
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}*/

char c[maxn][maxn];
int vis[maxn][maxn];
int n, m;
struct Node
{
	int x, y, s;
}node[maxn*maxn];
int cnt;
int up[maxn][maxn], down[maxn][maxn], l[maxn][maxn], r[maxn][maxn];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			cin >> c[i][j];
	for (int i = 1;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i - 1][j] == '*')
				up[i][j] = up[i - 1][j] + 1;
		}
	for (int i = n-2;i >=0;i--)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i+1][j] == '*')
				down[i][j] = down[i + 1][j] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 1;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i][j-1] == '*')
				l[i][j] = l[i][j-1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = m-2;j >= 0;j--)
		{
			if (c[i][j] == '*'&&c[i][j + 1] == '*')
				r[i][j] = r[i][j + 1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*')
			{
				int res = min(up[i][j], min(down[i][j], min(l[i][j], r[i][j])));
				if (res > 0)
				{
					vis[i - res][j]++;
					vis[i + res + 1][j]--;
					vis[i][j - res]++;
					vis[i][j - res + 1]--;
					node[cnt].x = i;
					node[cnt].y = j;
					node[cnt].s = res;
					cnt++;
				}
			}
		}
	for(int i=1;i<n;i++)
		for (int j = 1;j < m;j++)
		{
			vis[i][j] += vis[i][j - 1];
		}
	for (int i = 1;i<n;i++)
		for (int j = 1;j < m;j++)
		{
			vis[i][j] += vis[i-1][j];
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			if (c[i][j] == '*'&&vis[i][j] == 0)return cout << -1, 0;
	cout << cnt << endl;
	for (int i = 0;i < cnt;i++)
		cout << node[i].x + 1 << " " << node[i].y + 1 << " " << node[i].s << endl;
	return ~~(0 - 0);
}


#include<iostream>
#include<stack>
#include<string>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<ctime>
#include<math.h>
#include<functional>
#include<cstring>
#include<iomanip>
#include<set>
#include<utility>
#include<limits.h>
#include<stdio.h>
#define lowbit(x) (x)&(-x)

typedef long long ll;
//
using namespace std;
const int maxn = 100 + 10;
const int maxm = 2e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 0x3ffffff;
const double eps = 1e-5;
/*ll gcd(ll a, ll b)//最大公约数
{
return b == 0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b)*b;
}
ll fast_pow(ll a, ll k)//快速幂
{
ll ans = 1;
a = a%mod;
while (k != 0)
{
if (k & 1) ans = (ans*a) % mod;
k >>= 1;
a = (a*a) % mod;
}
return ans;
}
ll C(ll n, ll m)//组合数的计算
{
ll ans = 1;
for (ll i = 1;i <= m;i++)
ans = (ans*(n - m + i) / i) % mod;
return ans%mod;
}

bool is_prime(ll x)//素数判断
{
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
ll temp = sqrt(1.0*x);
for (ll i = 5;i <= temp;i += 6)
if (x%i == 0 || x % (i + 2) == 0) return false;
return true;
}
int prime[maxm], pnum = 0;//素数表，pnum是索引
bool p[maxm] = { 0 };//如果被筛掉，就为true
void Find_Prime()//更快的筛选法，遇到一个素数，就把它的倍数全部筛掉
{
for (int i = 2;i < maxm;i++)
{
if (p[i] == false)//不用一个数一个数的判断素数了
{
prime[pnum++] = i;
for (int j = i + i;j < maxm;j += i)//筛掉素数的倍数
p[j] = true;
}
}
}

void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}//x是a在mod b下的逆元
ll CRT(int a[],int m[],int n)
{
ll M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];///M为除数乘积
}
for(int i=0; i<n; i++)
{
t=M/m[i];///除了mi以外的n-1个整数乘积
Exgcd(t,m[i],x,y);///求逆元，由扩展欧几里得转换成t*ti+m[i]*y=1来求ti
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}*/

char c[maxn][maxn];
bool vis[maxn][maxn];
int n, m;
struct Node
{
	int x, y, s;
}node[maxn*maxn];
int cnt;
int up[maxn][maxn], down[maxn][maxn], l[maxn][maxn], r[maxn][maxn];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			cin >> c[i][j];
	for (int i = 1;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i - 1][j] == '*')
				up[i][j] = up[i - 1][j] + 1;
		}
	for (int i = n-2;i >=0;i--)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i+1][j] == '*')
				down[i][j] = down[i + 1][j] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 1;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i][j-1] == '*')
				l[i][j] = l[i][j-1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = m-2;j >= 0;j--)
		{
			if (c[i][j] == '*'&&c[i][j + 1] == '*')
				r[i][j] = r[i][j + 1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*')
			{
				int res = min(up[i][j], min(down[i][j], min(l[i][j], r[i][j])));
				if (res > 0)
				{
					for (int p = i - res;p <= i + res;p++)
						vis[p][j] = true;
					for (int p = j - res;p <= j + res;p++)
						vis[i][p] = true;
					node[cnt].x = i;
					node[cnt].y = j;
					node[cnt].s = res;
					cnt++;
				}
			}
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			if (c[i][j] == '*'&&vis[i][j] == false)return cout << -1, 0;
	cout << cnt << endl;
	for (int i = 0;i < cnt;i++)
		cout << node[i].x + 1 << " " << node[i].y + 1 << " " << node[i].s << endl;
	return ~~(0 - 0);
}


#include<iostream>
#include<stack>
#include<string>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<ctime>
#include<math.h>
#include<functional>
#include<cstring>
#include<iomanip>
#include<set>
#include<utility>
#include<limits.h>
#include<stdio.h>
#define lowbit(x) (x)&(-x)

typedef long long ll;
//
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 2e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 0x3ffffff;
const double eps = 1e-5;
/*ll gcd(ll a, ll b)//最大公约数
{
return b == 0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b)*b;
}
ll fast_pow(ll a, ll k)//快速幂
{
ll ans = 1;
a = a%mod;
while (k != 0)
{
if (k & 1) ans = (ans*a) % mod;
k >>= 1;
a = (a*a) % mod;
}
return ans;
}
ll C(ll n, ll m)//组合数的计算
{
ll ans = 1;
for (ll i = 1;i <= m;i++)
ans = (ans*(n - m + i) / i) % mod;
return ans%mod;
}

bool is_prime(ll x)//素数判断
{
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
ll temp = sqrt(1.0*x);
for (ll i = 5;i <= temp;i += 6)
if (x%i == 0 || x % (i + 2) == 0) return false;
return true;
}
int prime[maxm], pnum = 0;//素数表，pnum是索引
bool p[maxm] = { 0 };//如果被筛掉，就为true
void Find_Prime()//更快的筛选法，遇到一个素数，就把它的倍数全部筛掉
{
for (int i = 2;i < maxm;i++)
{
if (p[i] == false)//不用一个数一个数的判断素数了
{
prime[pnum++] = i;
for (int j = i + i;j < maxm;j += i)//筛掉素数的倍数
p[j] = true;
}
}
}

void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}//x是a在mod b下的逆元
ll CRT(int a[],int m[],int n)
{
ll M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];///M为除数乘积
}
for(int i=0; i<n; i++)
{
t=M/m[i];///除了mi以外的n-1个整数乘积
Exgcd(t,m[i],x,y);///求逆元，由扩展欧几里得转换成t*ti+m[i]*y=1来求ti
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}*/

char c[maxn][maxn];
int vis[maxn][maxn];
int n, m;
struct Node
{
	int x, y, s;
}node[maxn*maxn];
int cnt;
int up[maxn][maxn], down[maxn][maxn], l[maxn][maxn], r[maxn][maxn];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			cin >> c[i][j];
	for (int i = 1;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i - 1][j] == '*')
				up[i][j] = up[i - 1][j] + 1;
		}
	for (int i = n-2;i >=0;i--)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i+1][j] == '*')
				down[i][j] = down[i + 1][j] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 1;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i][j-1] == '*')
				l[i][j] = l[i][j-1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = m-2;j >= 0;j--)
		{
			if (c[i][j] == '*'&&c[i][j + 1] == '*')
				r[i][j] = r[i][j + 1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*')
			{
				int res = min(up[i][j], min(down[i][j], min(l[i][j], r[i][j])));
				if (res > 0)
				{
					vis[i - res][j]++;
					vis[i + res + 1][j]--;
					vis[i][j - res]++;
					vis[i][j - res + 1]--;
					node[cnt].x = i;
					node[cnt].y = j;
					node[cnt].s = res;
					cnt++;
				}
			}
		}
	for(int i=0;i<n;i++)
		for (int j = 1;j < m;j++)
		{
			vis[i][j] += vis[i][j - 1];
		}
	for (int j = 0;j<m;j++)
		for (int i = 1;i < n;i++)
		{
			vis[i][j] += vis[i-1][j];
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			if (c[i][j] == '*'&&vis[i][j] == 0)return cout << -1, 0;
	cout << cnt << endl;
	for (int i = 0;i < cnt;i++)
		cout << node[i].x + 1 << " " << node[i].y + 1 << " " << node[i].s << endl;
	return ~~(0 - 0);
}


#include<iostream>
#include<stack>
#include<string>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<ctime>
#include<math.h>
#include<functional>
#include<cstring>
#include<iomanip>
#include<set>
#include<utility>
#include<limits.h>
#include<stdio.h>
#define lowbit(x) (x)&(-x)

typedef long long ll;
//
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 2e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 0x3ffffff;
const double eps = 1e-5;
/*ll gcd(ll a, ll b)//最大公约数
{
return b == 0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b)*b;
}
ll fast_pow(ll a, ll k)//快速幂
{
ll ans = 1;
a = a%mod;
while (k != 0)
{
if (k & 1) ans = (ans*a) % mod;
k >>= 1;
a = (a*a) % mod;
}
return ans;
}
ll C(ll n, ll m)//组合数的计算
{
ll ans = 1;
for (ll i = 1;i <= m;i++)
ans = (ans*(n - m + i) / i) % mod;
return ans%mod;
}

bool is_prime(ll x)//素数判断
{
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
ll temp = sqrt(1.0*x);
for (ll i = 5;i <= temp;i += 6)
if (x%i == 0 || x % (i + 2) == 0) return false;
return true;
}
int prime[maxm], pnum = 0;//素数表，pnum是索引
bool p[maxm] = { 0 };//如果被筛掉，就为true
void Find_Prime()//更快的筛选法，遇到一个素数，就把它的倍数全部筛掉
{
for (int i = 2;i < maxm;i++)
{
if (p[i] == false)//不用一个数一个数的判断素数了
{
prime[pnum++] = i;
for (int j = i + i;j < maxm;j += i)//筛掉素数的倍数
p[j] = true;
}
}
}

void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}//x是a在mod b下的逆元
ll CRT(int a[],int m[],int n)
{
ll M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];///M为除数乘积
}
for(int i=0; i<n; i++)
{
t=M/m[i];///除了mi以外的n-1个整数乘积
Exgcd(t,m[i],x,y);///求逆元，由扩展欧几里得转换成t*ti+m[i]*y=1来求ti
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}*/

char c[maxn][maxn];
int vis[maxn][maxn];
int n, m;
struct Node
{
	int x, y, s;
}node[maxn*maxn];
int cnt;
int up[maxn][maxn], down[maxn][maxn], l[maxn][maxn], r[maxn][maxn];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			cin >> c[i][j];
	for (int i = 1;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i - 1][j] == '*')
				up[i][j] = up[i - 1][j] + 1;
		}
	for (int i = n-2;i >=0;i--)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i+1][j] == '*')
				down[i][j] = down[i + 1][j] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 1;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i][j-1] == '*')
				l[i][j] = l[i][j-1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = m-2;j >= 0;j--)
		{
			if (c[i][j] == '*'&&c[i][j + 1] == '*')
				r[i][j] = r[i][j + 1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*')
			{
				int res = min(up[i][j], min(down[i][j], min(l[i][j], r[i][j])));
				if (res > 0)
				{
					for (int p = i - res;p <= i + res;p++)
					{
						if (vis[p][j] == true) break;
						vis[p][j] = true;
					}

					for (int p = j - res;p <= j + res;p++)
					{
						if (vis[i][p] == true) break;
						vis[i][p] = true;
					}
					node[cnt].x = i;
					node[cnt].x = i;
					node[cnt].y = j;
					node[cnt].s = res;
					cnt++;
				}
			}
		}

	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			if (c[i][j] == '*'&&vis[i][j] == 0)return cout << -1, 0;
	cout << cnt << endl;
	for (int i = 0;i < cnt;i++)
		cout << node[i].x + 1 << " " << node[i].y + 1 << " " << node[i].s << endl;
	return ~~(0 - 0);
}


#include<iostream>
#include<stack>
#include<string>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<ctime>
#include<math.h>
#include<functional>
#include<cstring>
#include<iomanip>
#include<set>
#include<utility>
#include<limits.h>
#include<stdio.h>
#define lowbit(x) (x)&(-x)

typedef long long ll;
//
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 2e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 0x3ffffff;
const double eps = 1e-5;
/*ll gcd(ll a, ll b)//最大公约数
{
return b == 0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b)*b;
}
ll fast_pow(ll a, ll k)//快速幂
{
ll ans = 1;
a = a%mod;
while (k != 0)
{
if (k & 1) ans = (ans*a) % mod;
k >>= 1;
a = (a*a) % mod;
}
return ans;
}
ll C(ll n, ll m)//组合数的计算
{
ll ans = 1;
for (ll i = 1;i <= m;i++)
ans = (ans*(n - m + i) / i) % mod;
return ans%mod;
}

bool is_prime(ll x)//素数判断
{
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
ll temp = sqrt(1.0*x);
for (ll i = 5;i <= temp;i += 6)
if (x%i == 0 || x % (i + 2) == 0) return false;
return true;
}
int prime[maxm], pnum = 0;//素数表，pnum是索引
bool p[maxm] = { 0 };//如果被筛掉，就为true
void Find_Prime()//更快的筛选法，遇到一个素数，就把它的倍数全部筛掉
{
for (int i = 2;i < maxm;i++)
{
if (p[i] == false)//不用一个数一个数的判断素数了
{
prime[pnum++] = i;
for (int j = i + i;j < maxm;j += i)//筛掉素数的倍数
p[j] = true;
}
}
}

void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}//x是a在mod b下的逆元
ll CRT(int a[],int m[],int n)
{
ll M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];///M为除数乘积
}
for(int i=0; i<n; i++)
{
t=M/m[i];///除了mi以外的n-1个整数乘积
Exgcd(t,m[i],x,y);///求逆元，由扩展欧几里得转换成t*ti+m[i]*y=1来求ti
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}*/

char c[maxn][maxn];
int n, m;
struct Node
{
	int x, y, s;
}node[maxn*maxn];
int cnt;
int up[maxn][maxn], down[maxn][maxn], l[maxn][maxn], r[maxn][maxn];
int jx[maxn][maxn], jy[maxn][maxn];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++)
			cin >> c[i][j];
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++)
		{
			if (c[i][j] == '*'&&c[i - 1][j] == '*')
				up[i][j] = up[i - 1][j] + 1;
		}
	for (int i = n;i >=1;i--)
		for (int j = 1;j <= m;j++)
		{
			if (c[i][j] == '*'&&c[i+1][j] == '*')
				down[i][j] = down[i + 1][j] + 1;
		}
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++)
		{
			if (c[i][j] == '*'&&c[i][j-1] == '*')
				l[i][j] = l[i][j-1] + 1;
		}
	for (int i = 1;i <= n;i++)
		for (int j = m;j >= 1;j--)
		{
			if (c[i][j] == '*'&&c[i][j + 1] == '*')
				r[i][j] = r[i][j + 1] + 1;
		}
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++)
		{
			if (c[i][j] == '*')
			{
				int res = min(up[i][j], min(down[i][j], min(l[i][j], r[i][j])));
				if (res > 0)
				{

					jx[i - res][j]++;
					jx[i + res+1][j]--;
					jy[i][j - res ]++;
					jy[i][j + res+1]--;
					node[cnt].x = i;
					node[cnt].y = j;
					node[cnt].s = res;
					cnt++;
				}
			}
		}
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= m;j++) {
			jx[i][j] += jx[i - 1][j];
			jy[i][j] += jy[i][j - 1];
		}
	}
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++)
			if (c[i][j] == '*'&&jx[i][j] == 0 && jy[i][j] == 0)return cout << -1, 0;
	cout << cnt << endl;
	for (int i = 0;i < cnt;i++)
		cout << node[i].x  << " " << node[i].y << " " << node[i].s << endl;
	return ~~(0 - 0);
}


#include<iostream>
#include<stack>
#include<string>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<ctime>
#include<math.h>
#include<functional>
#include<cstring>
#include<iomanip>
#include<set>
#include<utility>
#include<limits.h>
#include<stdio.h>
#define lowbit(x) (x)&(-x)

typedef long long ll;
//
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 2e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 0x3ffffff;
const double eps = 1e-5;
/*ll gcd(ll a, ll b)//最大公约数
{
return b == 0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b)*b;
}
ll fast_pow(ll a, ll k)//快速幂
{
ll ans = 1;
a = a%mod;
while (k != 0)
{
if (k & 1) ans = (ans*a) % mod;
k >>= 1;
a = (a*a) % mod;
}
return ans;
}
ll C(ll n, ll m)//组合数的计算
{
ll ans = 1;
for (ll i = 1;i <= m;i++)
ans = (ans*(n - m + i) / i) % mod;
return ans%mod;
}

bool is_prime(ll x)//素数判断
{
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
ll temp = sqrt(1.0*x);
for (ll i = 5;i <= temp;i += 6)
if (x%i == 0 || x % (i + 2) == 0) return false;
return true;
}
int prime[maxm], pnum = 0;//素数表，pnum是索引
bool p[maxm] = { 0 };//如果被筛掉，就为true
void Find_Prime()//更快的筛选法，遇到一个素数，就把它的倍数全部筛掉
{
for (int i = 2;i < maxm;i++)
{
if (p[i] == false)//不用一个数一个数的判断素数了
{
prime[pnum++] = i;
for (int j = i + i;j < maxm;j += i)//筛掉素数的倍数
p[j] = true;
}
}
}

void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}//x是a在mod b下的逆元
ll CRT(int a[],int m[],int n)
{
ll M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];///M为除数乘积
}
for(int i=0; i<n; i++)
{
t=M/m[i];///除了mi以外的n-1个整数乘积
Exgcd(t,m[i],x,y);///求逆元，由扩展欧几里得转换成t*ti+m[i]*y=1来求ti
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}*/

char c[maxn][maxn];
int vis[maxn][maxn];
int n, m;
struct Node
{
	int x, y, s;
}node[maxn*maxn];
int cnt;
int up[maxn][maxn], down[maxn][maxn], l[maxn][maxn], r[maxn][maxn];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			cin >> c[i][j];
	for (int i = 1;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i - 1][j] == '*')
				up[i][j] = up[i - 1][j] + 1;
		}
	for (int i = n-2;i >=0;i--)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i+1][j] == '*')
				down[i][j] = down[i + 1][j] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 1;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i][j-1] == '*')
				l[i][j] = l[i][j-1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = m-2;j >= 0;j--)
		{
			if (c[i][j] == '*'&&c[i][j + 1] == '*')
				r[i][j] = r[i][j + 1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*')
			{
				int res = min(up[i][j], min(down[i][j], min(l[i][j], r[i][j])));
				if (res > 0)
				{
					vis[i - res][j]++;
					vis[i + res + 1][j]--;
					vis[i][j - res]++;
					vis[i][j - res + 1]--;
					node[cnt].x = i;
					node[cnt].y = j;
					node[cnt].s = res;
					cnt++;
				}
			}
		}
	for(int i=0;i<n;i++)
		for (int j = 1;j < m;j++)
		{
			vis[i][j] += vis[i][j - 1];
		}
	for (int i = 1;i<n;i++)
		for (int j = 0;j < m;j++)
		{
			vis[i][j] += vis[i-1][j];
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			if (c[i][j] == '*'&&vis[i][j] == 0)return cout << -1, 0;
	cout << cnt << endl;
	for (int i = 0;i < cnt;i++)
		cout << node[i].x + 1 << " " << node[i].y + 1 << " " << node[i].s << endl;
	return ~~(0 - 0);
}


#include<iostream>
#include<stack>
#include<string>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<ctime>
#include<math.h>
#include<functional>
#include<cstring>
#include<iomanip>
#include<set>
#include<utility>
#include<limits.h>
#include<stdio.h>
#define lowbit(x) (x)&(-x)

typedef long long ll;
//
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 2e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 0x3ffffff;
const double eps = 1e-5;
/*ll gcd(ll a, ll b)//最大公约数
{
return b == 0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b)*b;
}
ll fast_pow(ll a, ll k)//快速幂
{
ll ans = 1;
a = a%mod;
while (k != 0)
{
if (k & 1) ans = (ans*a) % mod;
k >>= 1;
a = (a*a) % mod;
}
return ans;
}
ll C(ll n, ll m)//组合数的计算
{
ll ans = 1;
for (ll i = 1;i <= m;i++)
ans = (ans*(n - m + i) / i) % mod;
return ans%mod;
}

bool is_prime(ll x)//素数判断
{
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
ll temp = sqrt(1.0*x);
for (ll i = 5;i <= temp;i += 6)
if (x%i == 0 || x % (i + 2) == 0) return false;
return true;
}
int prime[maxm], pnum = 0;//素数表，pnum是索引
bool p[maxm] = { 0 };//如果被筛掉，就为true
void Find_Prime()//更快的筛选法，遇到一个素数，就把它的倍数全部筛掉
{
for (int i = 2;i < maxm;i++)
{
if (p[i] == false)//不用一个数一个数的判断素数了
{
prime[pnum++] = i;
for (int j = i + i;j < maxm;j += i)//筛掉素数的倍数
p[j] = true;
}
}
}

void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}//x是a在mod b下的逆元
ll CRT(int a[],int m[],int n)
{
ll M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];///M为除数乘积
}
for(int i=0; i<n; i++)
{
t=M/m[i];///除了mi以外的n-1个整数乘积
Exgcd(t,m[i],x,y);///求逆元，由扩展欧几里得转换成t*ti+m[i]*y=1来求ti
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}*/

char c[maxn][maxn];
bool vis[maxn][maxn];
int n, m;
struct Node
{
	int x, y, s;
}node[maxn*maxn];
int cnt;
int up[maxn][maxn], down[maxn][maxn], l[maxn][maxn], r[maxn][maxn];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			cin >> c[i][j];
	for (int i = 1;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i - 1][j] == '*')
				up[i][j] = up[i - 1][j] + 1;
		}
	for (int i = n-2;i >=0;i--)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i+1][j] == '*')
				down[i][j] = down[i + 1][j] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 1;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i][j-1] == '*')
				l[i][j] = l[i][j-1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = m-2;j >= 0;j--)
		{
			if (c[i][j] == '*'&&c[i][j + 1] == '*')
				r[i][j] = r[i][j + 1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*')
			{
				int res = min(up[i][j], min(down[i][j], min(l[i][j], r[i][j])));
				if (res > 0)
				{
					for (int p = i - res;p <= i + res;p++)
						vis[p][j] = true;
					for (int p = j - res;p <= j + res;p++)
						vis[i][p] = true;
					node[cnt].x = i;
					node[cnt].y = j;
					node[cnt].s = res;
					cnt++;
				}
			}
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			if (c[i][j] == '*'&&vis[i][j] == false)return cout << -1, 0;
	cout << cnt << endl;
	for (int i = 0;i < cnt;i++)
		cout << node[i].x + 1 << " " << node[i].y + 1 << " " << node[i].s << endl;
	return ~~(0 - 0);
}


#include<iostream>
#include<stack>
#include<string>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<ctime>
#include<math.h>
#include<functional>
#include<cstring>
#include<iomanip>
#include<set>
#include<utility>
#include<limits.h>
#include<stdio.h>
#define lowbit(x) (x)&(-x)

typedef long long ll;
//
using namespace std;
const int maxn = 1000 + 10;
const int maxm = 2e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 0x3ffffff;
const double eps = 1e-5;
/*ll gcd(ll a, ll b)//最大公约数
{
return b == 0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a / gcd(a, b)*b;
}
ll fast_pow(ll a, ll k)//快速幂
{
ll ans = 1;
a = a%mod;
while (k != 0)
{
if (k & 1) ans = (ans*a) % mod;
k >>= 1;
a = (a*a) % mod;
}
return ans;
}
ll C(ll n, ll m)//组合数的计算
{
ll ans = 1;
for (ll i = 1;i <= m;i++)
ans = (ans*(n - m + i) / i) % mod;
return ans%mod;
}

bool is_prime(ll x)//素数判断
{
if (x == 2 || x == 3) return true;
if (x % 6 != 1 && x % 6 != 5) return false;
ll temp = sqrt(1.0*x);
for (ll i = 5;i <= temp;i += 6)
if (x%i == 0 || x % (i + 2) == 0) return false;
return true;
}
int prime[maxm], pnum = 0;//素数表，pnum是索引
bool p[maxm] = { 0 };//如果被筛掉，就为true
void Find_Prime()//更快的筛选法，遇到一个素数，就把它的倍数全部筛掉
{
for (int i = 2;i < maxm;i++)
{
if (p[i] == false)//不用一个数一个数的判断素数了
{
prime[pnum++] = i;
for (int j = i + i;j < maxm;j += i)//筛掉素数的倍数
p[j] = true;
}
}
}

void Exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) x = 1, y = 0;
else Exgcd(b, a % b, y, x), y -= a / b * x;
}//x是a在mod b下的逆元
ll CRT(int a[],int m[],int n)
{
ll M=1,ans=0,t,x,y;
for(int i=0; i<n; i++)
{
M*=m[i];///M为除数乘积
}
for(int i=0; i<n; i++)
{
t=M/m[i];///除了mi以外的n-1个整数乘积
Exgcd(t,m[i],x,y);///求逆元，由扩展欧几里得转换成t*ti+m[i]*y=1来求ti
ans=(ans+a[i]*x*t)%M;
}
return (ans+M)%M;
}*/

char c[maxn][maxn];
int vis[maxn][maxn];
int n, m;
struct Node
{
	int x, y, s;
}node[maxn*maxn];
int cnt;
int up[maxn][maxn], down[maxn][maxn], l[maxn][maxn], r[maxn][maxn];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			cin >> c[i][j];
	for (int i = 1;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i - 1][j] == '*')
				up[i][j] = up[i - 1][j] + 1;
		}
	for (int i = n-2;i >=0;i--)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i+1][j] == '*')
				down[i][j] = down[i + 1][j] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 1;j < m;j++)
		{
			if (c[i][j] == '*'&&c[i][j-1] == '*')
				l[i][j] = l[i][j-1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = m-2;j >= 0;j--)
		{
			if (c[i][j] == '*'&&c[i][j + 1] == '*')
				r[i][j] = r[i][j + 1] + 1;
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			if (c[i][j] == '*')
			{
				int res = min(up[i][j], min(down[i][j], min(l[i][j], r[i][j])));
				if (res > 0)
				{
					vis[i - res][j]++;
					vis[i + res + 1][j]--;
					vis[i][j - res]++;
					vis[i][j - res + 1]--;
					node[cnt].x = i;
					node[cnt].y = j;
					node[cnt].s = res;
					cnt++;
				}
			}
		}
	for(int i=0;i<n;i++)
		for (int j = 1;j < m;j++)
		{
			vis[i][j] += vis[i][j - 1];
		}
	for (int j = 0;j<m;j++)
		for (int i = 1;i < n;i++)
		{
			vis[i][j] += vis[i][j - 1];
		}
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
			if (c[i][j] == '*'&&vis[i][j] == 0)return cout << -1, 0;
	cout << cnt << endl;
	for (int i = 0;i < cnt;i++)
		cout << node[i].x + 1 << " " << node[i].y + 1 << " " << node[i].s << endl;
	return ~~(0 - 0);
}


#include <bits/stdc++.h>
using namespace std;
int n,m;
char arr[1005][1005], res[1005][1005], val[1005][1005][4];
int row[4] = {0,1,0,-1};
int col[4] = {1,0,-1,0};
vector<pair<pair<int,int>,int> > v;

void warna(int x, int y, int ray){
    res[x][y] = '*';
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            res[targetrow][targetcol] = '*';
        }
    }
}

void output(){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            printf("%c", res[i][j]);
        }
        printf("\n");
    }
}

int main(){
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        getchar();
        for(int j = 0; j < m; j++){
            scanf("%c", &arr[i][j]);
            res[i][j] = '.';
        }
    }

    for(int i = 0; i < n; i++){
        int temp = 0;
        for(int j = 0; j < m; j++){
            val[i][j][0] = temp;
            if(arr[i][j] == '*')temp++;
        }
        temp = 0;
        for(int j = m-1; j >= 0; j--){
            val[i][j][1] = temp;
            if(arr[i][j] == '*')temp++;
        }
    }

    for(int j = 0; j < m; j++){
        int temp = 0;
        for(int i = 0; i < n; i++){
            val[i][j][2] = temp;
            if(arr[i][j] == '*')temp++;
        }
        temp = 0;
        for(int i = n-1; i >= 0; i--){
            val[i][j][3] = temp;
            if(arr[i][j] == '*')temp++;
        }
    }

    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                int last = min(min(val[i][j][0],val[i][j][1]),min(val[i][j][2],val[i][j][3]));
                if(last > 0){
                    v.push_back(make_pair(make_pair(i,j),last));
                    warna(i,j,last);
                }
            }
        }
    }
    //output();
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] != res[i][j]){
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", v.size());
    for(int i = 0; i < v.size(); i++){
        printf("%d %d %d\n", v[i].first.first+1, v[i].first.second+1, v[i].second);
    }
}


#include <bits/stdc++.h>
using namespace std;
int n,m;
char arr[1005][1005], res[1005][1005];
int row[4] = {0,1,0,-1};
int col[4] = {1,0,-1,0};
vector<pair<pair<int,int>,int> > v;

bool valid(int x, int y){
    if(x<0 or x >= n or y<0 or y >= m or arr[x][y] == '.')return false;
    return true;
}

bool cek(int x, int y, int ray){
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            //cout<<x<<" "<<y<<" "<<targetrow<<" "<<targetcol<<endl;
            if(!valid(targetrow,targetcol))return false;
        }
    }
    return true;
}

void warna(int x, int y, int ray){
    res[x][y] = '*';
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            res[targetrow][targetcol] = '*';
        }
    }
}

int cari(int x, int y, int a, int b){
    if(a>=b)return a;

    int mid = (a+b)>>1;
    mid += (a+b)%2;

    if(cek(x,y,mid)){
        cari(x,y,mid,b);
    } else{
        cari(x,y,a,mid-1);
    }
}

void output(){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            printf("%c", res[i][j]);
        }
        printf("\n");
    }
}

int main(){
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        getchar();
        for(int j = 0; j < m; j++){
            scanf("%c", &arr[i][j]);
            res[i][j] = '.';
        }
    }
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                int last = cari(i,j,0,500);
                if(last > 0){
                    v.push_back(make_pair(make_pair(i,j),last));
                    warna(i,j,last);
                }
            }
        }
    }
    //output();
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] != res[i][j]){
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", v.size());
    for(int i = 0; i < v.size(); i++){
        printf("%d %d %d\n", v[i].first.first+1, v[i].first.second+1, v[i].second);
    }
}


#include <bits/stdc++.h>
using namespace std;
int n,m;
char arr[1005][1005], res[1005][1005], val[1005][1005][4];
int row[4] = {0,1,0,-1};
int col[4] = {1,0,-1,0};
vector<pair<pair<int,int>,int> > v;

void warna(int x, int y, int ray){
    res[x][y] = '*';
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            res[targetrow][targetcol] = '*';
        }
    }
}

void output(){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            printf("%c", res[i][j]);
        }
        printf("\n");
    }
}

int main(){
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        getchar();
        for(int j = 0; j < m; j++){
            scanf("%c", &arr[i][j]);
            res[i][j] = '.';
        }
    }

    for(int i = 0; i < n; i++){
        int temp = 0;
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                val[i][j][0] = temp;
                temp++;
            } else {
                temp = 0;
            }
        }
        temp = 0;
        for(int j = m-1; j >= 0; j--){
            if(arr[i][j] == '*'){
                val[i][j][1] = temp;
                temp++;
            } else{
                temp = 0;
            }
        }
    }

    for(int j = 0; j < m; j++){
        int temp = 0;
        for(int i = 0; i < n; i++){
            if(arr[i][j] == '*'){
                val[i][j][2] = temp;
                temp++;
            } else{
                temp = 0;
            }
        }
        temp = 0;
        for(int i = n-1; i >= 0; i--){
            if(arr[i][j] == '*'){
                val[i][j][3] = temp;
                temp++;
            } else {
                temp = 0;
            }
        }
    }

    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                int last = min(min(val[i][j][0],val[i][j][1]),min(val[i][j][2],val[i][j][3]));
                if(last > 0){
                    v.push_back(make_pair(make_pair(i,j),last));
                    warna(i,j,last);
                }
            }
        }
    }
    //output();
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] != res[i][j]){
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", v.size());
    for(int i = 0; i < v.size(); i++){
        printf("%d %d %d\n", v[i].first.first+1, v[i].first.second+1, v[i].second);
    }
}


#include <bits/stdc++.h>
using namespace std;
int n,m;
char arr[1005][1005], res[1005][1005], val[1005][1005][4];
int row[4] = {0,1,0,-1};
int col[4] = {1,0,-1,0};
vector<pair<pair<int,int>,int> > v;

void warna(int x, int y, int ray){
    res[x][y] = '*';
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            res[targetrow][targetcol] = '*';
        }
    }
}

void output(){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            printf("%c", res[i][j]);
        }
        printf("\n");
    }
}

int main(){
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        getchar();
        for(int j = 0; j < m; j++){
            scanf("%c", &arr[i][j]);
            res[i][j] = '.';
        }
    }

    for(int i = 0; i < n; i++){
        int temp = 0;
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                val[i][j][0] = temp;
                temp++;
            }
        }
        temp = 0;
        for(int j = m-1; j >= 0; j--){
            if(arr[i][j] == '*'){
                val[i][j][1] = temp;
                temp++;
            }
        }
    }

    for(int j = 0; j < m; j++){
        int temp = 0;
        for(int i = 0; i < n; i++){
            if(arr[i][j] == '*'){
                val[i][j][2] = temp;
                temp++;
            }
        }
        temp = 0;
        for(int i = n-1; i >= 0; i--){
            if(arr[i][j] == '*'){
                val[i][j][3] = temp;
                temp++;
            }
        }
    }

    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                int last = min(min(val[i][j][0],val[i][j][1]),min(val[i][j][2],val[i][j][3]));
                if(last > 0){
                    v.push_back(make_pair(make_pair(i,j),last));
                    warna(i,j,last);
                }
            }
        }
    }
    //output();
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] != res[i][j]){
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", v.size());
    for(int i = 0; i < v.size(); i++){
        printf("%d %d %d\n", v[i].first.first+1, v[i].first.second+1, v[i].second);
    }
}


#include <bits/stdc++.h>
using namespace std;
int n,m;
char arr[1005][1005], res[1005][1005], val[1005][1005][6];
int row[4] = {0,1,0,-1};
int col[4] = {1,0,-1,0};
vector<pair<pair<int,int>,int> > v;

void warna(int x, int y, int ray){
    res[x][y] = '*';
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            res[targetrow][targetcol] = '*';
        }
    }
}

void output(){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            printf("%c", res[i][j]);
        }
        printf("\n");
    }
}

int main(){
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        getchar();
        for(int j = 0; j < m; j++){
            scanf("%c", &arr[i][j]);
            res[i][j] = '.';
        }
    }

    for(int i = 0; i < n; i++){
        int temp = 0;
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                val[i][j][0] = temp;
                temp++;
            } else {
                temp = 0;
            }
        }
        temp = 0;
        for(int j = m-1; j >= 0; j--){
            if(arr[i][j] == '*'){
                val[i][j][1] = temp;
                temp++;
            } else{
                temp = 0;
            }
        }
    }

    for(int j = 0; j < m; j++){
        int temp = 0;
        for(int i = 0; i < n; i++){
            if(arr[i][j] == '*'){
                val[i][j][2] = temp;
                temp++;
            } else{
                temp = 0;
            }
        }
        temp = 0;
        for(int i = n-1; i >= 0; i--){
            if(arr[i][j] == '*'){
                val[i][j][3] = temp;
                temp++;
            } else {
                temp = 0;
            }
        }
    }

    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                int last = min(min(val[i][j][0],val[i][j][1]),min(val[i][j][2],val[i][j][3]));
                if(last > 0){
                    v.push_back(make_pair(make_pair(i,j),last));
                    warna(i,j,last);
                }
            }
        }
    }
    //output();
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] != res[i][j]){
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", v.size());
    for(int i = 0; i < v.size(); i++){
        printf("%d %d %d\n", v[i].first.first+1, v[i].first.second+1, v[i].second);
    }
}


#include <bits/stdc++.h>
using namespace std;
int n,m;
char arr[105][105], res[105][105];
int row[4] = {0,1,0,-1};
int col[4] = {1,0,-1,0};
vector<pair<pair<int,int>,int> > v;

bool valid(int x, int y){
    if(x<0 or x >= n or y<0 or y >= m or arr[x][y] == '.')return false;
    return true;
}

bool cek(int x, int y, int ray){
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            //cout<<x<<" "<<y<<" "<<targetrow<<" "<<targetcol<<endl;
            if(!valid(targetrow,targetcol))return false;
        }
    }
    return true;
}

void warna(int x, int y, int ray){
    res[x][y] = '*';
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            res[targetrow][targetcol] = '*';
        }
    }
}

int cari(int x, int y, int a, int b){
    if(a>=b)return a;

    int mid = (a+b)>>1;
    mid += (a+b)%2;

    if(cek(x,y,mid)){
        cari(x,y,mid,b);
    } else{
        cari(x,y,a,mid-1);
    }
}

void output(){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            printf("%c", res[i][j]);
        }
        printf("\n");
    }
}

int main(){
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        getchar();
        for(int j = 0; j < m; j++){
            scanf("%c", &arr[i][j]);
            res[i][j] = '.';
        }
    }
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                int last = cari(i,j,0,500);
                if(last > 0){
                    v.push_back(make_pair(make_pair(i,j),last));
                    warna(i,j,last);
                }
            }
        }
    }
    //output();
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] != res[i][j]){
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", v.size());
    for(int i = 0; i < v.size(); i++){
        printf("%d %d %d\n", v[i].first.first+1, v[i].first.second+1, v[i].second);
    }
}


#include <bits/stdc++.h>
using namespace std;
int n,m;
char arr[1005][1005], res[1005][1005];
int val[1005][1005][4];
int row[4] = {0,1,0,-1};
int col[4] = {1,0,-1,0};
vector<pair<pair<int,int>,int> > v;

void warna(int x, int y, int ray){
    res[x][y] = '*';
    for(int i = 0; i < 4; i++){
        for(int k = 1; k <= ray; k++){
            int targetrow = x+row[i]*k;
            int targetcol = y+col[i]*k;
            res[targetrow][targetcol] = '*';
        }
    }
}

void output(){
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            printf("%c", res[i][j]);
        }
        printf("\n");
    }
}

int main(){
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++){
        getchar();
        for(int j = 0; j < m; j++){
            scanf("%c", &arr[i][j]);
            res[i][j] = '.';
        }
    }

    for(int i = 0; i < n; i++){
        int temp = 0;
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                val[i][j][0] = temp;
                temp++;
            } else {
                temp = 0;
            }
        }
        temp = 0;
        for(int j = m-1; j >= 0; j--){
            if(arr[i][j] == '*'){
                val[i][j][1] = temp;
                temp++;
            } else{
                temp = 0;
            }
        }
    }

    for(int j = 0; j < m; j++){
        int temp = 0;
        for(int i = 0; i < n; i++){
            if(arr[i][j] == '*'){
                val[i][j][2] = temp;
                temp++;
            } else{
                temp = 0;
            }
        }
        temp = 0;
        for(int i = n-1; i >= 0; i--){
            if(arr[i][j] == '*'){
                val[i][j][3] = temp;
                temp++;
            } else {
                temp = 0;
            }
        }
    }

    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] == '*'){
                int last = min(min(val[i][j][0],val[i][j][1]),min(val[i][j][2],val[i][j][3]));
                if(last > 0){
                    v.push_back(make_pair(make_pair(i,j),last));
                    warna(i,j,last);
                }
            }
        }
    }
    //output();
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(arr[i][j] != res[i][j]){
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", v.size());
    for(int i = 0; i < v.size(); i++){
        printf("%d %d %d\n", v[i].first.first+1, v[i].first.second+1, v[i].second);
    }
}


#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 1010;
char matrix[MAX_N][MAX_N] = { '.' };
bool used[MAX_N][MAX_N] = { false };

int main () {
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
    int N, M, cnt = 0;
    scanf("%d%d", &N, &M);
    for(int i = 0; i < N; i += 1) {
        for(int j = 0; j < M; j += 1) {
            scanf(" %c", &matrix[i][j]);
        }
    }
    vector < pair < pair <int, int>, int> > ans;
//    for(int rep = 0; rep < 100; rep += 1) {
        for(int i = 1; i < N - 1; i += 1) {
            for(int j = 1; j < M - 1; j += 1) {
                if(matrix[i][j] == '*' && matrix[i - 1][j] == '*' && matrix[i + 1][j] == '*' && matrix[i][j + 1] == '*' && matrix[i][j - 1] == '*') {
                    int cntLeft = 0, cntRight = 0, cntTop = 0, cntBot = 0;
                    int ii = i + 1, jj = j + 1;
                    while(ii < N && matrix[ii][j] == '*') {
                        cntRight += 1;
                        ii += 1;
                    }
                    ii = i - 1;
                    while(ii >= 0 && matrix[ii][j] == '*') {
                        cntLeft += 1;
                        ii -= 1;
                    }
                    while(jj < M && matrix[i][jj] == '*') {
                        cntBot += 1;
                        jj += 1;
                    }
                    jj = j - 1;
                    while(jj >= 0 && matrix[i][jj] == '*') {
                        cntTop += 1;
                        jj -= 1;
                    }
                    int cnt1 = min(min(cntRight, cntLeft), min(cntTop, cntBot));
                    if(cnt1 >= 1) {
                        ii = i + 1, jj = j + 1;
                        ans.push_back({{i + 1, j + 1}, {cnt1}});
                        used[i][j] = true;
                        cnt += 1;
                        int currCnt = cnt1;
                        while(ii < N && matrix[ii][j] == '*' && currCnt != 0) {
                            used[ii][j] = true;
                            ii += 1;
                            currCnt -= 1;
                        }
                        ii = i - 1;
                        currCnt = cnt1;
                        while(ii >= 0 && matrix[ii][j] == '*' && currCnt != 0) {
                            used[ii][j] = true;
                            ii -= 1;
                            currCnt -= 1;
                        }
                        currCnt = cnt1;
                        while(jj < M && matrix[i][jj] == '*' && currCnt != 0) {
                            used[i][jj] = true;
                            jj += 1;
                            currCnt -= 1;
                        }
                        jj = j - 1;
                        currCnt = cnt1;
                        while(jj >= 0 && matrix[i][jj] == '*' && currCnt != 0) {
                            used[i][jj] = true;
                            jj -= 1;
                            currCnt -= 1;
                        }
                    }
                }
            }
        }
//    }
    for(int i = 0; i < N; i += 1) {
        for(int j = 0; j < M; j += 1) {
            if(matrix[i][j] == '*' && !used[i][j]) {
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", cnt);
    for(int i = 0; i < cnt; i += 1) {
        printf("%d %d %d\n", ans[i].first.first, ans[i].first.second, ans[i].second);
    }
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double

bool valid(int r, int c, int n, int m, vector<string>&A)
{
    return r>=0 && c>=0 && r<n && c<m && A[r][c]=='*';
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    int n,m;
    int dr[]={-1,1,0,0};
    int dc[]={0,0,-1,1};
    cin>>n>>m;
    vector<string>A(n);
    vector<vector<int>>v(n,vector<int>(m));
    for(auto&s:A)cin>>s;
    vector<array<int,3>>ats;

    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
        if(A[i][j]=='*')
        {
            int k  = 0;
            while(1)
        {
            bool ok = 1;
            k++;
            for(int z=0; z<4; z++)
                if(!valid(i+k*dr[z],j+k*dc[z],n,m,A))ok=0;

            if(!ok)break;

            v[i][j]=1;
            for(int z=0; z<4; z++)
                v[i+dr[z]*k][j+dc[z]*k]=1;
        }
            if(k==1)continue;
            ats.push_back({i+1,j+1,k-1});
        }

        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            if(A[i][j]=='*' && !v[i][j])return cout<<-1,0;

    cout<<ats.size()<<"\n";
    for(auto&p:ats)
        cout<<p[0]<<" "<<p[1]<<" "<<p[2]<<"\n";
}


#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); i++)

const int dx[] = {1, 0, -1,  0};
const int dy[] = {0, 1,  0, -1};
const int N = 1001;

int n, m;
vector<string> f;
int d[N][N][4];
int r[N][N], a[N][N], b[N][N];

int getd(int i, int j, int k) {
    int dxk = dx[k];
    int dyk = dy[k];
    int result = 0;
    while (i >= 0 && i < n && j >= 0 && j < m && f[i][j] == '*')
        result++, i += dxk, j += dyk;
    return result;
}

int main() {
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> m;
    f = vector<string>(n);
    forn(i, n)
        cin >> f[i];

    memset(d, -1, sizeof(d));
    int result = 0;
    for (int i = 1; i + 1 < n; i++)
        for (int j = 1; j + 1 < m; j++)
            if (f[i][j] == '*') {
                bool around = true;
                forn(k, 4)
                    around = around && (f[i + dx[k]][j + dy[k]] == '*');
                if (around) {
                    r[i][j] = INT_MAX;
                    forn(k, 4)
                        r[i][j] = min(r[i][j], getd(i, j, k) - 1);
                    result++;
                    a[i][j - r[i][j]] = max(a[i][j - r[i][j]], 2 * r[i][j] + 1);
                    b[i - r[i][j]][j] = max(b[i - r[i][j]][j], 2 * r[i][j] + 1);
                }
            }

    vector<string> g(n, string(m, '.'));
    forn(i, n) {
        int v = 0;
        forn(j, m) {
            v = max(v - 1, a[i][j]);
            if (v > 0)
                g[i][j] = '*';
        }
    }
    forn(j, m) {
        int v = 0;
        forn(i, n) {
            v = max(v - 1, b[i][j]);
            if (v > 0)
                g[i][j] = '*';
        }
    }

    if (f == g) {
        cout << result << endl;
        forn(i, n)
            forn(j, m)
                if (r[i][j] > 0)
                    cout << i + 1 << " " << j + 1 << " " << r[i][j] << endl;
    } else
        cout << -1 << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double

bool valid(int r, int c, int n, int m, vector<string>&A)
{
    return r>=0 && c>=0 && r<n && c<m && A[r][c]=='*';
}

string A[1000];
int v[1000][1000];

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n,m;
    int dr[]={-1,1,0,0};
    int dc[]={0,0,-1,1};
    cin>>n>>m;
    //vector<string>A(n);
    //vector<vector<int>>v(n,vector<int>(m));
    for(int i=0; i<n; i++)cin>>s[i];
    vector<array<int,3>>ats;

    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
        if(A[i][j]=='*')
        {
            int k  = 0;
            while(1)
        {
            bool ok = 1;
            k++;
            for(int z=0; z<4; z++)
                if(!valid(i+k*dr[z],j+k*dc[z],n,m,A))ok=0;

            if(!ok)break;

            v[i][j]=1;
            for(int z=0; z<4; z++)
                v[i+dr[z]*k][j+dc[z]*k]=1;
        }
            if(k==1)continue;
            ats.push_back({i+1,j+1,k-1});
        }

        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            if(A[i][j]=='*' && !v[i][j])return cout<<-1,0;

    cout<<ats.size()<<"\n";
    for(auto&p:ats)
        cout<<p[0]<<" "<<p[1]<<" "<<p[2]<<"\n";
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double

bool valid(int r, int c, int n, int m, vector<string>&A)
{
    return r>=0 && c>=0 && r<n && c<m && A[r][c]=='*';
}

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n,m;
    int dr[]={-1,1,0,0};
    int dc[]={0,0,-1,1};
    cin>>n>>m;
    vector<string>A(n);
    vector<vector<int>>v(n,vector<int>(m));
    for(auto&s:A)cin>>s;
    vector<array<int,3>>ats;

    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
        if(A[i][j]=='*')
        {
            int k  = 0;
            while(1)
        {
            bool ok = 1;
            k++;
            for(int z=0; z<4; z++)
                if(!valid(i+k*dr[z],j+k*dc[z],n,m,A))ok=0;

            if(!ok)break;

            v[i][j]=1;
            for(int z=0; z<4; z++)
                v[i+dr[z]*k][j+dc[z]*k]=1;
        }
            if(k==1)continue;
            ats.push_back({i+1,j+1,k-1});
        }

        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            if(A[i][j]=='*' && !v[i][j])return cout<<-1,0;

    cout<<ats.size()<<"\n";
    for(auto&p:ats)
        cout<<p[0]<<" "<<p[1]<<" "<<p[2]<<"\n";
}


#include <bits/stdc++.h>

using namespace std;

#define forn(i, n) for (int i = 0; i < int(n); i++)

const int dx[] = {1, 0, -1,  0};
const int dy[] = {0, 1,  0, -1};
const int N = 1001;

int n, m;
vector<string> f;
int d[N][N][4];
int r[N][N], a[N][N], b[N][N];

int getd(int i, int j, int k) {
    int dxk = dx[k];
    int dyk = dy[k];
    int result = 0;
    while (i >= 0 && i < n && j >= 0 && j < m && f[i][j] == '*')
        result++, i += dxk, j += dyk;
    return result;
}

int main() {
    cin >> n >> m;
    f = vector<string>(n);
    forn(i, n)
        cin >> f[i];

    memset(d, -1, sizeof(d));
    int result = 0;
    for (int i = 1; i + 1 < n; i++)
        for (int j = 1; j + 1 < m; j++)
            if (f[i][j] == '*') {
                bool around = true;
                forn(k, 4)
                    around = around && (f[i + dx[k]][j + dy[k]] == '*');
                if (around) {
                    r[i][j] = INT_MAX;
                    forn(k, 4)
                        r[i][j] = min(r[i][j], getd(i, j, k) - 1);
                    result++;
                    a[i][j - r[i][j]] = max(a[i][j - r[i][j]], 2 * r[i][j] + 1);
                    b[i - r[i][j]][j] = max(b[i - r[i][j]][j], 2 * r[i][j] + 1);
                }
            }

    vector<string> g(n, string(m, '.'));
    forn(i, n) {
        int v = 0;
        forn(j, m) {
            v = max(v - 1, a[i][j]);
            if (v > 0)
                g[i][j] = '*';
        }
    }
    forn(j, m) {
        int v = 0;
        forn(i, n) {
            v = max(v - 1, b[i][j]);
            if (v > 0)
                g[i][j] = '*';
        }
    }

    if (f == g) {
        cout << result << endl;
        forn(i, n)
            forn(j, m)
                if (r[i][j] > 0)
                    cout << i + 1 << " " << j + 1 << " " << r[i][j] << endl;
    } else
        cout << -1 << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double

bool valid(int r, int c, int n, int m, string A[])
{
    return r>=0 && c>=0 && r<n && c<m && A[r][c]=='*';
}

string A[1000];
int v[1000][1000];

int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n,m;
    int dr[]={-1,1,0,0};
    int dc[]={0,0,-1,1};
    cin>>n>>m;
    //vector<string>A(n);
    //vector<vector<int>>v(n,vector<int>(m));
    for(int i=0; i<n; i++)cin>>A[i];
    vector<array<int,3>>ats;

    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
        if(A[i][j]=='*')
        {
            int k  = 0;
            while(1)
        {
            bool ok = 1;
            k++;
            for(int z=0; z<4; z++)
                if(!valid(i+k*dr[z],j+k*dc[z],n,m,A))ok=0;

            if(!ok)break;

            v[i][j]=1;
            for(int z=0; z<4; z++)
                v[i+dr[z]*k][j+dc[z]*k]=1;
        }
            if(k==1)continue;
            ats.push_back({i+1,j+1,k-1});
        }

        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            if(A[i][j]=='*' && !v[i][j])return cout<<-1,0;

    cout<<ats.size()<<"\n";
    for(auto&p:ats)
        cout<<p[0]<<" "<<p[1]<<" "<<p[2]<<"\n";
}


#include <bits/stdc++.h>

using namespace std;
typedef long long  ll;
typedef pair<int, int> pii;

char grid[1000][1000];
bool vis[1000][1000];
int main()
{
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    ifstream cin("hack2.txt");
    memset(vis, false, sizeof(vis));
    int n, m; cin>>n>>m;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>grid[i][j];
        }
    }
    vector<pair<pii, int>> ans;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(grid[i][j]=='.')continue;
            int x1 = j, x2 = j, y1 = i, y2 = i;
            int siz = -1;
            while(x1>=0&&x2<m&&y1>=0&&y2<n&&
                  grid[i][x1]=='*'&&grid[i][x2]=='*'&&grid[y1][j]=='*'&&grid[y2][j]=='*'){
                siz++;
                if(siz>=1){
                    vis[i][x1]=true;
                    vis[i][x2]=true;
                    vis[y1][j]=true;
                    vis[y2][j]=true;
                }
                x1--; x2++; y1--; y2++;
              }
            //cout<<i+1<<' '<<j+1<<' '<<siz<<'\n';
            if(siz>=1){
                vis[i][j]=true;
                ans.push_back({{i+1, j+1},siz});
            }
        }
    }
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(grid[i][j]=='*'&&!vis[i][j]){
                cout<<-1;
                return 0;
            }
        }
    }
    cout<<ans.size()<<endl;
    for(auto i:ans)cout<<i.first.first<<' '<<i.first.second<<' '<<i.second<<'\n';
    return 0;
}