Ответы пользователя по тегу Алгоритмы
  • Составить алгоритм перебора вариантов с весом?

    @dimoff66
    Кратко о себе: Я есть
    Если перестановки не нужны, то все просто. Каждый элемент либо входит в следующий вариант, либо нет. Соответственно делаете цикл 1 до pow(2, count($arr)). Преобразовываете каждое число цикла в двоичное встроенной функцией decbin, переворачиваете результат, и по нему составляете новый вариант - если 1 на соответствующем месте возвращенной decbin строки, то включаете элемент, если 0, то исключаете.

    $arr = [0 => 'a', 1 => 'b', 2 => 'c'];
    $res = [];
    
    for ($i = 1; $i < pow(2, count($arr)); $i++ ) {
        $bin = decbin($i);
        $case = "";
        foreach(str_split(strrev($bin)) as $ind => $symb) if ($symb == "1") $case .= $arr[$ind];
        $res[] = $case;
    }
    
    echo implode(", ", $res); // a, b, ab, c, ac, bc, abc
    Ответ написан
    Комментировать
  • Как извлечь объекты из массива в новый объект?

    @dimoff66
    Кратко о себе: Я есть
    let customKeys 
    const items = Array.from(['custom', 'default']).flatMap(group => {
      const scope = group + "Data"
    
      // Собираем элементы группы
      const items = (data[group] || []).flatMap(({ id, links }) => 
        links.map(link => ({...link, id, scope }))
      )
    
      const getKey = v => JSON.stringify([v.id, v.number])
    
      if (!customKeys) {
        // индексируем ключи кастомных элементов
        customKeys = items.reduce((agg, v) => 
          Object.assign(agg, {[getKey(v)]: v})
        , {})
    
        return items 
      } else {
        // Для ключей, найденных ранее, устанавливаем родителя и отфильтровываем
        const defaultIds = []
        const defaultItems = items.filter(v => {
          const child = customKeys[getKey(v)]
          if (child) {
            child.parent = v 
            defaultIds.push(v.id)
          } else {
            return true
          }    
        })
    
        // Оставляем в data.default лишь элементы с id, не найденные в custom
        if (defaultIds.length) {
          const idsSet = new Set(defaultIds)
          const copy = [...data.default]
          data.default.length = 0 
          data.default.push(...copy.filter(v => !idsSet.has(v.id)))
        }
    
        return defaultItems
      }
    })
    
    console.log(data) // Дата без кастомных ключей в дефолт скоуп
    console.log(items) // Результат
    Ответ написан
    1 комментарий
  • Как решить задачу с CodeWars Simple Fun #159: Middle Permutation?

    @dimoff66
    Кратко о себе: Я есть
    Клай, Я написал такой вот алгоритм
    import math
    def middle_permutation(string):
        res, letters = '', sorted(list(string))
        fct = math.factorial(len(letters))
        remained = math.ceil(fct / 2)
        
        while (len(letters)):
            fct /= len(letters)
            cnt = math.ceil(remained/ fct) - 1
            res = res + letters.pop(cnt)
            remained -= fct * cnt 
            if (remained == 0):
                remained = fct
                
        return res


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

    @dimoff66
    Кратко о себе: Я есть
    Основная оптимизация при условии что числа могут быть любого размера - считывать размерность чисел, сохраняя в массив числа с наибольшей на данный момент или считывать их позиции если файл доступен для чтения полностью а не последовательно. Как только найдется число большей разрядности все прочие ранее сохраненные данные можно обнулить без сравнения.

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

    @dimoff66
    Кратко о себе: Я есть
    Интервал известен заранее? Если нет, то сколько чисел будут считаться прогрессией? больше 2?

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

    Например для последовательности 8, 4, 12, 7, 3
    Получаем отсортированный массив 3, 4, 7, 8, 12
    Для 3ки ничего не находим
    Для 4ки проверяем 7: 7 * 2 - 4 = 10 (10 не найдено)
    Для 4ки проверяем 8: 8 * 2 - 4 = 12 (12 есть, значит последовательность найдена)
    Ответ написан
    4 комментария
  • Как получить все возможные перестановки?

    @dimoff66
    Кратко о себе: Я есть
    Переводите изначальный массив в плоский, содержащий все одиночные значения с добавленным флагом check

    $paramsFlat = [
      ['value' => ['option1' => 1], 'check' => 0],
      ['value' => ['option1' => 2], 'check' => 0],
      ...
      ['value' => ['option3' => 2], 'check' => 0],
    ];


    Теперь все что вам нужно - в цикле получить все варианты с check, алгоритмически проще всего это сделать, представив двоичное число с количеством разрядов равное количеству элементов:
    в вашем примере таковых 9, то есть:
    000000001
    000000010
    000000011
    000000100
    ..
    111111111

    Соответственно алгоритм на каждом шаге такой - ищем в $paramsFlat первый элемент с check === 0, меняем его на единицу, а свойство check всех элементов до него обнуляем

    После каждого шага включаете в очередной элемент итогового массива $result только элементы $paramsFlat с check === 1

    Функция получения следующего элемента может выглядеть примерно так (не тестировал и не оптимизировал, но смысл полагаю ясен)

    function getNext($paramsFlat) {
        foreach($paramsFlat as &$elem) {
            // Инвертируем значения до первого найденного нуля
            if($elem['checked'] = !$elem['checked']) break;    
        }
        
        // Получаем массив, содержащий отмеченные элементы
        $retVal = array_filter($paramsFlat, function($v) {return $v['checked'];});
        if(!count($retVal)) return false;
        
        // Возвращаем массив из значений отмеченных элементов
        return array_map(function($v) {return $v['value'];}, $paramsFlat);
    }
    Ответ написан
  • Как отсортировать одномерный массив точек, с учётом расстояния между ними?

    @dimoff66
    Кратко о себе: Я есть
    var sourceList = [11, 14, 15, 17, 27, 28, 32, 52, 53, 54, 55, 56, 57, 75, 90, 97];
       sourceList.sort();
    
       var max_d = 9, K = 4;
       
       var result = [];
       var sequence = [sourceList[0] - max_d];
    
       sourceList.forEach(num => {
          if(num - sequence[sequence.length - 1] >= max_d) {
             if(sequence.length >= K) result = sequence;
             sequence = [];
          }
          sequence.push(num);
       });
       if(sequence.length >= K) result = sequence;
    
       console.log(result);
    Ответ написан
    4 комментария
  • С чего начать изучать алгоритмы?

    @dimoff66
    Кратко о себе: Я есть
    Не нужно никогда и ни при каких обстоятельствах учить алгоритмы. Нужно знать об их существовании и при необходимости подсмотреть. Все необходимые алгоритмы инкапсулированы в методы языков. Вам не нужно знать алгоритмы сортировки, потому что в методах sort языков они реализованы более менее оптимально. Теоретически может возникнуть ситуация, когда необходимо сделать сортировку супербыстрой, но для новчика это вообще не является задачей №1 и даже номер 5.

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

    @dimoff66
    Кратко о себе: Я есть
    Но я Си учил не по учебникам, просто я работаю волшебником...

    ЗЫ Это внутреннее ощущение, оно появляется действительно с опытом, может пройти год или два коммерческой разработки. Ты вдруг смотришь на свой старый код и ясно понимаешь как его оптимизировать. Это магия, этому нельзя научиться.

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

    @dimoff66
    Кратко о себе: Я есть
    function combine($arr, $k) {
       $combs = [];
       $comb = range(0, $k - 1);
       
       while($comb) {
          $combs[] = array_map(function($i) use($arr) {return $arr[$i];}, $comb);
          
          for($i = $k - 1, $max = count($arr) - 1; $i > -1; $i--, $max--) {
             if($comb[$i] < $max) {
                $comb[$i] ++;
                for($j = $i + 1; $j < $k; $j++) {
                   $comb[$j] = $comb[$j - 1] + 1;
                }
                break;
             } 
          }
          if($i < 0) $comb = null;
       }
       
       return $combs;
    }
    
    print_r(combine([1,2,3,4,5], 3));
    Ответ написан
    Комментировать
  • Есть идеи как можно оптимизировать алгоритм по комбинаторике?

    @dimoff66
    Кратко о себе: Я есть
    Родион Альметов,

    1) Сортируем по первому параметру, который "не суть" + по толщине
    2) Проходим циклом по отсортированному массиву, высчитывая для каждого прямоугольника ближайших соседей, НЕ удовлетворяющих условию соседства. Допустим для прямоугольника №5 это будут №2 и №7, значит прямоугольник можно соединить только с номерами 3, 4, и 6.

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

    @dimoff66
    Кратко о себе: Я есть
    Для любой квадратной размерности, длина совпадающих символов регулируется,
    по умолчанию равна длине массива

    function checkWinner(arr, length) {
       length = length || arr.length;
       var winner = [
          arr.map(row=>row.join('')).join(' '),
          arr.map((_,v)=>arr.map(row=>row[v]).join('')).join(' '),
          arr.map((_,v)=>arr[v][v]).join(''),
          arr.map((_,v)=>arr[v][arr.length - v - 1]).join(''),
       ].join(' ').match('1'.repeat(length) + '|' + '2'.repeat(length));
    
       return +((winner || ['0'])[0][0]);
    }
    Ответ написан