| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | «  : 13-05-2006 13:37 »  |  | 
 
 Помогите запрограммировать такую штуку: вводится число классов, в каждом классе число элементов (например числа). Нужно получить строки заданной длины N из всевозможных перестановок этих чисел. Например, 4 класса, в них 2, 2, 1, 1 элементов: [1,1], [2,2], [3], [4], длина строки =3. Должно получиться: 112113
 114
 121
 122
 123
 124
 131
 132
 134
 141
 142
 143
 211
 212
 213
 214
 221
 223
 232
 234
 241
 242
 243
 311
 312
 314
 321
 322
 324
 341
 342
 411
 412
 413
 421
 422
 423
 431
 432
 Вся проблема в том, что заранее неизвестна длина строки N, и поэтому нельзя сделать просто определенное число вложенных циклов. Помогите пожалуйста!! очень нужно
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #1 : 13-05-2006 15:01 »  |  | 
 
 Litanika, Покажи на пальцах, как ты получил например первое число 112. Что то я никак не могу понять логику. |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | « Ответ #2 : 13-05-2006 15:10 »  |  | 
 
 FinchБеру первый элемент из первого класса, затем если есть там еще элементы, беру еще элемент, если нет, то из следующего. Так последний элемент в строке (третий) перебираю по всем классам. Получилось 112, 113, 114
 Затем откатываюсь на шаг назад, заменяю вторую единицу на 2: 12 и опять прохожу по всем классам, получаю: 121, 122, 123, 124. И т.д. Если в классе не хватает элемента (например 313 не получается, т.к. тройка одна), то эта комбинация пропускается (по идее первой должна была быть строка 111, но единиц только 2)
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #3 : 13-05-2006 15:55 »  |  | 
 
 Т.е. это все можно свести в один обший массив [1,1,2,2,3,4]. Из членов данного массива нужно составить все возможные комбинации с заданной длиной комбинации. Я правильно понял? |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | « Ответ #4 : 13-05-2006 16:49 »  |  | 
 
 Finchда, точно. можно свести наверно в один массив. мне вообще-то нужны будут все комбинации заданной длины в каком-то диапазоне, то есть например, макс. длина 15, то все строки длины 1, 2, 3, ..., 15. Кстати, Litanika, Покажи на пальцах, как ты получил например первое число 112. Что то я никак не могу понять логику.
 я женского пола   |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| MS | 
								|  | « Ответ #5 : 13-05-2006 17:04 »  |  | 
 
 Litanika, а на чем тебе это нужно написать? |  
						| 
								|  |  
								|  |  Записан | 
 
 Ничто так не ограничивает полёт мысли программиста, как компилятор |  |  | 
	| 
			| 
					
						| MS | 
								|  | « Ответ #6 : 13-05-2006 17:11 »  |  | 
 
 Немогу точно объястить,  примерно так: берем первый элемент меняем местами со вторым, выводим, потом с третьим и т.д. так с каждым, чтобы каждый элемент побывал на месте других, и после каждой комбинации вывод. Вот   |  
						| 
								|  |  
								|  |  Записан | 
 
 Ничто так не ограничивает полёт мысли программиста, как компилятор |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #7 : 13-05-2006 17:13 »  |  | 
 
 я женского пола 
 Извиняюсь если обидел. У тебя в профиле не указано. Значит исходим из обшего правила   В твоем случае всего всевозможных комбинаций 120 (6*5*4). Недавно поднималась тема с подобной задачей https://forum.shelek.ru/index.php/topic,8560.msg126526.html . Просмотри ее. Конечно нужно будет адаптировать под себя. Но в ней высказывалось несколько идей.  |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #8 : 13-05-2006 17:47 »  |  | 
 
 если представить всё в одном массиве, то искать нужно сочетание индексов.  5  4  8   (<-массив)  0  1  2   (<-индексы) для случая массива длиной==3 и длины строки перестановок==3  алгоритм такой  (числа - это ИНДЕКСЫ): ("-" означает неверное сочетание, "--" означает переполнение одного из индексов. Правильное сочетание вынесено) -------------------------------       012 013-- 020-       021 022- 023-- 030-- 100- 101-       102 103-- 110-       120 121- 122- 123-- 130-- 200-       201 202- 203--       210 211- 212- 213-- 220- 230-- 300-- стоп ------------------------------- а реализацию чичас придумаю    (если опять же не опоздаю) мммм... или не усну   )))))) |  
						| 
								|  |  
								| « Последнее редактирование: 13-05-2006 18:52 от Алексей1153 » |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | « Ответ #9 : 13-05-2006 19:39 »  |  | 
 
 MS, мне нужно написать на delphi. это часть большой задачи по мат. моделированию |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #10 : 13-05-2006 19:49 »  |  | 
 
 Litanika, ммм, тогда я писать прогу не буду. Моск сломал   ) Алгоритм вроде я понятно показал? Его можно расширить для любого количества чисел и длины сочетаний.. |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | « Ответ #11 :  13-05-2006 19:57 »   |  | 
 
 Алексей1153, можно хотя бы алгоритм, как там называется, на алгоритмическом языке, или как-то так, а то у меня от циферок уже голова болит...  |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #12 : 13-05-2006 20:09 »  |  | 
 
 Litanika, ну смотри в том посте:
 содержание массива "классов" (как ты его называешь) нафик не важно. Важно - количество элементов.  Также имеется некий массив (назовём буфер для краткости), в котором перебираем сочетания. То есть исходные данные - длина массива "классов" (назовём его Arr) и длина буфера.
 Элементы Arr - пронумерованы от 0 до (длина Arr -1)
 В буфере - индексы массива Arr. То есть переставляем индексы только.
 
 1) инициализируем буфер так : 01234...
 2) для получения следующего сочетания - увеличиваем самый последний индекс, учитываем его переполнение и повторение. Если никак, то переходим на индекс ранее (см колонку цифр в посте вверху)
 3) повторять до тех пор, пока в буфере самый первый индекс нельзя увеличить
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | « Ответ #13 : 13-05-2006 20:16 »  |  | 
 
 Алексей1153, эмм, ладно, спасибо, щас пойду пробовать, надеюсь получится
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | « Ответ #14 : 13-05-2006 20:27 »  |  | 
 
 вот например у меня в буфере 6 элементов: 0123456, длина комбинации - 4я первое сочетание беру 0123 и перебираю до 6000? и я так понимаю, еще надо отлавливать, когда повторяются цифры, да? а вот как же это отловить?
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #15 : 13-05-2006 20:53 »  |  | 
 
 Litanika,  struct XXX{
 //nDestLen - это длина строки для перебора сочетаний
 //nSourLen - это количество элементов
 static bool Calc(int nDestLen,int nSourLen)
 {
 int* pnDest=0;
 BYTE* pbyIndxBusy=0;
 
 if(nDestLen>nSourLen)
 {
 //ошибка
 return false;
 }
 
 //массив для сочетаний индексов
 pnDest=new int[nDestLen];
 
 //для для пометки занятости индексов
 pbyIndxBusy=new BYTE[nSourLen];
 memset(pbyIndxBusy,0,nSourLen);
 
 int inxMax=nSourLen-1;
 
 //индексы == 0...(nSourLen-1)
 //инитное заполнение pnDest
 for(int i=0;i<nDestLen;i++)
 {
 pnDest[i]=i;
 pbyIndxBusy[i]=1;//помечаем - индекс занят
 }
 
 //погнали
 for(;;)
 {
 ////////////////////////////////////////////////////
 //ТУТ:
 //pnDest[nDestLen] - ОЧЕРЕДНОЕ ПРАВИЛЬНОЕ СОЧЕТАНИЕ
 //сохранения результатов нет, надо делать отдельно
 ////////////////////////////////////////////////////
 
 //ищем следующее сочетание
 int L,i;
 int nTempInd;
 for(L=nDestLen-1;L>=0;L--)
 {
 nTempInd=pnDest[L];
 //помечаем индекс как незанятый
 pbyIndxBusy[nTempInd]=0;
 
 //увеличиваем индекс, пока не найдём незанятый, либо пока
 //не переполнится
 bool bOverFlow=false;
 for(;;)
 {
 nTempInd++;
 if(nTempInd>inxMax){bOverFlow=true;break;}//переполнение индекса
 
 //смотрим - не занят  ли индекс
 if(!pbyIndxBusy[nTempInd])
 {
 //сохраняем индекс и помечаем как занятый
 pnDest[L]=nTempInd;
 pbyIndxBusy[nTempInd]=1;
 break;
 }
 }
 
 if(bOverFlow)
 {
 //переполнение индекса
 pnDest[L]=0;
 
 //переходим к изменению предыдущего индекса
 continue;
 }
 
 //"левая часть" сочетания найдена. Дописываем "правую часть"
 
 int i1=0;//для поиска незанятых индексов
 
 bool bErr=false;
 L++;
 //ищем незанятые индексы
 for(;L<nDestLen;)
 {
 if(!pbyIndxBusy[i1])
 {
 //записываем индекс
 pnDest[L]=i1;
 //помечаем индекс как занятый
 pbyIndxBusy[i1]=1;
 //двигаемся правее
 L++;
 continue;
 }
 
 i1++;
 if(i1>=nSourLen){bErr=true;break;}
 }
 
 if(bErr)
 {
 //непонятная ошибка - сюда никогда
 //не должны попасть (по идее...)
 L=0;
 break;
 }
 
 break;
 }
 
 //проверяем на СТОП
 if(L<0) break;
 }
 
 //удаляем временные массивы
 if(pnDest)delete[]pnDest;
 if(pbyIndxBusy)delete[]pbyIndxBusy;
 
 /////////
 return true;
 }
 };
 
 
//вызов: if(XXX::Calc(3,7)) {    //посчитано, но результаты не сохранены } |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #16 : 13-05-2006 20:56 »  |  | 
 
 (заходи в асю , я сейчас онлайн) вот рабочий код на си++, я вроде протестил. Ну и , соответственно тебе надо переложить на дельфи..  там, где           //ТУТ:           //pnDest[nDestLen] - ОЧЕРЕДНОЕ ПРАВИЛЬНОЕ СОЧЕТАНИЕ - в этом месте в буфере pnDest длиной nDestLen - очередная правильная последовательность. Тебе нужно куда-то сохранить её отсюда. ------------------------------- а вызывать так: if(XXX::Calc(3,7)) {    //посчитано, но результаты не сохранены } else {    //длина буфера меньше количества элементов } ----------------------------- вот например у меня в буфере 6 элементов: 0123456, длина комбинации - 4я первое сочетание беру 0123 и перебираю до 6000? и я так понимаю, еще надо отлавливать, когда повторяются цифры, да? а вот как же это отловить?
 
 ммм... я тебя запутал слегка... перефразирую цитату "правильно" : вот например у меня в МАССИВЕ ЭЛЕМЕНТОВ 6 элементов: 0163449, длина комбинации (==длина БУФЕРА) - 4. я первое сочетание беру 0123 и перебираю до 6000?... |  
						| 
								|  |  
								| « Последнее редактирование: 16-06-2009 03:25 от Алексей1153++ » |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| MS | 
								|  | « Ответ #17 : 14-05-2006 06:06 »  |  | 
 
 Litanika, тебе срочно, дня 2 можешь подождать?  |  
						| 
								|  |  
								|  |  Записан | 
 
 Ничто так не ограничивает полёт мысли программиста, как компилятор |  |  | 
	| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | « Ответ #18 : 14-05-2006 09:16 »  |  | 
 
 Алексей1153, большое спасибо за код, но у меня не получается переделать его в delphi, ругается, что L используется в for и тогда нельзя L:=L+1 делать   (MS , мне чем быстрее, тем лучше, к понедельнику к обеду надо. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #19 : 14-05-2006 09:34 »  |  | 
 
 Litanika, ну так  -  сделай в 
 for(; ; )
 {
 }
 просто работу с L продумай, это несложно
 
 L=nDestLen-1
 for(; ; )
 {
 if(!(L>=0))break;
 ...
 ...
 L--;
 }
 
 
 только учти continue - а то (L--) не произойдёт
 |  
						| 
								|  |  
								| « Последнее редактирование: 14-05-2006 09:53 от Алексей1153 » |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Dimka 
								ДеятельКоманда клуба    Offline 
								Пол:    | 
								|  | « Ответ #20 : 14-05-2006 11:25 »  |  | 
 
 Переменное количество вложенных циклов - это признак того, что задачу удобнее решать рекурсивно. |  
						| 
								|  |  
								|  |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #21 : 14-05-2006 11:37 »  |  | 
 
 dimka, может и удобно, но не люблю я рекурсию    Напиши свой вариант - может сразу на дельфи, девушка тебе только спасибо скажет   |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Dimka 
								ДеятельКоманда клуба    Offline 
								Пол:    | 
								|  | « Ответ #22 : 14-05-2006 13:38 »  |  | 
 
 Ну, во-первых, это задача не на техническую специфику или на особенности языка программирования, а теоретическая - на развитие навыков программирования, поэтому, как преподаватель, считаю вредным для девушки выдавать для неё готовые решения. Во-вторых, у меня нет под рукой Delphi, чтобы отладить решение; только Borland Pascal 7.0 имеется. |  
						| 
								|  |  
								|  |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	| 
			| 
					
						| Litanika 
								Гость
 | 
								|  | « Ответ #23 : 16-05-2006 11:14 »  |  | 
 
 Всем спасибо, я нашла решение, правда с помощью рекурсии. Кому интересно, в приложении. Тему можно закрыть. |  
						| 
								| 
 |  
								|  |  Записан | 
 |  |  | 
	|  |