Найти соседей вектора

Чтобы найти соседей вектора и вернуть массив векторов, которые являются соседями вектора:

vector<XY> neighboursOf(XY coord){
    short x = coord.x;
    short y = coord.y;

    vector<XY> neighbours;
    neighbours.reserve(9);

    neighbours.push_back(XY(x-1, y));
    neighbours.push_back(XY(x-1, y-1));
    neighbours.push_back(XY(x-1, y+1));

    neighbours.push_back(XY(x+1, y));
    neighbours.push_back(XY(x+1, y-1));
    neighbours.push_back(XY(x+1, y+1));
    neighbours.push_back(XY(x+1, y-1));

    neighbours.push_back(XY(x, y-1));
    neighbours.push_back(XY(x, y+1));

    return neighbours;
}
}

XY это класс, у которого есть члены x и y:

class XY{
    public:
    XY(short x=0, short y=0);
    short x;
    short y;
};

XY::XY(short x, short y) {
    this->x = x;
    this->y = y;
}

Параметр — вектор желтого квадрата, массив соседей должен быть черными квадратами.

Пример

2 ответа
2

В XY класс выглядит так, как будто было бы лучше в виде простого struct:

struct XY
{
    short x;
    short y;
};

Тогда нам не нужно объявлять конструктор, потому что он может быть агрегатно-инициализированный.

Я предполагаю, что ваш vector это псевдоним для std::vector здесь, поскольку определения не видно.

Восемь утверждений о заполнении вектора выглядят разумными. Дубликат x+1, y-1 хотя, вероятно, непреднамеренно.

Вы могли бы с пользой использовать emplace_back вместо того, чтобы писать эти конструкторы. Мы могли бы создать вектор напрямую, со всеми значениями элементов в качестве его списка инициализаторов:

std::vector<XY> neighboursOf(XY coord)
{
    auto const x = coord.x;
    auto const y = coord.y;

    return { {x-1, y-1}, {x, y-1}, {x+1, y-1},
             {x-1, y  },           {x+1, y  },
             {x-1, y+1}, {x, y+1}, {x+1, y+1} };
}

Посмотрите, как форматирование здесь помогает нам увидеть, что каждый сосед включается ровно один раз?

Можно написать умный цикл, но он будет труднее читать и не более эффективен, чем простой код.

Обратите внимание: если у нас конечная сетка, нам может потребоваться особое поведение на краях. И если у нас есть бесконечная сетка, мы столкнемся с арифметическим переполнением (неопределенное поведение), когда мы достигнем пределов short.

    Я предлагаю инициализировать вектор при создании, так как вы знаете все необходимые элементы во время компиляции. Кроме того, если вы не меняете размер этого вектора, вероятно, лучше использовать std::array вместо std::vector. Имейте в виду, что большинство компиляторов x64 C ++ по умолчанию используют указатели, выровненные по QWORD (8-байтовые), поэтому лучше выровнять ваши переменные с размером указателя. Существует ptrdiff_t печатать <cstddef> библиотека, созданная для этой цели. Проверьте следующий фрагмент кода:

    #include <array>
    #include <cstddef>
    
    class XY
    {
    public:
        ptrdiff_t x;
        ptrdiff_t y;
    public:
        XY(ptrdiff_t x=0, std::ptrdiff_t y=0): x(x), y(y) {}
    };
    
    std::array<XY, 9> neighboursOf(XY coord)
    {
        auto x = coord.x;
        auto y = coord.y;
    
        std::array<XY, 9> neighbours
            {
                XY(x-1, y), XY(x-1, y-1), XY(x-1, y+1),
                XY(x+1, y), XY(x+1, y-1), XY(x+1, y+1),
                XY(x+1, y-1), XY(x, y-1), XY(x, y+1)
            };
        
        return neighbours;
    }
    

    Вы можете проверить вывод компилятора на Godbolt и сравните его со своим кодом.

    • 1

      Нам удалось написать очень похожие ответы с интервалом в несколько секунд!

      — Тоби Спейт


    • Да, я просто проверял вывод ассемблера, прежде чем опубликовать ответ.

      — Михаил Мушинский

    • Дубликат XY(x+1, y-1) был непреднамеренным кстати, так что вы можете отредактировать это

      — mTvare

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *