Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » алгоритм сравнения 7ми букв по составным вариантам

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки

Открыть новую тему     Написать ответ в эту тему

spajwan

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
суть задачи:
 
1) УСЛОВИЕ
 
есть 7мь букв    A B C D E F G
 
есть ряд значений представленных рандомно в столбик из: 5ти,  4х, 3х и 2х букв
 
все значения этих выпавших вариантов записаны в один общий столбик в порядке убывания, а варианты  представлены следующими буквами:
 
 
сперва значения из 5ти букв
 
потом значения из  4х букв
 
потом из 3х букв  
 
потом из 2х  букв  
   
 
2) ЗАДАЧА
 
 
сравнить значения из общего столбика  и найти те составные  варианты (5+2 или 3+4 или 2+2+3), значения которых по кол-ву  составляли  те самые 7мь букв A B C D E F G  (порядок выпадания  разный)  - главное что бы ни одна из букв не повторялась дважды в составном варианте
 
 
язык программирования - Делфи, или Паскаль  

Всего записей: 56 | Зарегистр. 21-06-2009 | Отправлено: 19:29 27-12-2015 | Исправлено: spajwan, 19:35 27-12-2015
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Я бы попробовал так:
1. Варианты грузим в массив строк.
2. Пишем рекурсивную функцию.  
На вход она получает строку, которую должна анализировать.
Внутри она проходит циклом весь массив вариантов.
Если какой-то вариант совпадает с анализируемой строкой, - это конец одного из вариантов. Можно озаботиться выводом одного из найденных результатов.  
Если какой-то вариант совпадает с началом строки, это ещё один вариант разбора, совпадающее начало отрезаем, вызываем себя с оставшейся частью входной строки.
3. Вызываем созданную функцию с параметром стартовой строки 'ABCDEFG'
4. Думаем, в каком виде нам нужен результат и из какого места его удобнее выводить.
 
5. Раз массив отсортирован, скорее всего, у вас есть ограничение по времени, так что на пятом шаге - предаёмся оптимизации.  
 
 
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:17 29-12-2015
spajwan

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid  
 
ваш вариант меня заинтриговал  
 
 а наглядный примерчик с кодом можете показать ?

Всего записей: 56 | Зарегистр. 21-06-2009 | Отправлено: 13:24 30-12-2015 | Исправлено: spajwan, 13:25 30-12-2015
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
А я думаю, что для вас это - учебное задание.
Мои дети периодически такое пишут.
 
Так что вы попробуйте написать код сами, а что будет непонятно - спрашивайте.
Приводите здесь куски кода и покопаемся. Помочь вам разобраться - мне не трудно.
А делать вместо вас домашку - мне кажется бессмысленным занятием
 
Входные данные, поди, текстовый файл input.txt ?
Загрузку строк и вывод результата, вы же всё равно собирались писать самостоятельно, раз форматы файлов не приводите.  
А остальное... в основной программе только вызов функции со стартовой строкой.
Саму функцию можно кодить прямо по моему описанию...
"На вход получаем строку...
Циклом проходим массив... "
и т.д.
 
Не получится - покажите код, который не работает, расскажите что не понятно.
 
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 15:21 30-12-2015
spajwan

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid да задача ещё та - спасибо что тратите на меня ваше время ...
 
вот почитал про рекурсивную функцию, но как её применить когда не получается варианты из файла (или из мемо ) загрузить в массив
 
насчёт данных  ( поди, текстовый файл input.txt ?)
 
да не совсем так - планировалось вообще вставлять текст в одно мемо - а на выходе результаты в другом мемо (для наглядности), но и с открытием файла (входные данные) тоже думаю хороший вариант.
 
понимаю что нужен цикл - и циклом должен идти перебор всех слов (вариантов из букв) из файла (или мемо).
 
(на этом этапе у меня часто вообще возникают ошибки о несовместимости типов)
 
и далее, раз слова (варианты из букв) в файле идут в столбик - значит по сути в каждой строке будет одно слово, и нужно его скопировать до переноса строки, а потом занести в массив строк.
 
можете этот момент описать подробно как для новичка - ?
 
имеется ввиду - вообще другой аналогичный пример, мне важно понять принцип (что бы самому его  научиться реализовывать)

Всего записей: 56 | Зарегистр. 21-06-2009 | Отправлено: 02:11 12-01-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Если допишете, решение задачи будет коротким и элегантным
 
1.  
В Delphi есть хэлп. По любому классу можно почитать, как этот класс устроен.
Если с английским сложно - translate.yandex.ru
За пару обращений вы легко запомните 30 слов, необходимых для свободного чтения статей хэлпа
 
2.
Если вы уже владеете синтаксисом ООП в Delphi...
у TMemo есть Lines типа TStrings. Оттуда всё можно забрать и через него же, в другое мемо положить.
 
Если нет...  
пока придётся просто поверить.
Memo1.Lines.Count - количество строк
Memo1.Lines[i] - i-я строка. Строки нумеруются с 0.
 
Этого достаточно чтобы описать массив строк и в цикле загрузить в него содержимое мемо.
 
Для вывода результата:
Memo2.Clear; - очистить мемо.
Memo2.Lines.Add(); - добавить строку.
 
Чтобы не заколачивать каждый раз содержимое Memo1, его удобнее указать в Design-time, чтобы оно стартовало уже с набором "рандомных значений в порядке убывания длины".
 
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:58 12-01-2016 | Исправлено: KDPoid, 08:20 12-01-2016
spajwan

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid
 
вот пробовал - но что-то не получается
 
1 попытка выглядит так
 
program Proba_array;
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TntStdCtrls;
 
type
  TForm1 = class(TForm)
    mmo1: TTntMemo;
    mmo2: TTntMemo;
    btn1: TTntButton;
 
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
 
var
  Form1: TForm1;
  i : Integer;
 
 
procedure TForm1.btn1Click(Sender: TObject);
 
Var i:Byte;
    s :  WideString;
 
begin
 
if mmo1.Lines.Count<>0 then
 
for i:=0 to mmo1.Lines.Count-1 do //  цикл, равный кол-ву строк
     mmo1.Lines[i];
     s := Lines[2];
 
       mmo2.Clear;  //  очистить мемо
       mmo2.Lines.Add(s);  //  добавить строку
 
end;
 
 
end.
 
 
 
Добавлено:
KDPoid
 
2 попытка - пробовал другим способом, но тоже что-то не выходит:
 
procedure TForm1.btn1Click(Sender: TObject);
var
  s,d : WideString;
  i,Len : Integer;
  mas: array [1..10] of WideString ;
begin
    s := mmo1.Text;
    Len:= Length (s);
 
    for i :=1 to Len do
       begin
       mas[i] := s[i];
       end;
 
     d := mas[3];
 
 
    mmo2.Clear;
    mmo2.Lines.Add(d);
end;

Всего записей: 56 | Зарегистр. 21-06-2009 | Отправлено: 00:09 14-01-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Посмотрим на ваш код.
 
procedure TForm1.btn1Click(Sender: TObject);  
var  
  s,d : WideString;  
  i,Len : Integer;  
  mas: array [1..10] of WideString ;  
begin  
    for i:=0 to mmo1.Lines.Count-1 do //  цикл, равный кол-ву строк  
     mmo1.Lines[i];  // Выполняется ОДИН оператор. Вот этот. Который ничего не делает.
    // На вашу беду, это синтаксически корректная конструкция,  
   // так что при компиляции ошибки не будет.
 
    // После цикла один раз...  
     s := Lines[2]; // Что такое Lines[2] ? Вторая строка ? Где ? В mmo1 ? Почему именно вторая ?
 
       mmo2.Clear;  //  очистить мемо  
       mmo2.Lines.Add(s);  //  добавить строку s, которую мы непонятно как и откуда получили.
end;  
 
Попробуйте так:
 
procedure TForm1.btn1Click(Sender: TObject);  
var  
  s, d : WideString;  
  i, Len : Integer;  
  mas: array [1..10] of WideString ;  
begin  
   mmo2.Clear; // заранее очистить mmo2
   for i := 0 to mmo1.Lines.Count-1 do //  цикл, равный кол-ву строк  
   begin // единственный оператор, который выполняется в цикле - это скобка begin-end.  
           // Всё, что в ней - то и тело цикла.
      s := mmo1.Lines[i];  // Извлекаем i-ю строку в S.
      mmo2.Lines.Add(s);  //  добавить эту строку в мемо2.
  end;
end;  
 
Построчное копирование - это в целях вашего проекта.
TMemo.Text - отдаёт всё содержимое одной строкой, если бы нужно было именно копировать, всё содержимое обработчика кнопки можно было бы заменить на mmo2.Text := mmo1.Text;
 
Ну вот, теперь вам нужно забирать не в S, которая затирается новой строкой на каждом шаге цикла, а складывать всё в элементы mas.
 
В следующих вариантах кода подумайте вот о чём:
 
1. if mmo1.Lines.Count<>0 then  
Количество строк меньше нуля не может быть, лишняя проверка. Итого, вы проверяете чтобы, количество строк было не 0. А что если 0 ?
Тогда цикл будет  
For i := 0 to -1 do
Если конечное значение меньше начального, цикл не выполнится ни разу.  
Как в моём варианте: очистили mmo2, если в mmo1 ничего нет, ничего и не будет пытаться скопироваться, mmo2 останется пустым. Всё корректно.  
 
2. А что будет, если в mmo1 больше строк, чем отведено в mas ? Нужна будет проверка, чтобы не пытаться засунуть в несуществующие элементы mas.
 
Потом, пора уже создать процедуру, которая всё и будет делаеть.  
Какую-нибудь MySuperProcudure.
Описать её у формы, по аналогии с  procedure TForm1.btn1Click(Sender: TObject);  
Только у вас входным параметром будет не Sender странного типа, а свой параметр, типа string.
 
NB !!!
Переменные видны не выше того места, где определены.
У вас mas - доступен только внутри btn1Click
Перенесите его к  
var  
  Form1: TForm1;  
  i : Integer;  
Это переменные всего модуля, и видны всем, кто тут есть.
Так что, если mas будет тут, с ним можно будет работать и из btn1Click, и из вашей MySuperProcedure  
 
Пробуйте.

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 08:08 14-01-2016 | Исправлено: KDPoid, 16:06 16-01-2016
spajwan

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid
 
насчёт переменных для всего модуля:
 
да в принципе оно вроде бы так и есть, но запуская цикл в процедуре - Делфи выдаёт ошибку, и тогда приходится использовать локальную переменную (возможно что-то делаю не совсем верно)
 
варианты кода - первый
 
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TntStdCtrls;
 
type
  TForm1 = class(TForm)
    mmo1: TTntMemo;
    mmo2: TTntMemo;
    btn1: TTntButton;
     
    function Create_Array (n : WideString) : WideString;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
  s : WideString;
  a : array of WideString;
 
implementation
 
{$R *.dfm}
function TForm1.Create_Array (n : WideString) : WideString;
 var i : Integer;
 begin
     SetLength (Result,n);
     for var i := 0 to n-1 do
      Result [i] := s[i];
 end;  
 
 
procedure TForm1.btn1Click(Sender: TObject);
begin
     s := mmo1.Text;
     a := Create_Array(s);
     mmo2.Clear;
     mmo2.Lines.Add(a);
end;
 
end.
 
 
 
Добавлено:
KDPoid
 
вариант второй (обобщённый - разное  для проверки ) с учётом ваших правок
 
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TntStdCtrls;
 
type
  TForm1 = class(TForm)
    mmo1: TTntMemo;
    mmo2: TTntMemo;
    mmo3: TTntMemo;
    btn1: TTntButton;
    mmo4: TTntMemo;
 
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
  mas : array of WideString;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.btn1Click(Sender: TObject);
  Var
    s,st :  WideString;
    i,d,b :Byte;
begin
   mmo2.Clear;  //  заранее очистить мемо
   mmo3.Clear;
   mmo4.Clear;
 
   mmo1.Lines.Text;
   d := mmo1.Lines.Count;
   mmo3.Lines.Add(IntToStr(d));   //  вывод кол-ва строк в  3е мемо
 
 for i:=0 to mmo1.Lines.Count-1 do //  цикл, равный кол-ву строк
  begin
     s := mmo1.Lines[i];
     mmo2.Lines.Add(s);  //  вывод построчно во  2е мемо
 end;
 
 for b:=0 to mmo1.Lines.Count-1 do    //  цикл по заполнению динамического  массива
 begin
  s := mmo1.Lines[b];
  mas[b]:= s;
 end;
 
 //  проба вывода любого элемента из динамического массива
 
    st := mas[3];
    mmo4.Lines.Add (st);
end;
end.

Всего записей: 56 | Зарегистр. 21-06-2009 | Отправлено: 01:03 17-01-2016 | Исправлено: spajwan, 01:07 17-01-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Первый вариант:
Вы определяете:
  a : array of WideString;  
Массив строк неопределённого размера.
Это значит будет a[0], a[1],...a[n]
И каждый элемент - строка типа WideString;
 
А функция ваша:
Create_Array (n : WideString) : WideString;
Возвращает одну строку.
Т.е., когда вы делаете
 a := Create_Array(s);  
Дельфи в изумлении. Как одной строкой , которую возвращает Create_Array накрыть целый массив строк A ?
Пока можно по простому:

Код:
 
procedure TForm1.Create_Array;  
// Процедура заполнения A не нуждается во входном параметре. Memo1 описан у TForm1,  
// а значит доступен всем методам TForm1.
// И TForm1.btn1Click, и TForm1.Create_Array
// На выход ничего подавать не будем. Будем сразу писать в A, который тоже доступен всем.
 var i : Integer;  
 begin  
     SetLength (A, mmo1.Lines.Count); // Задаём размер A. В элементах. Т.е., сколько в нём  
                                                     // будет строк. Сколько строк в исходном мемо, пусть  
                                                     // таким и будет A.  
                                                     // Тогда не нужно будет проверять границы.
     for i := 0 to mmo1.Lines.Count - 1 do  
       a[i] := mmo1.Lines[i];  
 end;
 
 
 
Тогда

Код:
 
procedure TForm1.btn1Click(Sender: TObject);  
var
      i : integer; // i из Create_Array виден только там. Нам нужна своя переменная цикла.
begin  
     // предварительно из mmo1 ничего доставать не надо и никуда потом не направлять.
     // Create_Array всё само сделает.
     Create_Array;  
     // Ну вот, сделало. Осталось из A переложить всё в mmo2.
     mmo2.Clear;  
     for i := 0 to High(a) do // от 0 до номера самого последнего элемента A
       mmo2.Lines.Add(a[i]); // Add добавляет по одной строке, оно не может добавить сразу массив.
end;  
 

 
Во втором варианте всё выглядит рабочим.  
Можно двигаться дальше...  
 
Из общих рекомендаций:
1. В дельфи много разных строк. WideString, AnsiString, есть и более странные...
В ближайшее время вам не понадобится уточнять. Можно использовать просто string
Это что-то типа "Строки, которые сейчас в моде". Дельфи из шкуры вон лезет, чтобы упростить работу, оно ещё долго будет на ваших задачах легко определять, какие строки тут больше подходят и как с ними работать.
 
2. То же и с индексными переменными.
i,d,b :Byte;  
Среди всех целых типов с конкретными свойствами есть Integer - целое, которое наиболее удобно компилятору.
Для переменных цикла - это самый разумный вариант.
 
3. Про "Делфи выдаёт ошибку". Оно не ругается в стиле "Чё за хрень, работать не буду."
Ну, или почти никогда так не ругается.
Обычно, оно показывает где проблема, описывает почему и часто - как исправить.
Буквально "Я ждало скобку, а тут точка с запятой", "не могу засунуть целое в строку",
"Переменная цикла должна быть локальной" и т.д.
Так что читать самому и цитировать текст ошибки - полезно.
В окне сообщений даже команда в контекстном меню сделана "Скопировать текст ошибки в буфер обмена".
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 06:54 17-01-2016 | Исправлено: KDPoid, 06:58 17-01-2016
spajwan

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid
 
вроде получилось, по отдельности да - реально работает
 
но при попытке вывести для проверки массив строк и массив символов в разные мемо - ничего не происходит
 
компиляция происходит без проблем, появляется форма с 4мя мемо, два мемо в ручную заполняю данными, жму на кнопку - и ничего не происходит
 
массив символов - делал специально для пузырьковой сортировки, что бы при проверке строк было потом удобней работать.
 
т.е. есть начальная строка (эталон для сравнения так сказать) - делаем пузырьковую сортировку и заносим эту строку в переменную - но вот беда, в мемо (если отдельно делаю) выводит отсортированную строку посимвольно и только в столбик - как сделать что бы выводило отдельно целиком в строку ?
 
