Problem: King of Berland Berl IV has recently died. Hail Berl V! As a sign of the highest achievements of the deceased king the new king decided to build a mausoleum with Berl IV's body on the main square of the capital.

The mausoleum will be constructed from 2n blocks, each of them has the shape of a cuboid. Each block has the bottom base of a 1 × 1 meter square. Among the blocks, exactly two of them have the height of one meter, exactly two have the height of two meters, ..., exactly two have the height of n meters.

The blocks are arranged in a row without spacing one after the other. Of course, not every arrangement of blocks has the form of a mausoleum. In order to make the given arrangement in the form of the mausoleum, it is necessary that when you pass along the mausoleum, from one end to the other, the heights of the blocks first were non-decreasing (i.e., increasing or remained the same), and then — non-increasing (decrease or remained unchanged). It is possible that any of these two areas will be omitted. For example, the following sequences of block height meet this requirement:

  * [1, 2, 2, 3, 4, 4, 3, 1]; 
  * [1, 1]; 
  * [2, 2, 1, 1]; 
  * [1, 2, 3, 3, 2, 1]. 



Suddenly, k more requirements appeared. Each of the requirements has the form: "h[xi] signi h[yi]", where h[t] is the height of the t-th block, and a signi is one of the five possible signs: '=' (equals), '<' (less than), '>' (more than), '<=' (less than or equals), '>=' (more than or equals). Thus, each of the k additional requirements is given by a pair of indexes xi, yi (1 ≤ xi, yi ≤ 2n) and sign signi.

Find the number of possible ways to rearrange the blocks so that both the requirement about the shape of the mausoleum (see paragraph 3) and the k additional requirements were met.

Input

The first line of the input contains integers n and k (1 ≤ n ≤ 35, 0 ≤ k ≤ 100) — the number of pairs of blocks and the number of additional requirements.

Next k lines contain listed additional requirements, one per line in the format "xi signi yi" (1 ≤ xi, yi ≤ 2n), and the sign is on of the list of the five possible signs.

Output

Print the sought number of ways.

Examples

Input

3 0


Output

9


Input

3 1
2 &gt; 3


Output

1


Input

4 1
3 = 6


Output

3

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using LD = long double;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;
using PLD = pair<LD, LD>;
using VI = vector<int>;
using VLL = vector<LL>;
using VLD = vector<LD>;
using VPII = vector<PII>;
using VPLL = vector<PLL>;
using VPLD = vector<PLD>;
using VVI = vector<VI>;
const int inf = 1e9 + 7;
const int MOD = 998244353;
const LL INF = 1e18 + 7;
const long double PI = acos(-1);
const LD EPS = 1e-9;
namespace input {
template <class T>
istream& operator>>(istream& st, vector<T>& container) {
  for (auto& u : container) st >> u;
  return st;
}
template <class T, size_t N>
istream& operator>>(istream& st, array<T, N>& container) {
  for (auto& u : container) st >> u;
  return st;
}
template <class T, class U>
istream& operator>>(istream& st, pair<T, U>& p) {
  st >> p.first >> p.second;
  return st;
}
void re() {}
template <typename T, typename... TArgs>
void re(T& x, TArgs&... rest) {
  cin >> x;
  re(rest...);
}
}  // namespace input
using namespace input;
namespace output {
template <class T>
ostream& operator<<(ostream& st, const vector<T>& container) {
  for (auto& u : container) st << u << ' ';
  return st;
}
template <class T, size_t N>
ostream& operator<<(ostream& st, const array<T, N>& container) {
  for (auto& u : container) st << u << ' ';
  return st;
}
template <class T, class U>
ostream& operator<<(ostream& st, pair<T, U> p) {
  st << p.first << ' ' << p.second;
  return st;
}
void pr() {}
template <typename T>
void pr(const T& x) {
  cout << x;
}
template <typename T, typename... TArgs>
void pr(const T& x, const TArgs&... rest) {
  cout << x << ' ';
  pr(rest...);
}
template <typename... TArgs>
void prln(const TArgs&... args) {
  pr(args...);
  cout << '\n';
}
}  // namespace output
using namespace output;
namespace pairs {
template <class T, class U, class V>
pair<T, U> operator*(pair<T, U> p, V val) {
  return {p.first * val, p.second * val};
}
template <class T, class U, class V>
pair<T, U> operator/(pair<T, U> p, V val) {
  return {p.first / val, p.second / val};
}
template <class T, class U>
pair<T, U> operator-(pair<T, U> a, pair<T, U> b) {
  return {a.first - b.first, a.second - b.second};
}
template <class T, class U>
pair<T, U> operator+(pair<T, U> a, pair<T, U> b) {
  return {a.first + b.first, a.second + b.second};
}
}  // namespace pairs
using namespace pairs;
namespace triples {
template <class T1, class T2, class T3>
struct triple {
  T1 x;
  T2 y;
  T3 z;
  triple() : x(T1()), y(T2()), z(T3()){};
  triple(T1 _x, T2 _y, T3 _z) : x(_x), y(_y), z(_z) {}
};
template <class T1, class T2, class T3>
bool operator<(const triple<T1, T2, T3>& t1, const triple<T1, T2, T3>& t2) {
  if (t1.x != t2.x) return t1.x < t2.x;
  if (t1.y != t2.y)
    return t1.y < t2.y;
  else
    return t1.z < t2.z;
}
template <class T1, class T2, class T3>
bool operator>(const triple<T1, T2, T3>& t1, const triple<T1, T2, T3>& t2) {
  if (t1.x != t2.x) return t1.x > t2.x;
  if (t1.y != t2.y)
    return t1.y > t2.y;
  else
    return t1.z > t2.z;
}
template <class T1, class T2, class T3>
bool operator==(const triple<T1, T2, T3>& t1, const triple<T1, T2, T3>& t2) {
  return (t1.x == t2.x && t1.y == t2.y && t1.z == t2.z);
}
template <class T1, class T2, class T3>
inline istream& operator>>(istream& os, triple<T1, T2, T3>& t) {
  return os >> t.x >> t.y >> t.y;
}
template <class T1, class T2, class T3>
ostream& operator<<(ostream& os, const triple<T1, T2, T3>& t) {
  return os << t.x << " " << t.y << " " << t.z;
}
template <class T1, class T2, class T3>
triple<T1, T2, T3> operator+(triple<T1, T2, T3> a, triple<T1, T2, T3> b) {
  return {a.x + b.x, a.y + b.y, a.z + b.z};
}
template <class T1, class T2, class T3>
triple<T1, T2, T3> operator-(triple<T1, T2, T3> a, triple<T1, T2, T3> b) {
  return {a.x - b.x, a.y - b.y, a.z - b.z};
}
template <class T1, class T2, class T3, class T4>
triple<T1, T2, T3> operator*(triple<T1, T2, T3> a, T4 val) {
  return {a.x * val, a.y * val, a.z * val};
}
template <class T1, class T2, class T3, class T4>
triple<T1, T2, T3> operator/(triple<T1, T2, T3> a, T4 val) {
  return {a.x / val, a.y / val, a.z / val};
}
using TRII = triple<int, int, int>;
using TRLL = triple<LL, LL, LL>;
using TRLD = triple<LD, LD, LD>;
using VTRII = vector<TRII>;
using VTRLL = vector<TRLL>;
using VTRLD = vector<TRLD>;
}  // namespace triples
using namespace triples;
namespace geo {
template <class T>
T dotProduct(pair<T, T> a, pair<T, T> b) {
  return a.first * b.first + a.second * b.second;
}
template <class T>
T crossProduct(pair<T, T> a, pair<T, T> b) {
  return a.first * b.second - a.second * b.first;
}
template <class T>
T lengthPow(pair<T, T> a) {
  return a.first * 1ll * a.first + a.second * 1ll * a.second;
}
template <class T>
LD length(pair<T, T> a) {
  return sqrt(lengthPow(a));
}
template <class T>
T dotProduct(triple<T, T, T> a, triple<T, T, T> b) {
  return a.x * b.x + a.y * b.y + a.z * b.z;
}
template <class T>
T crossProduct(triple<T, T, T> a, triple<T, T, T> b) {
  return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
}
template <class T>
T lengthPow(triple<T, T, T> a) {
  return a.x * 1ll * a.x + a.y * 1ll * a.y + a.z * 1ll * a.z;
}
template <class T>
LD length(triple<T, T, T> a) {
  return sqrt(lengthPow(a));
}
}  // namespace geo
using namespace geo;
template <class T>
T invGeneral(T a, T b) {
  a %= b;
  if (a == 0) return b == 1 ? 0 : -1;
  T x = invGeneral(b, a);
  return x == -1 ? -1 : ((1 - (LL)b * x) / a + b) % b;
}
template <class T>
struct modular {
  T val;
  explicit operator T() const { return val; }
  modular() { val = 0; }
  modular(const LL& v) {
    val = (-MOD <= v && v <= MOD) ? v : v % MOD;
    if (val < 0) val += MOD;
  }
  friend ostream& operator<<(ostream& os, const modular& a) {
    return os << a.val;
  }
  friend void pr(const modular& a) { pr(a.val); }
  friend void re(modular& a) {
    LL x;
    re(x);
    a = modular(x);
  }
  friend bool operator==(const modular& a, const modular& b) {
    return a.val == b.val;
  }
  friend bool operator!=(const modular& a, const modular& b) {
    return !(a == b);
  }
  friend bool operator<(const modular& a, const modular& b) {
    return a.val < b.val;
  }
  modular operator-() const { return modular(-val); }
  modular& operator+=(const modular& m) {
    if ((val += m.val) >= MOD) val -= MOD;
    return *this;
  }
  modular& operator-=(const modular& m) {
    if ((val -= m.val) < 0) val += MOD;
    return *this;
  }
  modular& operator*=(const modular& m) {
    val = (LL)val * m.val % MOD;
    return *this;
  }
  friend modular pow(modular a, LL p) {
    modular ans = 1;
    for (; p; p /= 2, a *= a)
      if (p & 1) ans *= a;
    return ans;
  }
  friend modular inv(const modular& a) {
    auto i = invGeneral(a.val, MOD);
    assert(i != -1);
    return i;
  }
  modular& operator/=(const modular& m) { return (*this) *= inv(m); }
  friend modular operator+(modular a, const modular& b) { return a += b; }
  friend modular operator-(modular a, const modular& b) { return a -= b; }
  friend modular operator*(modular a, const modular& b) { return a *= b; }
  friend modular operator/(modular a, const modular& b) { return a /= b; }
};
using MI = modular<int>;
using PMI = pair<MI, MI>;
using VMI = vector<MI>;
using VPMI = vector<PMI>;
namespace debug {
template <typename _T>
inline void _debug(const char* s, _T x) {
  cerr << s << " = " << x << "\n";
}
template <typename _T, typename... args>
void _debug(const char* s, _T x, args... a) {
  while (*s != ',') cerr << *s++;
  cerr << " = " << x << ',';
  _debug(s + 1, a...);
}
}  // namespace debug
using namespace debug;
template <class T>
bool setMax(T& v, T newV) {
  if (v < newV) {
    v = newV;
    return true;
  }
  return false;
}
template <class T>
bool setMin(T& v, T newV) {
  if (v > newV) {
    v = newV;
    return true;
  }
  return false;
}
LL dp[100][100];
vector<pair<int, string> > ops[100];
bool checkEqual(int pos1, int pos2) {
  1999;
  for (auto [pos, op] : ops[pos1]) {
    1999;
    if (op == "=")
      if (pos != pos2 and pos != pos1) return false;
    1999;
    if (op == "<" or op == ">")
      if (pos == pos2 or pos == pos1) return false;
    1999;
  }
  1999;
  return true;
}
bool checkRange(int myPos, int l, int r) {
  1999;
  for (auto [pos, op] : ops[myPos]) {
    if (op == "=") continue;
    1999;
    if (pos < l or pos > r) continue;
    if (op == ">=" or op == ">") return false;
  }
  1999;
  return true;
}
int n;
void add(int pos1, int pos2, int l, int r, LL val) {
  int realR = 2 * n - 1 - r;
  1999;
  if (checkEqual(pos1, pos2) and checkEqual(pos2, pos1) and
      checkRange(pos1, l, realR) and checkRange(pos2, l, realR))
    dp[l][r] += val;
}
void solve() {
  int k;
  re(n, k);
  map<string, string> oth = {
      {"=", "="}, {">", "<"}, {"<", ">"}, {">=", "<="}, {"<=", ">="}};
  for (int i = (0); (1) > 0 ? i < (k) : i >= (k); i += (1)) {
    int a, b;
    string s;
    re(a, s, b);
    --a, --b;
    ops[a].push_back({b, s});
    ops[b].push_back({a, oth[s]});
  }
  dp[0][0] = 1;
  for (int i = 0; i < n; ++i) {
    for (int l = 0; l <= 2 * i; ++l) {
      int r = 2 * i - l;
      auto val = dp[l][r];
      1999;
      add(l, l + 1, l + 2, r, val);
      add(l, 2 * n - 1 - r, l + 1, r + 1, val);
      add(2 * n - 1 - r, 2 * n - 2 - r, l, r + 2, val);
    }
  }
  LL res = 0;
  for (int i = 0; i <= 2 * n; ++i) {
    res += dp[i][2 * n - i];
    1999;
  }
  prln(res / 3);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  cout << fixed << setprecision(13);
  int t = 1;
  for (int i = 1; i <= t; ++i) {
    solve();
  }
  return 0;
}