| 
| 
 | Вопрос # 550/ вопрос открыт / | 
 |  Здравствуйте, уважаемые эксперты!Делаю программу в делфи по нахождению возможных вариантов решения. Программа сама по себе простая. Дана строка цифр и надо чтоб компьютер произвел над этими цифрами 4 операции или сложение, или вычитание, или умножение, или деление чтобы получить определенную цифру. Например дана строка 123456, а надо получить 10. Решение 1*2+3+4-5+6=10. Исходная строка может быть любой длины. Помогите написать код для вычисления всевозможных решений. Можно конечно самому написать эти решения, но этих же решений может быть тысячи, и каждый вариант описыть это долго. И еще вопрос. У меня каждый элемент массива "a" присваивает каждую цифру из строки.Длина массива 15. Как сделать, если введенная строка меньше 15 элементов чтоб массив сам уменьшился до количества элементов строки. И потом уже производить операции над этими элементами массива. Надеюсь что найдется решение этих вопросов, ведь нет ничего невозможного. За ранее благодарен.
 Приложение:Переключить в обычный режим unit Unit1; interface uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;  type  TForm1 = class(TForm)    Edit1: TEdit;    Label1: TLabel;    Label2: TLabel;    Label3: TLabel;    Button1: TButton;    Label4: TLabel;    Label5: TLabel;    Label6: TLabel;    Edit2: TEdit;    procedure Edit1KeyPress(Sender: TObject; var Key: Char);    procedure Edit2KeyPress(Sender: TObject; var Key: Char);    procedure Button1Click(Sender: TObject);    procedure Edit1Exit(Sender: TObject);    procedure Edit2Exit(Sender: TObject);  private    { Private declarations }  public    { Public declarations }  end; var  Form1: TForm1;  a: array[1..15] of integer;  i,rez,summ: integer;implementation {$R *.dfm} procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);begin     Key := #0;end; procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);begin     Key := #0;end; procedure TForm1.Button1Click(Sender: TObject);begin     end; procedure TForm1.Edit1Exit(Sender: TObject);begin  for i:=1 to 15 do  begin     end;   Edit2.SetFocus;  Button1.Enabled:=true;  end; procedure TForm1.Edit2Exit(Sender: TObject);begin end; end.
|  |   Вопрос задал: Курцетов И.А. (статус: Посетитель)Вопрос отправлен: 4 мая 2007, 12:35
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: min@y™ Чтобы массивы были нужной длины, надо использовать динамические массивы. Вот за 15 минут я написал вполне работающий пример такого брутфорса (в приложении). Там как раз используются динамические массивы.
 Результат, выдаваемый программой при строке цифр 123456 и ответе 10 такой:
 Enter the digits: 123456
 Enter the result: 10
 //----------------------------------------
 1 / 2 + 3 - 4 + 5 + 6 =     10
 1 - 2 - 3 / 4 + 5 + 6 =     10
 1 * 2 + 3 + 4 - 5 + 6 =     10
 1 + 2 + 3 * 4 / 5 + 6 =     10
 1 * 2 + 3 * 4 / 5 + 6 =     10
 1 * 2 * 3 * 4 / 5 + 6 =     10
 1 + 2 * 3 + 4 * 5 / 6 =     10
 1 / 2 + 3 * 4 * 5 / 6 =     10
 //----------------------------------------
 Total equals: 8
 Приложение:Переключить в обычный режим program Q_0550; {$APPTYPE CONSOLE} uses  SysUtils; type  TOperation = (opAdd, opSub, opMul, opDiv); var       function PrepareArrays: Boolean;var  Index: Integer;begin  if Length(Digits) < 2            Result:= False;           Exit;         end;      try    for Index:= 1 to Length(Digits) do      Values[Index - 1]:= StrToInt(Digits[Index]);     Result:= True;  except   end;    if Result    then begin           SetLength(Operations, Length(Digits) - 1);           FillChar(Operations[0], Length(Operations), opAdd);         end;end;  procedure IncOperations;var  Index: Integer;begin  for Index:= 0 to Length(Operations) - 1 do    begin      if Operations[Index] <> opDiv        then Inc(Operations[Index])        else Operations[Index]:= opAdd;       if Operations[Index] <> opAdd        then Break;    end;end;  function Power4(const APower: Integer): Integer;var  p: Integer;begin  Result:= 4;  for p:= 2 to APower do    Result:= Result * 4;end;  function Operation2Char(const Op: TOperation): Char;begin  case Op of    opAdd: Result:= '+';    opSub: Result:= '-';    opMul: Result:= '*';    else   Result:= '/';  end; // of caseend;  function CalculateCurrent: Integer;var  Index: Integer;begin  Result:= Values[0];  for Index:= 1 to Length(Values) - 1 do    case Operations[Index - 1] of      opAdd: Result:= Result + Values[Index];      opSub: Result:= Result - Values[Index];      opMul: Result:= Result * Values[Index];    else     Result:= Result div Values[Index];    end; // of caseend;  procedure ResultOut;var  Index: Integer;begin  Write('  ', Values[0]);  for Index:= 1 to Length(Values) - 1 do    Write(' ', Operation2Char(Operations[Index - 1]), ' ', Values[Index]);  WriteLn(' = ', Total: 6);end;  function CalculateAll: Integer;var  Index, Count: Integer;begin  Result:= 0;             2                     4            3                    16 = 4^2            4                    64 = 4^3            N                    4^(N - 1)  }   Count:= Power4(Length(Values) - 1);  for Index:= 1 to Count do    begin      if CalculateCurrent = Total        then begin               ResultOut;               Inc(Result);             end;      IncOperations;    end;end; begin  repeat    Write('  Enter the digits: ');    ReadLn(Digits);  until PrepareArrays;   Write('  Enter the result: ');  ReadLn(Total);   WriteLn('//----------------------------------------');  Equals:= CalculateAll;  WriteLn('//----------------------------------------');  if Equals <> 0    then WriteLn('  Total equals: ', Equals)    else WriteLn('  Nothing found :(');   ReadLn;end. 
|  | Ответ отправил: min@y™ (статус: Доктор наук)Время отправки: 7 мая 2007, 10:20
 
 |  
 Мини-форум вопросаВсего сообщений: 6; последнее сообщение — 5 мая 2007, 17:50; участников в обсуждении: 2. 
