Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Перестановки чисел  (Прочитано 22409 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Litanika
Гость
« : 13-05-2006 13:37 » 

Помогите запрограммировать такую штуку: вводится число классов, в каждом классе число элементов (например числа). Нужно получить строки заданной длины N из всевозможных перестановок этих чисел. Например, 4 класса, в них 2, 2, 1, 1 элементов: [1,1], [2,2], [3], [4], длина строки =3. Должно получиться: 112
113
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
Спокойный
Администратор

il
Offline 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
Спокойный
Администратор

il
Offline 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
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 13-05-2006 17:04 » 

Litanika, а на чем тебе это нужно написать?
Записан

Ничто так не ограничивает полёт мысли программиста, как компилятор
MS
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 13-05-2006 17:11 » 

Немогу точно объястить,  примерно так:
берем первый элемент меняем местами со вторым, выводим, потом с третьим и т.д.
так с каждым, чтобы каждый элемент побывал на месте других, и после каждой комбинации вывод.
Вот Улыбаюсь
Записан

Ничто так не ограничивает полёт мысли программиста, как компилятор
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #7 : 13-05-2006 17:13 » 

Цитата
я женского пола
Извиняюсь если обидел. У тебя в профиле не указано. Значит исходим из обшего правила Улыбаюсь

В твоем случае всего всевозможных комбинаций 120 (6*5*4). Недавно поднималась тема с подобной задачей https://forum.shelek.ru/index.php/topic,8560.msg126526.html. Просмотри ее. Конечно нужно будет адаптировать под себя. Но в ней высказывалось несколько идей.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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. это часть большой задачи по мат. моделированию
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 13-05-2006 19:49 » 

Litanika, ммм, тогда я писать прогу не буду. Моск сломал Улыбаюсь) Алгоритм вроде я понятно показал? Его можно расширить для любого количества чисел и длины сочетаний..
Записан

Litanika
Гость
« Ответ #11 : 13-05-2006 19:57 » 

Алексей1153, можно хотя бы алгоритм, как там называется, на алгоритмическом языке, или как-то так, а то у меня от циферок уже голова болит...
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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? и я так понимаю, еще надо отлавливать, когда повторяются цифры, да? а вот как же это отловить?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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))
{
   //посчитано, но результаты не сохранены
}
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 14-05-2006 06:06 » 

Litanika, тебе срочно, дня 2 можешь подождать?
Записан

Ничто так не ограничивает полёт мысли программиста, как компилятор
Litanika
Гость
« Ответ #18 : 14-05-2006 09:16 » 

Алексей1153, большое спасибо за код, но у меня не получается переделать его в delphi, ругается, что L используется в for и тогда нельзя L:=L+1 делать Жаль(
MS, мне чем быстрее, тем лучше, к понедельнику к обеду надо.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 14-05-2006 11:25 » 

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

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 14-05-2006 11:37 » 

dimka, может и удобно, но не люблю я рекурсию Улыбаюсь Напиши свой вариант - может сразу на дельфи, девушка тебе только спасибо скажет Улыбаюсь
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 14-05-2006 13:38 » 

Ну, во-первых, это задача не на техническую специфику или на особенности языка программирования, а теоретическая - на развитие навыков программирования, поэтому, как преподаватель, считаю вредным для девушки выдавать для неё готовые решения. Во-вторых, у меня нет под рукой Delphi, чтобы отладить решение; только Borland Pascal 7.0 имеется.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Litanika
Гость
« Ответ #23 : 16-05-2006 11:14 » 

Всем спасибо, я нашла решение, правда с помощью рекурсии. Кому интересно, в приложении. Тему можно закрыть.

* Perestanovki.rar (7.8 Кб - загружено 839 раз.)
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines