#include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps = 1e-9;

//// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt" > "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\b.answer"

struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool findSet(int x, int y) {
		return root(x) == root(y);
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};


struct aUnionFind {
	vector<pair<int, long long int>> data;
	aUnionFind(int size) : data(size, make_pair(-1, 0)) { }

	//y is w bigger than x
	bool unionSet(const int x, const int y, const long long int w) {
		const int rx(root(x).first), ry(root(y).first);
		if (rx != ry) {
			data[rx].first += data[ry].first; data[ry].first = rx;
			data[ry].second = w + data[x].second - data[y].second;
			return true;
		}
		else {
			return root(x).second + w == root(y).second;
		}
	}
	bool findSet(const int x, const int y) {
		return root(x) == root(y);
	}

	//x is belong to first
	//x is second bigger than first
	pair<int, long long int> root(const int x) {
		if (data[x].first < 0) {
			return make_pair(x, 0);
		}
		else {
			pair<int, long long int>ndata;
			ndata.first = root(data[x].first).first;
			ndata.second = data[x].second + root(data[x].first).second;
			return data[x] = ndata;
		}
	}
	int size(const int x) {
		return -data[root(x).first].first;
	}
};
int dp[1001][1001][2];
int getans(const int odd, const int even, const int rest) {
	if (dp[odd][even][rest] != -1)return dp[odd][even][rest];
	else {
		if (odd + even == 2) {
			return dp[odd][even][rest] = rest;
		}
		else {
			set<int>nexts;
			if (rest)nexts.emplace(getans(odd, even, !rest));
			if (odd&&even) {
				nexts.emplace(getans(odd, even - 1, !rest));
			}
			if (odd >= 2) {
				nexts.emplace(getans(odd - 2, even + 1, rest));
			}
			if (even >= 2) {
				nexts.emplace(getans(odd, even - 1, !rest));
			}
			int num = 0;
			while (1) {
				if (nexts.find(num) == nexts.end()) {
					return dp[odd][even][rest] = num;
				}
				else {
					num++;
				}
			}
		}
	}
}

int main() {
	for (int i = 0; i < 1001; ++i) {
		for (int j = 0; j < 1001; ++j) {
			for (int k = 0; k < 2; ++k) {
				dp[i][j][k] = -1;
			}
		}
	}
	int V; cin >> V;
	UnionFind uf(V);
	vector<string>sts;
	for (int i = 0; i < V; ++i) {
		string st; cin >> st;
		sts.emplace_back(st);
		for (int j = 0; j < V; ++j) {
			if (st[j] == 'Y')uf.unionSet(i, j);
		}
	}
	map<int, pair<int, int>>mp;
	for (int i = 0; i <V; ++i) {
		mp[uf.root(i)].first++;
	}
	for (int i = 0; i < V; ++i) {
		for (int j = 0; j < V; ++j) {
			if (sts[i][j] == 'Y') {
				mp[uf.root(i)].second++;
			}
		}
	}
	vector<int>nums(2);
	int rest = 0;
	for (auto m : mp) {
		const int asize = m.second.first;
		const int used = m.second.second/2;
		const int total = asize*(asize - 1) / 2;
		rest += total - used;
		nums[asize % 2]++;
	}
	int ans = getans(nums[1], nums[0], rest % 2);
	if (ans)cout << "Taro" << endl;
	else cout << "Hanako" << endl;
	
	return 0;
}

Measured memory_bytes: 12060