// 101.cpp http://acm.uva.es/p/v1/101.html
// Solution to ACM problem #101 - "The Blocks Problem"
//
// Matthew Eagar - meagar@gmail.com
// Verified to work as of Feb 19 / 2005
#include
#include
#include
#include
struct Block {
Block(int i) : id(i), up(0), down(0), stackNum(0) { }
int id;
Block* up;
Block* down;
int stackNum;
};
class Stack {
public:
Stack(int id) : num(id), base(0) { }
int num;
Block* base;
void put(Block* b) {
if (base) {
Block* top = base;
while (top->up)
top = top->up;
top->up = b;
b->down = top;
} else {
base = b;
base->down = 0;
}
// set all the block's stack #'s
for (Block* blk = b; blk; blk = blk->up)
blk->stackNum = num;
}
void take(Block* b) {
assert (base != 0);
// find the block in question, remove it
if (base == b) {
base->down = 0;
base = 0;
} else {
Block * blk = base;
while (blk != b && (blk = blk->up));
if (blk == b) {
b->down->up = 0;
b->down = 0;
}
}
}
void print(std::ostream& os) const {
os << num << ':';
if (base) os << ' ';
for (const Block* blk = base; blk != 0; blk = blk->up) {
os << blk->id;
if (blk->up)
os << ' ';
}
}
};
inline std::ostream& operator<<(std::ostream& os, const Stack& s) {
s.print(os);
return os;
}
typedef std::vector BlockVec;
typedef std::vector StackVec;
BlockVec blocks;
StackVec stacks;
enum Command { CMD_MOVE = 1, CMD_PILE = 2 };
enum Argument { ARG_ONTO = 4, ARG_OVER = 8 };
void restorePos(Block* b) {
if (!b)
return;
restorePos(b->up);
stacks[b->stackNum].take(b);
stacks[b->id].put(b);
}
void doCommand(Command cmd, Argument arg, int blockA, int blockB) {
if (blocks[blockA]->stackNum == blocks[blockB]->stackNum) return;
switch (cmd | arg) {
case CMD_MOVE | ARG_ONTO:
// return all blocks
restorePos(blocks[blockA]->up);
restorePos(blocks[blockB]->up);
break;
case CMD_MOVE | ARG_OVER:
restorePos(blocks[blockA]->up);
break;
case CMD_PILE | ARG_ONTO: restorePos(blocks[blockB]->up);
break;
case CMD_PILE | ARG_OVER:
// nothing
break;
default:
assert(false);
}
stacks[blocks[blockA]->stackNum].take(blocks[blockA]);
stacks[blocks[blockB]->stackNum].put(blocks[blockA]);
}
int main() {
int numBlocks = 0; // 0 < numBlocks < 25
std::cin >> numBlocks;
// create the blocks
blocks.resize(numBlocks, 0);
for (int i = 0; i < numBlocks; ++i) {
blocks[i] = new Block(i);
stacks.push_back(Stack(i));
stacks[i].put(blocks[i]);
}
int blockA, blockB;
std::string arg;
for (std::string cmd; std::cin >> cmd && cmd != "quit";) {
std::cin >> blockA >> arg >> blockB;
doCommand
( (cmd == "move" ? CMD_MOVE : CMD_PILE)
, (arg == "onto" ? ARG_ONTO : ARG_OVER)
, blockA, blockB);
}
for (StackVec::const_iterator i = stacks.begin(); i != stacks.end(); ++i)
std::cout << *i << '\n';
}