#include <cstdio>
#include <cstdint>
#include <vector>
#include <algorithm>
#include <utility>
#include <tuple>
#include <map>
#include <queue>

constexpr size_t m1 = -1;
constexpr size_t di[] = {m1, 0, 1, 0};
constexpr size_t dj[] = {0, m1, 0, 1};

template <class F>
class fix_point: F {
public:
  explicit constexpr fix_point(F&& f) noexcept: F(std::forward<F>(f)) {}

  template <class... Args>
  constexpr decltype(auto) operator ()(Args&&... args) const {
    return F::operator ()(*this, std::forward<Args>(args)...);
  }
};

template <class F>
static inline constexpr decltype(auto) make_fix_point(F&& f) noexcept {
  return fix_point<F>{std::forward<F>(f)};
}

template <typename Weight>
struct edge {
  using value_type = Weight;
  size_t src, dst;
  value_type cost;

  edge(size_t src, size_t dst, value_type cost = 1):
    src(src), dst(dst), cost(cost)
  {}

  bool operator <(edge<value_type> const& rhs) const {
    if (cost != rhs.cost) return cost < rhs.cost;
    if (src != rhs.src) return src < rhs.src;
    return dst < rhs.dst;
  }
};

template <typename Weight>
struct graph: public std::vector<std::vector<edge<Weight>>> {
  using value_type = Weight;
  graph(size_t n): std::vector<std::vector<edge<value_type>>>(n) {}

  void connect_to(size_t src, size_t dst, value_type cost = 1) {
    (*this)[src].emplace_back(src, dst, cost);
  }

  void connect_with(size_t src, size_t dst, value_type cost = 1) {
    connect_to(src, dst, cost);
    connect_to(dst, src, cost);
  }
};

template <class Weight>
std::vector<size_t> strongly_connected_components(const graph<Weight>& g) {
  size_t n = g.size();
  graph<int> rev(n);
  for (const auto& v: g)
    for (const auto& e: v)
      rev.connect_to(e.dst, e.src);

  std::vector<bool> used(n);
  std::vector<size_t> vs;
  auto dfs = make_fix_point([&](auto f, size_t v) -> void {
      used[v] = true;
      for (size_t i = 0; i < g[v].size(); ++i)
        if (!used[g[v][i].dst]) f(g[v][i].dst);
      vs.push_back(v);
  });
  for (size_t i = 0; i < n; ++i)
    if (!used[i]) dfs(i);

  used.assign(n, false);
  std::vector<size_t> cmp(n);
  size_t num = 0;
  auto rdfs = make_fix_point([&](auto f, size_t v) -> void {
      used[v] = true;
      cmp[v] = num;
      for (size_t i = 0; i < rev[v].size(); ++i)
        if (!used[rev[v][i].dst]) f(rev[v][i].dst);
  });

  for (size_t i = vs.size(); i--;)
    if (!used[vs[i]]) {
      rdfs(vs[i]);
      ++num;
    }

  return cmp;
}

template <typename Weight>
void add_condition(graph<Weight>& g, size_t i, size_t j) {
  size_t k = g.size() / 2;
  // (i or j) <=> (!i implies j) and (!j implies i)
  size_t ni = ((i < k)? i+k : i-k);
  size_t nj = ((j < k)? j+k : j-k);
  g.connect_to(ni, j);
  g.connect_to(nj, i);
}

template <typename Weight>
std::vector<size_t> tsort(graph<Weight>& g) {
  // based on Kahn algorithm
  size_t n = g.size();
  std::vector<size_t> indeg(n);
  for (size_t i = 0; i < n; ++i)
    for (auto const& e: g[i]) ++indeg[e.dst];

  std::queue<size_t> q;
  for (size_t i = 0; i < n; ++i)
    if (indeg[i] == 0) q.push(i);

  std::vector<size_t> res;
  while (!q.empty()) {
    size_t v = q.front();
    q.pop();
    res.push_back(v);
    for (auto const& e: g[v])
      if (--indeg[e.dst] == 0) q.push(e.dst);
  }
  if (res.size() < n) return {};
  return res;
}

template <typename Weight>
bool satisfiable(graph<Weight> const& g) {
  std::vector<size_t> scc = strongly_connected_components(g);
  size_t n = g.size();
  size_t m = *std::max_element(scc.begin(), scc.end()) + 1;
  graph<int> h(m);
  for (size_t i = 0; i < n; ++i) {
    for (auto const& e: g[i]) {
      size_t u = scc[e.src];
      size_t v = scc[e.dst];
      if (u == v) continue;
      h.connect_to(u, v);
    }
  }
  {
    auto t = tsort(h);
    for (size_t i = 0; i < n/2; ++i) {
      size_t u = scc[i];
      size_t v = scc[i+n/2];
      if (t[u] == t[v]) return false;
    }
  }
  return !tsort(h).empty();
}

int testcase_ends() {
  size_t n;
  scanf("%zu", &n);
  if (n == 0) return 1;

  using zahyo = std::pair<size_t, size_t>;
  std::map<zahyo, size_t> map;
  graph<int> g(4*n);
  size_t neg = n+n;

  for (size_t i = 0; i < n; ++i) {
    size_t x, y;
    char d;
    scanf("%zu %zu %c", &x, &y, &d);
    size_t i0 = i << 1 | 0;
    size_t i1 = i << 1 | 1;
    map[zahyo(x, y)] = i0;
    size_t dx = (d == 'x');
    size_t dy = (d == 'y');
    map[zahyo(x+dx, y+dy)] = i1;

    add_condition(g, i0, i1);
    add_condition(g, neg+i0, neg+i1);
  }

  for (auto const& p: map) {
    size_t i, j;
    std::tie(i, j) = p.first;
    size_t id = p.second;
    for (size_t k = 0; k < 4; ++k) {
      size_t ni = i + di[k];
      size_t nj = j + dj[k];
      auto it = map.find(zahyo(ni, nj));
      if (it == map.end()) continue;
      size_t nid = it->second;
      if ((id >> 1) == (nid >> 1)) continue;

      add_condition(g, neg+id, nid);
      add_condition(g, id, neg+nid);
    }
  }

  puts(satisfiable(g)? "Yes":"No");
  return 0;
}

int main() {
  while (!testcase_ends()) {}
}



Measured memory_bytes: 29768