Может ли кто-нибудь помочь мне проверить этот код Python?

1

Я столкнулся с проблемой, когда хочу написать простой код перестановки,

def permutation(Ori, Curr, used):
  if len(Ori) == len(Curr):
      #print Curr
      return

  for i in xrange(len(Ori)):
      if used[i]:
          continue
      used[i] = True
      Curr.append(Ori[i])
      print Curr,i," after append"
      permutation(Ori, Curr, used)    # further level
      used[i] = False
      print Curr,i," before delete"
      Curr = Curr[0:-1]               # Curr.pop() works
      print Curr,i," after delete"
  return

if __name__ == "__main__":
  used = [False]*3
  Curr = []
  permutation([1,2,3], Curr, used)

в то время как результат неверен:

[1] 0  after append
[1, 2] 1  after append
[1, 2, 3] 2  after append
[1, 2, 3] 2  before delete
[1, 2] 2  after delete     <------
[1, 2, 3] 1  before delete <------
[1, 2] 1  after delete
[1, 2, 3] 2  after append
[1, 2, 3] 2  before delete
[1, 2] 2  after delete
[1, 2, 3] 0  before delete
[1, 2] 0  after delete
[1, 2, 2] 1  after append
[1, 2, 2] 1  before delete
[1, 2] 1  after delete
[1, 2, 3] 2  after append
[1, 2, 3] 2  before delete
[1, 2] 2  after delete

Я не знаю, почему у массива есть дополнительный номер на указанном шаге.


Извините, возможно, я не задал свой вопрос, я просто хочу знать причину, почему эта рекурсия вернула список, который, как я предполагал, был сжат. Я написал еще один фрагмент кода, может ли кто-нибудь сказать мне разницу между двумя комментариями? (A = A [0: -1] и A.pop())

def f(A):
     if(len(A) == 10):
         return
     A.append('a')
     f(A)
     print A
 #   A = A[0:-1]                             
 #   A.pop()
     return

 if __name__ == "__main__":
    f([])
  • 1
    вы захотите использовать функцию форматирования кода в stackoverflow ... к сожалению, скорее всего, этот вопрос будет закрыт, прежде чем вы сможете редактировать свой ответ
  • 1
    дополнительно вы можете предпочесть codereview.stackexchange.com; вопросы могут быть закрыты, если они слишком локализованы и не могут помочь другим в подобных ситуациях. Вы можете посмотреть на msmvps.com/blogs/jon_skeet/archive/2010/08/29/… . Во-первых, здесь нет комментариев и спецификаций, поэтому никто не знает, каково ваше намерение относительно функции или параметров.
Показать ещё 6 комментариев
Теги:
algorithm

2 ответа

4

В строке

permutation(Ori, Curr, used)    # further level

вы указываете указатели на списки, а не на копии списков. Выполняя это, когда permutation изменяет Curr, вы видите изменения в вызывающем контексте. Одним из возможных решений является вызов

permutation(Ori, Curr[:], used)    # further level

который передает копию Curr.

Почему работает Curr.pop()?

Потому что он изменяет Curr. Он действительно удаляет элемент из Curr до возвращения функции.

Использование Curr = Curr[0:-1] создает копию Curr без одного элемента. Элемент не удаляется из исходного списка (к которому у вызывающего контекста еще есть доступ). Поэтому практически ничего не происходит, потому что новый список без последнего элемента забывается, как только возвращается функция.

Другим возможным решением было бы не изменять полученный Curr вообще - заменить

Curr.append(Ori[i])

с

Curr = Curr + [Ori[i]]
1

Существует уже функция для создания перестановок:

http://docs.python.org/library/itertools.html#itertools.permutations

Примерный код (определенный в терминах product) - это "обычная" реализация на основе generator- по моему скромному мнению.

В случае, когда полезно подумать, вот код для генерации всех перестановок итерации:

def permutations(iter):
    """
        >>> print(list( permutations(range(3)) ))
        [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
    """
    elements = list(iter)

    # base case
    if len(elements)==0:
        yield []

    for i,elem in enumerate(elements):
        withoutElem = elements[:i]+elements[i+1:]
        for perm in permutations(withoutElem):
            yield [elem]+perm
  • 0
    Спасибо ниндзя, это работает. Но не могли бы вы сказать мне, почему мой код не работает?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню