Нужна функция/класс пермутаций

Статус
В этой теме нельзя размещать новые ответы.

satih

Хранитель порядка
Регистрация
19 Сен 2008
Сообщения
401
Реакции
721
Нужна функция пермутаций, есть скажем 100-200 предметов, нужно из них сделать 30-100к пермутаций, без повторов, _максимально_ разных, т.е. не просто подбором последних предметов, когда первые не меняются.

Может кто-то знает про готовый класс работы с пермутациями, или другие решения?
 
Вариантов с пермутациями в сети море, но каждый просто предлагает свою реализацию, так чтоб проверенный класс, вроде не нашел. Подумал такую реализацию, может просто сделать 100к пермутаций один раз (пускай не самым эффективным классом), а потом просто перемешивать 100-200 предметов? т.е. предметы в массив, берем базу из 100к пермутаций индексов, перемешиваем предметы в массиве, и при подставлении индекс -> предмет, получаем псевдо-рандомизацию..
 
В 100 раз проще будет нагенерить рандомом (не все возможные варианты подряд, а сколько-то тысяч полностью случайных) а потом их отфильтровать по "похожести" (прогнать через функцию "каждый-с-каждым", полученный массивчик отсортировать и взять нижнюю часть).
 
PHP:
$item=array(
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0'
);
$length=10;//сколько предметов в пермутации
$count=1000;//соклько пермутаций. указывать не более чем это возможно, иначе поулчится бесконечный цикл
//желательно даже существенно меньше.
//максимум factorial(count($item))/factorial(count($item)-$length)
//для данного случая 3628800

$permutation=array();
while(count($permutation)!=$count)
	{
	$perm=implode(',',array_rand($item,$length));
	if(!isset($permutation[md5($perm)]))
		$permutation[md5($perm)]=$perm;//md5 используется для оптимизации при очень длинных пермутациях
	}

foreach($permutation as $key=>$perm)
	{
	$perm=explode(',',$perm);
	for($i=0,$s=count($perm);$i<$s;$i++)
		{
		echo $item[$perm[$i]].', ';
		}
	echo '<br>';
	}
к сожалению на больших количествах пермутаций использование хеш-массива не столь эффективно, и тормзит все больше и больше.
100к пермутаций из 10-и элементов я просто не дождался
рекомендую для обеспечения уникальности пермутаций использовать HEAP-таблицу MySQL, либо же sqlite_open(':memory:');
на задачах требующих работы с большим количеством уникальных данных это будет в порядки быстрее. допилите сами, надеюсь
 
Спасибо за код, особенно за идею с md5.
Нужно для небольшого скрипта, мускул подключать слишком жирно, скриптик должен работать везде и неосложнять юзера дополнительными требованиями, да и вкладывать в него слишком много нехочу, поэтому думал может есть для такой (скорее всего) популярной задачи готовые решения, все же всем спасибо за помощь.
 
ради интереса оптимизировал для работы без базы:
100к пермутаций из 100 элементов создаются примерно за 5-7 секунд
PHP:
$item=array(
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0',
'item0',
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item0'
);
$length=10;//сколько предметов в пермутации
$count=100000;//соклько пермутаций. указывать не более чем это возможно, иначе поулчится бесконечный цикл
//желательно даже существенно меньше.
//максимум factorial(count($item))/factorial(count($item)-$length)
//для данного случая 3628800

$permutation=array();
do
	{
	for($i=0;$i<$count/10;$i++)
		$permutation[]=implode(',',array_rand($item,$length));
	array_unique($permutation);
	}
while(count($permutation)<$count);
/*
foreach($permutation as $key=>$perm)
	{
	$perm=explode(',',$perm);
	for($i=0,$s=count($perm);$i<$s;$i++)
		{
		echo $item[$perm[$i]].', ';
		}
	echo '<br>';
	}
*/
PS принимаю благодарность как в устной, так и в денежной форме ;)
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху