Ответы пользователя по тегу Алгоритмы
  • Можно ли быстрее чем за O(N) подсчитать сумму S(N,K,M) = sum i=0..N K*i%M?

    @Sumor
    Если я правильно понимаю, то это просто арифметическая прогрессия на кольце вычетов по модулю M.
    Так что нужно рассчитать сумму членов арифметической прогрессии по формуле:
    ((K + K*N)/2 * N) % M
    Ответ написан
    1 комментарий
  • Как работает алгоритм управляющий светодиодом компьютера оповещающий об процессе обращения к жесткому диску?

    @Sumor
    https://habr.com/ru/post/29194/
    В интернете блуждает интересная идея: на каждый сервер дата-центра ставить звуковуху, маленький динамик и небольшую программу, которая произносит случайное ругательство при прохождении каждого гигабайта через сетевуху.

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

    @Sumor
    Небольшой код для перемешивания с помощью порождающего элемента.
    Математическое обоснование основано на теории групп.
    Кратко:
    В конечном поле, мощностью равному простому числу p есть мультипликативная группа, которая включает в себя все элементы кроме нуля.
    В этой мультипликативной группе обязательно есть порождающий элемент.
    Что такое порождающий элемент? Это элемент (a), который можно последовательно возводить в степень и получить все элементы мультипликативной группы, то есть все элементы нашего поля, кроме нуля. Причём единица получится всегда последней. a^(p-1) = 1 (mod p)
    На том, что степени порождающего элемента проходят все элементы ровно по одному разу и построен предложенный алгоритм генерации перестановок. Он не годится для реальных дел, но в некоторых научных или ненаучных целях его можно использовать.
    Нужно взять простое число большее как минимум на 2 максимальной длины строки.
    0 в результате умножения не получается, а 1 будем считать признаком завершения подсчётов, элементы больше длины строки + 2 будем пропускать.
    Для поиска порождающих элементов нужно разложить число (p-1) на множители. Если элемент a является порождающим, то возведение его в степени полученных множителей не должно равняться 1 по модулю p.
    Как только один порождающий элемент найден, то порождающими будут его степени, взаимно простые с (p-1).

    Для примера взял число 19. (19-1)=18=2*3*3
    Проверяем число 2: 2^2 = 4≢1(mod p) 2^3 = 8≢1(mod p) - значит 2 - порождающий элемент.
    Числа 1, 5, 7, 11, 13, 17 - взаимно простые с 18, поэтому 2^1, 2^5, 2^7, 2^11, 2^13, 2^17 - порождающие элементы
    Это числа 2, 3, 10, 13, 14, 15. В данном случае у нас получится 6 вариантов перемешивания.
    И теперь код:
    public static void Main()
      {
        var str = "abcdefghijklmnop";
        Console.WriteLine(str);
        Console.WriteLine(string.Concat(Shuffle(str)));
      }
      private static Random Rnd = new Random((int)DateTime.Now.Ticks);
      public static IEnumerable<char> Shuffle(string str)
      {
        var prime = 19;	
        var makers = new [] {2, 3, 10, 13, 14, 15};
        var maker = makers[Rnd.Next(makers.Length)];
        if(prime < str.Length + 2) throw new Exception("Слишком длинная строка");
        var current = maker;
        while(current != 1)
        {		
          if(current < str.Length + 2)
            yield return str[current - 2];
          current *= maker;
          current %= prime;			
        }
      }
    Ответ написан
    1 комментарий
  • [Машина Тьюринга] Каким образом можно разделить число (в десятичной системе счисления) на 5?

    @Sumor
    Надо действительно умножать на два и удалить последнюю цифру.
    Умножать можно со старшего разряда, можно с младшего.
    Умножение на два алгоритмически достаточно простое и требует небольшого количества состояний.
    Нужно определиться с тем что будут означать состояния машины.
    Вот, примерная схема, деления на 5, оно же умножения на два со старшего разряда:
    Qt - Начало умножения текущей цифры
    Qr - На следующем шаге просто пойдём направо
    Qrr - Следующие два шага пойдём направо
    Ql - Следующий шаг пойдём налево для прибавления единицы
    Q1 - Добавление единицы от переполнения на предыдущих шагах
    Qlast - Дошли до конца и удаляем последнюю цифру
    Qend - Конец

    Остальное дело техники - внимательно прописать переходы между состояниями. Вот часть переходов
    1 + Qt -> 2 + Qr - на текущей позиции единица, мы вместо неё пишем двойку и готовимся на следующем шаге перейти к следующей цифре.
    2 + Qr -> Right + Qt - перешли направо к следующей цифре
    6 + Qt -> 2 + Ql - У нас переполнение, поэтому нужно вернуться налево и добавить единичку
    2 + Ql -> Left + Q1 - перешли налево для последующего добавления единички
    3 + Q1 -> 4 + Qrr - добавили единичку и планируем переместиться на две позиции направо для продолжения работы.
    4 + Qrr -> Right + Qr - перемещаемся направо к текущей позиции (остался один переход направо для продолжения алгоритма)
    _ + Qt -> Left + Qlast - мы дошли до конца числа - перемещаемся на последнюю цифру для затирания
    0 + Qlast -> _ + Qend - затёрли последнюю цифру и заканчиваем работу.

    Занимательный факт 1: 9 + Q1 - невозможное состояние
    Занимательный факт 2: когда состояние машины Qlast, то она должна указывать на 0.
    Ответ написан
    Комментировать
  • Как сделать эффект бесконечного холста?

    @Sumor
    Берёте канвас размером больше экрана, вплоть до двукратной ширины и высоты.
    При скролировании перемещаете канвас. Как только вы приблизитесь к границе - добавьте с той стороны новый канвас такого же размера. Перемещайте оба канваса пока первый не скроется из виду и вы его можете спокойно удалить.
    При таком подходе достаточно двух канвасов, если у вас перемещается по одной оси, и четырёх, если перемещение по двум осям.
    Ответ написан
    Комментировать
  • Задача заполнения поля пазлами. Какие варианты решения?

    @Sumor
    Мне видится метод ветвей и границ (умный перебор).
    Грубо говоря, когда ты ставишь фигуру на поле ты получаешь такую же задачу, но с меньшим количеством элементов и с меньшей площадью поля. Пробуя фигуру, ты по определённым критериям можешь оценить доступность варианта, и если он пока доступен - продолжить процедуру рекурсивно.

    Алгоритм, примерно, следующий:
    1. Выбор фигуры: любой, но для уменьшения количество возможных ветвей решения нужно выбрать фигуру, которая на текущем поле может находиться в наименьших местах. Для этого берём каждый вид фигуры и примеряем на каждое место. При проверке помечаем использованные места поля. Если обнаружится, что есть места, которые невозможно покрыть, то решение в такой конфигурации не существует - отбраковываем ветвь решения.
    2. Ставим фигуру в одно из возможных мест, тем самым мы уменьшаем количество фигур и размер доски. И рекурсивно переходим на шаг 1.

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

    Для первого примера: 1х2 - 18 возможных мест, 1х3 - 11 мест, 2х3 - 7 мест. Поэтому мы выбираем третью фигуру для первого шага ветвления.
    Ставим первую фигуру в угол (0,0) вертикально, получаем такую картину:
    0011
    0011
    0011
    0100
    При выполнении первого шага алгоритма выясняется, что поле (1,3) невозможно покрыть ни одной фигурой - ветвь обрывается, переходим к следующему варианту.

    Данный алгоритм точно найдёт нужное решение, так как он сводится, в худшем случае, к полному перебору.
    Ответ написан
    Комментировать
  • Как правильно записать буфер в файл? Какая должна быть кодировка?

    @Sumor
    По-умолчанию node.js работает с файлами как с текстовыми файлами в различных кодировках.
    bmp это бинарный (нетекстовый) формат. Для его чтения/записи нужно явно указывать кодировку 'binary' при вызове readFileSync, writeFileSync и т.п.
    Ответ написан
    1 комментарий
  • Как разложить на неприводимые в поле R множители?

    @Sumor
    Сначала надо попытаться найти корни многочлена. Если корни есть, то многочлен разделить на (x-x0), где x0 - корень и продолжить разложение с оставшимся многочленом. Если корней нет, или сложно найти, то надо пытаться найти (увидеть) формулы, которые позволят как-то упростить или "сложить" выражение.
    В данном случае вполне может получиться, что корней нет, но многочлен разделяется на два неприводимых многочлена вида (x^2 + bx + c).

    PS.
    Прикидки в excel показывают, что многочлен как минимум неотрицательный, и если имеет корень, то около числа 0,381966.
    Ответ написан
    Комментировать
  • Как реализовать случайные числа в большом диапазоне на js?

    @Sumor
    2^256 это примерно 78 десятичных знаков
    Берёте криптоалгоритм на 256 бит: можно AES, а можно и SHA256 (вам же не расшифровывать). Берёте инициализирующее значение - считаете значение - вот вам 256 почти случайных бит. Прибавляете к инициализирующему значению какое-либо другое - получаете следующее, и тд
    Ответ написан
    Комментировать
  • Есть идеи как можно оптимизировать алгоритм по комбинаторике?

    @Sumor
    Всё сводится к классическим задачам оптимизации. Скорее всего ваша задача очень похожа на задачу об укладке рюкзака.
    Решается, скорее всего, динамическим программированием или ветвями и границами.
    Ответ написан
    1 комментарий
  • Какой алгоритм применить, что бы передавать что одно лучше другого и в итоге получить таблицу?

    @Sumor
    Теорема о невозможности доказывает, что полностью справедливую систему построить невозможно. Нужно, учитывая предметную область, рассмотреть различные варианты обобщения коллективных оценок и выбрать наиболее удобную или подходящую.
    Неплохая статья на хабре с некоторыми способами ранжирования.
    Ответ написан
    1 комментарий
  • Как проверить в данной задаче можно ли делить чисто на 3 последнюю цифру?

    @Sumor
    Формулировка задания, я бы сказал очень неточная, но отвечаю так как я её понял.
    "Нужно найти разбиение стоимости на пяти- и трёхкопеечные монеты без остатка"
    Для стоимости более 15 копеек такое разбиение всегда можно найти. Для цены до 15 копеек возможность разбиения находится перебором.
    Для определения минимального количества трёхкопеечных монет смотрим на остаток деления на 5:
    остаток 0 - 0 (или 5) трёхкопеечных монет
    остаток 1 - 2 трёхкопеечных монеты
    остаток 2 - 4 трёхкопеечные монеты
    остаток 3 - 1 трёхкопеечная монета
    остаток 4 - 3 трёхкопеечные монеты
    Количество пятикопеечных монет считаем исходя из количества трёхкопеечных.

    NB: трёхкопеечные, а также пятикопеечные монеты пишутся вместе. Если вы пишите количество монет и не хотите склонять их названия, пишите количество после наименования: трёхкопеечных монет - 5.
    Ответ написан
    Комментировать
  • Как найти доступные множители числа?

    @Sumor
    Если вам не нужны множители, а нужна лишь проверка на составное число, то можно воспользоваться тестом Ферма.
    Подробнее статья на Хабре: Алгоритм проверки на простоту за O (log N)
    Ответ написан
    Комментировать
  • Как сравнить произвольные фигуры?

    @Sumor
    Прежде чем сравнивать нарисованные круги с эталонным, нужно определиться с мерой по которой вы будете сравнивать. Возможные варианты мер:
    1. Радиус.
    2. Площадь.
    3. Расположение центра
    Про расположение центра вам уже написали.
    Площадь можно посчитать в точках, расположенных внутри нарисованной фигуры (Цикл по x и y - проверяете принадлежность точки нарисованной фигуре).
    Для подсчёта радиуса нужно выбрать количество разбиений круга - 360, 100, 50 и подсчитать отклонение (линейное, квадратичное или любое подходящее) радиуса по указанным направлениям. В простейшем случае можно просто подсчитать максимальный и минимальный радиус нарисованного круга и сравнивать их.
    Ответ написан
    Комментировать
  • Принадлежность точки октанту?

    @Sumor
    Примерно так:
    k = (((uint)x&0x80000000) >> 31) | (((uint)y&0x80000000) >> 30) | (((uint)y&0x80000000) >> 29);

    Нумерация не совпадает с предложенной по ссылке, но точки из одного октанта будут сопоставлены одному числу от 0 до 7.
    Ответ написан
    Комментировать
  • Какая точность должна быть, чтобы избежать погрешности при пересчёте?

    @Sumor
    Ну для начала если у вас слагаемые amount имеют точность 0,01, то сумма (в предельном случае) будет иметь точность до 0,01*N, где N - количество слагаемых. У нас конечно есть центральная предельная теорема, которая говорит, что в среднем худшего случая не будет и матожидание суммы будет сумма слагаемых, но всё равно точность суммы будет хуже (больше), чем 0,01.

    Производя операцию
    percent[i] = amount[i] * 100 / Sum
    amount[i] имеет точность 0,01, Sum - 0,01*N
    Считаем точность вычислений percent: она получается от 0,01*100/(Sum + 0,01*N) до 0,01*100/(Sum - 0,01*N)
    Если пренебречь точностью Sum, и сумма у вас меньше 100, то погрешность будет точно больше 0,01 - отсюда несовпадение обратных преобразований.

    Методика тут указана примерная, насколько я помню математическое образование :)
    Точность в данном случае немного неверный термин. Ищите по словосочетанию "расчёт погрешности"
    Ответ написан
  • Какой хеш лучше получать у файла?

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

    @Sumor
    Самое главное, что в классическом морском бое, если расставлять корабли начиная с 4-х палубного, затем два 3-х палубных, затем три 2-х палубных и четыре однопалубных, то всегда существует расстановка кораблей. Это легко доказуемо. Если вы начнёте с однопалубных, то можете попасть впросак.
    Четырёхпалубный ставится выбором направления - горизонталь/вертикаль и выбор начальной клетки - всего 140 вариантов.
    Помечаете занятые клетки, клетки вокруг корабля и приступаете к трёхпалубным.
    Пробегаете незанятые клетки и пытаетесь проверить возможность поставить корабль по горизонтали или вертикали. Сохраняете в массив все возможные варианты, а затем выбираете один случайным образом.
    Повторяете пока не будут расставлены все корабли. Доказательство существования расстановки гарантирует, что у вас всегда будет место, куда поставить корабль.
    Ответ написан
    Комментировать
  • Как перекодировать string из Windows 1251 в UCS-2 (алгоритм)?

    @Sumor
    В Delphi есть специальный тип - WideString, который соответствует указателю на строку UTF-16.
    Для перевода используется функция StringToWideChar.
    Есть ещё WinApi функция MultiByteToWideChar.
    Ответ написан
  • Эмулятор для разработки алгоритмов диспечеризации?

    @Sumor
    Есть готовые языки моделирования с помощью которых можно быстро смоделировать различные процессы теории массового обслуживания. Рисуете схемку, задаёте параметры, запускаете, получаете результаты, изменяете параметры, запускаете, получаете результаты и тд, потом обобщение результатов.
    У каждого языка есть ограничения, нужно смотреть и пробовать.
    Смотрите, например, GPSS, Simulink
    Ответ написан
    Комментировать