|   | Дмитрий-998 (статус: 1-ый класс), 4 мая 2007, 21:46 [#1]:Есть вот такой вариант: 
 unit Unit1;
 
 interface
 
 uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;
 
 
 type
 TForm1 = class(TForm)
 Edit1: TEdit;
 Edit2: TEdit;
 Button1: TButton;
 Label1: TLabel;
 procedure Edit1KeyPress(Sender: TObject; var Key: Char);
 procedure Edit2KeyPress(Sender: TObject; var Key: Char);
 procedure Button1Click(Sender: TObject);
 private
 { Private declarations }
 public
 { Public declarations }
 end;
 
 type
 TMyThread = class(TThread)
 private
 Num: Array of Integer;
 Ch: Array of Char;
 NotFind: Boolean;
 procedure UpdateLabel;
 protected
 procedure Execute; override;
 end;
 
 var
 Form1: TForm1;
 MyThread: TMyThread;
 
 implementation
 
 {$R *.dfm}
 
 procedure TMyThread.UpdateLabel;
 var
 Str: String;
 I: Integer;
 begin
 Str:= IntToStr(Num[0]);
 For I:= 0 to Length(Ch) - 1 do
 Str:= Str + (Ch[I] + IntToStr(Num[I+1]));
 
 if not NotFind then
 Form1.Label1.Caption:= 'Результат равен: ' + Str
 else Form1.Label1.Caption:= 'Вариант не найден!'
 end;
 
 procedure TMyThread.Execute;
 var
 Res: Integer;
 Tmp: Integer;
 Str: String;
 CountNum, I: Integer;
 
 procedure Change;
 var
 J: Integer;
 begin
 For J:= CountNum-1 downto 0 do
 begin
 if Ch[J] = '+' then
 begin
 Ch[J]:= '-';
 Break;
 end;
 if Ch[J] = '-' then
 begin
 Ch[J]:= '/';
 Break;
 end;
 if Ch[J] = '/' then
 begin
 Ch[J]:= '*';
 Break;
 end;
 if Ch[J] = '*' then
 begin
 if J = 0 then NotFind:= True;
 Ch[J]:= '+';
 end;
 end;
 
 end;
 
 begin
 NotFind:= false;
 Str:= Form1.Edit1.Text;
 Res:= StrToInt(Form1.Edit2.Text);
 CountNum:= Length(Str);
 SetLength(Num, CountNum);
 Dec(CountNum);
 SetLength(Ch, CountNum);
 For I:= 0 to CountNum do
 Num:= StrToInt(Str[I+1]);
 For I:= 0 to CountNum do
 Ch:= '+';
 repeat
 Tmp:= Num[0];
 for I:= 1 to CountNum do
 begin
 if Ch[I-1] = '+' then
 Tmp:= Tmp + Num;
 if Ch[I-1] = '-' then
 Tmp:= Tmp - Num;
 if Ch[I-1] = '/' then
 Tmp:= Tmp div Num;
 if Ch[I-1] = '*' then
 Tmp:= Tmp * Num;
 end;
 if Tmp <> Res then Change;
 //    Sleep(100);
 
 Synchronize(UpdateLabel);
 
 until (Tmp = Res) or (NotFind);
 end;
 
 procedure TForm1.Button1Click(Sender: TObject);
 begin
 MyThread:= TMyThread.Create(false);
 end;
 
 end.
 |  
|   | Курцетов И.А. (статус: Посетитель), 5 мая 2007, 08:26 [#2]:Спасибо за код, но этот код выдает неправильные ответы, ну главное смысл как описать эти варианты понятен. Постараюсь доработать этот код, правда пока не все понимаю в нем. Буду разбираться в нем. |  
|   | Дмитрий-998 (статус: 1-ый класс), 5 мая 2007, 08:42 [#3]:В программе используется второй процесс, во избежании зависания основной программы, во время просчета, вы можете раздокументировать функцию Sleep для того чтоб видеть как он перебирает варианты... |  
|   | Курцетов И.А. (статус: Посетитель), 5 мая 2007, 09:28 [#4]:Прошу прощения за предыдущий ответ, программа работает, не все варианты правильные выдает.Я думаю убрать деление т.к. в некоторых случаях при делении программы выделяет только целую часть. А это неподходит для меня. Точнее для ребенка не подойдет. И я ща столкнулся с таким вариантом деления на 0, и сразу это вызвало ошибку, так что я лучше уберу деление. А так спасибо Вам. Если бы можно было этот ответ оценить, я бы поставил вам 5. Спасибо. |  
|   | Курцетов И.А. (статус: Посетитель), 5 мая 2007, 09:32 [#5]:Еще я думаю добавить в эту программу несколько вариантов, это соединение строк. Например 123456 чтобы не только программа брала отдельно цифры 1 или 2 или 3, а 12+3 уже или 23+4 и т.д. Но думаю уже сам справлюсь. Ведь основной код уже написан.
 |  
|   | Дмитрий-998 (статус: 1-ый класс), 5 мая 2007, 17:50 [#6]:Спасибо за оценку, код был написан за пять минут, поэтому нет проверок на ошибки, такие как деление на ноль, а для чисел с плавующей точкой используйте вычисление в нутри команды ROUND... |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |