Рубрики
Без рубрики

Алгоритм случайных сортировки без последовательных повторений

Фон, который я недавно работал над проектом по созданию контента, такого как Instagram … Помечено алгоритмами, питоном, блок -схемой, сортировкой.

Фон

Недавно я работал над проектом по созданию контента, такого как Instagram и Facebook. Существуют различные доступные типы контента, включая фотографии, видео, сообщения в блоге и опросы.

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

Естественно, я начал искать в Интернете, чтобы посмотреть, придумал ли кто -то другой этот алгоритм, но большинство алгоритмов, которые я нашел, были о перетасовке и вообще снятии дубликатов. Я, однако, нашел Вопрос о переполнении стека Примерно ту же идею, но главный ответ не был идеальным решением.

Затем я пошел на доску и взял на себя задачу найти рабочий и относительно оптимизированный алгоритм.

Сделай это сам

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

Проблема: Учитывая список элементов различных типов, создайте рандомизированный список без двух последовательных повторяющихся типов. Пример ввода: [A, A, A, A, B, B, B, C, C, D] Допустимый вывод: [C, A, D, B, A, B, A, C, A, B]

Чтобы решить эту проблему вручную, нам сначала нужно перетасовать список ввода. Предположим это [B, A, C, C, A, A, D, B, A, B] достаточно рандомизирован.

Начиная с первого элемента, B, мы продолжаем идти вправо и проверяем, такой же, как и последний. Первый последовательный повтор произошел в месте, где пункт 4, C. Мы откладываем этот элемент в сторону и продолжаем двигаться вправо. Еще один повторяющийся предмет, а затем найден.

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

Как только мы определили повторяющиеся предметы, мы ищем места между существующими предметами, где они могут поместиться. Окончательный сортированный список – [B, A, C, A, C, A, D, B, A, B] Анкет

Создание блок -схемы

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

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

Мой победный алгоритм начинается с перерыва списка ввода. Затем он создает два пустых списка: список для отсортированных элементов и один для повторяющихся элементов. Далее он переходит через рандомизированный список. Если текущий элемент отличается от последнего элемента, он добавляет его в список отсортированных элементов. В противном случае элемент добавляется в список повторяющихся элементов.

После того, как первая итерация закончилась, она неоднократно проникает через отсортированный список и пытается найти места, где он может разместить повторяющиеся элементы. Когда либо не останется повторяющимися предметами, либо не может найти где -то, чтобы соответствовать им, итерация останавливается, и она возвращает отсортированный список, объединенный с оставшимися повторяющимися элементами.

Превратить его в код

Мой нынешний любимый язык для алгоритмов прототипирования-Python, в первую очередь потому, что он не имеет кудрявых кронштейнов и имеет удобные встроенные функции, такие как random.shuffle () Анкет

import random

def randomize_list(input_list):
    randomized_list = input_list.copy()
    random.shuffle(randomized_list)
    return randomized_list


def get_repeated_items(input_list, type_key):
    repeated_items = []
    pre_sorted_list = []
    last_item = {}
    for item in input_list:
        if last_item and item[type_key] == last_item[type_key]:
            repeated_items.append(item)
            continue
        pre_sorted_list.append(item)
        last_item = item
    return repeated_items, pre_sorted_list

def recycle_repeated_items(repeated_items, pre_sorted_list, type_key):
    sorted_list = []
    last_item = {}
    changed = False
    for item in pre_sorted_list:
        filtered_types = [item[type_key]] + ([last_item[type_key]] if last_item else [])
        eligible_repeated_item = next(filter(lambda t: t[type_key] not in filtered_types, repeated_items), None)
        if eligible_repeated_item:
            changed = True
            repeated_items.remove(eligible_repeated_item)
            sorted_list.append(eligible_repeated_item)
        sorted_list.append(item)
        last_item = item
    return repeated_items, sorted_list, changed

def randomized_non_repeating_sort(input_list, type_key):
    randomized_list = randomize_list(input_list)
    repeated_items, sorted_list = get_repeated_items(randomized_list, type_key)
    repeated_items, sorted_list, changed = recycle_repeated_items(repeated_items, sorted_list, type_key)
    while repeated_items and changed:
        repeated_items, sorted_list, changed = recycle_repeated_items(repeated_items, sorted_list, type_key)
    return sorted_list + repeated_items

Я написал тест ниже, чтобы убедиться, что он работает, и измерить, насколько хорошо он работает под тяжелой нагрузкой:

original_list = [
    {'id': 10, 'type': 'A'},
    {'id': 11, 'type': 'A'},
    {'id': 12, 'type': 'A'},
    {'id': 13, 'type': 'A'},
    {'id': 14, 'type': 'B'},
    {'id': 15, 'type': 'B'},
    {'id': 16, 'type': 'B'},
    {'id': 17, 'type': 'C'},
    {'id': 18, 'type': 'C'},
    {'id': 19, 'type': 'D'}
]

print('Original list:')
print(original_list)

print('Randomized non-repeating list (1 of 1,000,000 tests):')

for _ in range(1,1000000):
    output_list = randomized_non_repeating_sort(original_list, 'type')
    repeated_items = get_repeated_items(output_list, 'type')[0]
    if repeated_items:
        raise Exception('CONSECUTIVE REPEATED ITEM FOUND!')
    if len(output_list) != len(original_list):
        raise Exception('LIST LENGTH MISMATCH!')

print(output_list)

"""
Output:
[{'id': 15, 'type': 'B'},
 {'id': 10, 'type': 'A'},
 {'id': 17, 'type': 'C'},
 {'id': 12, 'type': 'A'},
 {'id': 19, 'type': 'D'},
 {'id': 13, 'type': 'A'},
 {'id': 18, 'type': 'C'},
 {'id': 16, 'type': 'B'},
 {'id': 11, 'type': 'A'},
 {'id': 14, 'type': 'B'}]
"""

Я запустил код с Pycharm Profiler и обнаружил, что для сортировки из 10 пунктов требуется 0,018702 секунды.

Это отличная отправная точка, но определенно есть место для оптимизации!

Этот пост Первоначально был опубликован на Мой блог Где я пишу все о технологии.

Оригинал: “https://dev.to/themreza/random-sort-algorithm-without-consecutive-repeats-4no2”