Задать вопрос
Ответы пользователя по тегу Алгоритмы
  • Можно практический пример где можно использовать очередь на двух стеках?

    @Mercury13
    Программист на «си с крестами» и не только
    В разных необычных структурах данных.
    https://habr.com/ru/articles/483944/
    Вот очередь, поддерживающая за амортизированное O(1) необратимую ассоциативную операцию (например, минимум).
    А это, в свою очередь, позволяет за O(N) эту самую необратимую ассоциативную операцию вычислить в окнах по 10 (или по 20, или по 100).
    Ответ написан
    Комментировать
  • Как максимально эффективно по скорости написать этот алгоритм преобразования строки?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Каким-то образом преобразовать обе строки, чтобы избавиться от расхождений по стартовым слэшам. Слишком мало информации, КАК это сделать — возможна ситуация, когда вторая строка не начинается со слэша, а первая нет, но бывают ли другие?
    2. Убедиться, что вторая строка — префикс первой. Если нет — непонятно, что делать.
    3. Если вторая строка непуста и не кончается слэшом, убедиться, что в первой на этом месте слэш. Пропустить его.
    4.1. Если от первой строки ничего не осталось — если в конце слэш, пропустить, и извлечь кусок до следующего с конца слэша.
    4.2. А если осталось — извлечь кусок до слэша.
    5. Придумай методику хранения информации. Вероятно, выделить память? — тогда на каждый результат придётся давать free.
    Ответ написан
    Комментировать
  • Как сделать кэш динамики запасов?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Пока вижу такой способ закэшировать динамику запасов. Вместе с каждым событием держим двойной кэш.
    1. Товары по очереди (0, 1, 2, 0, 1, 2…)
    2. Тот товар, который задействован в событии.

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

    @Mercury13
    Программист на «си с крестами» и не только
    Если f(n) ≡ 0 (неотрицальна → асимптотически неотрицательна), то вполне срабатывает, что 0=Θ(0).
    То есть по нашему определению множества Θ, если оно непустое, то g обязана быть асимптотически неотрицательной — но не обязательно асимптотически положительной.
    Ответ написан
  • Как архитектурно правильно организовать классы в игре на JS. (ООП)?

    @Mercury13
    Программист на «си с крестами» и не только
    Статические методы класса как раз для оперирования с несколькими экземплярами класса?

    Статические поля и методы служат для работы с классом в целом. Примеры:
    • Есть десять объектов и новых создавать нельзя.
    • Общий для всей проги объектный пул, а второго, скорее всего, не будет.
    • Псевдоконструктор — Rect.xyxy(x1,y1,x2,y2) и Rect.xywh(x,y,w,h).
    • Функциональность никак не зависит от экземпляра объекта: calculateDamageWithCrit при условии, что генератор случайных чисел тоже статический (принадлежит библиотеке языка в целом, а не игровому миру).

    Где правильно хранить экземпляры классов врагов?

    С Wave вы, вероятно, сами запутались: это то информация о волне, то часть текущего состояния мира. Я бы всех врагов закинул в Game (правда, назвал бы объект World).

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

    Башня принадлежит игровому миру — тоже её в Game (или World).

    У башни есть массив с пулями которые она выпускает.

    Пули очень не стоит в башню — их лучше в тот же Game/World. Башню вы уничтожаете — пули тоже исчезают?

    И эта вот функция просчёта у меня просто в файле. Нужно ли её загонять в класс как метод?

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

    Важная штука: часто в играх есть неизменная информация о врагах, башнях, пулях (TowerType, EnemyType, BulletType, WaveInfo…), и есть конкретный экземпляр (Tower, Enemy, Bullet). Иногда враги, башни и пули объединяют в один GameObj, но это уже зависит от архитектуры. Возможно и так, и этак.
    Ответ написан
    6 комментариев
  • Преобразование шрифта?

    @Mercury13
    Программист на «си с крестами» и не только
    Вот разбор строки.
    6638d576265ed231173995.png

    Совместимая декомпозиция NFKD (а лучше совместимая композиция NFKC) конкретно тут не поможет (не меняет ни одного символа), но в других случаях может улучшить жизнь.

    Затем тебе придётся работать с визуально сходными символами, и начинать надо отсюда.
    https://util.unicode.org/UnicodeJsps/confusables.jsp

    6638d67702c6c545558246.png

    Этого тоже мало, но вот с этого начинать надо.
    Ответ написан
    Комментировать
  • Как определить сложность алгоритма?

    @Mercury13
    Программист на «си с крестами» и не только
    У нас два вложенных цикла, каждый порядка n.
    Значит, O(n)·O(n) = O(n²), если не докажем меньше.
    Не докажем, там обычная арифметическая прогрессия, которая что-то вроде n(n—1)/2.
    Ответ написан
    Комментировать
  • Для кого операция добавления элемента в середину медленнее — для List или для LinkedList?

    @Mercury13
    Программист на «си с крестами» и не только
    Если нужно искать точку, куда добавить (в LinkedList переместить итератор, в List переместить итератор ИЛИ отыскать индекс) — медленнее LinkedList из-за вопросов с кэшем.
    Если точка уже имеется и она в середине — медленнее List, просто из-за асимптотической сложности.
    Ответ написан
    3 комментария
  • Как решить задачу "Шестерки" с меньшими затратами памяти?

    @Mercury13
    Программист на «си с крестами» и не только
    Шаг 1. Что собой представляет 66666·6?
     ₃₃₃₃
     66666
    ×    6
    ------
    399996

    Таким образом, получается N+1 цифра: 3, N−1 девятка, и 6.

    Шаг 2. Что собой представляет 66666²?
         66666
        ×66666
    ----------
        399996
       399996
      399996
     399996
    399996
    ----------
    4444355556

    (Простите уж, был обломИЩЕ, так что вычислил на калькуляторе и без цифр переноса.)

    Могут быть вопросы, если очередная сумма перескочит за 100 и перенос будет двузначным — но нет, тут всё в порядке. Посчитаем (при достаточной длине кучи шестёрок):
    Десятая с конца (!) цифра — 9·9 + 6 + 8 [перенос] = 95, перенос 9
    Одиннадцатая — 9·10 + 6 + 9 = 105, перенос 10
    Двенадцатая — 9·11 + 6 + 10 = 115, перенос 11
    Так что без вопросов, всё остаётся как было.

    Дальше как-то сможете своими силами?
    Ответ написан
    Комментировать
  • Scratch задание Алгоритмика, как решить?

    @Mercury13
    Программист на «си с крестами» и не только
    Как я понял, робот смотрит вниз.
    Поверни вправо. Подумай, как надо двигаться, чтобы разрушить четыре блока, стоять в 3-й строке, 2-м столбце и смотреть вниз. Повтори четырежды.
    Ответ написан
    Комментировать
  • Будет ли работать бинарный поиск, если в массиве есть пробелы?

    @Mercury13
    Программист на «си с крестами» и не только
    Что такое вообще «пробелы»?
    1. Пробелы в исходном коде: за пределами закавыченных строк это только оформление и в исполнении не участвует. Ну и слова, разумеется, нужно разделять пробелами — как в паскалевском «packed array» или сишном «int main».
    2. Пропуски: не 1,2,3, а 1,4,5. Да, для этого бинарный поиск и предназначен: массив отсортирован, никаких других правил нет, найти или сам элемент, или место, куда вставить его.
    Например, ищем 7: 6 → больше, 13 → меньше, 12 → меньше. Не нашли; если нужно вставить — то после 6-ки.
    Ищем 1: 6 → меньше, 4 → меньше, 1 → попали.
    Ответ написан
    1 комментарий
  • Можете решать эту задачу?

    @Mercury13
    Программист на «си с крестами» и не только
    Изначально:
    1. У корня глубина 0.

    Команда ADD:
    1. вершина.предок = предок
    2. вершина.глубина = предок.глубина + 1

    Команда GET:
    1. Найти ту вершину, что глубже. Если у одной глубина 5, у другой 7 — подняться от второй на 2.
    2. А теперь параллельно и от первой, и от второй вершины поднимаемся вверх на единицу, пока не придём в одну и ту же вершину.

    Если хватит памяти — можно устроить какой-то кэш. Мой вариант — кэшировать предков порядка 1,2,4,8…
    Чтобы подняться от вершины на 30 единиц…
    1. Находим ближайшую степень двойки (16).
    2. Если эта степень есть в кэше — просто берём её.
    3. Иначе находим максимальную имеющуюся степень (например, 4). Заходим в эту вершину и рекурсивно поднимаемся от неё на 4, потом на 8, заполняя наш кэш.
    4. На оставшиеся 14 поднимаемся по тому же алгоритму.

    Чтобы найти общего предка двух вершин — у одной глубина 30, у другой 40.
    1. От той вершины, у которой 40, поднимаемся на 10 единиц. Алгоритм я привёл.
    2. Одинаковые? — тогда понятно.
    3. Имеют общего предка? — тогда понятно.
    4. Иначе поднимаемся на 1, 2, 4, 8, 16 единиц от каждой из них по указанному алгоритму, каждый из этих шагов при наличии кэша даст O(1). Находим последнюю НЕСОВПАДАЮЩУЮ глубину. Для них повторяем алгоритм.

    ВАРИАНТ КЭША ВТОРОЙ. Для вершины глубины 27=11010 кэшировать предков АБСОЛЮТНЫХ (то есть от корня!) глубин 16=1.0000, 24=11.000, 24 :) =110.00, 26=1101.0. Тогда при создании вершины весь кэш достаточно быстро строится на основе кэша вершины-предка.

    Чтобы подняться от вершины глубины 27 на расстояние, например, 5, нам нужна абсолютная глубина 27−5=22.
    Есть только 24 → действуем так. Выныриваем туда на 24, но там кэш совершенно негодный → а дальше нас проведёт кэш глубины 23. Так поднимаемся на 1 до 23-й и повторяем алгоритм.

    Чтобы найти общего предка двух вершин (их глубины, скажем, 27 и 42), точно так же уравниваем глубины. Затем поднимаемся до глубин 16, 24, 24, 26…, пока не найдём несовпадение. Идём в эти несовпадающие вершины, проходим от них к предку и повторяем алгоритм.
    Ответ написан
  • Какова будет грамматика для данного языка?

    @Mercury13
    Программист на «си с крестами» и не только
    L → EZUU M ZUUUUF
    M → ZUU M ZUUUU | S
    Для S грамматику вы уже придумали.
    Затем — не буду расписывать, они многословны, но просты — UZ → ZU

    А чтобы превратить Z в 0 и U в единицу, если i,n ∊ N+…
    Сделаем затравку…
    EZ → E0
    Ua → 1a
    cZ → c0
    UF → 1F
    …Уничтожим технические нетерминалы…
    E0 → 0
    1F → 1
    …И проведём волну!
    0Z → 00
    U1 → 11

    Вроде так.
    (Z = zero, U = unit)
    Ответ написан
    Комментировать
  • Как разбить числа по группам так, чтобы в группах находились близкие по значению числа?

    @Mercury13
    Программист на «си с крестами» и не только
    Это называется кластеризация, и самый ходовой метод для неё — K-means.
    Ответ написан
    2 комментария
  • Сложность алгоритмов для определения подстроки в строке?

    @Mercury13
    Программист на «си с крестами» и не только
    H = |haystack|, n = |needle|, a — размер алфавита.
    Примитивный алгоритм: предобработки нет, работа в среднем 2H, максимум O(Hn).
    Типичные быстрые алгоритмы: предобработка O(n) или O(n+a), работа в среднем <H, максимум O(Hn).
    Автоматные алгоритмы: предобработка O(na) или O(n+a), работа =H.
    Существуют СТРАШНЫЕ алгоритмы с работой в среднем <H и максимум O(H), где применяются — не знаю.
    Если нужно проводить несколько поисков одной «иголки» в разных «стогах», нужна всего одна предобработка.
    Ответ написан
    Комментировать
  • Как работает Hmac?

    @Mercury13
    Программист на «си с крестами» и не только
    HMAC — это так называемая имитовставка.
    То есть нечто среднее между хэш-функцией и электронной подписью.
    Тот, кто изменил сообщение и не знает ключа, НЕ МОЖЕТ подделать имитовставку — в отличие от хэш-функции.
    Но ключ подписи и проверки ОДИН И ТОТ ЖЕ — в отличие от электронной подписи.

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

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Придумал, причём тупо. Комбинаторикой высчитываем, какой длины (по принципу Дирихле) должно быть наше слово: например, если у нас цифры от 0 до 9 и 125 строк, достаточно взять трёхзначные. Вот мы берём 126 битов (ну или 128 для круглого счёта), из наших чисел берём только трёхзначные и начинаем заполнять биты. Есть, например, 025 — вот в 25-й бит и суём единичку. После этого остаётся найти в битовой маске ноль и преобразовать в нашу строку: на 45-м месте — значит, 045.
    Ответ написан
    Комментировать
  • Как правильно оценить сложность алгоритма O(n)?

    @Mercury13
    Программист на «си с крестами» и не только
    f(x) = O(g(x)) при x→y — это так называемый символ Ландау.
    И означает, что при x, достаточно близких к y, f(x)<k·g(x). Так что 2x или 1000x — извините, не важно.

    Отсюда же запись O(log n) — ведь разные логарифмы отличаются на константу, которую символы Ландау съедают.

    Чем символы Ландау интересны программистам?
    1. Кэшами, быстрым процессором, «хитрым» программированием и прочим на больших наборах данных можно выиграть, например, в разы. Порядком сложности алгоритма — намного, намного больше.
    2. Пока закон Мура действовал, объёмы данных росли экспоненциально — так что быстро доходило до того, что программу начинали использовать на наборах данных, для которых она просто не предназначалась.
    3. Практически приемлемые алгоритмы обычно имеют небольшую сложность — например, до O(n³). И, например, линейный алгоритм за приемлемое время обработает миллионы элементов, n log n — сотни тысяч, n² — тысячи, n³ — сотни.
    4. Программисты отлаживают на небольших наборах данных, которые можно обработать вручную. Так что разница между отладочными и боевыми данными бывает большая — а значит, порядок сложности должен влиять сильнее, чем остальные факторы.
    Ответ написан
    1 комментарий
  • Как выполнить размещение k элементов из n?

    @Mercury13
    Программист на «си с крестами» и не только
    Будут повторы?
    Если не будет — то достаточно отсортировать char’ы и использовать числовой алгоритм.
    Если будут — ищите «размещения с повторами», и тоже сортируйте.
    Ответ написан
    Комментировать
  • Где и как используют деревья в программировании?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Нечто, действительно имеющее древовидную форму — например, деревья каталогов на дисках, деревья сцен в 3D, деревья принятия решений.
    2. Деревья поиска — структуры данных, позволяющие добавлять-убирать объекты и позволяющие быстрый поиск по ключу. Например, словари всякие, индексы БД.
    3. Так называемая куча — структура данных, позволяющая добавлять-убирать объекты и поддерживающая минимальный элемент в этом множестве. Используется как вспомогательная в каких-нибудь алгоритмах.
    4. Двоичное разбиение пространства в 3D — известный способ сортировки от дальних к ближним.

    Кроме того, деревья могут не существовать в памяти, а только подразумеваться — в синтаксических разборах, теоретико-игровых обсчётах. Хотя один из вариантов промежуточного хранения разобранной формулы, чтобы потом по ней проводить многократные расчёты — дерево (но чаще используют обратную польскую запись).
    Ответ написан
    Комментировать