Quick actions

cmd+k|ctrl+k

Navigation

Languages

UVA101

Snippet info

Language

Cpp

Visibility

public

Author

kavenc

Created

2019-11-19T14:39:13Z

Updated

2019-11-20T12:38:38Z

#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;
}
INFO