#include <bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;

#define REP(i, n) for (int i = 0; i < (n); i++)
//#define int long long
#define FOR(i, m, n) for (int i = (m); i < (n); i++)
#define all(x) x.begin(), x.end()
using pii = pair<int, int>;
using ll = long long;
constexpr int MAX = 10010;
int siz[MAX];   //錬結成分のサイズ
int par[MAX];   //親
int Rank[MAX];  //木の深さ

// n要素で初期化
void init(int n) {
    REP(i, n) {
        par[i] = i;
        Rank[i] = 0;
        siz[i] = 1;
    }
}

//木の根を求める
int find(int x) {
    if (par[x] == x) {
        return x;
    } else {
        return par[x] = find(par[x]);  //経路圧縮(根に直接つなぎなおす)もしつつ
    }
}

// xとyの属する集合を併合
void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    //低いほうを高いほうにつなげる(効率化)
    if (Rank[x] < Rank[y]) {
        par[x] = y;
        siz[x] += siz[y];
        siz[y] = siz[x];
    } else {
        siz[y] += siz[x];
        siz[x] = siz[y];
        par[y] = x;
        if (Rank[x] == Rank[y]) Rank[x]++;
    }
}

// xとyが同じ集合に属するか否か
bool same(int x, int y) { return find(x) == find(y); }

int dp[1010][1010][2][2];  // 0→負け 1→勝ち
char A[1010][1010];
int e_cnt[1010];
int rec(int odd, int even, bool rem, bool p) {
    if (dp[odd][even][rem][p] != -1) return dp[odd][even][rem][p];
    //連結成分が1つ
    if (odd + even == 1) {
        return dp[odd][even][rem][p] = p;
    }
    // 2つ
    if (odd + even == 2) {
        return dp[odd][even][rem][p] = p ^ (!rem);
    }
    if (p == 1) {
        bool res = 0;
        // odd-odd
        if (odd >= 2) {
            if (rec(odd - 2, even + 1, rem, !p) == 1) res = 1;
        }
        // odd-even
        if (odd >= 1 && even >= 1) {
            if (rec(odd, even - 1, !rem, !p) == 1) res = 1;
        }

        // even-even
        if (even >= 2) {
            if (rec(odd, even - 1, !rem, !p) == 1) res = 1;
        }
        return dp[odd][even][rem][p] = res;
    } else {
        bool res = 1;
        // odd-odd
        if (odd >= 2) {
            if (rec(odd - 2, even + 1, rem, !p) == 0) res = 0;
        }
        // odd-even
        if (odd >= 1 && even >= 1) {
            if (rec(odd, even - 1, !rem, !p) == 0) res = 0;
        }

        // even-even
        if (even >= 2) {
            if (rec(odd, even - 1, !rem, !p) == 0) res = 0;
        }
        return dp[odd][even][rem][p] = res;
    }
}
bool solve() {
    int V;
    cin >> V;
    init(V);
    REP(i, V) {
        REP(j, V) {
            cin >> A[i][j];
            // if (j < i) continue;
            if (A[i][j] == 'Y') {
                unite(i, j);
                // e_cnt[find(i)]++;
            }
        }
    }
    REP(i, V) FOR(j, i, V) {
        if (A[i][j] == 'Y') {
            e_cnt[find(i)]++;
        }
    }
    int odd = 0, even = 0;
    int rem = 0;
    vector<bool> used(V);
    REP(i, V) {
        if (used[find(i)]) continue;
        int s = siz[find(i)];
        int e = s * (s - 1) / 2 - e_cnt[find(i)];
        // cerr << find(i) << " " << s << " " << e << endl;
        if (s & 1)
            odd++;
        else
            even++;
        rem += e;
        used[find(i)] = true;
    }
    REP(i, V + 1) REP(j, V + 1) REP(r, 2) REP(p, 2) dp[i][j][r][p] = -1;
    // cerr << "odd:" << odd << endl;
    // cerr << "even:" << even << endl;
    // cerr << "rem:" << rem << endl;
    if (rec(odd, even, rem % 2, 1) == 1)
        cout << "Taro" << endl;
    else
        cout << "Hanako" << endl;
}

signed main() {
    // while (solve())
    solve();
}



Measured memory_bytes: 19936