Red Knight's Shortest Path

  • + 0 comments

    C++ BFS-tree(more at https://github.com/IhorVodko/Hackerrank_solutions , feel free to give a star :) )

    constexpr char IMPOSSIBLE[] = "Impossible";
    
    enum class MoveDirections{
        UL, UR, R, LR, LL, L, START, DEFAULT 
    };
    
    auto const moves{std::map<::MoveDirections, std::pair<int, int>>{
        {MoveDirections::UL, {-2, -1}}, {MoveDirections::UR, {-2, 1}},
        {MoveDirections::R, {0, 2}}, {MoveDirections::LR, {2, 1}},
        {MoveDirections::LL, {2, -1}}, {MoveDirections::L, {0, -2}},
    }};
    
    auto const movesPrint{std::unordered_map<::MoveDirections, std::string>{
        {MoveDirections::UL, "UL"}, {MoveDirections::UR, "UR"},
        {MoveDirections::R, "R"}, {MoveDirections::LR, "LR"},
        {MoveDirections::LL, "LL"}, {MoveDirections::L, "L"}
    }};
    
    struct Node{
        using mD = MoveDirections;
        Node(): 
            row{0},
            col{0},
            direction{mD::DEFAULT},
            parent{},
            childs{}
        {}
        Node(
            int const rNew,
            int const cNew,
            mD const newDirection,
            std::shared_ptr<Node const> && newParent = nullptr
        ):
            row{rNew},
            col{cNew},
            direction{newDirection},
            parent{newParent},
            childs{}
        {}
        int row;
        int col;
        MoveDirections direction;
        std::shared_ptr<Node const> parent;
        mutable std::vector<std::shared_ptr<Node const>> childs;
    };
    
    void printShortestPath(
        int const size,
        int const rStart, 
        int const cStart, 
        int const rEnd,
        int const cEnd
    ){
        using namespace  std;
        using  mD = ::MoveDirections;
        auto boardFree{vector<vector<bool>>(size, vector<bool>(size, true))};
        auto root{make_shared<Node const>(rStart, cStart, mD::START)};
        auto qBFS(queue<shared_ptr<Node const>>{});
        qBFS.push(root);
        auto nodeCurrent{decltype(qBFS)::value_type{}};
        auto rNew{0};
        auto cNew{0};
        while(!qBFS.empty()){
            nodeCurrent = std::move(qBFS.front());
            qBFS.pop();
            for(auto const & [direction, move]: moves){
                rNew = nodeCurrent->row + move.first;
                cNew = nodeCurrent->col + move.second;
                if(!(0 <= rNew && rNew < size && 0 <= cNew &&
                    cNew < size && boardFree.at(rNew).at(cNew))
                ){
                    continue;
                }
                boardFree.at(rNew).at(cNew) = false;
                nodeCurrent->childs.emplace_back(make_shared<Node const>(
                    rNew, cNew, direction, std::move(nodeCurrent)));
                qBFS.push(nodeCurrent->childs.back());
                if(!(rNew == rEnd && cNew == cEnd)){
                    continue;
                }
                auto steps{0};
                auto pathReverse{vector<mD>{}};
                nodeCurrent = nodeCurrent->childs.back();
                while(nodeCurrent->parent){
                    ++steps;
                    pathReverse.emplace_back(nodeCurrent->direction);
                    nodeCurrent = nodeCurrent->parent;
                }
                cout << steps << '\n';
                transform(crbegin(pathReverse), crend(pathReverse), 
                    ostream_iterator<string>(cout, " "), [&](auto const & direction){
                        return  movesPrint.at(direction);
                    });
                return;
            }
        }
        cout << IMPOSSIBLE;
    }