Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 550

/ вопрос открыт /

Здравствуйте, уважаемые эксперты!
Делаю программу в делфи по нахождению возможных вариантов решения. Программа сама по себе простая. Дана строка цифр и надо чтоб компьютер произвел над этими цифрами 4 операции или сложение, или вычитание, или умножение, или деление чтобы получить определенную цифру. Например дана строка 123456, а надо получить 10. Решение 1*2+3+4-5+6=10. Исходная строка может быть любой длины. Помогите написать код для вычисления всевозможных решений. Можно конечно самому написать эти решения, но этих же решений может быть тысячи, и каждый вариант описыть это долго. И еще вопрос. У меня каждый элемент массива "a" присваивает каждую цифру из строки.Длина массива 15. Как сделать, если введенная строка меньше 15 элементов чтоб массив сам уменьшился до количества элементов строки. И потом уже производить операции над этими элементами массива. Надеюсь что найдется решение этих вопросов, ведь нет ничего невозможного. За ранее благодарен.

Приложение:
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9.  
  10. type
  11. TForm1 = class(TForm)
  12. Edit1: TEdit;
  13. Label1: TLabel;
  14. Label2: TLabel;
  15. Label3: TLabel;
  16. Button1: TButton;
  17. Label4: TLabel;
  18. Label5: TLabel;
  19. Label6: TLabel;
  20. Edit2: TEdit;
  21. procedure Edit1KeyPress(Sender: TObject; var Key: Char);
  22. procedure Edit2KeyPress(Sender: TObject; var Key: Char);
  23. procedure Button1Click(Sender: TObject);
  24. procedure Edit1Exit(Sender: TObject);
  25. procedure Edit2Exit(Sender: TObject);
  26. private
  27. { Private declarations }
  28. public
  29. { Public declarations }
  30. end;
  31.  
  32. var
  33. Form1: TForm1;
  34. a: array[1..15] of integer;
  35. i,rez,summ: integer;
  36. implementation
  37.  
  38. {$R *.dfm}
  39.  
  40. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
  41. begin
  42.  
  43. Key := #0;
  44. end;
  45.  
  46. procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
  47. begin
  48.  
  49. Key := #0;
  50. end;
  51.  
  52. procedure TForm1.Button1Click(Sender: TObject);
  53. begin
  54.  
  55.  
  56.  
  57.  
  58.  
  59. end;
  60.  
  61. procedure TForm1.Edit1Exit(Sender: TObject);
  62. begin
  63. for i:=1 to 15 do
  64. begin
  65.  
  66.  
  67.  
  68. end;
  69.  
  70. Edit2.SetFocus;
  71. Button1.Enabled:=true;
  72. end;
  73.  
  74. procedure TForm1.Edit2Exit(Sender: TObject);
  75. begin
  76.  
  77. end;
  78.  
  79. 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

Приложение:
  1. program Q_0550;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6. SysUtils;
  7.  
  8. type
  9. TOperation = (opAdd, opSub, opMul, opDiv);
  10.  
  11. var
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19. function PrepareArrays: Boolean;
  20. var
  21. Index: Integer;
  22. begin
  23. if Length(Digits) < 2
  24.  
  25. Result:= False;
  26. Exit;
  27. end;
  28.  
  29.  
  30.  
  31.  
  32. try
  33. for Index:= 1 to Length(Digits) do
  34. Values[Index - 1]:= StrToInt(Digits[Index]);
  35.  
  36. Result:= True;
  37. except
  38.  
  39. end;
  40.  
  41.  
  42. if Result
  43. then begin
  44. SetLength(Operations, Length(Digits) - 1);
  45. FillChar(Operations[0], Length(Operations), opAdd);
  46. end;
  47. end;
  48.  
  49.  
  50. procedure IncOperations;
  51. var
  52. Index: Integer;
  53. begin
  54. for Index:= 0 to Length(Operations) - 1 do
  55. begin
  56. if Operations[Index] <> opDiv
  57. then Inc(Operations[Index])
  58. else Operations[Index]:= opAdd;
  59.  
  60. if Operations[Index] <> opAdd
  61. then Break;
  62. end;
  63. end;
  64.  
  65.  
  66. function Power4(const APower: Integer): Integer;
  67. var
  68. p: Integer;
  69. begin
  70. Result:= 4;
  71. for p:= 2 to APower do
  72. Result:= Result * 4;
  73. end;
  74.  
  75.  
  76. function Operation2Char(const Op: TOperation): Char;
  77. begin
  78. case Op of
  79. opAdd: Result:= '+';
  80. opSub: Result:= '-';
  81. opMul: Result:= '*';
  82. else Result:= '/';
  83. end; // of case
  84. end;
  85.  
  86.  
  87. function CalculateCurrent: Integer;
  88. var
  89. Index: Integer;
  90. begin
  91. Result:= Values[0];
  92. for Index:= 1 to Length(Values) - 1 do
  93. case Operations[Index - 1] of
  94. opAdd: Result:= Result + Values[Index];
  95. opSub: Result:= Result - Values[Index];
  96. opMul: Result:= Result * Values[Index];
  97. else Result:= Result div Values[Index];
  98. end; // of case
  99. end;
  100.  
  101.  
  102. procedure ResultOut;
  103. var
  104. Index: Integer;
  105. begin
  106. Write(' ', Values[0]);
  107. for Index:= 1 to Length(Values) - 1 do
  108. Write(' ', Operation2Char(Operations[Index - 1]), ' ', Values[Index]);
  109. WriteLn(' = ', Total: 6);
  110. end;
  111.  
  112.  
  113. function CalculateAll: Integer;
  114. var
  115. Index, Count: Integer;
  116. begin
  117. Result:= 0;
  118.  
  119. 2 4
  120. 3 16 = 4^2
  121. 4 64 = 4^3
  122. N 4^(N - 1)
  123. }
  124.  
  125. Count:= Power4(Length(Values) - 1);
  126. for Index:= 1 to Count do
  127. begin
  128. if CalculateCurrent = Total
  129. then begin
  130. ResultOut;
  131. Inc(Result);
  132. end;
  133. IncOperations;
  134. end;
  135. end;
  136.  
  137. begin
  138. repeat
  139. Write(' Enter the digits: ');
  140. ReadLn(Digits);
  141. until PrepareArrays;
  142.  
  143. Write(' Enter the result: ');
  144. ReadLn(Total);
  145.  
  146. WriteLn('//----------------------------------------');
  147. Equals:= CalculateAll;
  148. WriteLn('//----------------------------------------');
  149. if Equals <> 0
  150. then WriteLn(' Total equals: ', Equals)
  151. else WriteLn(' Nothing found :(');
  152.  
  153. ReadLn;
  154. end.
  155.  


Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 7 мая 2007, 10:20


Мини-форум вопроса

Всего сообщений: 6; последнее сообщение — 5 мая 2007, 17:50; участников в обсуждении: 2.
Дмитрий-998

Дмитрий-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

Дмитрий-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

Дмитрий-998 (статус: 1-ый класс), 5 мая 2007, 17:50 [#6]:

Спасибо за оценку, код был написан за пять минут, поэтому нет проверок на ошибки, такие как деление на ноль, а для чисел с плавующей точкой используйте вычисление в нутри команды ROUND...

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:50
Выполнено за 0.03 сек.