Изменение порядка списка в соответствии с условиями - PullRequest
0 голосов
/ 08 ноября 2019

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

Функция presOrder должна принимать два параметра: (1) положительное целое число n, представляющее количество недель презентаций, и (2) списокИмена в порядке, который должен быть сохранен только для первого представления. Функция возвращает список списков для порядка представления на недели;каждый из списков содержит данные имена в полностью рандомизированном порядке, гарантирующем, что имена находятся в другом порядке по сравнению с предыдущей неделей, а каждое имя находится в другом положении по сравнению с предыдущей неделей. Другой порядок означает, что имена до и после на предыдущей неделе не должны совпадать на следующей неделе.

import random
import itertools

def notRandom(lst, plst, no):
    result = True
    for i in range(no-1):
        result = result and (lst[i] == plst[i+1])
    result = result and (lst[no-1] == plst[0])
    if result:
        return True
    result = True
    for i in range(1,no):
        result = result and (lst[i] == plst[i-1])
    result = result and (lst[0] == plst[no-1])
    if result:
        return True
    return False


# My attempt
def presOrder(n, namelst):
    permutation = itertools.permutations(namelst)
    rand = [] + [namelst]
    prev = namelst
    for lst in permutation:
        if not(notRandom(lst, prev, len(namelst))) and len(rand) < n:
            rndom = True
            for i in range(len(namelst)):
                if not(lst[i] == prev[i]):
                    rndom = rndom and True
                else:
                    rndom = rndom and False
            if rndom:
                rand += [lst]
                prev = lst[:]
        else:
            continue
    return rand


names = ['Abi Jones', 'Bob King', 'Carl Llewellyn', 'Danielle McIntosh', 'Earl Newell', 'Frank Olephante', 'George Brown', 'Harry Zephers']

#example
>>> print(presOrder(5, names))
>>> [['Abi Jones', 'Bob King', 'Carl Llewellyn', 'Danielle McIntosh', 'Earl Newell', 'Frank Olephante', 'George Brown', 'Harry Zephers'], ('Bob King', 'Abi Jones', 'Danielle McIntosh', 'Carl Llewellyn', 'Frank Olephante', 'Earl Newell', 'Harry Zephers', 'George Brown'), ('Carl Llewellyn', 'Bob King', 'Abi Jones', 'Danielle McIntosh', 'Earl Newell', 'Frank Olephante', 'George Brown', 'Harry Zephers'), ('Danielle McIntosh', 'Abi Jones', 'Bob King', 'Carl Llewellyn', 'Frank Olephante', 'Earl Newell', 'Harry Zephers', 'George Brown'), ('Earl Newell', 'Bob King', 'Abi Jones', 'Danielle McIntosh', 'Carl Llewellyn', 'Frank Olephante', 'George Brown', 'Harry Zephers')]

Кажется, что код работает (несколько), как есть, но мне нужночтобы проверить это больше. А пока как оптимизировать код для presOrder?

1 Ответ

0 голосов
/ 09 ноября 2019

Мой подход был бы таким:

import random

def test_positions(L1, L2):
    return any(a==b for a, b in zip(L1, L2))

def neighbours(L):
    return [set([a, b]) for a, b in zip(L[:-1], L[1:])]

def test_neighbours(L1, L2):
    return any(nb in neighbours(L2) for nb in neighbours(L1))

def pres_order(n, L):
    result = [names[:]]
#   random.shuffle(result[0])    # only needed for reording first row
    for i in range(1, n):
        result.append(names[:])
        random.shuffle(result[-1])
        while test_positions(result[-1], result[-2]) or test_neighbours(result[-1], result[-2]):
            random.shuffle(result[-1])
    return result

Идея состоит в том, чтобы сначала создать (случайным образом переупорядоченный (перемешанный)) вариант списка имен.
Затем добавитьследующая перемешанная версия - но перемешивайте снова и снова, пока не будут выполнены ваши два требования.
Добавляйте до длины списка == n.

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

Обратите внимание, что функция set в определении соседей будет предотвращать соседние пары имен в соседних строках независимо от их порядка. Если вы хотите запретить только точную копию пары (например, после [...'E', 'G',... ] [...'G', 'E',... ] должно быть разрешено, но [...'E', 'G',... ] нет), вы можете просто оставить установленную функцию в стороне.


Пример:

names = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
for l in pres_order(5, names):
    print(l)

# ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
# ['G', 'B', 'H', 'E', 'C', 'F', 'A', 'D']
# ['H', 'C', 'B', 'A', 'E', 'D', 'F', 'G']
# ['C', 'F', 'E', 'H', 'A', 'G', 'B', 'D']
# ['G', 'H', 'B', 'F', 'D', 'A', 'E', 'C']

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...