#include <vector>
#include <array>
#include <stack>
#include <queue>
#include <list>
#include <bitset>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>
#include <random>
#include <cmath>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <sstream>

using namespace std;


int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(12);

    int n;
    cin >> n;
    int m;
    cin >> m;
    vector<int> X(m), Y(m), Z(m);
    for (int i = 0; i < m; ++i) {
        cin >> X[i] >> Y[i] >> Z[i];
        --Y[i];
    }

    vector<vector<int>> events(n + 1);
    for (int i = 0; i < m; ++i) {
        events[X[i]].push_back(i);
    }

    int N = 1 << n;

    vector<vector<int>> cnts(n, vector<int>(N, 0));

    for (int i = 0; i < N; ++i) {
        for (int j = 0, c = 0; j < n; ++j) {
            if ((i >> j) & 1) {
                ++c;
            }
            cnts[j][i] = c;
        }
    }

    vector<int> bits(N, 0);
    for (int i = 0; i < N; ++i) {
        bits[i] = bits[i >> 1] + (i & 1);
    }

    vector<long long> dp(N, 0);
    dp[0] = 1;

    for (int i = 0; i < N; ++i) {
        int b = bits[i];
        bool ok = true;
        for (auto& j : events[b]) {
            int y = Y[j];
            int z = Z[j];
            if (cnts[y][i] > z) {
                ok = false;
                break;
            }
        }
        if (!ok) {
            dp[i] = 0;
            continue;
        }
        for (int j = 0; j < n; ++j) {
            if ((i >> j) & 1) {
                continue;
            }
            int ni = i | 1 << j;
            dp[ni] += dp[i];
        }
    }

    cout << dp[N - 1] << '\n';

    return 0;
}
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define sz(v)   ((int)(v).size())
#define  all(v)    ((v).begin()),((v).end())
#define  allr(v)    ((v).rbegin()),((v).rend())
#define   pb         push_back
#define   mp         make_pair
#define    clr(v,d)      memset( v, d ,sizeof(v))
#define    lcm(a,b)                ((a*b)/(__gcd(a,b)))
#define     PI                       acos(-1)
typedef  long long     ll ;
typedef  unsigned long long ull;
const double eps= (1e-9);
using namespace std;
using namespace __gnu_pbds;
int dcmp(double a,double b){   return fabs(a-b)<=eps ? 0: (a>b)? 1:-1  ;}
int getBit(ll num, int idx) {return ((num >> idx) & 1ll) == 1;}
int setBit1(int num, int idx) {return num | (1<<idx);}
ll setBit0(ll num, int idx) {return num & ~(1ll<<idx);}
ll flipBit(ll num, int idx) {return num ^ (1ll<<idx);}
void GO(){ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);}
int countNumBit1(int mask) {int ret=0; while (mask) 	{mask &= (mask-1);++ret;	}return ret;}
const ll N=100+5,mod=1000000007,sh=201,inf=2000000000;
typedef tree<
pair<ll,ll> ,
null_type,
less<pair<ll,ll> >,
rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;
string s[N];
bool check(int r1,int c1,int r2,int c2){

  if(s[r1][c1]=='#'||s[r2][c2]=='#') return 0;

  if(r1==r2&&c1==c2){

    return 1;
  }

  if(r1!=r2&&c1!=c2) return 0;

  if(r1==r2){

    if(c2<c1) swap(c1,c2);

    for(int i=c1;i<=c2;i++){
        if(s[r1][i]=='#') return 0;
    }
    return 1;
  }
  else{
    if(r2<r1) swap(r1,r2);

    for(int i=r1;i<=r2;i++){
        if(s[i][c1]=='#') return 0;
    }
    return 1;
  }

}
int main(){
     GO();

     int T=1;
    // cin>>T;
     while(T--){

        int n,m,r,c;
        cin>>n>>m>>r>>c;
        r--;
        c--;

        for(int i=0;i<n;i++){
            cin>>s[i];
        }
        int ans=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                ans+= check(r,c,i,j);
            }
        }

        cout<<ans<<"\n";







     }

}
