все способы подходят некоторые колышки в данной дыры


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

Я написал ниже код, чтобы решить проблему, и он работает как задумано. Сокровенные кортежи из ответов соответствует колышек в лунку, т. е. (4, 7) означает поставить Д4 Д7 колышек в лунку, и эти кортежи составляют набор, который представляет как все колышки в.

Я не совсем доволен решением. Это не... достаточно быстро, и он чувствует себя слишком сложным. Есть ли разумный способ пойти об этом?

def fit(pegs, holes):
    for h in holes:
        for p in pegs:
            if p <= h:
                pegs_left = [x for x in pegs if x != p]
                if pegs_left:
                    free_holes = [x for x in holes if x != h]
                    for rest in fit(pegs_left, free_holes):
                        yield frozenset(((p, h),)) | rest
                else:
                    yield frozenset(((p, h),))


def fitted(pegs, holes):
    return sorted(sorted(x) for x in set(fit(pegs, holes)))   

pegs = [2, 4, 7]
holes = [1, 3, 4, 6, 9]

print fitted(pegs, holes)
# [[(2, 3), (4, 4), (7, 9)], 
#  [(2, 3), (4, 6), (7, 9)], 
#  [(2, 4), (4, 6), (7, 9)], 
#  [(2, 6), (4, 4), (7, 9)]]


Комментарии
1 ответ


  1. Я рекомендую использовать одну переменную буквой фамилии, в частности использование П и H.
    Я думаю, что код будет понятнее, если вы используете шпенек и отверстие.

  2. Ваш код будет перерыв, если у вас есть несколько отверстий или колышки одинакового размера.

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

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

У вас есть колышки: 2, 4, 7

Ваша задача-выбрать три отверстия: 1, 3, 4, 6, 9 которые подходят колышки.

itertools.permutations(holes, 3)

будет производить итератор по всем возможным вариантам от 3 отверстия из списка. Что-то вроде:

1 3 4
1 3 6
1 3 9
1 4 3
...

Мы интерпретировать каждое значение в качестве задания отверстий для колышков. Так 1,3,4 означает (2, 1), (4, 3), (7,4). Конечно, не все такие уступки являются допустимыми. Поэтому мы отфильтровать недействительные (т. е. там, где колышки не подходят).

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

Вот моя реализация:

import itertools

def check_fits(pegs, holes):
for peg, hole in zip(pegs, holes):
if peg > hole:
return False
return True

def fit(pegs, holes):
assert len(pegs) <= len(holes)
for selected_holes in itertools.permutations(holes, len(pegs)):
if check_fits(pegs, selected_holes):
yield zip(pegs, selected_holes)

pegs = [2, 4, 7]
holes = [1, 3, 4, 6, 9]

for item in fit(pegs, holes):
print item

модуле itertools.перестановок позволит создать большое количество недопустимое колышки в отверстия. Например, в приведенном выше примере, это будет генерировать значительное количество назначений, которые пытаются соответствовать колышек размер 2 в отверстие в размер 1. Простой рекурсивной функции может не тратить время на так много плохих заданий. Однако модуле itertools.перестановка написан на C, и поэтому, наверное, все-таки имеет преимущество в скорости над такой рекурсивный алгоритм.

6
ответ дан 14 мая 2011 в 05:05 Источник Поделиться