и почему по отдельности работает - а всё вместе не работает ?
 

Код:
 
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TntStdCtrls;
 
type
  TForm1 = class(TForm)
    mmo1: TTntMemo;
    mmo2: TTntMemo;
    btn1: TTntButton;
    mmo3: TTntMemo;
    mmo4: TTntMemo;
    procedure Create_Mas_Char();
    procedure Create_Array ();
    procedure Puzirek ();
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
  s : WideString;
  a : array of WideString;
  mas: array of WideChar;
  r: WideChar;
 
 
implementation
 
{$R *.dfm}
procedure TForm1.Create_Array ();
 var i : Integer;
 begin
     SetLength (a,mmo1.Lines.Count);
     for i := 0 to mmo1.Lines.Count do
      a[i] := mmo1.Lines[i];
 end;
 
procedure TForm1.Create_Mas_Char();
var
   i,n : Integer;
begin
      s := mmo3.Text;
      n := Length (s);
 
      SetLength (mas, n);
      for i := 1 to n  do
      mas[i] := s[i];
end;
 
procedure TForm1.Puzirek ();
var
   i,j : Integer;
 begin
    Create_Mas_Char();
 
    for i :=1 to High(mas)-1 do
     for j :=1 to  High(mas)-i do
      if (mas[j]>mas[j+1]) then
       begin
        r := mas[j];
        mas[j] := mas[j+1];
        mas[j+1] := r;
       end;
 
 end;
 
 procedure TForm1.btn1Click (Sender: TObject);
 var
   i,n,b : Integer;
 begin
      Create_Array ();
            mmo2.Clear;
      for i := 0 to High (a) do
      mmo2.Lines.Add(a[i]);
 
      Puzirek ();
      mmo4.Clear;
      n := Length (s);
      for b:=1 to n do
      mmo4.Lines.Add (mas[b]);
 end;
 
end.
 

Всего записей: 56 | Зарегистр. 21-06-2009 | Отправлено: 04:06 18-01-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Хинт1: Ограничение видимости переменных не просто так придумали, оно сильно облегчает жизнь.
Советую определять переменные только в той области, где она нужна.
a, mas, Form1 - выглядит разумным.
А вот  
s : WideString;  
Это рабочая строка, которая в разных местах будет использоваться по разному ? Тогда и определять её надо в тех местах.  
 
Хинт2: Если у переменной есть какой-то конкретный смысл, удобнее использовать мнемонические имена.
 
Теперь про код:
 for b:=1 to n do  
      mmo4.Lines.Add (mas[b]);  
Выводим в mmo4, n строк по одной букве из mas
А чему равно n ?
А-а... n := Length (s);
А что такое s ? Какая-то глобальная переменная, которая могла быть задана чем угодно и где угодно. Строка.
Т.е. вы пытаетесь вывести в mmo4 столько букв из mas, сколько букв в строке s ?
Ну ладно, мало ли цель какая....  
А что в S ? Содержимое mmo3.  
Если оно пустое, то S пустое, n = 0, цикл заполнения mmo4 не сработает ни разу. Ошибок не будет.
 
В дельфи есть возможность выполнять ваши программы по одному оператору.
Горячие команды не скажу, они могут меняться настройками и дефолтовое значение разное у разных версий.
Их можно посмотреть в меню Run
Run to cursor - ну и так понятно
Step over
Trace into
 
Две последних - выполняют программу по одной строке, останавливаясь после каждой.
Это позволяет посмотреть как работает логика. Во время остановки можно посмотреть текущие значения переменных, например, наведя мышку на название переменной.  
Разница у них в выполнении процедур.
Если мы стоим на Create_Array, "Step over" выполнит процедуру целиком и остановится на mmo2.Clear;
Trace Into - зайдёт внутрь Create_Array и позволит выполнять построчно её содержимое.
 
Попробуйте пройтись по содержимому btn1Click и будет понятно, что происходит и почему.

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:36 18-01-2016 | Исправлено: KDPoid, 14:42 18-01-2016
spajwan

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid    
 
Спасибо за подсказки.
 
Но у меня возникает следующая ситуация при использовании
 

Цитата:
Trace Into
 - проще говоря нажатии F7, меня перебрасывает на другие юниты.
 
может вы в курсе как побороть эту проблему, может в настройках чего вкл или выкл нужно ?
 
и ещё вот набросал маленький пробник на меньшее кол-во вариантов, вроде компилируется без проблем - а потом выскакивает ошибка
 
то что делаю не так ?
 

Код:
 
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, TntStdCtrls;
 
type
  TForm1 = class(TForm)
    mmo1: TTntMemo;
    mmo2: TTntMemo;
    edt1: TTntEdit;
    edt2: TTntEdit;
    lbl1: TTntLabel;
    btn1: TTntButton;
    procedure Mas_Strok;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
  A : array of WideString;
 
implementation
 
{$R *.dfm}
procedure TForm1.Mas_Strok();
var
    i : Integer;
  begin
       SetLength (A,mmo1.Lines.Count);  //
       for i := 0 to mmo1.Lines.Count - 1 do
        A[i] := mmo1.Lines[i];
 
  end;
 
 procedure TForm1.btn1Click(Sender: TObject);
var
  s,s2,st : WideString;
  k : Integer; //  кол-во символов в строке
  k1,k2,k3 : Integer; //  числовое значение  строк (вводной и 2х строк из массива)
  v : Integer; //  счётчик вариантов
  i,j : Integer;
  n, n2 : Integer;
  mas : array of WideChar;
  i2,i3,i4 : Integer;
  r : WideChar;
begin
     s := edt1.Text;
     k := Length (s);
 
     Mas_Strok();
     v := 0;
     n :=  mmo1.Lines.Count;
 
     for i :=0 to n - 1 do
      begin
          k1 := Length (A[i]);
 
        for j := 1+i to n do
         begin
           k2 := Length (A[j]);
           k3 := k1+k2;
           if k3 = k then
          begin
           st := A[i] + A[j];    //  делаем конкатенацию строк
           n2 := Length (st);
 
            SetLength(mas,n2);   //  создаётся массив символов
            for i2 := 1 to n2 do
            begin
               mas[i2] := st[i2];
            end;
 
             for i3 := 0 to n2 do   //   делается пузырьковая сортировка
              if mas[i3] > mas[i3+1] then
               begin
                 r := mas[i3];
                 mas[i3] := mas[i3+1];
                 mas[i3+1] := r;
               end;
 
              for i4 := 1 to n2 do  // вывод массива символов в строку
              begin
               s2 := '';
               s2 := s2 + mas[i4];
              end;
 
               if s = s2 then
               begin
                  mmo2.Lines.Add(A[i] + ' :: ' + A[j]);
                  v := v +1;
               end;  
 
          end;
         end;
      end;
 
     edt2.Text := IntToStr(v);
 
end;
 
end.
 

Всего записей: 56 | Зарегистр. 21-06-2009 | Отправлено: 19:29 21-01-2016 | Исправлено: spajwan, 19:31 21-01-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Про F7. Это не бага, это фича.
Дельфи старается взять на себя максимальное количество рутины. Оно генерит кучу паскалевского кода самостоятельно. И подключает ранее созданные библиотеки. А когда вы делаете F7 на функции из такой библиотеки, оно честно предлагает продолжить отладку выполняя по одному оператору код из библиотеки.  
Используйте F8, оно не будет влезать внутрь процедур. А F7 - только когда действительно интересно посмотреть, что внутри.
 
Про код.
Ошибки времени исполнения, они тоже достаточно информативны.
Дельфи пишет в чём проблема и останавливается на операторе, в котором ошибка.
Приводите название ошибки и указывайте, где взрывается.
 
В этот раз угадаю в чём причина "какой-то ошибки"....
Один цикл
 for i :=0 to n - 1 do  
Разумно. В n количество строк, массив A имеет элементы от 0 до n-1
А вот внутренний цикл.
 for j := 1+i to n do
На последнем проходе, попытка обратиться к A[j], будет вызывать ошибку.
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 15:56 22-01-2016 | Исправлено: KDPoid, 15:59 22-01-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
spajwan
...И вот теперь, когда вы получили громоздкий, корявый и неуклюжий код из циклов, сравните насколько меньше букв надо колотить, если владеть рекурсией...
 
В форме заводим кнопку, для старта, мемо для вывода результата:

Код:
TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  ...

В приватной части объявляем мозговище:

Код:
private
    Elements : Array of String; // Кусочки из которых мы собираем.
// Функция, которая всё и делает.
// WS - Текущая строка, которую ещё надо собирать
// Res - Часть решения, которое мы уже нашли.
    procedure Analyze(const WS, Res : String);
...

На кнопку вешаем запуск:

Код:
procedure TForm1.Button1Click(Sender: TObject);
begin
// Начальные значения доступных элементов.
  SetLength(Elements,10);
  Elements[0] := 'BCDEFG';
  Elements[1] := 'GDFA';
  Elements[2] := 'BCDE';
  Elements[3] := 'EFG';
  Elements[4] := 'ABC';
  Elements[5] := 'FG';
  Elements[6] := 'GF';
  Elements[7] := 'D';
  Elements[8] := 'F';
  Elements[9] := 'A';
// Понеслась. Анализируем строку ABCDEFG, решение у нас пустое
  Analyze('ABCDEFG','');
end;

Ну и сама функция чистого самопознания:

Код:
Procedure TForm1.Analyze(const WS, Res: String);
var i: integer;
    tmpS: string;
begin
  // Цикл по всем элементам. Мы не паримся, сколько их, поэтому от первого до последнего.
  for i:= Low(Elements) to High(Elements) do
  begin
    if WS = Elements[i] then // если текущий элемент - это вся строка, значит мы нашли конец решения
    begin
      // Выводим итоговое решение в мемо. Начало, которое к нам пришло, и конец, который мы обнаружили.  
      if Res<>EmptyStr then memo1.Lines.Add(Res+'+'+WS)
                       else memo1.Lines.Add(Res+WS);
    end
      else
    begin // текущий элемент - не конец.
      // Выделим из анализируемой строки начало, равное длине нашего элемента. Для удобства.    
      tmpS := copy(WS,1,Length(Elements[i]));
      if tmpS = Elements[i] then // Если начало строки равно текущему элементу, значит это середина решения.
      begin
         // Из анализируемой строки уберём начало, равное нашему элементу, и прибавим его к решению.
        // А потом вызовем новый экземпляр Analyze, с остатком целевой строки и уже найденной частью решения.  
        // Пусть она поищет продолжения.  
        if Res<>EmptyStr
          then Analyze(Copy(WS, Length(tmpS)+1, Length(WS) - Length(tmpS)), Res + '+' + tmpS)
          else Analyze(Copy(WS, Length(tmpS)+1, Length(WS) - Length(tmpS)), Res + tmpS);
      end;
    end;
  end;
end;

 
Вот и всё. Попробуйте наколотить это всё в свой проект.
Включите отображение локальных переменных, стека, watch list, в который добавьте просмотр Elements[i].
Пройдитесь по алгоритму по шагам, при помощи F8-F7.
Возможно, понадобится карандаш, 4 листа бумаги и литр колы.
Этого достаточно, чтобы понять, как эта штука работает.
 
Надеюсь, вам хватит самоуважения разобраться, а не копипастить.    
 
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 10:28 20-02-2016 | Исправлено: KDPoid, 09:33 23-02-2016
Antono89



Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
[q][/q]
Довольно неплохой алгоритм!

Всего записей: 5 | Зарегистр. 18-02-2016 | Отправлено: 00:39 21-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
spajwan,
А вот как раз и грузилка про рекурсию.
http://digital-flame.ru/2016/02/20/delphi-rekursiya-po-prostomu/
На пальцах и с прибаутками

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:14 21-02-2016
spajwan

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
KDPoid
 
Спасибо за наглядный пример  
 
надеюсь смогу понять как это работает - с карандашом бумагой и чаем.
 
дело в том - что на огороде мы с успехом травим тлю на капусте колой, да-да именно так
 
двух литровки вполне хватает - открываем крышку --> накручиваем на бутылку с колой ручную пшакалку --> пшакаем  капусту колой и тли как не бывало.
 
так что уж лучше с чаем - и полезней и приятней.
 
 
а статья в блоге действительно  прикольная и познавательная

Всего записей: 56 | Зарегистр. 21-06-2009 | Отправлено: 22:27 22-02-2016
Открыть новую тему     Написать ответ в эту тему

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » алгоритм сравнения 7ми букв по составным вариантам


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru