Mutant Flatworld Explorers
#include <iostream>
#include <memory>
#include <set>
#include <string>
#include <tuple>
using namespace std;
class world
{
public:
world(int width, int height) : m_width(width), m_height(height)
{
}
bool contain(int x, int y) const
{
return (0 <= x && x < m_width) && (0 <= y && y < m_height);
}
bool check_scent(int x, int y) const
{
return m_scents.count(make_tuple(x, y)) > 0;
}
void leave_scent(int x, int y)
{
m_scents.insert(make_tuple(x, y));
}
private:
int m_width, m_height;
set<tuple<int, int>> m_scents;
};
class orientation
{
public:
enum
{
N, E, S, W // clockwise
};
public:
orientation() : m_value(N)
{
}
operator int() const
{
return m_value;
}
void turn_left()
{
if (m_value == N) m_value = W; else m_value--;
}
void turn_right()
{
if (m_value == W) m_value = N; else m_value++;
}
friend istream &operator >>(istream &is, orientation &o)
{
while (isspace(is.peek())) is.get();
switch (is.get())
{
case 'N':
o.m_value = N;
break;
case 'E':
o.m_value = E;
break;
case 'S':
o.m_value = S;
break;
case 'W':
o.m_value = W;
break;
}
return is;
}
friend ostream &operator <<(ostream &os, const orientation &o)
{
static const string nesw("NESW");
os << nesw.at(o.m_value);
return os;
}
private:
int m_value;
};
class robot
{
public:
robot(const shared_ptr<world> &world, int x, int y, const orientation &o) :
m_world(world), m_x(x), m_y(y), m_o(o)
{
}
void turn_left()
{
m_o.turn_left();
}
void turn_right()
{
m_o.turn_right();
}
void forward()
{
int bx = m_x, by = m_y; // backup
switch (m_o)
{
case orientation::E:
m_x++;
break;
case orientation::W:
m_x--;
break;
case orientation::N:
m_y++;
break;
case orientation::S:
m_y--;
break;
}
if (!m_world->contain(m_x, m_y))
{
m_x = bx, m_y = by;
if (!m_world->check_scent(m_x, m_y))
{
m_world->leave_scent(m_x, m_y);
throw lost();
}
}
}
friend ostream &operator <<(ostream &os, const robot &r)
{
os << r.m_x << " " << r.m_y << " " << r.m_o;
return os;
}
public:
class lost : public exception {};
private:
shared_ptr<world> m_world;
int m_x, m_y;
orientation m_o;
};
void test_case()
{
int wx, wy;
cin >> wx >> wy;
shared_ptr<world> w(new world(wx + 1, wy + 1));
int x, y;
orientation o;
while (cin >> x >> y >> o)
{
robot bot(w, x, y, o);
string commands;
cin >> commands;
try
{
for (auto command : commands)
{
switch (command)
{
case 'L':
bot.turn_left();
break;
case 'R':
bot.turn_right();
break;
case 'F':
bot.forward();
break;
default:
throw;
}
}
cout << bot << endl;
}
catch (robot::lost &e)
{
cout << bot << " LOST" << endl;
}
}
}
int main()
{
test_case();
return 0;
}