#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
#include <map>
#include <queue>
#include <algorithm>
#include <tuple>
#include <cstdint>

using namespace std;
using pii = pair<int, int>;
using tiii = tuple<int, int, int>;
static const uint64_t HASH_BASE = 12345678891ull;
static const int dx[] = { 1, 0, -1, 0 };
static const int dy[] = { 0, -1, 0, 1 };

inline bool between(int a, int b, int c){
	return a <= b && b < c;
}

map<uint64_t, pii> enumerate_hashes(vector<string> field){
	const int n = field.size(), m = field[0].size();
	map<uint64_t, pii> table;
	for(int y = 0; y < n; ++y){
		for(int x = 0; x < m; ++x){
			if(field[y][x] == '.'){ continue; }
			vector<pii> cells;
			cells.emplace_back(y, x);
			field[y][x] = '.';
			for(size_t i = 0; i < cells.size(); ++i){
				const auto p = cells[i];
				for(int d = 0; d < 4; ++d){
					const int yy = p.first + dy[d], xx = p.second + dx[d];
					if(!between(0, yy, n) || !between(0, xx, m)){ continue; }
					if(field[yy][xx] == '.'){ continue; }
					cells.emplace_back(yy, xx);
					field[yy][xx] = '.';
				}
			}
			sort(cells.begin(), cells.end());
			int xmin = x, ymin = y;
			for(const auto& p : cells){
				ymin = min(ymin, p.first);
				xmin = min(xmin, p.second);
			}
			uint64_t h = 0;
			for(const auto& p : cells){
				h = (h * HASH_BASE) + (p.first  - ymin + 1);
				h = (h * HASH_BASE) + (p.second - xmin + 1);
			}
			table.emplace(h, pii(ymin, xmin));
		}
	}
	return table;
}

inline bool query(int d){
	static const char *table[] = {
		"? R", "? U", "? L", "? D"
	};
	static char s_buffer[128];
	cout << table[d] << endl;
	cin >> s_buffer;
	return s_buffer[0] == 'Y';
}

pair<uint64_t, pii> locate_self(int n, int m){
	unordered_set<int> history;
	auto pack = [](int y, int x, int d) -> int { return ((y & 0x7fff) << 17) | ((x & 0x7fff) << 2) | d; };
	auto unpack_y = [](int p) -> int { return p >> 17; };
	auto unpack_x = [](int p) -> int { return (p << 15) >> 17; };
	pii cur(0, 0);
	int d = 0;
	while(query(d)){
		cur.first  += dy[d];
		cur.second += dx[d];
	}
	history.emplace(pack(cur.first, cur.second, d));
	d = (d + 1) % 4;
	while(history.find(pack(cur.first, cur.second, d)) == history.end()){
		history.emplace(pack(cur.first, cur.second, d));
		if(query(d)){
			cur.first  += dy[d];
			cur.second += dx[d];
			d = (d + 3) % 4;
		}else{
			d = (d + 1) % 4;
		}
	}
	int ymin = 0, xmin = 0;
	for(const auto& p : history){
		ymin = min(ymin, unpack_y(p));
		xmin = min(xmin, unpack_x(p));
	}
	vector<string> field(n + 2, string(m + 2, ' '));
	for(const auto& p : history){
		field[unpack_y(p) - ymin + 1][unpack_x(p) - xmin + 1] = '#';
	}
	const int nn = n + 2, mm = m + 2;
	queue<pii> q;
	q.emplace(0, 0);
	while(!q.empty()){
		const pii p = q.front();
		q.pop();
		for(int d = 0; d < 4; ++d){
			const int y = p.first + dy[d], x = p.second + dx[d];
			if(!between(0, y, nn) || !between(0, x, mm)){ continue; }
			if(field[y][x] != ' '){ continue; }
			field[y][x] = '.';
			q.emplace(y, x);
		}
	}
	uint64_t h = 0;
	for(int i = 0; i < n; ++i){
		for(int j = 0; j < m; ++j){
			if(field[i + 1][j + 1] == '.'){ continue; }
			h = (h * HASH_BASE) + i + 1;
			h = (h * HASH_BASE) + j + 1;
		}
	}
	return make_pair(h, pii(-ymin, -xmin));
}

int main(){
	ios_base::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;
	vector<string> field(n);
	for(int i = 0; i < n; ++i){ cin >> field[i]; }
	auto table = enumerate_hashes(field);
	const auto self = locate_self(n, m);
	const auto island_pos = table[self.first];
	const int y = island_pos.first  + self.second.first;
	const int x = island_pos.second + self.second.second;
	cout << "! " << y << " " << x << endl;
	return 0;
}




Measured memory_bytes: 23032