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

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Для начала простой случай, где вероятность линейна на всём диапазоне, один сегмент.
    Генератор случайных чисел даёт дробное от 0 до 1 с постоянной вероятностью.

    Теперь вспомните график параболы y = x^2 Там на шаге x от 0 до 1, y растет от 0 до 1, на шаге от 3 до 4 y растёт уже от 9 до 16, на 7. Взяв равномерно-случайную величину от 0 до 16, квадратный корень из неё неравномерно попадёт на диапазон от 0 до 4. Вероятнее на диапазон 3-4, чем на 0-1. И вероятность попадания в точку x будет прямо пропорциональна x.

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

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Число цифр в числе получается округлением в большую сторону отношения натурального логарифма этого числа к натуральному логарифму от 10: ceil( ln(x) / ln(10)) Специальный случай "единица" – для нее логарифм даст 0, поэтому длину единицы в квадрате приплюсуем вручную )

    Можно завести счетчик длины последовательности и переменную для текущего числа. Начиная от 1 накапливать в счетчике суммарную длину последовательности, прибавляя число цифр в очередном квадрате.

    Когда последовательность наберёт как минимум данное K, текущее значение в квадрате содержит искомую цифру. Разность длины набранной последовательности и K определит, какую именно цифру этого квадрата взять.
    Ответ написан
    Комментировать
  • Алгоритм выборки топ 10 фотографий?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Посмотрите алгоритмы сортировки. Например, методом пузырька придётся до 10 раз пройти по всему массиву, итого 199+198+197+...+189 = 2123 сравнений.

    Но т.к. интересует только верхушка, можно оптимизировать. Разбить фотогрфии на пары, сравнить попарно, отбросить проигравших. Так уменьшается вдвое число кандидатов. 200 -> 100 -> 50 -> 25 -> 13 за 100+50+12=162 сравнения. Оставшиеся 13 надо уже пузырьковым методом отсортировать до отбора топ-10: 12+11+10+...+3 = 75
    Итого всего 237 сравнений, если не ошибаюсь.

    В фильме «Социальная сеть» (2010) есть эпизод, где молодой Цукерберг якобы использовал алгоритм начисления шахматного рейтинга ELO в своём первом приложении FaseMash для сравнения, какая из девушек привлекательнее. Там тоже посетители выбирают одну из двух фотографий. Может ли это сократить число необходимых сравнений, вопрос открытый.
    Ответ написан
    4 комментария
  • Сгенерировать M уникальных случайных чисел в диапазоне от 1..N. Быстрый алгоритм есть?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Нужна функция биективной (1:1) проекции упорядоченных чисел от 1 до N на такой же диапазон.

    Самый простой пример, чтобы понятно представить идею, это зеркалирование порядка битов в числе:
    0 000 -> 000 0
    1 001 -> 100 4
    2 010 -> 010 2
    3 011 -> 110 6
    4 100 -> 001 1
    5 101 -> 101 5
    6 110 -> 011 3
    7 111 -> 111 7

    Теперь, чтобы получить очередное случайное, просто берите подряд следующее.

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

    Так не придётся хранить, перемешивать, генерировать случайные. Для "псевдослучайности" можно варьировать функцию. Например, не зеркалить порядок битов, а перемешивать биты как-то иначе. Каждый вариант перемешки битов создаёт новый «перемешанный массив» всех возможных значений.

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

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Интуиция
    Представьте, что у вас барабан рулетки, и шарик равновероятно попадает на любой сектор.
    Чтобы на таком реализовать вашу задачу, нужно на числа от А до X выделить по 1 ячейке.
    И на числа от X до B, на каждое, выделить не по 1, а по F ячеек.

    Реализация
    Длина "рулетки" получается (X-A) + F * (B-X)
    Получите случайное целое на этом диапазоне. Если оно попало выше X, остаётся поделить на F разницу выпавшего числа и X.
    Ответ написан
    Комментировать
  • К каким задачам относится описанная мной, и какими алгоритмами можно ее решить?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    По периметру каждой фигуры должна идти дорога? Может, её сразу учесть и «растолстить» каждую фигуру на пол-клетки? А далее решать как и раньше )
    Ответ написан
    4 комментария
  • Как сделать рандом из массива с указанной вероятностью для элементов?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Сложить все веса. Их сумма это 100%, «единица».
    Взять случайное число от 0 до 1.
    Спроецировать на ваш диапазон, посмотреть, куда попали.

    $sum = array_sum($a);
    $rnd = rand() / getrandmax(); // от 0 до 1
    $runningSum = 0;
    foreach($a as $k => $v) {
      $runningSum += $v / $sum;
      if ($runningSum >= $rnd) {
        $key = $k;
        break;
      }
    }
    if (!$key) $key = $k;
    
    echo "Выпало: " . $key . PHP_EOL;
    Ответ написан
    5 комментариев
  • Как найти связные области в 3D?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Вроде бы, тут почти нечего читать по теме.
    Представьте кубик Рубика 3х3х3 со всеми внутренними кубиками.
    Каждый кубик это 1 или 0.

    Надо найти индексы связанных областей ("островов") из единичек.

    на пальцах
    Для плоского 2D и размера 5х5 например это могло бы выглядеть так:
    YX| 0 1 2 3 4
    --|-----------
    0 | 0 1 0 0 1
    1 | 1 1 0 1 1
    2 | 1 0 1 1 0
    3 | 0 1 1 0 0
    4 | 0 0 1 0 0


    Ячейки считать связанными, если не по диагонали, а точно сверху, снизу, справа или слева есть еще одна с 1. На примере выше две области связанны (нумерация слева направо и сверху вниз):
    [(1,0), (0,1), (1,1), (0,2)],
    [(4,0), (3,1), (4,1), (2,2), (3,2), (1,3), (2,3), (2,4)]


    В 3D добавляется третье измерение, третья ось для поиска соседей, третья координата.

    Про двухмерный поиск связных областей на Хабре.
    Адаптация к 3D, алгоритм маппинга координат в одномерный массив и оптимизация – на вашей совести.
    Ответ написан
    3 комментария
  • Алгоритм поиска пустых прямоугольников?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Вроде бы, всё просто. Никакой NP-полноты.
    1. Разбить, как вы и описали, по гайдам на мелкие. Это максимальное число полигонов.
    2. Взять любой, и начать присоединять к нему смежные, насколько возможно.
    3. Взять следующий пустой не затронутый.
    4. Процесс останавливается, когда больше ни к одному 4-угольнику нельзя присоединить еще один.

    Поверхностно кажется, что так получится наименьшее возможное число. Хотя не гарантируется максимизация площадей. Хотя, пожалуй, такой подход может не найти оптимальный вариант, когда границы нескольких исходных блоков легли точно на одной линии. Тогда выиграет вариант, захватывающий обе пустоты. Представьте силуэт буквы «Т». Его можно замостить всего двумя прямоугольниками. Но алгоритм может прозевать такую возможность и предложить 3 блока.

    Представьте себе Г-образный набор блоков. Как ни крути, там не менее 2 в итоге получится. Заметьте, что в обоих вариантах у вас получилось по 9 прямоугольников.

    П.2 подробнее. Тут возможны разные стратегии. В частности:
    • Можно от блока «пойти» в одну сторону, присоединяя соседей, пока не упрётся в непустую область. Затем попытаться расшириться во вторую сторону всеим набранными блоками, до упора. Затем в третью и четвертую.
    • Можно идти спиралью. 1 шаг наверх, 1 шаг вправо, 1 шаг вниз, 1 шаг влево и т.д. пока подряд 4 шага ни один не даст прироста.
    Ответ написан
  • Как реализовать алгорим задачи о сумме подмножеств?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Необязательно же искать оптимальный (кратчайший) набор, дающий нужную сумму?

    Предлагаю от простого к сложному двигаться:
    1. проверить каждое из N на остаток деления S % n = 0 Вдруг, найдётся число, которое надо просто повторить m раз, чтобы получить S
    2. проверить каждую пару чисел из N на разницу: если найдётся разница в 1, можно получить любое число через эти два
    3. проверить каждую тройку чисел из N Подзадача та же, получить 1. Есть 1 – есть любое целое.
    Ответ написан
    2 комментария
  • Зачем давать право выбора машине?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Эксперимент Машины Морали – пока чисто теоретический, и имеет больше отношения к исследованию общества, чем к воплощению в железе.

    Поэтому прямой ответ: машине выбор никто и не даёт.
    Ответ написан
    Комментировать
  • Как ускорить работу скрипта?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    В начале у ребят только деньги. В конце 1 пустая бутылка и весь выпитый напиток без посуды.
    Начальное кол-во денег минус P делится без остатка на (F - P)

    Работающее решение на JavaScript
    function f(F, P) {
      const D = F - P; // стоимость напитка без посуды
    
      // сколько останется денег если 1 раз купить, выпить и сдать?
      function drink(m) {
        const n = Math.floor(m / F);
        if (n <= 0) throw "Nope";
        return m - n * D;
      }
      
      for( let M = P + D * Math.ceil((F + 1) / D); M <= D * Math.floor(2 * 109 / D); M += D) {
        try {
          if (F === drink(drink(drink(drink(M))))) return M;
        } catch(e) {
          continue;
        }
      }
    }
    
    f(7, 3) // 83
    spoiler
    import math
    
    F,P = map(int, input("Введите два целых через пробел:").split())
    
    
    def bruteforce(F, P):
        D = F - P
        
        def drink(m):
            n = math.floor(m / F)
            if 0 == n:
                raise Exception()
            return m - n * D
    	
    
        for M in range(P, int(1e9), D):
            try:
                rem = drink(drink(drink(drink(M))))
                if (F == rem):
                    return M
            except Exception as E:
                pass
                
        return "Нет решения"
    
    print(bruteforce(F, P))
    Ответ написан
    9 комментариев
  • Как найти "стабильность/колебание" последовательности?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    «Стабильностью» считаем точное попадание данных в одну из предопределённых функций - линейную, периодическую? Могут ли быть другие варианты «стабильности» ?

    Можно проверять каждую из гипотез [ a*x + b, a*sin(b*x) + c] на данных, подбирая коэффициенты, минимизируя отклонения. Посчитать сумму квадратов отклонений данных от теории, сделать вывод, попадает идеально или нет.

    См. Регрессионный анализ
    Ответ написан
    Комментировать
  • Существует ли быстрый алгоритм проверки пересечения линии полигона с собой?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Известны ли какие-то особенности полигона, или каждая следующая вершина может оказаться где угодно?

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

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Ответ написан
    Комментировать
  • Как из набора голосов в голосовании получить рейтинг?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Рейтинг = Нижняя граница доверительного интервала Вильсона (Wilson) для параметра Бернулли


    https://habr.com/company/darudar/blog/143188/
    Ответ написан
  • Как масштабировать произвольный многоугольник?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Масштабирование происходит относительно выбранной точки, центра. Из центра проводятся векторы в каждую из вершин многоугольника. Длина каждого вектора умножается на k. При умножении на 0, многоугольник коллапсирует в эту точку. Или при плавном увеличении k, многоугольник «растет» из этого центра. И располагаться этот центр может где угодно – точка произвольная.

    Вам нужно только решить, где центр.

    Если расположить центр в (0, 0) задача упрощается, т.к. координаты вершин совпадают с векторами в них из центра.

    На JS могла бы быть примерно такая функция, принимающая на вход коэффициент k, массив координат центра и массив массивов координат точек:
    function scale( k, center, points) {
      return points.map( p => p.map( (x, i) => center[i] + k * (x - center[i])));
    }
    
    scale(
      2, // в два раза
      [3, 1], // относительно точки (3,1)
      [ [0,0], [1,1], [3,1], [10,10] ] // этот четырёхугольник
    )
    // [ [-3, -1], [-1, 1], [3, 1], [17, 19] ]

    В любом N-мерном пространстве годится. Сделал живой пример, можно поиграть: клик по полю назначает центр масштабирования
    Ответ написан
  • Можно ли в Фотошопе сделать афинное преобразование по опорным точкам?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Vanishing Point – встроенная фишка в шопе.

    Однажды настраиваете перспективную сетку и потом просто copy-paste изображение и натаскиваете на эту сетку - оно трансформируется под заданную перспективу.
    Ответ написан
    1 комментарий
  • Получение четного числа несколькими способами?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Верно. Способов несколько. Всего бесконечность минус 1:

    Берём любое случайное целое. Умножаем на 2. Это первое чётное.
    Проверяем, что результат не равен половине исходного числа – это единственное исключение.
    Второе чётное – это из исходного вычесть первое.

    Разница двух чётных – число чётное. Неравенство слагаемых мы гарантируем проверкой единственного случая выше.
    Ответ написан
  • Как решить задачу о распределении временных интервалов?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Это типичная задача упаковки (packing problem).

    В «коробку» длиной 100 и шириной K надо впихнуть комплект колбас шириной 1 и разной длины.
    Ответ написан
    Комментировать