#include <iostream>
#include <list>
#include <regex>
#include <string>
#include <utility>
struct Block {
int Id;
std::pair<int, int> Position;
Block *Previous;
Block *Next;
};
static inline void ResetAbove(Block &From) {
Block *Current = From.Next;
From.Next = nullptr;
while (Current != nullptr) {
auto &Pos = Current->Position;
Pos.first = Current->Id;
Pos.second = 0;
auto Next = Current->Next;
Current->Next = Current->Previous = nullptr;
Current = Next;
}
}
static inline void AppendSingle(Block &To, Block &From) {
To.Next = &From;
From.Previous = &To;
From.Position.first = To.Position.first;
From.Position.second = To.Position.second + 1;
}
static inline void AppendMulti(Block &To, Block &From) {
auto FixBlock = &From;
To.Next = FixBlock;
FixBlock->Previous = &To;
for (int Index = To.Position.second + 1; FixBlock != nullptr; ++Index) {
FixBlock->Position.first = To.Position.first;
FixBlock->Position.second = Index;
FixBlock = FixBlock->Next;
}
}
static inline Block *FindTail(Block &From) {
auto Block = &From;
while (Block->Next != nullptr) {
Block = Block->Next;
}
return Block;
}
int main() {
int NumBlocks;
int FirstBlock, SecondBlock;
std::string Cmd;
const std::regex CmdRegex("([a-z]+) (\\d+) ([a-z]+) (\\d+)");
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
std::smatch Match;
std::cin >> NumBlocks;
std::cin.ignore();
// Initializations
std::vector<Block> Blocks(NumBlocks);
for (int Index = 0; Index < NumBlocks; ++Index) {
auto &Block = Blocks[Index];
Block.Id = Index;
Block.Position.first = Index;
Block.Position.second = 0;
}
while (std::getline(std::cin, Cmd) && Cmd.front() != 'q') {
if (Cmd.front() == 'q') {
break;
}
std::regex_match(Cmd, Match, CmdRegex);
int First = std::stoi(Match[2].str());
int Second = std::stoi(Match[4].str());
auto &FirstBlock = Blocks[First];
auto &SecondBlock = Blocks[Second];
if (First == Second
|| FirstBlock.Position.first == SecondBlock.Position.first) {
// Illegal command
continue;
}
auto Previous = FirstBlock.Previous;
if (Previous != nullptr) {
Previous->Next = nullptr;
}
if (Match[1].str().front() == 'm') {
// Reset blocks on top of First
ResetAbove(FirstBlock);
if (Match[3].str().back() == 'o') {
// Move Onto
ResetAbove(SecondBlock);
AppendSingle(SecondBlock, FirstBlock);
} else {
// Move Over
// Find tail of SecondBlock
auto SecondTail = FindTail(SecondBlock);
AppendSingle(*SecondTail, FirstBlock);
}
} else {
if (Match[3].str().back() == 'o') {
// Pile Onto
ResetAbove(SecondBlock);
AppendMulti(SecondBlock, FirstBlock);
} else {
// Pile Over
auto SecondTail = FindTail(SecondBlock);
AppendMulti(*SecondTail, FirstBlock);
}
}
}
for (auto &Block : Blocks) {
std::cout << Block.Id << ":";
if (Block.Position.second == 0) {
auto Current = &Block;
while (Current != nullptr) {
std::cout << " " << Current->Id;
Current = Current->Next;
}
}
std::cout << "\n";
}
return 0;
}