Циклические операторы перестановки в python

Мне нужен функционал python (функция, создающая функции), которая создает все операторы циклической перестановки для списка длины N.

Для списка Python a (например, a = [1, 2, 3, 4,5,6], N= 6) можно определить функцию

def cyclic_perm(a):
    n = len(a)
    b = [[a[i - j] for i in range(n)] for j in range(n)]
    return b

это дает вам все возможные циклические перестановки списка, в данном случае 6 списков.

Я хотел бы, чтобы функция давала мне не список, а (в данном случае) 6 операторов, каждый из которых при применении к списку дает один из переставленных списков.

Я не уверен, что означает последнее предложение. Не могли бы вы привести пример?

DeepSpace 16.05.2019 16:55

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

quamrana 16.05.2019 16:57

Также вы можете просто сохранить параметры в словаре. Но, пожалуйста, предоставьте желаемый результат.

Error - Syntactical Remorse 16.05.2019 16:57

Кстати, вам, вероятно, лучше использовать itertools.permutations, чем изобретать велосипед.

DeepSpace 16.05.2019 16:58

Он у вас уже есть lambda a, j: [a[i - j] for i in range(len(a))]. Это функция, которая по заданному списку и смещению возвращает повернутый список.

Dan D. 16.05.2019 16:58

@DeepSpace Вращения не являются перестановками. Они представляют собой подмножество, поддерживающее циклическую смежность.

Dan D. 16.05.2019 16:59

@ДанД. достаточно справедливо, но я уверен, что есть рецепт itertools, который не заставит нас (или ОП) изобретать велосипед :) (не то, чтобы в данном случае это было так сложно...)

DeepSpace 16.05.2019 17:00

обычное определение "циклической перестановки" - это совершенно другое понятие, чем то, о чем вы просите.

user2357112 supports Monica 20.03.2020 22:27
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
5
8
4 354
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете написать функцию, которая возвращает функции:

def cyclic_perm(a):
    n = len(a)
    b = [[a[i - j] for i in range(n)] for j in range(n)]
    return b

def cyclic_perm_func(a):
    n = len(a)
    def wrapper(a, n, j):
        def cyc():
            return [a[i - j] for i in range(n)]
        return cyc
    b = [wrapper(a, n, j) for j in range(n)]
    return b

a = [1, 2, 3, 4,5,6]
print(cyclic_perm(a))  # Your original function
f = cyclic_perm_func(a) # f is now a list of functions
print([g() for g in f])  # Let's call each in turn

Выход:

[[1, 2, 3, 4, 5, 6], [6, 1, 2, 3, 4, 5], [5, 6, 1, 2, 3, 4], [4, 5, 6, 1, 2, 3], [3, 4, 5, 6, 1, 2], [2, 3, 4, 5, 6, 1]]
[[1, 2, 3, 4, 5, 6], [6, 1, 2, 3, 4, 5], [5, 6, 1, 2, 3, 4], [4, 5, 6, 1, 2, 3], [3, 4, 5, 6, 1, 2], [2, 3, 4, 5, 6, 1]]

Обратите внимание на wrapper(), который является способом захвата всех параметров, которые нужны обернутой функции cyc() в каждом экземпляре.

Может быть, немного поздно, но это так невероятно блестяще! Просто нужно было сказать это; действительно впечатляет! Спасибо; это было как раз то, что мне было нужно.

William Martens 02.03.2021 19:41
Ответ принят как подходящий

Я не совсем уверен, какова цель этого упражнения, но вы можете сделать это с частичными функциями.

from functools import partial

def reorder_from_idx(idx, a):
    return a[idx:] + a[:idx]

def cyclic_perm(a):
    return [partial(reorder_from_idx, i) for i in range(len(a))]


a = [1, 2, 3, 4, 5, 6]
result = cyclic_perm(a)
print(result)
#[functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 0),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 1),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 2),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 3),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 4),
# functools.partial(<function reorder_from_idx at 0x00000298D92189D8>, 5)]
result[3](a)
#[4, 5, 6, 1, 2, 3]

Хороший пример частичных функций @ParitoshSingh +1 Думаю, мне нужно больше узнать о них!

Devesh Kumar Singh 16.05.2019 17:22

Вы можете сделать следующее. Вызов функции cyclic_perm в input_list вернет список операторов (функций), которые при вызове в input_list дадут вам желаемый результат.

input_list = [1, 2, 3, 4, 5, 6]


def cyclic_perm(a):
    n = len(a)
    result = []
    for j in range(n):
        def f(l, k=j):
            return list(map(lambda i: l[i - k], range(n)))
        result.append(f)
    return result


for op in cyclic_perm(input_list):
    print(op(input_list))

Я интерпретирую ваш запрос как «учитывая количество циклов n, реализовать функцию, которая принимает n и возвращает функцию, которая при передаче итерируемого объекта возвращает сдвинутые n позиции итерируемого объекта».

Рассмотрим more_itertools.circular_shifts:

Дано

import functools as ft

import more_itertools as mit


iterable = range(6, 10)

Код

def composed_shifts(n):
    """Return a function of `n` circular shifts."""
    def f(x):    
        return ft.partial(mit.circular_shifts(x).__getitem__, n)()
    return f

Демо

composed_shifts(1)                                         # 1
# <function __main__.composed_shifts.<locals>.f(x)>

composed_shifts(1)(iterable)                               # 2
# (7, 8, 9, 6)

composed_shifts(3)(iterable)
# (9, 6, 7, 8)

Подробности

Наша composed_shifts() функция принимает целое число n сдвигов и

  1. возвращает функцию
  2. что при передаче итерации возвращает значение по индексу списка из mit.circular_shifts(). Подробнее см. ниже.

круговой сдвиг — это особый тип циклической перестановки, показанный ниже:

mit.circular_shifts(iterable))

Выход

[(6, 7, 8, 9),                                             # 0 shifts
 (7, 8, 9, 6),                                             # 1   " 
 (8, 9, 6, 7),                                             # 2   " 
 (9, 6, 7, 8)]                                             # 3   "

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

Резюме

  • Сдвиг (индекс) n делится на __getitem__() из mit.circular_shifts()
  • Внутренняя функция fсочиняет последняя частичная функция

Установите эту стороннюю библиотеку через > pip install more_itertools.

Другие вопросы по теме