2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Прохождение по циклу с произвольным числом счётчиков
Сообщение20.11.2008, 23:48 
Аватара пользователя
В ходе написания появилась постребность проводить перебор по количеству параметров, заранее неизвестному. Для этих целей построил такой алгоритм (описан на Паскале), может кому ещё пригодится:

Динамические массивы a – массив счётчиков m – максимальных значения для каждого из счётчиков. Минимальные значения каждого из счётчиков равны 0. Всего счётчиков maxI+1: от a[0] до a[MaxI].

В алгоритме используются две метки – похоже этот тот случай, когда их использование оправдано

Вначале все счётчики – нули.

i:=maxI;

lb0: While i<maxI do inc(i);
///////////////
Собственно тело цикла
///////////////

lb1: inc(a[i]);
if a[i]>m[i] then
begin
a[i]:=0;
dec(i);
if i<0 then exit;
goto lb1;
end
else
goto lb0;

 
 
 
 
Сообщение21.11.2008, 05:10 
Аватара пользователя
While i<maxI do inc(i); Ужас заменяется на i:=maxI;
Отметок можно избавиться
Код:
i:=maxI;
repeat
inc(a[i]);
if a[i]>m[i] then
  begin
  a[i]:=0;
  dec(i);
  end else  i:=maxI;
until i<0


Только по моему, тут у тебя еще и ошибка в коде.

 
 
 
 
Сообщение21.11.2008, 13:04 
Аватара пользователя
Pavia писал(а):
While i<maxI do inc(i); Ужас заменяется на i:=maxI;


Согласен, конечно, можно, этот у меня в коде остался со времени разработки алгоритма, когда я думал, что при движении вправо по массиву счётчиков с ними тоже пришлось бы что-то делать.

Pavia писал(а):
While i<maxI do inc(i); Ужас заменяется на i:=maxI;


По поводу реализации без goto – в твоём варианте надо бы что-то под корректировать, вот попробуй повесить на кнопочку в форме с компонентом Memo такой код:

Код:
procedure TForm1.Button1Click(Sender: TObject);
var i,j:integer;
s:string;
label lb0;
label lb1;

begin
Memo1.clear;
maxI:=4; //Инициализируем массивы, пусть переменных будет 5
setlength(a,maxI+1);
setlength(m,maxI+1);
for j:=0 to maxI do
m[j]:=j+2;
for j:=0 to maxI do
a[j]:=0;
i:=maxI;

lb0: While i<maxI do inc(i);
/////////////// Собственно тело цикла
  s:='';
  for j:=0 to maxI do
   s:=s+inttostr(a[j]);
  memo1.Lines.Add(s);
///////////////

lb1: inc(a[i]);
     if a[i]>m[i] then
      begin
        a[i]:=0;
        dec(i);
        if i<0 then exit;
        goto lb1;
      end
     else
      goto lb0;
end;


Он должен в Мемо1 вывести список всех 5-ти значных чисел, у которых первая цифра от 0 до 2, вторая – от 0 до 3, и т.д., пятая – от 0 до 6.

И такой:
Код:
procedure TForm1.Button2Click(Sender: TObject);
var i,j:integer;
s:string;
begin
Memo1.clear;
maxI:=4;
setlength(a,maxI+1);
setlength(m,maxI+1);
for j:=0 to maxI do
m[j]:=j+2;
for j:=0 to maxI do
a[j]:=0;
i:=maxI;

repeat
/////////////// Тело цикла должно быть здесь ведь, до первого изменения счётчика?
  s:='';
  for j:=0 to maxI do
   s:=s+inttostr(a[j]);
  memo1.Lines.Add(s);
///////////////

inc(a[i]);
if a[i]>m[i] then
  begin
  a[i]:=0;
  dec(i);
  end else  i:=maxI;
until i<0;

end;

Здесь будут выдаваться лишние числа.

Добавлено спустя 13 минут 15 секунд:

Похоже, понял как надо подправить код, чтобы обойтись без меток:

Код:
while true do
begin
  i:=maxI;
///////////////Тело цикла
  s:='';
  for j:=0 to maxI do
   s:=s+inttostr(a[j]);
  memo1.Lines.Add(s);
///////////////
inc(a[i]);
  while a[i]>m[i] do
  begin
    a[i]:=0;
    dec(i);
    inc(a[i]);
    if i<0 then exit;
  end;

end;

 
 
 
 
Сообщение21.11.2008, 15:37 
Аватара пользователя
Цитата:
Здесь будут выдаваться лишние числа.

Я конечно понимаю в чужом коде труднее разбираться.

Код:
procedure TForm1.Button2Click(Sender: TObject);
var i,j:integer;
s:string;
begin
Memo1.clear;
maxI:=4;
setlength(a,maxI+1);
setlength(m,maxI+1);
for j:=0 to maxI do
m[j]:=j+2;
for j:=0 to maxI do
a[j]:=0;
i:=maxI;


/////////////// Тело цикла должно быть здесь ведь, до первого изменения счётчика?
  s:='';
  for j:=0 to maxI do
   s:=s+inttostr(a[j]);
  memo1.Lines.Add(s);
///////////////

repeat

inc(a[i]);
if a[i]>m[i] then
  begin
  a[i]:=0;
  dec(i);
  end else begin
  i:=maxI;
/////////////// Тело цикла должно быть здесь ведь, до первого изменения счётчика?
  s:='';
  for j:=0 to maxI do
   s:=s+inttostr(a[j]);
  memo1.Lines.Add(s);
///////////////

  end;
until i<0;

end;

 
 
 [ Сообщений: 4 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group