Задать вопрос
  • Как определить последовательность действий?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Это называется поиск в пространстве состояний. Если бы вы могли построить граф - взять все возможные состояния поля A1 x все возможные состояния поля A2... и провести из каждого ребра, соответствующие всем возможным действиям, то это была бы тупо задача на поиск пути в графе.

    Проблема в том, что состояний очень много. Поэтому граф не генерируется, а строится на лету. А дальше все-равно в этом графе запускается какой-то алгоритм поиска пути. Например A*. Или dfs со всякими эвристическими оптимизациями. Главное это накрутить достаточно оптимизаций, чтобы алгоритм не касался слишком большого количества состояний - потому что все просмотренные состояния надо хранить как-то в памяти.
    Ответ написан
    3 комментария
  • Инициализирование класса?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас в примере вообще классы без данных, поэтому разницы никакой нет между первым и вторым вариантом. Третий выделят память под объект не на стеке, а в куче - поэтому и выделение и работа с объектом, обычно, будет дольше.

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

    Если бы в объекте был еще и конструктор, то первый и второй варинт были бы идентичными.

    Третий вариант всегда инициализирует объект и выделяет память, поэтому он будет медленнее.
    Ответ написан
    Комментировать
  • Как узнать, пересекутся векторы?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Введите 2 переменные t и q - это "время" на первом и втором луче, составьте 2 уравнения. Решите их - найдете время пересечения на каждом луче. Убедитесь, что пересечения при t>=0, q>=0:
    x1+t*vx1=x2+q*vx2
    y1+t*vy1=y2+q*vy2


    надо проверить, что оно имеет решение. Преобразуйте его к стандартному виду:
    t*vx1-q*vx2=x2-x1
    t*vy1-q*vy2=y2-y1


    Решите систему методом Краммера. Если определитель системы != 0 - то найдте 2 переменные q и t. Проверьте, что они обе неотрицательные.

    Если определитель равен нулю, то прямые или не пересекаются вообще, или совпадают. Они совпадают, если оба вспомогательные определители системы равны 0.

    В этом случае надо проверить, что лучи пересекаются по отрезку или лучу. Для этого надо проверить, а не лежит ли начало второго луча на первом и наоборот. Для этой проверки можно воспользоватся векторным произведением векторов. Считаете вектор {x2-x1, y2-y1} и умножаете на вектор {vx1, vy1}. Эти 2 вектора или смотрят в одну сторону (и пересечение есть), или в разные. В первом случае векторное произведение будет положительно, во втором - отрицательно. Нулевое произведение считайте как положительное - это значит что или точки совпадают или вектор направления нулевой.

    Т.е. весь алгоритм
    1) Считайте 3 определителя по методу краммера
    2) Если главный определитель не 0, считайте q и t. Пересечение есть, если q>=0 и t>=0.
    3) Если главный определитель 0, но хотя бы один из вспомогательных не 0 - пересечения нет.
    4) Считайте векторное произведение {x2-x1, y2-y1} на {vx1, vy1}. Если оно неотрицательно - пересечение есть.
    5) Считайте векторное произведение {x1-x2, y1-y2} на {vx2, vy2}. Если оно неотрицательно - пересечение есть.
    Ответ написан
    1 комментарий
  • Как передать в функцию указатель если она принимает ссылку?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Никак. Заставьте вашу функцию принимать указатель:

    template <typename type>
      static void readMemory(uintptr_t offset, unsigned int length, type* var) {
        ReadProcessMemory(targetHandle, (LPVOID)offset, var, length * sizeof(type), 0);
      }
    
    uint8_t arr[100500];
    readMemory<uint8_t>(0x00, 10, arr);
    Ответ написан
    2 комментария
  • Алгоритм поиска минимального количества ходов, требуемых для приведения всех элементов к одному числу (Python)?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Во-первых, в вашем алгоритме цикл while вообще не нужен. Сколько нужно операций +1, чтобы из a получить a+12345? Ровно 12345. Вам надо просто вычесть одно число из другого.

    Далее, мысль должна быть такая: Вот вы знаете, сколько нужно операций, чтобы все числа в массиве привести к X. Вопрос: сколько операций вам понадобится для приведения всех чисел к X+1? (Подсказка - если число было меньше X, то теперь понадобится на 1 операцию больше. Если число было больше X - то понадобится на 1 операцию меньше).

    Теперь вам надо посмотреть, подумать и выбрать оптимальное X, которому вы будете приводить все числа. Ваш вариант с max/2 не оптимален.
    Ответ написан
    5 комментариев
  • Почему у временного объекта можно вызывать non-const метод?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    По поводу вызова неконстантных методов - а с чего вы взяли, что они не дожны быть возможны? Временные объекты не имеют const квалификаторов. Иначе нельзя было бы делать вещи типа SomethingBuilder().WithA().WithB().Finalize().

    //! f6() = X(1);

    Оператор присвоения требует Lvalue слева. Временный объект же - Rvalue. Eго можно ставить только справа от =. А не потому что у него const квалификатор.

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

    //! f6().modify();

    Вот тут попытка вызова неконстантного метода у константного (и временного - но это не важно) объекта.

    //! f7(f5());

    Видимо, это чтобы исключить некоторый класс ошибок. Если вы передаете в качестве неконстантной ссылки что либо, значит оно должно внутри менятся и снаружи эти изменения должны быть видны. Иначе можно было бы передавать по константной ссылке или по значению. Но вы передаете туда временный объект - его никак снаружи видно не будет. Он существует только в этой строчке. Поэтому в C++ нельзя инициализировать неконстантные lvalue ссылки через rvalue (временные объекты).
    Ответ написан
    1 комментарий
  • Как прочитать масив данных динамической длинны?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам придется переписать функцию readMemory, чтобы она принималаlength и читала length*sizeof(type). Или вызывайте прямо ReadProcessMemory в вашей функции.

    Текущая реализация для вашей цели не подходит вообще. Тип шаблона должен быть известен на этапе компиляции. А вы хотите как-то в нем передать динамическую длину.
    Ответ написан
    4 комментария
  • С чего начать изучение алгоритмов?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Почитайте Кнут "искусство программирования" а также Кормен "алгоритмы: построение и анализ".
    Ответ написан
    Комментировать
  • Объявлять переменные внутри или перед циклом?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Современным движкам должно быть пофигу.
    Ответ написан
  • Как исправить ошибку сборки проекта, при подключении sdl?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы, похоже, создали обычный оконный проект, а надо было создавать консольное приложение. Легче всего будет пересоздать проект. Внимательно смотрите, что вы там выбираете.
    Ответ написан
  • Геометрическая прогрессия и сложный процент это одно и то же?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Нет. Распишите формулы, они будут разные. В прогрессии каждый раз добавляется степень коэффициента q. В проценте происходит домножение на (1+q):
    A+Aq+Aq^2+Aq^3+...
    A+Aq+(Aq+Aq^2)+(Aq+2*Aq^2+Aq^3)+...
    Ответ написан
    Комментировать
  • Как называется матрица возможных состояний объекта?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    машина состояний?
    Ответ написан
    1 комментарий
  • Как сымитировать правильную скорость выполнения различных сортировок путём usleep?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы наткнулись на важное свойство ассимптотического анализа. O(n^2) -означает, что на достаточно больших n, время работы будет примерно n^2 с точностью до константы. Эта самая константа может быть хоть 0.5, хоть 10000000.

    Сравните 2 алгоритма:
    // n(n-1)/2 инкремента.
    for(i = 0; i < n; ++i){
      for (j = i+1; j < n; j++) {
        cnt1++;
      }
    }
    // n^2 инкремента.
    for(i = 0; i < n; ++i){
      for (j =0; j < n; j++) {
        cnt2++;
      }
    }


    Оба алгоритма имеют O(n^2) сложность, но один делает примерно в 2 раза меньше операций.

    Суть в том, что хоть алгоритмы и работают с одинаковой ассимптотикой, они могут работать разное время! Особые странности могут быть при маленьких n. O(n log n) алгоритм часто может быть медленнее O(n^2) алгоритма. Поэтому все настоящие реализации сортировок для маленьких массивов запускают более тупые квадратичные алгоритмы.

    Если же вы хотите показать только ассимптотику, то возьмите n побольше, и тогда эти 30% будут незаметны по сравнению с десятикратным замедлением O(n^2) относительно O(n log n). Или нормируйте ваши сортировки. Искуственно ускорьте одни алгоритмы и замедлите другие, чтобы получить именно тот результат, который вы хотите. Но это как-то нечестно что ли. Если же вы все-таки хотите именно этого, назначьте каждой сортировке время C\*n^2 или С\*n\*log n миллисекунд. Прогоните алгоритмы сортировки без визуализации, подсчитайте, сколько операций замедления вы бы сделали (тот же самый код, что у вас, только вместо usleep() делайте sleep_count++). В конце подсчитайте коэффициент замедления - сколько каждый usleep должен спать, чтобы суммарно sleep_count их спал заданное время. И запускайте каждую сортировку уже с подсчитанными параметрами для usleep.
    Ответ написан
    Комментировать
  • Почему нельзя возвращать объект по значению в non-const &?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Первое - это Retrun Value Optimization. Компилятор видит, что результат работы функции используется для инициализации переменной и вместо выделения памяти под временный объект и копирования сразу заполняет результат.

    По поводу ссылки. Результат работы функции в вашем случае - prvalue

    там же по ссылке написано:
    An rvalue may be used to initialize a const lvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.

    An rvalue may be used to initialize an rvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.


    Т.е. стандартом запрещено инициализировать не const ссылку через prvalue.

    Почему это сделано? Потому что эти самые prvalue/rvalue по сути являются временными объектами. У них нельзя взять адрес, у них нет имени, компилятор может засунуть их куда угодно и уничтожить сразу за текущим выражением.

    Если бы можно было делать ссылку на эти временные объекты и как-то их менять потом, это бы усложняло анализ и возможность некоторых оптимизаций. Как, например, RVO в вашем вопросе. Пришлось бы создавать временную переменную в main для хранения результата, потому что функция память под результат не выделяет. Поэтому в стандарте C++ этого нет.

    Потом, когда в С++11 ввели rvalue ссылки и перелопатили категории значений - разрешили инициализировать rvalue ссылки через prvalue.

    Поэтому работают
    const int& r1 = f();
    int&& r2 = f();
    Ответ написан
    1 комментарий
  • Как в массиве хранить указатели на объекты разных типов?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Если все эти типы унаследованны от одного и того же класса, то можно хранить указатели на базовый класс.
    Ответ написан
    3 комментария
  • Как решить задачу, используя одну формулу и не успользуя if, else, elif?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Бинарный поиск.
    Можно реализовать без if-ов вообще.
    Суть в том, что у вас есть текущий отрезок. Находите середину, спрашиваете про нее. Получаете ответ R = 0 или 1. Потом прибавляете половину отрезка к левой границе, умноженную на R и вычитаете ее из правой границы, умноженную на 1-R. Таким образом сдвинется только одна граница. Остается вопрос, что делать с выходом из цикла. Там же внутри if запрятан.

    Можно или скопировать код 7 раз (2^7 > 100), или иметь бесконечный цикл, который будет сравнивать границы и вызвать одну из двух функций в массиве на 2 элемента. Одна из функций выведет ответ и завершит работу программы через exit. Вторая - не будет делать ничего.
    Ответ написан
    Комментировать
  • Как исправить ошибку EXC_BAD_ACCESS (code=1, address=0x0)?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы "создаете" класс sf::RectangleShape через malloc в составе временных массивов pq, qr. Он оказывается заполнен мусором. Нарушены какие-то его внутренние инварианты. Может быть куча проблем: начиная от того, что там переопределен оператор присванивания, который должен что-то где-то почистить, заканчивая тем, что таблица виртуальных методов у класса будет испорчена. Любая попытка сделать что угодно с таким экземпляром класса - скорее всего неопределенное поведение.

    Если уж вы используете классы из C++, то выделять память надо через new[], а не malloc. Тогда экземпляр класса создасться нормально и конструктор вызовется.

    Можно было бы подумать, что memmove решил бы вашу проблему - но, опять же, при этом нарушаются внутренние инварианты. Какой-нибудь unique_ptr внутри будет уже не уникальным. Такие операции работы с памятью можно делать только для POD (Plain old data) - структур состоящих из структур, массивов и базовых типов.

    Или, еще лучше использовать vector для временных массивов. Тогда вам не придется заботиться об освобождении памяти. Еще, вместо копирования можно использовать std::move, может работать бысрее, если эти sf классы имеют более эффективные операторы перемещения.
    Ответ написан
    1 комментарий
  • Как вынести определение конструктора шаблонного класса(вариативного) вне него?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Надо так:
    template<typename ...Args>
    UniformBuffer<Args...>::UniformBuffer(Args... arg)
    { 
    //код
    }


    У вас шаблоном является сам класс, а не его методы.
    Ответ написан
    2 комментария
  • Сортировка точек против часовой стрелки?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Вы что-то напутали, Atan вадает углы против часовой стрелки.

    Вот только угол идет от -pi до pi, а не от 0 до 2pi. Если вы хотите, чтобы первая точка была {1, 0}, то надо к отрицательным углам прибавлять 2pi перед сравнением.

    Это будет работать, но не очень оптимально. Atan - медленная штука. Можно сравнивать знаки координат сначала.

    Если одна точка с положительным y, а другая с отрицательным - положительная идет раньше. Если одна из точек имеет y=0 или знаки одинаковые - сравнивайте знаки по x. Выше и ниже оси OX - сравнения должны давать разные выводы (выше оси OX, положительные x идут раньше отрицательных, ниже оси OX - наоборот).

    Или для каждой точки в зависимости от двух знаков координат надо назначить квадрант от 1 до 4. И сначала сортировать по ним.

    Если же точки лежат в одном квадранте (знаки одинаковые) то можно сравнивать их с помощью векторного произведения векторов. Подстовляете туда координаты двух точек и, если значение положительное, то первая точка лежит раньше второй. Нулевое значение - значит они на одном и том же углу. Если отрицательное - перовая точка лежит позже второй.
    Ответ написан
    Комментировать
  • Как можно реализовать данный код без библиотеки string?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Заведите char массивы какой-то достаточной длины. Читайте через gets_s. Сравнивайте строки через strcmp.
    Ответ написан
    Комментировать