Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

Google API в Delphi - проект с открытым исходным кодом.

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

А тут я коплю на лицензию Delphi XE на iPad =).
Сумма пожертвования не фиксирована.

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

Вы сейчас или в ближайшем обозримом будущем планируете разрабатывать кроссплатформенное приложение с использованием Firemonkey?



Loading ... Loading ...

Блоги и сообщества

Статьи по Delphi DelphiFeeds.ru - Все Delphi-блоги Рунета Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Новостной блог о высоких технологиях
Система Orphus
Опубликовал Vlad 15 марта 2010 в 15:40.
Категории: Основы Delphi.


Несмотря на то, что тема поста относится больше не к программированию, а к математике, определение всех перестановок в массиве (неважно какого типа) может потребоваться и при работе в Интернет. Простой пример - определть все возможные названия сайтов, составленных из 3 ключевых слов. Или провести синонимизацию какого-либо участа текста, используя заданные массивы слов-синонимов. Что касается количества перестановок, то тут все просто - количество перестановок будет равно факториалу количества элементов в массиве, т.е., если у нас есть массив M, то количество перестановок k будет равно:
k = Length(M)!
для трехэлементного массива k=1*2*3=6
для четырех элементов: k=1*2*3*4=24 и т.д.
Осталось только вывести все возможные перестановки.

Чтобы продемонстрировать вариант перебора всевозможных перестановок зададимся простой целью:
Есть набор чисел: 1, 2, 3. Необходимо вывести все возможные перестановки этих чисел.
Итак на входе у нас будет массив (1,2,3).
Нам надо переставить числа так, чтобы в итоге все числа выставились в ряд: 3, 2, 1.
Для достижения поставленой цели нам потребуется:

  1. Вспомогательная функция определения количества перестановок (вычисления факториала числа). Хоть у нас и есть чётко заданый масси, следует учитывать будущее этого алгоритма - вывести перестановки для массивов любой длины.
  2. Функция получения следующей перестановки.
  3. Функция перемещения двух элементов в массиве.

Самое простое - то написать функцию перестановки двух элементов в массиве (первая задача на первом курсе по информатике):

procedure Swap(var a, b: byte);
var  c: byte;
begin
   c := a;
   a := b;
   b := c
end;

Вычисление факториала - тоже не вызовет никаких проблем и затруднений:

function Factorial(n: Word): Longint;
var f: LongInt;
     i: Integer;
begin
  f := 1;
  for i := 2 to n do
    f := f * i;
  Result:=f;
end;

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

type
  TSingleArray = array of byte;
procedure Next(var X: TSingleArray; var Yes: boolean);
var i,j: byte;
begin
  i:=High(X)-1;//начинаем с предпоследнего элемента
  { поиск i }
  while (i >= Low(X)) and (X[i] > X[i + 1]) do
    dec(i);
  if (i >= Low(X))and(i<=high(X)) then
    begin
      j:=i+1;//следующий за X[i] элемент
    {поискj}
      while (j<high(X)) and (X[j+1]>X[i]) do
       inc(j);
      Swap(X[i], X[j]);//меняем местами
      for j:=i+1 to (high(X)+i) div 2 do
         Swap(X[j], X[high(X)-j+i+1]);
      Yes:=true
    end
  else
    Yes:=false;//все перестановки завершены
end;

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

procedure GenerateBytes(const Key: array of byte);
var
  i,j: integer;
  ByteArray: TByteArray;
  Yes:boolean;
 
procedure Next(var X: TSingleArray; var Yes: boolean);
var  i, j: byte;
begin
  i:=High(X)-1;
  { поиск i }
  while (i >= Low(X)) and (X[i] > X[i + 1]) do
    dec(i);
  if (i >= Low(X))and(i<=high(X)) then
    begin
      j:=i+1;
    { поиск j }
      while (j<high(X)) and (X[j+1]>X[i]) do
       inc(j);
      Swap(X[i], X[j]);
      for j:=i+1 to (high(X)+i) div 2 do
        Swap(X[j], X[high(X)-j+i+1]);
      Yes:=true
    end
  else
    Yes:=false;
end;
 
begin
  SetLength(ByteArray, Factorial(Length(Key)));//устанавливаем размер первого измерения
  SetLength(ByteArray[0],length(Key));//второе измерение
  i:=0;
    repeat
      SetLength(ByteArray[i],length(a));//добавляем элемент во второе измерение
      for j:=0 to length(a)-1 do
        ByteArray[i,j]:=a[j];//записываем перестановку
      inc(i);
      Next(a, Yes);//ищем следующую перестановку
    until not Yes;
end;

После завершения процедуры массив ByteArray будет содержать следующие элементы:

((1,2,3),
 (1,3,2),
 (2,1,3),
 (2,3,1),
 (3,1,2),
 (3,2,1))

Немного видоизменив функцию Next можно составить массив перестановок, например, для нескольких слов.

------------------------
Очень долгое время для просмотра фильмов на компьютере использую плеер Light Alloy. Небольшой по размеру, содержит все необходимые функции и настройки для видео, неприхотлив к ресурсам. Сегодня нашел где скачать бесплатно light alloy. Кстати, для тех, кто не в курсе - этот плеер разрабатывается в Delphi :) и скоро нас ждет выход новой версии этого плеера.
------------------------
Понравилась статья? Тогда:
Делись! Загружай! Плюсуй!
   Отправить PDF на   
Читай ещё статьи на WebDelphi.ru

Комментарии (9)

WP_Cloudy
  • Alk пишет:

    Добрый день, Vlad.
    Почитал ваши статьио авторизации и постинге с использованием  Synapse. Попытался сделать свое подобное, но к сожалению не вышло. Не хотите рассмотреть авторизацию и постинг в движке википедии?(там много нового  кирилические урл, как то генерируются «boundary=—————————14902356128489″ и пр.). Если нужно могу предоставить сайт сустановленным движоком вики. Заранее спасибо.

  • Vlad пишет:

    Ответ отправил Вам на e-mail :)

  • Spayn пишет:

    Очень вовремя нашёл ваш пост!! Как раз в универе изучаем комбинаторику и пишем всё на паскале. Есть такая не большая просьба.. вы гуру в паскале а я , так сказать нуб, был бы рад увидеть подробные посты по написанию генераций сочетаний с повторениями и без.

  • Vlad пишет:

    Это я-то гуру? :))) Очень-очень грубая лесть :)))

  • Spayn пишет:

    Раз не нравится гуру, то мастер в делфи точно ;) и у меня есть одна просьба, мы в универе проходим абстрактные типы данных, не могли бы вы про это написать пару статей? для совсем нубов, было бы очень приятно и полезно!

  • bgmt пишет:

    Доброго времени суток. Влад подскажите пожалуйста, как сделать следующее. Есть 3 массива с наборами символов. Нужно сформировать все возможные варианты по трем массивам при условии, что в комбинации должно быть определенное число символов из 1 массива определенное из 2 и определенное из третьего. А то уже всю голову сломал.
    Пример:
    1 массив (e, t, h, y,  j…)
    2 массив (ук, df, as,  fg,  vb…)
    3 массив (KLP, FGH, LPK, FBI…..)
    и известно что в комбинации должно быть 5 элементов из 1 массива, 2 элемента из 2 массива и 9 элементов из третьего массива, длина комбинации будет фиксированная на время всего перебора, определяться будет количеством элементов из массивов по условию.
    5+2+9 Последовательность выбора должна быть произвольной из любого массива.
    Спасибо.

  • Vlad пишет:

    bgmt, незнаю :) Я программист больше по хобби, чем по профессии, поэтому задачи комбинаторики изучаю по мере того как передо мной встают такие задачи. Таких случаев как описан у Вас мне не попадалось.

  • bgmt пишет:

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

  • Vlad пишет:

    К сожалению после падения винта осталось только всё, что есть в блоге

Ваш ответ

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

Пожалуйста, заключайте исходный код в тэги [code][/code].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник