Задать вопрос
  • Не могу решать задачи по программированию?

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

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

    Вообще тут не нужен обход в ширину, тут, кажется, достаточно цикла по всем вершинам.

    А так ваш алгоритм зачем-то имеет внешний цикл по User user и если он натыкается на какую-то еще не посещенную вершину, то дальше уже перебирает все вершины в очереди и добавляет их соседей в очередь в цикле, фактически выполняя обход в ширину. Правда там в очереди будет лежать какая-то случайная вершина из цикла по user. Так что это будет обход вширину сразу из двух вершин.

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Линейная. O(N+M). Ибо там цикл по i от 0 до startMedianIndex и вся остальная мишура на i вообще никак не влияет. Больше циклов в программе нет. Не понимаю, что тут может быть непонятного.
    Ответ написан
    Комментировать
  • Что делать, когда Wolfram говорит, что будет корень, а считать не хочет - a³+b³=z³?

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

    Точнее всех будет считать python если использовать библиотеку Decimal:
    from decimal import *
    getcontext().prec = 400
    a = Decimal('112312312312312311231231231231231123123123123123112312312312312311231231231231231123123123123123');
    print(pow(a,Decimal(1/3.0)))


    Можете хоть тысячи знаков считать, ограничения - в основном скорость работы и требования по памяти.
    Ответ написан
    5 комментариев
  • Как хешировать в хеш таблице узлы дерева?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Итак, у вас ключи - какая-то древовидная структура и вам надо быстро определять, а есть ли такая структура в таблице. Я правильно понял?

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

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

    Или можно тупо записать вашу структуру данных в строку (Например, расставив скобки вокруг каждого поддерева вроде "(a(b)(ccc(dd))" - это узел a, у которого есть дети b и ccc, у последнего есть ребенок dd) и потом как угодно хешировать уже строку, тогда ничего самостоятельно реализовавать ничего вообще не надо (to_json и hash от строки возможно уже есть).
    Ответ написан
    2 комментария
  • Как найти точки для обьекта и нарисовать его?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Точно так же, как вы в проедыдущем вопросе находили координаты тик-марков, вы можете тут найти 2 координаты - пятая точка на острие стрелки и центр короткой стороны. Теперь, можно ввести систему координат из центра окружности так, чтобы ось ox шла вдоль стрелки. Для этого вам надо найти 2 перпендикулярных вектора. Один у вас уже есть - это вектор между двумя известными уже точками. Он же будет cos(alpha), sin(alpha). Перпендикулярный вектор будет -sin(alpha), cos(alpha). Теперь надо только взять координаты 5 точек в этой системе координат (как будто бы стрелка лежит горизонтально) и сложить x, помноженный на первый вектор с у помноженным на 2 вектор.

    В итоге будет что-то вроде:
    x' = x*cosa + y*sina
    y' = -x*sina + y*cosa


    Это же выражение является заодно матрцей поворота на угол alpha.

    А координаты там что-то вроде: {r0, w/2}, {r0, -w/2}, {r1, -w/2}, {r1 + w/2, 0}, {r1, w/2}, гже r0, r1 - радиусы окружностей между которыми стрелка натянута. w - ширина стрелки. Эти пары подставляйте ввиде x,y в формулу выше и получите x', y' - координаты точек на экране.
    Ответ написан
  • Невидимый оверлей для записи видео/демке экрана/скриншотах?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Смотрите, чтобы окно было не видно записью экрана, оно должно быть "выше" этой самой записи. Например, рисоваться прямо в экранную память перед демонстрацией экрана. Такие штуки, действительно, зовутся overlay - hardware overlay. Что бы вы средствами winapi с вашим окном не делали, оно останется "ниже" захватчика экрана.

    То, что вам нужно нельзя сделать на чистом winapi. Тут нужен именно DirectX. Придется ручками что-то там рисовать в поверхность. Гуглите "directx overlay".
    Ответ написан
    Комментировать
  • В чем причина данной ошибки?

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


    У вас 2 раза определен class парсер::ВыражениеParser.

    Компилятор даже указал на оба определения: они оба в файле ВыражениеParser.h, но включенного 2 раза из разных исходников:
    In file included from ВыражениеVisitor.h:8,
                     from ВыражениеParser.cpp:6:
    ВыражениеParser.h:15:8: ошибка: повторное определение «class парсер::ВыражениеParser»
    ...
    In file included from ВыражениеListener.h:8:
    ВыражениеParser.h:13:8: замечание: предыдущее определение «class парсер::ВыражениеParser»


    Пока похоже, что вы там намудрили с include-guard'ами из-за чего один и тот же хедер включается несколько раз. Выкладывайте начало файла ВыражениеParser.h.
    Ответ написан
  • Как сделать преобразование фурье для изображения по xy?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Двумерное преобразование фурье обычно делается так: отдельно каждую строку одномерным перобразованием фурье, потом на вот этой новой матрице - отдельно каждый столбец. Обратное преобразование в обратном порядке: cначала каждый столбец, потом каждую строку (хотя можно и в другом порядке, просто так концептуально понятнее, почему оно работает).

    Если у вас всего 4 пикселя, то возможно x и y - это будут 2 строки входной матрицы.
    Ответ написан
    Комментировать
  • Как присвоить динамическому массиву типа void* значение в Си?

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

    А так, скорее всего вам подойдет функция memset. Какими-нибудь нулями все заполнить - отлично можно. Хоть там int, хоть char, хоть float.
    Ответ написан
  • Как вывести буквы, которые используется наиболее кол-во раз?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Задача разбивается на 2: 1) подсчитать для каждой буквы количество ее вхождений, 2) Найти максимум и вывести его индекс.

    Первая задача решается просто - заведите массив счетчиков. Например, на 256 элементов. Для каждой буквы строки увеличивайте счетчик с индексом равным символу (помните, же, что char в C++ - это целочисленный тип?)

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Если не обязательно делать поворт на месте, то вся суть алгоритма вот в этой одной строке:
    result[i][j] = arr[n-1-j][i];
    Надо только циклы прогнать по нужным границам, да массив нужного размера создать.

    Если матрица квадратная, то элементы сдвигаются по кругу в четверках - и это можно сделать без дополнительного массива . Можно делать сдвиг по кругу со временной переменной. Что-то вроде этого:
    tmp = arr[i][j];
    arr[i][j] = arr[n-1-j][i];
    arr[n-1-j][i] = arr[n-1-i][n-1-j];
    arr[n-1-i][n-1-j] = arr[j][n-1-i];
    arr[j][n-1-i] = tmp;


    И надо аккуратно границы цикла подобрать, чтобы там только левый верхний угол обработался. Иначе вы 4 раза в каждом круге сдвините, и ничего не поменяется.
    Ответ написан
    Комментировать
  • Может ли веб-страница записывать действия в браузере без разрешения на это?

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

    Вы можете узнать, на какую ссылку юзер ткнул, но дальше - все.
    Ответ написан
    Комментировать
  • Как найти точки на дуге?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Точка на окружности радиуса r, с центром x0, y0, под углом alpha к горизонтальной оси имеет координаты:
    x = x0 + r*cos(alpha)
    y = y0 + r*sin(alpha)


    У вас есть 2 окружности - внешняя, и невидимая внутренняя. Тикмарки - это куски радиуса между ними. По формуле выше (с двумя разными радиусами) вы можете найти 2 точки конца каждого отрезка.
    Ответ написан
    22 комментария
  • Почему -Wconversion разрешает передачу integer literal в char параметр?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ну вообще, char - integral type. Поэтому передавать туда числовую константу можно - это никакой не варнинг. Компилятор сам понимает, что она должна быть типа char и даже проверяет на переполнение и выдает warning, если что.
    Ответ написан
    2 комментария
  • Как найти минимальное число прохождений по автомату до конечного состояния с N вероятностью?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Есть простой трюк сильно упростить задачу: Измените переходы из "конечной" вершины - она теперь с вероятностью 100% будет вести только в саму себя. Таким образом, процесс хотя бы раз достигший вершины, навсегда в ней останется.

    А вопрос из задачи (если его понимать как: минимальное количество шагов, чтобы хотя бы раз посетить конечную вершину с вероятностью >99%) становится эквивалентен: минимальное количество шагов, чтобы быть в конечной вершине с вероятностью не меньше 99%.

    А тут уже надо найти минимальное число k, такое что соответствующее значение в матрице A^k было бы > 0.99. A тут - это матрица переходов.

    Можно или в тупую умножать матрицу саму на себя, пока значение в строке начальной вершины и столбце конечной вершины не станет достаточно большим. Это будет O(N^3*ответ). Или можно делать хитро: бинарным поиском перебирайте степень, а внутри логарифмическим возведением в степень считайте A^k. Это будет O(N^3*log(ответ)^2).
    Ответ написан
    Комментировать
  • Как написать функцию sin из библиотеки math.h в Си?

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

    Ваша функция, как и стандартная, работает с радианами и выдает такой же результат от того же аргумента Pi*30/180=Pi/6.

    Посмотрите, ведь в result и во второй строке вывода вы передаете один и тот же агумент и получаете один итот же 0.500000. Только во второй строке у вас вместо Pi написано 3.1415265.
    Ответ написан
  • Как решать подобные задачи?

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

    Так и тут. Перебирайте длину круга бинарным поиском. И запоминайте, сколько метров вы уже прошли и сколько полных кругов получили в ответ.

    Вот у вас есть гипотеза m=(l+r)/2 - вы хотите проверить, а как она соотносится с длинной круга. Допустим, вы уже прошли x метров и прошли k полных кругов. Уже только из этой информации можно оценить, какая длина круга может быть. Во-первых, убедитесь, сравните floor(x/m) и k. Если floor(x/m) > k вы уже знаете, что длина круга больше m, ведь для круга длины m и более коротких значений вы бы насчитали floor(x/m) или больше оборотов. Если floor(x/m) < k, то уже очевидно, что длина круга меньше m. Если же floor(x/m) = k, то спросите run m-x%m - сколько осталось пройти до финиша, если бы длина круга была равна m. Если вы получили в ответ 1, то значит круг не длинее m. В протвином случае круг строго длиннее m.
    Ответ написан
    4 комментария
  • Посчитать многоугольник почему не работает програма?

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

    Код проверки будет примерно такой:
    def can_construct_polygon(lengths):
      return len(lengths)>0 and max(lengths) < sum(lengths)/2


    В списке lengths надо передать длины всех отрезков. Если у вас там вектора на плоскости заданы в vectors, то через map подсчитайте их длины сначала.

    Edit:

    Раз поворачивать вектора-отрезки нельзя, то действительно, составить многоугольник можно, если по-координатная сумма векторов дает (0, 0).

    Все еще остается вопрос, а допускаются ли вырожденные мноугольники? Например, можно ли составить такой из веторов (1,0), (-1,0). Если допускаются, то проверять длины не надо. Если нет, то все еще надо, как я выше указал, сравнить максимальную длину с суммой всех длин.

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

    Ваш код вроде бы правильно проверяет на сумму векторов покомпонентно. Попробуйте добавить еще и проверку длин.
    Ответ написан
  • Что можно убрать чтобы оптимизировать затраты памяти?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    (Отредактировал ответ согласно комментариям). Как выяснилось, в задаче длины вот групп одинаковых цифр могут достигать 10^18. Поэтому попытка развернуть эту запись обречена на провал: все эти цифры потребуют миллионов террабайт. Естественно, ваша программа падает еще на этапе ввода ( а еще, вы там читаете int, в который такие большие числа не влезают, что будет дополнительной ошибкой).

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

    Главная часть решения - это научиться складывать две группы цифр равной длины (плюс перенос). Вроде 7777 + 4444 +1 = 12222 - 4 двойки и 1 единица (помните, порядок у нас развернутый же). Тут можно всегда выделять в отдельную группу первую цифру из-за переноса. Отдельный случай будет, похоже, если цифры дают в сумме 9 и есть перенос (10000..000). А иначе вы получите что-то вида abbbbbbc в оставшихся цифрах. Главное, что при сумме нельзя группы распаковывать.

    В конце разверните группы и объедините подряд идущие группы для одинаковых цифр.
    Ответ написан