Loading...
ViktorVidolov avatar ViktorVidolov 2 Точки

Splender

Здравейте колеги,

Аз съм малко назад с материала, защото реших да почивам малко по-дълно, но ще се постарая да наваксам. За момента имам затруднение със задачата Splender. Знам че не е задължителна но ми стана любопитно и не съм много сигурен къде греша, надявам се да може да ми помогнете.

Това е кодът ми:
 

#include <iostream>
#include <list>
#include <iterator>
#include <vector>
#include <string>

class Splender
{
private:
    std::list<char> _dirPriorities = {'S', 'E', 'N', 'W'};
    bool _endCondition = false;
    bool _inverted = false;
    bool _breaker = false;
    std::list<char>::iterator _currPriorioty = _dirPriorities.begin();
    std::vector<std::vector <char>> _map;
    std::pair<int,int> _currentLocation;
   

    void _advancePriority(){
        if(!_inverted){
            if(_currPriorioty == _dirPriorities.end()){
                _currPriorioty = _dirPriorities.begin();
            }
            else _currPriorioty++;

        }
        else{
            if(_currPriorioty == _dirPriorities.begin()){
                _currPriorioty = _dirPriorities.end();
            }
            else _currPriorioty--;
        }
    }

    std::pair<int,int> _futureLocation(){
        auto output = std::make_pair(_currentLocation.first, _currentLocation.second);
        switch (*_currPriorioty)
        {
        case 'S':
            output = std::make_pair(_currentLocation.first+1, _currentLocation.second);
            break;
        case 'E':
            output = std::make_pair(_currentLocation.first, _currentLocation.second+1);
            break;
        case 'N':
            output = std::make_pair(_currentLocation.first-1, _currentLocation.second);
            break;
        case 'W':
            output = std::make_pair(_currentLocation.first, _currentLocation.second-1);
            break;
        default:
            std::cout << "something went wrong in calculating the future direction";
            break;
        }
        return output;
    }   
    void _printMove(){
        switch (*_currPriorioty)
        {
        case 'S':
            std::cout << "SOUTH\n";
            break;
        case 'E':
            std::cout << "EAST\n";
            break;
        case 'N':
            std::cout << "NORTH\n";
            break;
        case 'W':
            std::cout << "WEST\n";
            break;
        default:
            std::cout << "something went wrong in calculating the future direction";
            break;
        }
    }

public:
    Splender(){
        int x=0,y=0;
        std::cin >> x>> y;
        std::cin.ignore();
        for (int i = 0; i < x; i++)
        {
            std::vector <char> line;
            std::string stringLine;
            getline(std::cin,stringLine);
            for (int j = 0; j < y; j++)
            {
                char token = stringLine[j];
                if(token == '@'){
                    _currentLocation = std::make_pair(i,j);
                }
                line.push_back(token);
            }
            _map.push_back(line);
        }
    }
    ~Splender(){
        _map.clear();
    }
    bool getEndGoal(){
        return _endCondition;
    }
    void makeTurn(){
        auto futurelocation = _futureLocation();
        char nextStep = _map[futurelocation.first][futurelocation.second];
        switch (nextStep)
        {
        case ' ':
            _currentLocation = futurelocation;
            _printMove();
            break;
        case '#':
            _advancePriority();
            _currentLocation = _futureLocation();
            _printMove();
            break;
        case 'X':
            if(_breaker){
                _map[futurelocation.first][futurelocation.second] = ' ';
                _currentLocation = futurelocation;
                _printMove();
            }
            else {
                _advancePriority();
                _currentLocation= _futureLocation();
                _printMove();
            }
            break;
        case 'B':
            _breaker = !_breaker;
            _currentLocation = futurelocation;
            _printMove();
            break;
        case 'I':
            _inverted = !_inverted;
            _currentLocation = futurelocation;
            _printMove();
            break;
        case 'S':
            _printMove();
            _currPriorioty = _dirPriorities.begin();
            _currentLocation = futurelocation;
            break;
        case 'E':
            _printMove();
            _currPriorioty = _dirPriorities.begin();
            std::advance(_currPriorioty, 1);
            _currentLocation = futurelocation;
            
            break;
        case 'N':
            _printMove();
            _currPriorioty = _dirPriorities.begin();
            std::advance(_currPriorioty, 2);
            _currentLocation = futurelocation;            
            break;
        case 'W':
            _printMove();
            _currPriorioty = _dirPriorities.begin();
            std::advance(_currPriorioty, 3);
            _currentLocation = futurelocation;
            break;
        case '$':
            _printMove();
            _endCondition = true;
            break;
        default:
            break;
        }
    }

};


int main(){
    std::cin.sync_with_stdio(false);
    std::cout.sync_with_stdio(false);

    Splender splender;

    while(!splender.getEndGoal()){
        splender.makeTurn();
    }
    
    return 1;
}


 

Тагове:
0
C++ OOP
j.petrov_90 avatar j.petrov_90 373 Точки

Привет колега,

Задачата на пръв прочит изглежда добре.

Малко закачка на твой гръб:
Поста ти съдържа само съобщителни изречения. Не виждам къде си задал въпрос.

Сега сериозно:
Ако не се опиташ да насочиш мен или останалите колеги драстично намаляш шанса някой да ти помогне.
Виждам, че си написал "не знам къде греша", но това не е точно така.

Как разбра, че грешиш? Judge ли така каза? Ти сам ли го установи?
Можеше например да кажеш - минават ми нулеви тестовете, но не ми стига времето.
Или програмата ми гърми. Или не гърми, но просто не получавам съответния тест и т.н.

Като за начало какво можеш да промениш?
- промени това return 1 на края на main-а ти на return 0 (всичко различно от 0 значи грешка).
- използвай enum-и, а не хардкоудвай char literals в switch case-овете
- напиши още някоя друга функция. В момента цялата ти задача е решена в една функция.
- опитай да използваш още повече ООП. "Картата" може да е отделен клас и обект и Splender да я използва в последствие.
- използвай struct Point { int x; int y;}; или row/col за репрезентация на 2D координати. std::pair<int, int> рязко става нечетимо и неинтуитивно, когато половината ти задача е извиквания на something.first, something.second 

След това се опитай да формулираш по-добре въпроса си и те очаквам пак на линия за да разрешим проблема.

Поздрави

0
16/08/2021 23:16:37
ViktorVidolov avatar ViktorVidolov 2 Точки

Благодаря много за съветите!

Поправих малко кода спрямо предложенията, но пакл имам същите проблеми като преди:

  • Имам 5 теста, които гърмят за време - 2,5,6,8,9
  • И един който гърми заради грешка - 10.
#include <iostream>
#include <list>
#include <iterator>
#include <vector>
#include <string>

enum Direction{ SOUTH = 'S', EAST = 'E', NORTH = 'N', WEST = 'W', BREAKER = 'B', IVERTED = 'I', START = '@', EMPTY = ' ', WALL = '#', OBSTACLE = 'X', END = '$'};

struct Point{
    int x,y;
};

class Map{
    private:
    std::vector<std::vector <char>> _map;
    public:
    void collectData(Point &startingpoint){
        int x=0,y=0;
        std::cin >> x>> y;
        std::cin.ignore();
        for (int i = 0; i < x; i++)
        {
            std::vector <char> line;
            std::string stringLine;
            getline(std::cin,stringLine);
            for (int j = 0; j < y; j++)
            {
                char token = stringLine[j];
                if(token == START){
                    startingpoint.x = i;
                    startingpoint.y = j;
                }
                line.push_back(token);
            }
            _map.push_back(line);
        }
    }
    char getChar(Point point){
        return _map[point.x][point.y];
    }
    void removeChar(Point point){
        _map[point.x][point.y] = EMPTY;
    }
};

class Splender
{
private:

    std::list<char> _dirPriorities = {SOUTH, EAST, NORTH, WEST};
    bool _endCondition = false;
    bool _inverted = false;
    bool _breaker = false;
    std::list<char>::iterator _currPriorioty = _dirPriorities.begin();
    Map _map;
    Point _currentLocation;
   

    void _advancePriority(){
        if(!_inverted){
            if(_currPriorioty == _dirPriorities.end()){
                _currPriorioty = _dirPriorities.begin();
            }
            else _currPriorioty++;

        }
        else{
            if(_currPriorioty == _dirPriorities.begin()){
                _currPriorioty = _dirPriorities.end();
            }
            else _currPriorioty--;
        }
    }

