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

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    В фотокамерах автофокус обращает внимание на несколько контрольных точек кадра: центр, по третям и т.д. Алгоритмы видимо пробуют разные варианты фокусировки и останавливаются на том, что даёт максимум контрольных точек в фокусе.

    Само определение в фокусе / размыто: наличие высокочастотных деталей в исследуемой области. В размытом изображении мелких контрастных переходов нет, все детали крупнее какого-то порога.

    Алгоритм – применить High-pass фильтр к картинке, и смотреть, есть ли что, отличное от серого, и как его много.
    пример

    Выбрал две области на картинке (маленькие зеленые квадраты) – к которым применен high-pass фильтр с радиусом 2px в Photoshop. Результаты рядом и увеличены, в желтых квадратах:
    65b132a196b6c677954361.jpeg
    Ответ написан
    Комментировать
  • Как из массива целых чисел найти все возможные комбинации (не только двух чисел, а и более) дающие искомую сумму?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    задача NP-полная = нужен полный перебор всех возможных комбинаций

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

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

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Ваш алгоритм хорош.
    Лучше «лаконичного» тем, что не занимается сортировкой там, где это не нужно.
    Представьте массив [1, 2, 1000, 1001,...] далее все 100500 элементов больше 1000.
    Совсем незачем сортировать весь этот максимальный хвост между собой, когда интересуют только минимальные значения.

    Вот разбор проблемы поиска двух наименьших значений в массиве. Там ешё предлагается вариант в 2 прохода по массиву: найти наименьшее, и вторым проходом найти наименьшее, большее найденного. Тоже O(n), но можно и за 1 проход, как вы и предложили.
    вариант

    Без пересоздания массива. Держать две переменные, значения, которых по возрастанию. Максимум две проверки условий на итерации.
    const sumTwoSmallestNumbers = arr => {
      let a = arr[0];
      let b = arr[1];
      if (a > b) {
        [a, b] = [b, a];
      }
    
      for (let i = 2; i < arr.length; i++) {
        const v = arr[i];
        if (v < a) {
          b = a;
          a = v;
        } else if (v < b) {
          b = v;
        }
      }
    
      return a + b;
    };
    
    sumTwoSmallestNumbers([55, 44, 1, 99, 2]); // 3
    Ответ написан
    4 комментария
  • Как эффективно и лаконично отсортировать файл из строк не вмещающихся в память?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Отдельные мысли:
    1 Tb / 2 Gb = 500 чисел, не много.

    Сначала собрать массив индексов строк в отсортированном порядке.
    После окончания сортировки записать финальный файл с реальными числами.

    Merge Sort, да, хорош, потому что O(n log n)

    Числа – фикс. размера, поэтому для сравнения двух очередных чисел, читать можно от старших регистров к младшим, до первого различия, которое может наступить уже в первых цифрах.
    Считывать длинные числа можно маленькими блоками, да хоть по байту (нет), пока не наступит различие в пользу одного из двух.

    Все 500 можно считывать маленькими шажками от старших регистров к младшим.
    Считали 500 блоков (по килобайту?) – расставили в порядке.
    Далее считываем следующие блоки только для тех из 500, что на предыдущем сравнении оказались равными.

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

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    выложить монетки игроков в одну линию
    100 + 700 = 800 монеток.
    Выбрать из них любую случайно с равными шансами между монетками.
    Чья это оказалась монетка — тот и выграл!

    Проценты тут не при чём.
    Ответ написан
    4 комментария
  • Как распределить значение по ячейкам примерно равномерно?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Для каждой ячейки известна её оставшаяся до потолка 1 «ёмкость».

    Сложить ёмкости = capacity вместимость всего массива.
    Если X > capacity — «невпихуемо!» — задача не имеет решения.

    Коэффициент k = X / capacity меньше или равен 1.
    Идти по ячейкам, откусывать от X в очередную кусочек, пропорционально ёмкости этой ячейки с коэфф. k.

    Так в каждую доложат пропорционально её ёмкости, сглаживая неравномерность заполнения.
    шесть строк на JS
    const spread = (value, arr) => {
      const CELL_MAX = 1;
      const sum = arr.reduce((acc, c) => acc + c);
      const capacity = arr.length * CELL_MAX - sum;
      if (value > capacity) throw new Error("Value won't fit");
      const k = value / capacity;
      return arr.map(el => el + (CELL_MAX - el) * k);
    }
    
    spread(0.2, [ 0.1, 0.1 ]) // [ 0.2, 0.2 ]
    spread(0.2, [ 0.1, 0.99 ]) // [ 0.29780219780219785, 0.9921978021978022 ]
    Ответ написан
    2 комментария
  • Как однозначно конвертировать цвет из RGB в HSL и обратно, получая один и тот же результат?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    цветовые пространства RGB и HSL не совпадают, поэтому несоответствия неизбежны.

    Например, полностью черному rgb(0, 0, 0) соответствует множество hsl(*, *, 0).

    Хотя например, в этой работе предлагают точный целочисленный метод конвертации: Integer-based accurate conversion between RGB and ... (на англ.). Один из авторов — Владимир Чернов, выпускник Петербургского Политехнического университета.
    Ответ написан
    1 комментарий
  • Как проверить вхождение диапазона дат в определенный диапазон?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    1. ассоциативный массив, где ключи даты, значения обозначают начало это или конец интервала.
    2. отсортировать по ключам
    3. двигаться слева направо, следить чтобы не было два начала подряд.
    Ответ написан
  • Алгоритм максимально равномерного распределения предметов?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Расставить начальные значения на оси.
    Значение указывает на одно или больше «ведёрок» из начального массива, которые надо наполнять.
    Двигаться слева направо, накапливая «вёдра», в которые льём.

    На каждом шаге известно, сколько осталось запаса для разлива.
    Есть «ёмкость» шага – кол-во вёдер умноженное на длину текущего шага.
    Пока запас выше или равен ёмкости – добавляем в текущие вёдра поровну и к следующему шагу.
    Потом, если что-то осталось – разделить поровну, округлив в бОльшую сторону, и по очереди раздавать по актуальным ведёркам.
    JavaScript
    далеко не оптимальный код, но, вроде, рабочий
    function spread(arr, src) {
      const result = [...arr]; // копия исходного массива
      if (src <= 0) return result;
    
      const axis = {}; // value: [ids of bins]
      arr.forEach((v, i) => {
        if (!axis[v]) axis[v] = [];
        axis[v].push(i);
      });
    
      const keys = Object.keys(axis).sort((a, b) => a - b);
    
      const bins = [...axis[keys[0]]]; // ids of "bins" we're filling
      for (let i = 1; i < keys.length; i++) {
        const currentKey = keys[i];
        const prevKey = keys[i - 1];
        const diff = currentKey - prevKey;
        const capacity = bins.length * diff;
        
        if (src < capacity) break;
    
        bins.forEach(key => result[key] += diff);
        src -= capacity;
        bins.push(...axis[currentKey]);
      }
    
      if (src) {
        const want = Math.ceil(src / bins.length);
        bins.forEach(key => {
          const given = Math.min(src, want)
          result[key] += given;
          src -= given;
        });
      }
    
      console.log(result);
      return result;
    }
    
    spread([30, 50, 350], 300); // [ 190, 190, 350 ]
    spread([30, 50, 350], 1001); // [ 477, 477, 477 ]
    spread([130, 50, 50, 101], 800); // [ 282, 283, 283, 283 ]
    Ответ написан
  • Массовое сравнение сток, поиск пересечений, каким инструментом воспользоваться?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    примерно объёмы инфы:
    100к слов (по 10 символов) в «первом множестве» — это примерно 1Mb
    150к текстов по 50 слов по 10 символов в слове это 75Mb
    Т.е. всё весьма компактно.

    Искать наверное стоит программой, в оперативке.

    Сначала проиндексировать тексты. Составить словарь, где ключ – слово, значение – массив индексов текстов, где оно встречается.

    Затем искать среди ключей этого словаря слова из первого множества.

    Можно ещё сократить/ускорить, если работать не с самими словами, а только с целыми индексами. Любое слово класть в Set (где значения уникальны) и далее работать с индексом слова в этом наборе.
    Ответ написан
    2 комментария
  • Как называется задача или алгоритм выявляния из заданного набора тех прямоугольников, которые больше всего не подходят для замощения заданной области?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Задача о замощении в общем случае же NP-полная, решается полным перебором всех вариантов.

    Ну и как уже подсказали: нужна функция оценки варианта замощения.
    Ответ написан
    Комментировать
  • Как найти максимально похожий цвет?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Самое простое — считать сумму квадратов расстояний по каждому из компонентов: R, G и B.

    Для пары 0000DD, 0000C8 «расстояние» будет такое:
    (0x00 - 0x00)^2 + (0x00 - 0x00)^2 + (0xDD - 0xC8)^2 = 441
    Так посчитать до каждого из определённых цветов, найти минимум.

    Можно сравнивать в других цветовых моделях. Например, в HSV (оттенок, насыщенность, яркость) — если посчитаете, что насыщенный красный и тусклый красный точно того же оттенка «ближе», чем той же яркости оранжевый. Речь о возможно разных «весах» каналов в деле определения близости двух цветов.
    Ответ написан
    Комментировать
  • Какой алгоритм вычисления кратности чисел более эффективен?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Цикл последовательности = 3 * 5 = 15

    Можно рассчитать или захардкодить повторяющийся блок, и копировать его, добавляя i * 15, где i = 0, 1, 2, ..

    В последнем блоке придется искать, на каком элементе остановиться.
    Ответ написан
    3 комментария
  • Алгоритм поиска минимального количества ходов, требуемых для приведения всех элементов к одному числу (Python)?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Визуально можно представить: на плоскоть бросили случайно кучку точек )
    Оси X и Y, приём X не важен в данном случае. Y – значения в массиве.

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

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

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Линейная регрессия
    Ответ написан
    Комментировать
  • Какой алгоритм для вычисления оптимальной задержки для API и сообщения её ПО пользователя, чтобы не генерировать лишнюю нагрузку?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Сервер получает запросы 2 типов: Hit (если для него есть задача) и Miss (когда стукнулся, а заданий нет).
    • Штраф запросу Hit – время, которое появившаяся задача ожидала запроса.
    • Штраф запросу Miss – порядковый номер этого холостого запроса от этого клиента - 1 (1-й запрос бесплатно : )

    Задания поступают случайно и непредсказуемо. Исполнители подключаются тоже случайно и непредсказуемо.

    Вопрос как минимизировать штрафы.

    Маловато данных.

    Я бы делал задержку случайной величиной с нелинейным распределением. Вероятнее всего малая задержка, и по экспоненте уменьшается вероятность задержек более длинных.
    График
    602ff598991c9802769845.png
    Или, половина «шляпы» нормального распределения:
    602ff62996122863074501.gif

    Параметр, которым рулить (и рулить очень плавно) — крутизна этой экспоненты распределения.

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

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    С краями ошиблись: 3 бита (3 вопроса) — это числа от 0 до 7.
    Каждым вопросом уточняется бит, от старших к младшим:
    0  000
    1  001
    2  010
    3  011
    4  100 - четыре?  - больше (старший бит 1xx )
    5  101
    6  110 - шесть? - больше ( 11x )
    7  111 - семь – ага
    Ответ написан
    4 комментария
  • Название алгоритма для генерации не похожих смиволов?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    При генерации кодов используют алфавит, лишённый похожих символов.
    Исключены и буквы, похожие на цифры, и цифры, похожие на буквы.

    Например: 3479BDFGHJKLMNPRSTWXZ

    См. также: Homoglyph
    Ответ написан
    Комментировать
  • Как упорядочить очередь из разных групп?

    sergiks
    @sergiks Куратор тега Алгоритмы
    ♬♬
    Арифметика расставит элементы каждой группы отдельно на отрезке.
    a   a   a
    b   b   b
    c c c c c c

    Найти длину самой длинной группы. Делить её на длину очередной группы — получится шаг для группы.
    Назначить каждому элементу свойством его положение на «отрезке».
    Сложить все в один массив и отсортировать по этому положению.

    Результат недетерменирован. Скажем, в этом примере на позиции 0 сразу три элемента: a, b и c. Какой из них будет на котором из трёх первых мест – ничем не определено.

    реализация на JS
    const groups = {
      A: ['a', 'a', 'a',],
      B: ['b', 'b', 'b', 'b',],
      C: ['c', 'c', 'c', 'c', 'c', 'c',],
    };
    
    const longest = Math.max.apply(null, Object.values(groups).map(a => a.length));
    const sortMe = [];
    for (let p in groups) {
      const values = groups[p];
      const step = longest / values.length; // 1 and bigger
      values.forEach((v, i) => sortMe.push({w: i * step, v: v}));
    }
    
    sortMe.sort((a, b) => a.w - b.w);
    
    const result = sortMe.map(el => el.v);
    
    console.log(result);
    // ["a", "b", "c", "c", "b", "a", "c", "b", "c", "a", "c", "b", "c"]
    Ответ написан
    3 комментария
  • В каком направлении решить Алгоритмическую задачу?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Напишите программу

    Написать не только функцию. «Оно» должно уметь читать и писать локальные файлы.

    [b][b][/b] --> [b]<b></b>
    Искать пары открывающих-закрывающих изнутри наружу.

    Для «вдохновения» можно найти готовые реализации MarkDown parser'ов на JS.
    Ответ написан