• Как разделить mesh на отдельные сегменты?

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

    Чтобы не копировать кучу раз данные туда-сюда создайте один массив из треугольников. Потом заведите еще один массив int-ов для пометок, к какому мешу каждый из треугольников принадлежит. Вы его заполните и потом можно за один проход разложить треугольники по новым мешам.

    Еще заведите массив списков длинной сколько у вас точек. Пройдитесь по каждому треугольнику и засуньте его номер в 3 списка для каждой из его вершин.

    Ну, а дальше, Breadth-First-Search запускаете. Пройдитесь циклом по всем треугольникам, если он еще не помечен, запускаете BFS от него. Помечайте его новым номером, помещайте его номер в очередь, и циклом пока очередь не пуста, извлекаете из нее элемент. Смотрите 3 списка для трех вершин. Если треугольник оттуда еще не помечен, помечаете его текущим номером меша, кладете в очередь.

    Еще для ускорения можно после просмотра списка треугольников для вершины отчищать его.

    Альтернативный вариант - завести hash_map из пары вершин в номер треугольника. Пройдитесь по треугольникам, и для каждого ребра, если оно еще не помечено, кладите номер треугольника в map. Иначе текущий и второй треугольник связаны - добавьте каждый из них в список инцидентности для второго. В таком варианте у каждого труегольника будет три ребра в соседей по сторонам.

    Только перед обращением к мапе точки сортируйте.
    Ответ написан
  • Как нарисовать кривую Лагранжа через полином?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Надо на P домножать координаты i-ой точки.
    Ответ написан
  • Как достать из браузера куки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Да-да, конечно. Браузер вы пишите.

    Надо смотреть как конкретный браузер эти куки хранит. Найти нужный файлик на компьютере, распарсить его. Если вы пишите браузер, то это по сравнению с ним - элементарная задача.

    Chrome, например, хранит куки в SQLite базе в папке профиля пользователя. Тут вам понадобится найти SQLite библиотеку, с помощью ее открыть файл и взять оттуда данные.

    Учтите, что разные браузеры хранят куки по разоному. Даже разные версии браузеров. Так что вам придется поддерживать кучу случаев.
    Ответ написан
  • Как из массива целых чисел найти все возможные комбинации (не только двух чисел, а и более) дающие искомую сумму?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Во-первых, таких комбинаций может быть до 2^n, где n - количество чисел в массиве.

    Можно рекурсивно перебрать числа: функция принимает список уже выбранных чисел, их сумму и сколько первых чисел массива обработаны. Если все числа обработаны, функция сравнивает сумму с искомой и, если надо, выводит список. Потом завершается. Если еще не все числа обработанны, то функция два раза рекурсивно вызвается с параметрами: Текущее число добавлено или нет в список, обработано на одно чисел больше.

    Другой вариант, через битовые маски, без рекурсии. Перебирайте число от 0 до 2^n-1. Потом смотрите на него, как на битовую маску. Так вы переберете все подмножества из n элементов. Если i-ый бит установлен, то берите i-ое число в сумму. Если сумма совпала с искомой - вы нашли вариант.

    Ну и самый быстрый вариант: с использованием динамического программирования. Как в задаче о рюкзаке вам надо подсчитать F(i,j) - можно ли числами с i-ого по последнее собрать сумму равную j. Потом рекурсивый перебор оптимизируется с этой информацией. Вы текущее число берете или нет и запускаетесь рекурсивно, если оставшимеся числами можно набрать оставшуюся сумму до ответа.

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Смотрите внимателно на тип параметра в функции. Это char. Один символ, или число от 0 до 255. А вы потом рабоатете с ним, как со строкой (указателем на char). Вы передаете это число от 0 до 255 в strcat, он пытается записать что-то по адресу от 0 до 255 и, ожидаемо, падает.

    Поставьте там звездочку.

    Еще комментарии: ".txt\0". Терминирующий \0 ставить не надо, "" уже его ставит само. 10 символов на filename может не хватить.
    Ответ написан
    3 комментария
  • Почему std::swap вызывает конструктор перемещения?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Чтобы поменять два значения местами, надо сначала одно значение переложить в какую-то временную перменную. Вот тут и вызывается конструктор.

    void swap(T &a, T &b) {
      T tmp{std::move(a)};
      a = std::move(b);
      b = std::move(tmp);
    }
    Ответ написан
    8 комментариев
  • Задача на геометрию. Как быстро найти подходящую выборку элементов из матрицы?

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

    Еще, угол поворота надо искать троичным поиском, ибо функция не монотонна, а пооизводную фиг найдете. В итоге у вас будет троичный поиск, запускающий двоичный поиск, щапускающий поиск паросочетания.
    Ответ написан
  • Что значит O(1)?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Время работы алгоритма - константа. Т.е. не зависит от размера входных данных (или их нет вообще)
    Ответ написан
    Комментировать
  • Почему Config::search у меня возвращает мусор?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Проблема вот в этой строчке:
    return str.c_str();

    Тут вы возвращаете указатель на внутренние данные у str. Но при выходе из функуции str уничтожается - это же локальная переменная. В итоге у вас получается висячий указатель (указатель на память, которой вы уже не владеете). Эту память какая-то другая часть вашей программы переиспользует и там остается что-то не ваше, выглядещее для вас, как мусор.

    Вообще, это undefined behavior - доступ к висячему указателю. Программа вполне может и аварийно завершится.

    Для решения этой проблемы возвращайте std::string. Или выделяйте char* вручную, через new[] (только не забудьте указатель потом удалить в вызывающем коде). Но лучше, конечно, возвращать string и не мучатся с ручным управлением указателями.
    Ответ написан
  • Как сократить код с подпрограмой?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Эти три функции идентичны, с точностью до переименования локальных переменных. Вы три раза написали одно и тоже. Можно 2 функции просто удалить и использовать отсавшуюся три раза.

    Ну какая разница, как у вас там переменная называется sA или sB - результат будет один и тот же.

    Да, может вы путаетесь, но аргумент в функции можно тоже переменовать. Хоть там и написано int masivA(int* a), этот a - это аргумент. Он никак не привязан к массиву a в main(). Туда можно передать и a и b и любой другой массив.
    Ответ написан
    4 комментария
  • Аварийное прекращение создания объекта из класса, который является родителем?

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

    Второй варинат: флаг инициализации в предке. В начале конструктора выставляйте его в false. В конце удавшегося конструктора выставляйте этот флаг в true. В конструкторах наследников надо сначала убедится, что инициализация предка удалась. Потом в вызывающем коде можно проверить, что класс проинициализировался, посмотрев на этот же флаг.

    Но этот метод не так легко обобщается на цепочки наследников. Надо чтобы все они одинаково интерпретировали этот флаг и меняли его при неудачной инициализации.
    Ответ написан
    3 комментария
  • Как в целом пишут представление (структуры данных) деревьев в коде? и в чём суть Деревьев?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    1) Можно представлять дерево всеми способами, как и граф. Но в этом случае о деревьях обычно и не говорят. Ну граф, ну без цикла может даже быть. Ну и что? Пользы никакой не несет. Вот если же дерево представлять подвешанным - с одним корнем, с детьми и родителем у каждой вершины, то уже есть куча полезных применений. В основном при реализации всяких хитрых структур данных.

    2) Дерево представляется в виде массива. Но не любое. А только полу-полное двоичное дерево (у каждой вершины до 2 детей. Если ребенок один, то левый. Все уровни, кроме последнего заполненны целиком, последний заполнен слева-направо).

    3) Дерево нельзя представить в виде списка в общем случае. Потому что список - линеен, а дерево нет. Можно детей в каждой вершине хранить списком. Ну или вырожденное дерево, где у каждой вершины есть только один ребенек.

    4) Нет.

    5) Нет.
    Ответ написан
  • Как определить коллизию квадратов?

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

    Квадрат - это все точки (X, Y), которые удовлетворяют неравенствам:
    x1 <= X <= x1 + w1
    y1 <= Y <= y1 + w1


    Пересечение двух квадратов - это точки, которые удовлетворяют одновременно каждой паре неравенств, т.е. удовлетворяют сразу четырем неравенствам:
    x1 <= X <= x1 + w1
    y1 <= Y <= y1 + w1
    x2 <= X <= x2 + w2
    y2 <= Y <= y2 + w2


    Тут уже видно, что фактически есть пара неравенств на X, и есть пара неравенств на Y. Они независимые. Вот и получается, что пересечение можно искать отдельно по каждой оси.

    Рассмотрим одну пару:
    x1 <= X <= x1 + w1
    x2 <= X <= x2 + w2


    Вообще, такие системы неравнеств решают в школе, классе этак в 7.

    Сконцентрируемся на левых границах. Что значит, что X >= x1 и X >= x2? Это значит, что X больше обоих чисел x1 и x2. Это можно записать одним неравнеством - X больше максимума из двух чисел:
    max(x1, x2) <= X

    Так же и по правым границам:
    X <= min(x1 + w1, x2 + w2)

    В итоге:
    max(x1, x2) <= X <= min(x1 + w1, x2 + w2)

    Эти неравенства имеют решение, если левая граница не превосходит правой:
    max(x1, x2) <= min(x1 + w1, x2 + w2)

    Вот у вас условие, что по оси OX есть хоть одна точка пересечения. Если вам касающиеся квадраты не надо считать пересекающимеся, то замените знак <= на строгое неравенство.

    Точно также проверьте, что есть пересечение по OY. Если пересечение есть и там и там, то квадраты пересекаются. Т.е. весь ваш код должен найти 2 минимума, 2 максимума, сделать 2 сравнения и соединить их через логичиское И.
    Ответ написан
    5 комментариев
  • Является ли множество рациональных чисел подмножеством рациональных чисел?

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Если библиотека выдает всегда одно и то же решение из нескольких оптимальных, то можно случайным образом перемешивать входные данные. Просто все блюда тасуйте перед передачей данных в библиотеку. Это с большой вероятностью выдаст разные решения из оптимальных.
    Ответ написан
  • Почему substr работает странно?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Потому что читайте документацию. substr принимает начало и длину подстроки, а не конец.

    Соответственно, надо делать вот так:
    std::string variable_value = var.substr(variable_value_start + 1, variable_value_end - variable_value_start - 1);
    Ответ написан
    Комментировать
  • Как выводить числа на семисегментный дисплей в Microprocesor Simulator 5v32?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Прибавить 0x9E-3=0x9B? Ну это если коды цифр идут подряд
    Ответ написан
  • Как сделать чтобы число с каждым разом увеличивалось, до определенного значения, за определенное кол-во раз?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Гуглите логарифмы и экспоненты. Берите арифметическую прогрессию после логарифма. Получится геометрическая прогрессия.

    exp_i= exp_1*k^i
    k=exp(( log(exp_n)-log(exp_1) )/(n-1))
    Ответ написан
    7 комментариев
  • Почему вначале все работает, а потом нет?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Потому что кривой алгоритм. Вы пропускаете те строки, где 0 на диагонали стоит. А надо искать строку, где в i-ом столбце стоит не 0 и менять ее с i-ой строкой сначала. Перечитайте алгоритм в методичке. Или погуглите алгоритм гаусса.

    Да и я уж не помню, для не квадратных матриц ранг вообще определен-то?
    Ответ написан
    Комментировать
  • Какой алгоритм быстрее и почему?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Ваш алгоритм быстрее. Но в задаче часто бывает сработает не только самый быстрый код. Например, если там чисел всего 10 в массиве, то вы никакими измерениями разницу между сортировкой и вашим решением не намеряете (если только не запустите оба решения миллионы раз. Но это же уже другая задача. Ваша задача - найти минимальные 2 числа в одном массиве и ограничение по времени, если и есть, будет считаться по одному массиву)

    Поэтому иногда имеет смысл написать не самый быстрый алгоритм, но зато гораздо более простой. Если он проходит, то зачем кодить больше?

    В вашем алгоритме еще проблема, что не очевидно, почему он работает. Надо аккуратно рассматреть все 6 случев расположения arr[0], arr[1] и numbers[i] и убедиться, что инваринат "2 минмальных числа лежат в arr" поддерживается. Тут легко накосячить, перепутать 0 и 1, не там проверку поставить и все.

    Обычно, когда такой алгортм реализуют, поддерживают более строгий инвариант "минимальное число в arr[0], следующее минимальное число в arr[1]". Тогда проверки чуть чуть упрощаются и за логикой решения следить проще.
    Ответ написан
    1 комментарий