    Point _futureLocation(){
        auto output = _currentLocation;
        switch (*_currPriorioty)
        {
        case SOUTH:
            output.x++;
            break;
        case EAST:
            output.y++;
            break;
        case NORTH:
            output.x--;
            break;
        case WEST:
            output.y--;
            break;
        default:
            std::cout << "something went wrong in calculating the future direction";
            break;
        }
        return output;
    }   
    void _printMove(){
        switch (*_currPriorioty)
        {
        case SOUTH:
            std::cout << "SOUTH\n";
            break;
        case EAST:
            std::cout << "EAST\n";
            break;
        case NORTH:
            std::cout << "NORTH\n";
            break;
        case WEST:
            std::cout << "WEST\n";
            break;
        default:
            std::cout << "something went wrong in calculating the future direction";
            break;
        }
    }
    void _calculateFuture(char nextStep, Point futurelocation){
        switch (nextStep)
        {
        case EMPTY:
            _currentLocation = futurelocation;
            _printMove();
            break;
        case WALL:
            _advancePriority();
            _currentLocation = _futureLocation();
            _printMove();
            break;
        case OBSTACLE:
            if(_breaker){
                _map.removeChar(futurelocation);
                _currentLocation = futurelocation;
                _printMove();
            }
            else {
                _advancePriority();
                _currentLocation= _futureLocation();
                _printMove();
            }
            break;
        case BREAKER:
            _breaker = !_breaker;
            _currentLocation = futurelocation;
            _printMove();
            break;
        case IVERTED:
            _inverted = !_inverted;
            _currentLocation = futurelocation;
            _printMove();
            break;
        case SOUTH:
            _printMove();
            _currPriorioty = _dirPriorities.begin();
            _currentLocation = futurelocation;
            break;
        case EAST:
            _printMove();
            _currPriorioty = _dirPriorities.begin();
            std::advance(_currPriorioty, 1);
            _currentLocation = futurelocation;
            
            break;
        case NORTH:
            _printMove();
            _currPriorioty = _dirPriorities.begin();
            std::advance(_currPriorioty, 2);
            _currentLocation = futurelocation;            
            break;
        case WEST:
            _printMove();
            _currPriorioty = _dirPriorities.begin();
            std::advance(_currPriorioty, 3);
            _currentLocation = futurelocation;
            break;
        case END:
            _printMove();
            _endCondition = true;
            break;
        default:
            break;
        }
    }

public:
    Splender(){
        _map.collectData(_currentLocation);
    }
    ~Splender(){
    }
    bool getEndGoal(){
        return _endCondition;
    }
    void makeTurn(){
        auto futurelocation = _futureLocation();
        char nextStep = _map.getChar(futurelocation);
        _calculateFuture(nextStep, futurelocation);
    }

};


int main(){
    std::cin.sync_with_stdio(false);
    std::cout.sync_with_stdio(false);

    Splender splender;

    while(!splender.getEndGoal()){
        splender.makeTurn();
    }
    
    return 0;
}


 

0
j.petrov_90 avatar j.petrov_90 373 Точки

Привет, отново,

Благодаря за насоката.
Сега с радост ще ти помогна, защото ще ми отнеме 10 минути, а не 2 часа :)

Задачата ти е добре.
2 малки корекции (по-скоро издребнявания от моя страна)
- не ползвай std::list - ползвай std::vector
- не копирай нищо различно от примитивен тип данни. Визирам структурата ти Point. Подавай я по референция на функциите.

Виждам, че ти гърми нулев тест в Judge.
Нулините тестове за тестове, на които им имаш входа и изхода (в условието на задачата).
Защо поне не опита да пуснеш локално този тест с входните му данни?
Щеше да си разбереш проблема.
Няма значение - жив и здрав.

Забелязвам, че всички твои успешни тестове минават мигновенно ~0ms.
Всички гърмящи за време тестове умират на 6000ms (6 секунди).
И умират, защото Judge ги е убил, а не защото са отнели точно 6 секунди.
Това е ясна индикация, че стигат да безкраен цикъл в някой случай.
Пример за безкраен цикъл в този сценарий: EAST, WEST, EAST, WEST, EAST ...

Последният тест ти гърми, защото си изтървал едно от условията в задачата.
На картата може да има двойка телепорти. Прочети пак условието.

Поздрави и те очаквам пак със 100/100!
 

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.