Как сгенерировать неповторяющиеся комбинации, меняя только один элемент за раз


Оглавление (нажмите, чтобы открыть):

Генерация сочетаний из N элементов

Сочетания из N элементов по K в лексикографическом порядке

Постановка задачи. Даны натуральные числа N и K. Рассмотрим множество чисел от 1 до N. Требуется вывести все различные его подмножества мощности K, причём в лексикографическом порядке.

Алгоритм весьма прост. Первым сочетанием, очевидно, будет сочетание (1,2. K). Научимся для текущего сочетания находить лексикографически следующее. Для этого в текущем сочетании найдём самый правый элемент, не достигший ещё своего наибольшего значения; тогда увеличим его на единицу, а всем последующим элементам присвоим наименьшие значения.

С точки зрения производительности, этот алгоритм линеен (в среднем), если K не близко к N (т.е. если не выполняется, что K = N — o(N)). Для этого достаточно доказать, что сравнения «a[i] k раз, т.е. в (N+1) / (N-K+1) раз больше, чем всего есть сочетаний из N элементов по K.

Сочетания из N элементов по K с изменениями ровно одного элемента

Требуется выписать все сочетания из N элементов по K, но в таком порядке, что любые два соседних сочетания будут отличаться ровно одним элементом.

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

Может показаться удивительным, но задача генерации сочетаний также непосредственно решается с помощью кода Грея. А именно, сгенерируем коды Грея для чисел от 0 до 2 N -1, и оставим только те коды, которые содержат ровно K единиц. Удивительный факт заключается в том, что в полученной последовательности любые две соседние маски (а также первая и последняя маски) будут отличаться ровно двумя битами, что нам как раз и требуется.

Для доказательства вспомним факт, что последовательность G(N) кодов Грея можно получить следующим образом:

т.е. берём последовательность кодов Грея для N-1, дописываем в начало каждой маски 0, добавляем к ответу; затем снова берём последовательность кодов Грея для N-1, инвертируем её, дописываем в начало каждой маски 1 и добавляем к ответу.

Теперь мы можем произвести доказательство.

Сначала докажем, что первая и последняя маски будут отличаться ровно в двух битах. Для этого достаточно заметить, что первая маска будет иметь вид N-K нулей и K единиц, а последняя маска будет иметь вид: единица, потом N-K-1 нулей, потом K-1 единица. Доказать это легко по индукции по N, пользуясь приведённой выше формулой для последовательности кодов Грея.

Теперь докажем, что любые два соседних кода будут отличаться ровно в двух битах. Для этого снова обратимся к формуле для последовательности кодов Грея. Пусть внутри каждой из половинок (образованных из G(N-1)) утверждение верно, докажем, что оно верно для всей последовательности. Для этого достаточно доказать, что оно верно в месте «склеивания» двух половинок G(N-1), а это легко показать, основываясь на том, что мы знаем первый и последний элементы этих половинок.

Приведём теперь наивную реализацию, работающую за 2 N :

Стоит заметить, что возможна и в некотором смысле более эффективная реализация, которая будет строить всевозможные сочетания на ходу, и тем самым работать за O (Cn k n). С другой стороны, эта реализация представляет собой рекурсивную функцию, и поэтому для небольших n, вероятно, она имеет большую скрытую константу, чем предыдущее решение.

Собственно сама реализация — это непосредственное следование формуле:

Эта формула легко получается из приведённой выше формулы для последовательности Грея — мы просто выбираем подпоследовательность из подходящих нам элементов.

Генерация сочетаний без повторений

Требуется перебрать все комбинации группы символов от A до X где X может быть любой другой буквой.

Пример: дана последовательность ABCD, функция должна выдать AB, AC, AD, BC, BD, CD, ABC, BCD, CDA, ABD (вроде ничего не забыл), т.е. позиция символа в группе не важна — важна лишь уникальность самой группы.

Гуглил в сторону размещений и сочетаний. Но так и не понял что именно из этого мне требуется. Грешен — не учил математику. Умные люди, объясните на пальцах или кодом, буду признателен.

Update: Обычно говорят, — и года не прошло. А вот у меня как раз прошел. Снова понадобилось, в этот раз подошел обстоятельно — вот код на PHP:

2 ответа 2

Предисловие

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

Алгоритм

Если учитывать и одиночные комбинации (A, B, C, D), то таких комбинаций всего 2 n — 1, где n — количество символов в исходной строке.

Допустим, что у нас строка из n символов. То есть, у нас n позиций в строке.

Рассмотрим каждую позицию нулём (0) либо единицей (1). Договоримся ставить 1 на той позиции, на которой мы хотим видеть символ, а 0 на той, на которой не хотим.

Получится примерно следующая строка из n нулей и единиц

Эта строка кодирует комбинацию

А теперь выпишем двоичный набор длиной в n элементов

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

Этот набор (без первого) будет описывать всевозможные комбинации исходной строки.

Пример

Возьмём строку ABCD. В ней 4 символа, а значит, у нас будет 2 4 — 1 = 15 комбинаций.

Выпишем двоичный набор из 4 элементов

И получаем следующие варианты

Если вам не нужны одиночные комбинации, то можете их выбросить 🙂

Для начала — о терминах.
Возьмём для примера новогодние подарки. которых N штук в мешке.
Перестановки — когда эти подарки раскладывают на N полок (порядок важен).
Вариантов: N! .
Размещения — когда их пытаются разложить на M полок (попадают не все, порядок важен).
Вариантов: N! / M! .
Сочетания — когда их пытаются переложить в другой мешок (порядок неважен), в который входит только M штук.
Вариантов: N! / (M!(N-m)!) = CN M .

Судя по постановке задачи (порядок неважен), речь идёт о сочетаниях, причём могут потребоваться либо они все (M = 1. N) либо диапазон в 2-3 элемента.

Программно реализована функция, которая может вызываться с разным числом параметров. Если на входе только массив символов, на выходе — все возможные сочетания. Но можно указать также M (один дополнительный параметр) или диапазон M (параметры from, to ).

Программа на PHP:

Заметим, что в соответствии с формулой бинома Ньютона суммарное число всех перестановок символизирует число (1+1) N . При N=4 это 16, но программа в первом варианте выдаёт 15. Чтобы баланс сходился, надо добавить к перестановкам пустую строку.

Создать список одного элемента, повторенного n раз в Python

Я знаю, что понимание списка сделает это, но мне было интересно, есть ли еще более короткий (и более Питонический?) подход.

Я хочу создать серию списков, все разной длины. Каждый список будет содержать один и тот же элемент e, повторенный n раз (где n = длина списка). Как создать списки, не делая

для каждого списка?

6 ответов

вы также можете написать:

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

тестирование производительности

на первый взгляд кажется это повторение-самый быстрый способ создать список из n одинаковых элементов:

но подождите-это нечестный тест.

функции itertools.repeat на самом деле он не создает список, он просто создает объект, который можно использовать для создания списка, если хотите! Давайте попробуем еще раз, но преобразование в список:

поэтому, если вам нужен список, используйте [e] * n . Если вы хотите лениво генерировать элементы, используйте repeat .

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

создать список одного элемента, повторенного n раз в Python

неизменяемые элементы

для неизменяемых элементов, таких как None, strings, tuples или frozensets, вы можете сделать это следующим образом:

обратите внимание, что это лучше всего использовать только с неизменяемыми элементами (строки, кортежи, frozensets,) в списке, потому что все они указывают на тот же элемент в том же месте в памяти. Я часто использую это, когда мне нужно построить таблицу со схемой всех строки, так что мне не нужно давать отображение один к одному.

Мастер Йода рекомендует:  Как правильно работать с отзывчивыми изображениями

изменяемые элементы

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

в этом контексте подчеркивание-это просто выбрасываемое имя переменной.

если у вас есть только номер, что бы быть:

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

предостережения для использования неизменяемого метода с изменяемыми элементами:

остерегайтесь делать это с изменяемыми объектами, когда вы меняете один из них, они все меняются, потому что они все то же самое

Itertools имеет функцию только для этого:

конечно itertools дает итератор, а не список. [e] * n дает список, но, в зависимости от того, что вы будете делать с теми последовательностей itertools вариант может быть гораздо более эффективным.

как указывали другие, использование оператора * для изменяемого объекта дублирует ссылки, поэтому, если вы измените один, вы измените их все. Если вы хотите создать независимые экземпляры изменяемого объекта, синтаксис xrange является наиболее подходящие для Python способ сделать это. Если вас беспокоит наличие именованной переменной, которая никогда не используется, Вы можете использовать анонимную переменную подчеркивания.

Как получить список уникальных(не повторяющихся) значений?

Представим себе большой список различных наименований, ФИО, табельных номеров и т.п. А необходимо из этого списка оставить список все тех же наименований, но чтобы они не повторялись — т.е. удалить из этого списка все дублирующие записи. Как это иначе называют: создать список уникальных элементов, список неповторяющихся, без дубликатов. Для этого существует несколько способов: встроенными средствами Excel, встроенными формулами и, наконец, при помощи кода Visual Basic for Application(VBA) и сводных таблиц. В этой статье рассмотрим каждый из вариантов.

при помощи встроенных возможностей Excel 2007 и выше
В Excel 2007 и 2010 это сделать проще простого — есть специальная команда, которая так и называется — Удалить дубликаты (Remove Duplicates) . Расположена она на вкладке Данные (Data) подраздел Работа с данными (Data tools)

Как использовать данную команду. Выделяете столбец(или несколько) с теми данными, в которых надо удалить дублирующие записи. Идете на вкладку Данные (Data)Удалить дубликаты (Remove Duplicates) .

Если выделить один столбец, но рядом с ним будут еще столбцы с данными(или хотя бы один столбец), то Excel предложит выбрать: расширить диапазон выборки этим столбцом или оставить выделение как есть и удалить данные только в выделенном диапазоне. Важно помнить, что если не расширить диапазон, то данные будут изменены лишь в одном столбце, а данные в прилегающем столбце останутся без малейших изменений.

Появится окно с параметрами удаления дубликатов

Ставите галочки напротив тех столбцов, дубликаты в которых надо удалить и жмете Ок. Если в выделенном диапазоне так же расположены заголовки данных, то лучше поставить флаг Мои данные содержат заголовки, чтобы случайно не удалить данные в таблице(если они вдруг полностью совпадают со значением в заголовке).

Способ 1: Расширенный фильтр
В случае с Excel 2003 все посложнее. Там нет такого инструмента, как Удалить дубликаты. Но зато есть такой замечательный инструмент, как Расширенный фильтр. В 2003 этот инструмент можно найти в ДанныеФильтрРасширенный фильтр. Прелесть этого метода в том, с его помощью можно не портить исходные данные, а создать список в другом диапазоне. В 2007-2010 Excel, он тоже есть, но немного запрятан. Расположен на вкладке Данные (Data) , группа Сортировка и фильтр (Sort & Filter)Дополнительно (Advanced)
Как его использовать: запускаем указанный инструмент — появляется диалоговое окно:


  • Обработка: Выбираем Скопировать результат в другое место (Copy to another location) .
  • Исходный диапазон (List range) : Выбираем диапазон с данными(в нашем случае это А1:А51 ).
  • Диапазон критериев (Criteria range) : в данном случае оставляем пустым.
  • Поместить результат в диапазон (Copy to) : указываем первую ячейку для вывода данных — любую пустую(на картинке — E2 ).
  • Ставим галочку Только уникальные записи (Unique records only) .
  • Жмем Ок.

Примечание: если вы хотите поместить результат на другой лист, то просто так указать другой лист не получится. Вы сможете указать ячейку на другом листе, но. Увы и ах. Excel выдаст сообщение, что не может скопировать данные на другие листы. Но и это можно обойти, причем довольно просто. Надо всего лишь запустить Расширенный фильтр с того листа, на который хотим поместить результат. А в качестве исходных данных выбираем данные с любого листа — это дозволено.

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

Для этого надо просто в пункте Обработка выбрать Фильтровать список на месте (Filter the list, in-place) .

Способ 2: Формулы
Этот способ сложнее в понимании для неопытных пользователей, но зато он создает список уникальных значений, не изменяя при этом исходные данные. Ну и он более динамичен: если изменить данные в исходной таблице, то изменится и результат. Иногда это бывает полезно. Попытаюсь объяснить на пальцах что и к чему: допустим, список с данными у Вас расположен в столбце А ( А1:А51 , где А1 — заголовок). Выводить список мы будем в столбец С , начиная с ячейки С2 . Формула в C2 будет следующая:
<=ИНДЕКС( $A$2:$A$51 ;НАИМЕНЬШИЙ(ЕСЛИ(СЧЁТЕСЛИ( $C$1:C1 ; $A$2:$A$51 )=0;СТРОКА( $A$1:$A$50 ));1))>
<=INDEX( $A$2:$A$51 ;SMALL(IF(COUNTIF( $C$1:C1 ; $A$2:$A$51 )=0;ROW( $A$1:$A$50 ));1))>
Детальный разбор работы данной формулы приведен в статье: Как просмотреть этапы вычисления формул
Надо отметить, что эта формула является формулой массива. Об этом могут сказать фигурные скобки, в которые заключена данная формула. А вводится такая формула в ячейку сочетанием клавиш — Ctrl+Shift+Enter. После того, как мы ввели эту формулу в C2 мы её должны скопировать и вставить в несколько строк так, чтобы точно отобразить все уникальные элементы. Как только формула в нижних ячейках вернет #ЧИСЛО! — это значит все элементы отображены и ниже протягивать формулу нет смысла. Чтобы ошибку избежать и сделать формулу более универсальной(не протягивая каждый раз до появления ошибки) можно использовать нехитрую проверку:
для Excel 2007 и выше:
<=ЕСЛИОШИБКА(ИНДЕКС( $A$2:$A$51 ;НАИМЕНЬШИЙ(ЕСЛИ(СЧЁТЕСЛИ( $C$1:C1 ; $A$2:$A$51 )=0;СТРОКА( $A$1:$A$50 ));1));"")>
<=IFERROR(INDEX( $A$2:$A$51 ;SMALL(IF(COUNTIF( $C$1:C1 ; $A$2:$A$51 )=0;ROW( $A$1:$A$50 ));1));"")>
для Excel 2003:
<=ЕСЛИ(ЕОШ(НАИМЕНЬШИЙ(ЕСЛИ(СЧЁТЕСЛИ( $C$1:C1 ; $A$2:$A$51 )=0;СТРОКА( $A$1:$A$50 ));1));"";ИНДЕКС( $A$2:$A$51 ;НАИМЕНЬШИЙ(ЕСЛИ(СЧЁТЕСЛИ( $C$1:C1 ; $A$2:$A$51 )=0;СТРОКА( $A$1:$A$50 ));1)))>
<=IF(ISERR(SMALL(IF(COUNTIF( $C$1:C1 ; $A$2:$A$51 )=0;ROW( $A$1:$A$50 ));1));"";INDEX( $A$2:$A$51 ;SMALL(IF(COUNTIF( $C$1:C1 ; $A$2:$A$51 )=0;ROW( $A$1:$A$50 ));1)))>
Тогда вместо ошибки #ЧИСЛО! (#NUM!) у вас будут пустые ячейки(не совсем пустые, конечно — с формулами :-)).

Чуть подробнее про отличия и нюансы формул ЕСЛИОШИБКА и ЕСЛИ(ЕОШ можно прочесть в этой статье: Как в ячейке с формулой вместо ошибки показать 0

Способ 3: код VBA
Данный подход потребует разрешения макросов и базовых знаний о работе с ними. Если не уверены в своих знаниях для начала рекомендую прочитать эти статьи:

  • Что такое макрос и где его искать? к статье приложен видеоурок
  • Что такое модуль? Какие бывают модули? потребуется, чтобы понять куда вставлять приведенные ниже коды

Оба приведенных ниже кода следует помещать в стандартный модуль. Макросы должны быть разрешены.

Исходные данные оставим в том же порядке — список с данными расположен в столбце » А «( А1:А51 , где А1 — заголовок). Только выводить список мы будем не в столбец С , а в столбец Е , начиная с ячейки Е2 :

Sub Extract_Unique() Dim vItem, avArr, li As Long ReDim avArr(1 To Rows.Count, 1 To 1) With New Collection On Error Resume Next For Each vItem In Range(«A2», Cells(Rows.Count, 1).End(xlUp)).Value ‘Cells(Rows.Count, 1).End(xlUp) – определяет последнюю заполненную ячейку в столбце А .Add vItem, CStr(vItem) If Err = 0 Then li = li + 1: avArr(li, 1) = vItem Else: Err.Clear End If Next End With If li Then [E2].Resize(li).Value = avArr End Sub

С помощью данного кода можно извлечь уникальные не только из одного столбца, но и из любого диапазона столбцов и строк. Если вместо строки
Range(«A2», Cells(Rows.Count, 1).End(xlUp)).Value
указать Selection.Value , то результатом работы кода будет список уникальных элементов из выделенного на активном листе диапазона. Только тогда неплохо бы и ячейку вывода значений изменить — вместо [E2] поставить ту, в которой данных нет.
Так же можно указать конкретный диапазон:

Или другой столбец:

Range(«C2», Cells(Rows.Count, 3).End(xlUp)).Value

здесь отдельно стоит обратить внимание то, что в данном случае помимо изменения А2 на С2 изменилась и цифра 1 на 3. Это указание на номер столбца, в котором необходимо определить последнюю заполненную ячейку, чтобы код не просматривал лишние ячейки. Подробнее про это можно прочитать в статье: Как определить последнюю ячейку на листе через VBA?

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

Sub Extract_Unique() Dim x, avArr, li As Long Dim avVals Dim rVals As Range, rResultCell As Range On Error Resume Next ‘запрашиваем адрес ячеек для выбора уникальных значений Set rVals = Application.InputBox(«Укажите диапазон ячеек для выборки уникальных значений», «Запрос данных», «A2:A51», Type:=8) If rVals Is Nothing Then ‘если нажата кнопка Отмена Exit Sub End If ‘если указана только одна ячейка — нет смысла выбирать If rVals.Count = 1 Then MsgBox «Для отбора уникальных значений требуется указать более одной ячейки», vbInformation, «www.excel-vba.ru» Exit Sub End If ‘отсекаем пустые строки и столбцы вне рабочего диапазона Set rVals = Intersect(rVals, rVals.Parent.UsedRange) ‘если указаны только пустые ячейки вне рабочего диапазона If rVals Is Nothing Then MsgBox «Недостаточно данных для выбора значений», vbInformation, «www.excel-vba.ru» Exit Sub End If avVals = rVals.Value ‘запрашиваем ячейку для вывода результата Set rResultCell = Application.InputBox(«Укажите ячейку для вставки отобранных уникальных значений», «Запрос данных», «E2», Type:=8) If rResultCell Is Nothing Then ‘если нажата кнопка Отмена Exit Sub End If ‘определяем максимально возможную размерность массива для результата ReDim avArr(1 To Rows.Count, 1 To 1) ‘при помощи объекта Коллекции(Collection) ‘отбираем только уникальные записи, ‘т.к. Коллекции не могут содержать повторяющиеся значения With New Collection On Error Resume Next For Each x In avVals If Len(CStr(x)) Then ‘пропускаем пустые ячейки .Add x, CStr(x) ‘если добавляемый элемент уже есть в Коллекции — возникнет ошибка ‘если же ошибки нет — такое значение еще не внесено, ‘добавляем в результирующий массив If Err = 0 Then li = li + 1 avArr(li, 1) = x Else ‘обязательно очищаем объект Ошибки Err.Clear End If End If Next End With ‘записываем результат на лист, начиная с указанной ячейки If li Then rResultCell.Cells(1, 1).Resize(li).Value = avArr End Sub

Мастер Йода рекомендует:  Как определить CMS сайта – шпаргалка для начинающих

Способ 4: Сводные таблицы
Несколько нестандартный способ извлечения уникальных значений.

  • Выделяем один или несколько столбцов в таблице, переходим на вкладку Вставка (Insert) -группа Таблица (Table)Сводная таблица (PivotTable)
  • В диалоговом окне Создание сводной таблицы (Create PivotTable) проверяем правильность выделения диапазона данных (или установить новый источник данных)
  • указываем место размещения Сводной таблицы:
    • На новый лист (New Worksheet)
    • На существующий лист (Existing Worksheet)
  • подтверждаем создание нажатием кнопки OK

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

  • выделил диапазон A1:B51 на листе Извлечение по критерию
  • вызвал меню вставки сводной таблицы: вкладка Вставка (Insert) -группа Таблица (Table)Сводная таблица (PivotTable)
    выбрал вставить на новый лист (New Worksheet)
  • назвал этот лист Уникальные сводной таблицей
  • поле Данные поместил в область строк
  • поле ФИО в область фильтра. Почему? Чтобы удобно было выбирать одно или несколько ФИО и в сводной отображался бы список уникальных месяцев только для выбранных фамилий

В чем неудобство работы со сводными в данном случае: при изменении в исходных данных сводную таблицу придется обновлять вручную: Выделить любую ячейку сводной таблицы -Правая кнопка мыши —Обновить (Refresh) или вкладка Данные (Data)Обновить все (Refresh all)Обновить (Refresh) . А если исходные данные пополняются динамически и того хуже — надо будет заново указывать диапазон исходных данных. И еще один минус — данные внутри сводной таблицы нельзя менять. Поэтому если с полученным списком необходимо будет работать в дальнейшем, то после создания нужного списка при помощи сводной его надо скопировать и вставить на нужный лист.

Чтобы лучше понимать все действия и научиться обращаться со сводными таблицами настоятельно рекомендую ознакомиться со статьей Общие сведения о сводных таблицах — к ней приложен видеоурок, в котором я наглядно демонстрирую простоту и удобство работы с основными возможностями сводных таблиц.

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

Tips_All_ExtractUnique.xls (108,0 KiB, 14 458 скачиваний)

Статья помогла? Поделись ссылкой с друзьями!

Как сгенерировать неповторяющиеся комбинации, меняя только один элемент за раз

Добрый День Всем.

Столкнулась с проблемой, которую сама не могу решить. Прошу помощь.

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

Условие- указать название колонок и количество значений в каждой колонке. Например, комбинация будет состоять из одного значения в кол1, двух значений из кол2, двух значений из кол3. Итого, комбинация состоит из 5 значений.

Поиском воспользовалась. Ответа не нашла, т.к. комбинация состоит из неравного количества значений в колонках.

Заранее благодарю за помощь.
Алина

Добрый День Всем.

Столкнулась с проблемой, которую сама не могу решить. Прошу помощь.

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

Условие- указать название колонок и количество значений в каждой колонке. Например, комбинация будет состоять из одного значения в кол1, двух значений из кол2, двух значений из кол3. Итого, комбинация состоит из 5 значений.

Поиском воспользовалась. Ответа не нашла, т.к. комбинация состоит из неравного количества значений в колонках.

Заранее благодарю за помощь.
Алина Алина_

Сообщение Добрый День Всем.

Столкнулась с проблемой, которую сама не могу решить. Прошу помощь.

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

Условие- указать название колонок и количество значений в каждой колонке. Например, комбинация будет состоять из одного значения в кол1, двух значений из кол2, двух значений из кол3. Итого, комбинация состоит из 5 значений.

Поиском воспользовалась. Ответа не нашла, т.к. комбинация состоит из неравного количества значений в колонках.

Заранее благодарю за помощь.
Алина Автор — Алина_
Дата добавления — 12.01.2015 в 19:20

JayBhagavan Дата: Вторник, 13.01.2015, 10:53 | Сообщение № 2

Языком ты или построишь жизнь,или разрушишь ее до основания.Думайте что говорите.(с)А.Хакимов

Ответить

MCH Дата: Вторник, 13.01.2015, 11:23 | Сообщение № 3

Если нужно другое решение, то приложите пример того, что нужно.

Если нужно другое решение, то приложите пример того, что нужно. MCH

Если нужно другое решение, то приложите пример того, что нужно. Автор — MCH
Дата добавления — 13.01.2015 в 11:23

Алина_ Дата: Вторник, 13.01.2015, 20:48 | Сообщение № 4

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

Спасибо за помощь,
Алина

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

Спасибо за помощь,
Алина Алина_

Сообщение МСН, спасибо за полезную ссылку.
В данном случае не подходит, т.к. из каждой колонки выбирается только по одному значению.
Пример отредактировала.

Спасибо за помощь,
Алина Автор — Алина_
Дата добавления — 13.01.2015 в 20:48

MCH Дата: Среда, 14.01.2015, 01:00 | Сообщение № 5

Задачу можно решить на макросах, но даже с такой небольшой выборкой исходных данных получается 450 вариантов генераций (=ЧИСЛКОМБ(3;1)*ЧИСЛКОМБ(6;2)*ЧИСЛКОМБ(5;2))
Каково количество исходных данных?

Если имеется только 5 столбцов с числами, то можно сделать небольшой макрос по составлению всех сочетаний.

Задачу можно решить на макросах, но даже с такой небольшой выборкой исходных данных получается 450 вариантов генераций (=ЧИСЛКОМБ(3;1)*ЧИСЛКОМБ(6;2)*ЧИСЛКОМБ(5;2))
Каково количество исходных данных?

Если имеется только 5 столбцов с числами, то можно сделать небольшой макрос по составлению всех сочетаний. MCH

Сообщение Задачу можно решить на макросах, но даже с такой небольшой выборкой исходных данных получается 450 вариантов генераций (=ЧИСЛКОМБ(3;1)*ЧИСЛКОМБ(6;2)*ЧИСЛКОМБ(5;2))
Каково количество исходных данных?

Если имеется только 5 столбцов с числами, то можно сделать небольшой макрос по составлению всех сочетаний. Автор — MCH
Дата добавления — 14.01.2015 в 01:00

Нерекурсивный алгоритм генерации перестановок

Предлагаемый ниже нерекурсивный алгоритм несколько отличается от изложенных в книге Липского [1] и обнаруженных мной в русскоязычном сегменте интернета. Надеюсь будет интересно.

Кратко постановка задачи. Имеется множество размерности N. Необходимо получить все N! возможных перестановок.
Далее, для простоты, используем в качестве множества целые числа (1..N). Вместо чисел можно использовать любые объекты, т.к. операций сравнения элементов множества в алгоритме нет.
Для хранения промежуточных данных сформируем структуру данных следующего вида:

и заполним ее первоначальными значениями

Номер элемента в массиве masiv будем далее называть уровнем.
В список первого уровня заносим все элементы множества. На первом уровне размерность списка равна N и сам список не изменяется по всему ходу выполнения алгоритма. При первичном заполнении все указатели в массиве устанавливаются на первый элемент в списке.
На каждом следующем уровне его список формируется на основании списка предыдущего уровня, но без одного элемента, который помечен указателем. На предпоследнем уровне (N-2) список содержит три элемента. На последнем уровне (N-1) список содержит два элемента. Список нижнего уровня формируется как список предыдущего уровня без элемента, на который указывает указатель предыдущего уровня.
В результате первичного заполнения получены две первых перестановки.Это общий массив сформированный на верхних уровнях ( 1… (N-2)) из элементов списка на которые указывают указатели.

и из списка последнего уровня- две пары элементов в разном порядке ( два хвостика 1 2 и 2 1)

Все дальнейшие перестановки формируются также, всегда с предпоследнего уровня (N-2),
Порядок получения последующих перестановок состоит в том, что находясь на предпоследнем уровне (N-2) и сформировав две перестановки пытаемся увеличить указатель выбранного элемента на 1.
Если это возможно, то на последнем уровне меняем список и повторяемся.
Если на предпоследнем уровне увеличить указатель не удается (перебраны все возможные варианты ), то поднимаемся до уровня на котором увеличение указателя (перемещение вправо) возможно. Условие окончания работы алгоритма — указатель на первом уровне выходит за N.
После сдвига указателя вправо меняем список под ним и двигаемся вниз до предпоследнего уровня (N-2) также обновляя списки и устанавливая указатели выбранного элемента в 1.
Более наглядно и понятно работа алгоритма представлена на рисунке ниже ( для размерности множества N =5). Номер на рисунке соответствует уровню в описании. Возможно даже, что кроме рисунка для понимания алгоритма ничего и не надо.

Конечно, при реализации алгоритма можно было использовать и обычный двухмерный массив, тем более что для небольших N выигрыш объема памяти ничего не дает, а на больших N мы можем не дождаться окончания работы алгоритма.
Один из способов реализации алгоритма на VBA ниже. Для его запуска можно создать книгу Excel с макросами, создать модуль на вкладке разработчик VB и скопировать текст в модуль. После запуска generate() на Лист1 будут выведены все перестановки.


Как в excel сгенерировать все уникальные комбинации 6-ти цифр (1,2,3,4,5,6)? Спасибо!

имеются ввиду сочетания (т.е. в каждой комбнации 6 неповторяющихся элементов 123456, 234561 и т.д.), без повторений (только уникальные).

На выходе должно получиться 6!=720 комбинаций.

Нашел как это сделать в нете, но нужно как-то в xls

[ссылка появится после проверки модератором]

‘ метод вертикальной прогонки

Private nRow As Long
Private nTotal As Long ‘ счётчик перестановок

Public Sub transposition6()
nRow = 1
nTotal = 0
permut «1», 2
Cells(nRow, 1) = «total permutations generated:» & nTotal
End Sub

Private Sub permut(s As String, nNext As Integer)
If nNext = 7 Then ‘ завершить рекурсию после 6 уровней
Cells(nRow, 1) = s
nRow = nRow + 1
nTotal = nTotal + 1
Exit Sub
End If

Dim i As Integer
For i = 0 To nNext — 1
permut Left(s, i) & nNext & Mid(s, i + 1), nNext + 1
Next i
End Sub

Создать список одного элемента, повторенного N раз

Я хочу создать серию списков различной длины. Каждый список будет содержать один и тот же элемент e , повторенный n раз (где n = длина списка).

Как мне создать списки, не используя понимание списка [e for number in xrange(n)] для каждого списка?

Вы также можете написать:

Следует отметить, что если e — это, например, пустой список, вы получаете список с n ссылками на один и тот же список, а не на n независимых пустых списков.

Тестирование производительности

На первый взгляд кажется, что повтор — это самый быстрый способ создать список с n идентичными элементами:

Но подождите — это не честный тест.

Функция itertools.repeat фактически не создает список, она просто создает объект, который можно использовать для создания списка, если хотите! Попробуйте еще раз, но перейдем к списку:

Итак, если вы хотите список, используйте [e] * n . Если вы хотите генерировать элементы лениво, используйте repeat .

Будьте осторожны, когда повторяющийся элемент является списком. Список не будет клонирован: все элементы будут ссылаться на один и тот же список!

Создание списка отдельных элементов повторяется n раз в Python

Неизменные предметы

Для неизменяемых элементов, таких как None, bools, ints, float, string, кортежи или frozensets, вы можете сделать это следующим образом:

Обратите внимание, что это лучше всего использовать только с неизменяемыми элементами (строками, кортежами, frozensets,) в списке, поскольку все они указывают на один и тот же элемент в одном и том же месте в памяти. Я использую это часто, когда мне нужно создать таблицу со схемой из всех строк, чтобы мне не приходилось давать сильно избыточное сопоставление один к одному.

Изменяемые предметы

Я уже давно использую Python, и никогда не видел ни одного варианта использования, где бы я делал это с изменяемым экземпляром. Вместо этого, чтобы получить, скажем, изменчивый пустой список, набор или команду, вы должны сделать что-то вроде этого:

Подчеркивание — это просто одноразовое имя переменной в этом контексте.

Если у вас есть только номер, это будет:

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

Предостережения относительно использования неизменяемого метода с изменяемыми элементами:

Остерегайтесь делать это с изменяемыми объектами, когда вы меняете один из них, они все меняются, потому что они все один и тот же объект:

foo теперь возвращается:

Но с неизменяемыми объектами вы можете заставить его работать, потому что вы изменяете ссылку, а не объект:

Но опять же, изменяемые объекты не годятся для этого, потому что операции на месте изменяют объект, а не ссылку:

Элементы комбинаторики. Для вычисления вероятности события необходимо уметь рассчитывать число различных комбинаций, т.е

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

Определение. Размещением из различных элементов по элементов называется соединение, которое отличается либо составом, либо порядком своих элементов.

Число размещений обозначается символом и вычисляется по формуле

где , причем 1! = 1, 0! = 1.

Пример 1.2. Сколько трехзначных чисел с неповторяющимися цифрами можно составить из цифр 1,2,3…9?.

Решение. Каждое трехзначное число является размещением из девяти цифр по три. Их число равно .

Определение. Сочетаниями из элементов по элементов называются соединения, которые различаются только составом своих элементов.

Число сочетанийобозначается символом и вычисляется по формуле

Пример 1.3. Сколькими способами можно выбрать 2 детали из ящика, содержащего 10 деталей?

Решение. Т.к. порядок выбора деталей неважен, то взять 2 детали из имеющихся десяти можно способами.

Определение. Перестановками из элементов называются всевозможные соединения из этих элементов.

Число перестановок обозначается символом и вычисляется по формуле

Пример 1.4. В конкурсе выступают 7 участников. Порядок их выступления определяется жребием. Сколько различных вариантов жеребьёвки при этом возможно? Решение. Каждый вариант жеребьёвки отличается только порядком участников конкурса, т.е. является перестановкой .

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Сдача сессии и защита диплома — страшная бессонница, которая потом кажется страшным сном. 8764 — | 7143 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

Методы генерации случайного сочетания

Задача:
Необходимо сгенерировать случайное сочетание из [math] n [/math] элементов по [math] k [/math] с равномерным распределением вероятности, если есть в наличии функция для генерации случайного числа в заданном интервале.

Содержание

Наивное решение [ править ]

Пусть [math]S[/math] — множество из [math]n[/math] элементов, тогда для генерации случайного сочетания сделаем следующее:

  • Шаг 1. Запишем в массив [math]C[/math] числа от [math]1[/math] до [math]k[/math] ,
  • Шаг 2. Выберем случайный номер сочетания [math]r[/math] ,
  • Шаг 3. Применим алгоритм получение следующего сочетания [math]r — 1[/math] раз к массиву [math]C[/math] ,
  • Шаг 4. В [math]C[/math] хранятся номера позиции из [math]S[/math] входящих в случайное сочетание, запишем в [math]C[/math] эти элементы.

Псевдокод [ править ]

  • [math]\mathtt[/math] — массив, в котором находятся все элементы множества [math]\mathtt[/math] .

Сложность алгоритма — [math]O( \cdot n)[/math] .

Решение за время [math]O(nk)[/math] [ править ]

Пусть [math]S[/math] — множество из [math]n[/math] элементов, тогда для генерации случайного сочетания сделаем следующее:

  • Шаг 1. Выберем в множестве случайный элемент,
  • Шаг 2. Добавим его в сочетание,
  • Шаг 3. Удалим элемент из множества.

Эту процедуру необходимо повторить [math]k[/math] раз.

Псевдокод [ править ]

  • [math]\mathtt[/math] — массив, в котором находятся все элементы множества [math]\mathtt[/math] ,
  • [math]\mathtt[/math] — такой массив, что если [math]\mathtt[/math] , то [math]\mathtt[/math] элемент присутствует в множестве [math]\mathtt[/math] ,

Доказательство корректности алгоритма [ править ]

На первом шаге мы выбираем один элемент из [math]n[/math] , на втором из [math]n — 1[/math] [math]\dots[/math] на [math]k[/math] -ом из [math]n — k + 1[/math] . Тогда общее число исходов получится [math]n \times (n — 1) \times \dots \times (n — k + 1)[/math] . Это эквивалентно [math][/math] . Однако заметим, что на этом шаге у нас получаются лишь размещения из [math]n[/math] по [math]k[/math] . Но все эти размещения можно сопоставить одному сочетанию, отсортировав их. И так как размещения равновероятны, и каждому сочетанию сопоставлено ровно [math]k![/math] размещений, то сочетания тоже генерируются равновероятно.

Решение за время [math]O(n)[/math] [ править ]

Для более быстрого решения данной задачи воспользуемся следующим алгоритмом: пусть задан для определенности массив [math]a[/math] размера [math]n[/math] , состоящий из [math]k[/math] единиц и [math]n — k[/math] нулей. Применим к нему алгоритм генерации случайной перестановки. Тогда все элементы [math]i[/math] , для которых [math]a[i] = 1[/math] , включим в сочетание.

Псевдокод [ править ]

  • [math]\mathtt[/math] — массив, в котором находятся все элементы множества [math]\mathtt[/math] ,
  • [math]\mathtt[/math] — функция генерации случайной перестановки.

Доказательство корректности алгоритма [ править ]

Заметим, что всего перестановок [math]n![/math] , но так как наш массив состоит только из [math]0[/math] и [math]1[/math] , то перестановка только [math]0[/math] или только [math]1[/math] ничего в нем не меняет. Заметим, что число перестановок нулей равно [math](n — k)![/math] , единиц — [math]k![/math] . Следовательно, всего уникальных перестановок — [math][/math] . Все они равновероятны, так как была сгенерирована случайная перестановка, а каждой уникальной перестановке сопоставлено ровно [math]k!(n — k)![/math] перестановок. Но [math][/math] — число сочетаний из [math]n[/math] по [math]k[/math] . То есть каждому сочетанию сопоставляется одна уникальная перестановка. Следовательно, генерация сочетания происходит также равновероятно.

Оценка временной сложности [ править ]

Алгоритм состоит из двух невложенных циклов по [math]n[/math] итераций каждый и функции генерации случайной перестановки [math]\mathrm[/math] , работающей за [math]O(n)[/math] по алгоритму Фишера—Йетcа. Следовательно, сложность и всего алгоритма [math]O(n)[/math]

Добавить комментарий