![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопросы новичка про цикл и неповторяющиеся числа в массиве.
volkafff © (2011-01-15 17:07:00)Здравствуйте!
1)Я могу написать во так:
z=array[1..10]of integer;
for i:=1 to 10 do
begin
z[i]:=5;
end;
То есть я циклом присваиваю всем элементам массива значение "5".
А как мне сделать что-то подобное:
For i:=1 to 10 do
begin
image[i].visible:=false;
end;
То есть я хочу присвоить 10-ти объектам одно и тоже значение одного и того же свойства.Не получается. Пробовал и круглые,и квадратные скобки- всё равно.Что сделать?
2) Мне нужно,чтобы в массиве были сгенерированные неповторяющиеся числа(порядок карт в колоде).
Хотел сделать так:
X=array[1..10]of integer;(все числа этого массива равны нулю)
number=array[1..10]of integer; (здесь будут храниться сгенерированные числа)
(L-это label)
for i:=1 to 10 do
begin
L:
Z:=random(9)+1;(генерация числа от 1 до 10(для этого генерируется число от 0 до 9 и прибавляется единица))
if x[z]=0 then (в массиве Х только нули.Как только сгенерируется число,скажем,5,то x[5]:=1; сделано для отслеживания повторяющихся чисел)
begin
number[i]:=z;(если небыло раньше такого числа-присвоить его другому массиву под индексом [i])
x[z]:=1;
end
else
goto L(в противном случае повторить генерацию)
end;
Вся проблема способа в том,что двухъядерный компьютер завис на генерации пяти чисел, а я хотел сгенерировать 92 числа. Что мне можно сделать?
Sha (2011-01-17 21:02:00) [1]Процедуры, приведенные в [28], можно немного изменить, чтобы подчеркнуть их общность:
procedure Shuffle(var a: TIntegerArray);
var
i, r, tmp: integer;
begin;
for i:=1 to Length(a)-1 do begin;
r:=Random(i+1);
tmp:=a[i]; a[i]:=a[r]; a[r]:=tmp;
end;
end;
function GetShuffled(n: integer): TIntegerArray;
var
i, r: integer;
begin;
SetLength(Result,n);
for i:=0 to n-1 do begin;
r:=Random(i+1);
Result[i]:=Result[r]; Result[r]:=i;
end;
end;
Inovet (2011-01-17 17:10:00) [2]> [42] Anatoly Podgoretsky © (17.01.11 13:49)
> К тебя просто компьютер стал быстрее, только на три штуки и хватает.
Так чем быстрее, тем больше повторов должно быть.
KSergey (2011-01-17 14:01:00) [3]> Dennis I. Komarov © (17.01.11 11:57) [37]
> > Боюсь, что элемент случайности потеряется напрочь.
> Это еще, вдруг, с какого?
Из природы генераторов псевдослучайных последовательностей, которыми все эти random и являются.
Ega23 (2011-01-17 13:54:00) [4]
> А ты разве не видишь повторы, по три штуки в ряд.
Да я пример просто привёл.
Anatoly Podgoretsky (2011-01-17 13:49:00) [5]
> Гм.. На D2010 и вправду сработало. Раньше, помнится, одинаковые
> числа с некоторой периодичностью выдавались. Типа
А ты разве не видишь повторы, по три штуки в ряд. К тебя просто компьютер стал быстрее, только на три штуки и хватает.
Dennis I. Komarov (2011-01-17 12:52:00) [6]
> RWolf © (17.01.11 12:12) [39]
Ну я [35] и написал, и смайлики еще расовал...
Ega23 (2011-01-17 12:21:00) [7]Удалено модератором
RWolf (2011-01-17 12:12:00) [8]
> Dennis I. Komarov © (17.01.11 11:57) [37]
procedure Randomize;
var
Counter: Int64;
begin
if QueryPerformanceCounter(Counter) then
RandSeed := Counter
else
RandSeed := GetTickCount;
end;
т.е. смысл алгоритма псевдослучайных чисел теряется; с таким же успехом можно считывать значения таймера.
А если CPU не умеет performance counter, то числа вовсе будут повторяться (GetTickCount тикает сравнительно редко).
Ega23 (2011-01-17 12:11:00) [9]
> А чего? :) Будет заслучайнее чем просто случайно ;)
Гм.. На D2010 и вправду сработало. Раньше, помнится, одинаковые числа с некоторой периодичностью выдавались. Типа
var
i: Integer;
begin
for i := 1 to 10 do
begin
Randomize;
Memo1.Lines.Add(IntToStr(Random(1000)));
end;
100
100
100
435
435
435
976
976
976
и т.п.
Dennis I. Komarov (2011-01-17 11:57:00) [10]
> Боюсь, что элемент случайности потеряется напрочь.
Это еще, вдруг, с какого?
RWolf (2011-01-17 11:19:00) [11]
> Dennis I. Komarov © (17.01.11 11:17) [35]
Боюсь, что элемент случайности потеряется напрочь.
Dennis I. Komarov (2011-01-17 11:17:00) [12]
> Randomize вызывать внутри цикла - мсье знает толк в извращениях.
А чего? :) Будет заслучайнее чем просто случайно ;)
Ega23 (2011-01-17 01:14:00) [13]
> v_a_belousov (15.01.11 18:28) [5]
>
> var i: integer; List: TStringList;
> begin
> repeat
> Randomize;
Randomize вызывать внутри цикла - мсье знает толк в извращениях.
DiamondShark (2011-01-16 23:13:00) [14]
> Servy © (16.01.11 22:56) [32]
Все везде подвох ищут.
Разумеется, первый вариант.
Servy (2011-01-16 22:56:00) [15]
> > Random(1), очевидно, всегда возвращает 0.
>
> "Семён Семёныч!"
Боюсь, сия фраза оказалось для меня слишком двусмысленной. Если она означала "Я признаю, что я дал маху", тогда вопрос видимо закрыт. Если же в качестве Семен Семеныча подразумевался я, то могу привести цитату из хелпа:
function Random(const ARange: Integer): Integer; overload;
In Delphi code, Random returns a random number within the range 0 <= X < Range
И заявить, что мне неизвестны другие целые числа, кроме нуля в диапазоне 0 <= X < 1.
DiamondShark (2011-01-16 22:44:00) [16]
> Random(1), очевидно, всегда возвращает 0.
"Семён Семёныч!"
Servy (2011-01-16 22:32:00) [17]
> Если в функции GetShuffled K := Random(I + 1) никогда не
> даст 0, то в Result[0] будет мусорное значение.
Random(1), очевидно, всегда возвращает 0. Если вызова Random(1) не было, это означает, что цикл не выполнился ни разу и размер возвращаемого массива - 0. Можно было вынести Result[0] := 1 за цикл и начинать его с единицы, но понадобилась бы дополнительная проверка, что N > 0 и мне показалось что так, как приведено в [28] будет компактней и нагляднее.
DiamondShark (2011-01-16 22:07:00) [18]
> Servy © (16.01.11 20:31) [28]
Если в функции GetShuffled K := Random(I + 1) никогда не даст 0, то в Result[0] будет мусорное значение.
Servy (2011-01-16 20:31:00) [19]Алгоритм из второй части [0] был бы рабочим, если бы автор потрудился прочитать хелп по функции Random:
> Z:=random(9)+1;(генерация числа от 1 до 10(для этого генерируется
> число от 0 до 9 и прибавляется единица))
Random(9) генерирует случайное число от 0 до 8, соответственно ваш алгоритм уходит в бесконечный цикл после генерации первых 9 чисел, так как сколько Random не вызывай, 10ка в Z не выпадает никогда. Кстати, это можно было бы обнаружить с помощью отладчика, пользуйтесь им.
Кроме того, использование меток (label) - моветон, об этом еще Дейкстра полвека назад писал. И ваша реализация подвержена указанной в [21] проблеме:
> идея "долбится миллион раз пока случайным образом не получишь
> оставшееся единственным число..." на двоечку. ;)
> [23]
Ваш метод просто реализуем и довольно хорош для изучения начинающим. Однако, он проводит N * ln(N) генераций случайных чисел (и возможно перестановок). Кроме того, я затрудняюсь доказать, что он дает все N! возможных перестановок с _равной_ вероятностью, скорее всего это не так.
Метод из [3] кажется мне более правильным, если мы хотим получить равномерное распределение, но удаление случайного элемента из списка при достаточной его длине - затратная операция, так что вряд ли этот алгоритм оптимален с точки зрения производительности.
К счастью, все уже украдено до нас. Как указано по второй ссылке в [26], Кнут во втором томе Искусства программирования в разделе 3.4.2 рассматривает оптимальный алгоритм для получения случайной перестановки. Приведу свою реализацию на Делфи, функция Shuffle для перемешивания заданного массива и функция GetShuffled для получения случайной перестановки чисел [1..N]:
program Project6;
{$APPTYPE CONSOLE}
uses
SysUtils, Types;
procedure Shuffle(var X: TIntegerDynArray);
var
I, K, Tmp: Integer;
begin
for I := High(X) downto 1 do
begin
K := Random(I + 1);
// swap X[K] <-> X[I]
Tmp := X[K];
X[K] := X[I];
X[I] := Tmp;
end;
end;
function GetShuffled(N: Integer): TIntegerDynArray;
var
I, K: Integer;
begin
SetLength(Result, N);
for I := 0 to High(Result) do
begin
K := Random(I + 1);
Result[I] := Result[K];
Result[K] := I + 1; // убрать + 1 для перестановки[0..N-1]
end;
end;
procedure Print(X: TIntegerDynArray);
var
I: Integer;
begin
for I := 0 to High(X) do
Write(X[I], ' ');
Writeln;
end;
var
Test: TIntegerDynArray;
begin
try
Writeln('Shuffle test');
SetLength(Test, 5);
Test[0] := 1;
Test[1] := 3;
Test[2] := 5;
Test[3] := 9;
Test[4] := 15;
Shuffle(Test);
Print(Test);
Writeln('GetShuffled test');
Print(GetShuffled(10));
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Полученные перестановки:
Shuffle test
3 9 5 15 1
GetShuffled test
9 5 6 8 2 1 4 3 10 7
Для разных результатов при разных запусках естественно нужен Randomize.
sniknik (2011-01-16 15:55:00) [20]> Автор не хотел стандартных компонентов, в это, надо полагать, входят и методы всякие.
если не хочет стандартного, то берет только "идею" и реализует все сам.
но честно говоря после (по сути)
> Мне понравилось:
> -- Как мне продварковать влендишным способом?
> Следует описание алгоритма по-русски.
> -- Я ничего не понял. Можно кодом?
> Следует кусок кода.
> - Я ничего не понял. Можно по-русски объяснить?
как то подумалось рановато ему еще чураться стандартного, ему бы хоть как научиться (и лучше правильно).
> Вот наподибие, тько вручную.
можно и так. пишите код. ;) автор вопроса по описанию на это не способен.