Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.04.17;
Скачать: CL | DM;

Вниз

Вопросы новичка про цикл и неповторяющиеся числа в массиве.   Найти похожие ветки 

 
volkafff ©   (2011-01-15 17:07) [0]

Здравствуйте!
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 числа. Что мне можно сделать?


 
Сергей М. ©   (2011-01-15 17:28) [1]


> двухъядерный компьютер завис на генерации пяти чисел, а
> я хотел сгенерировать 92 числа


92 дели на 5, умножь на 2 и прибавь к результату еще процентов 30-40 "про запас" - получишь число ядер, способных решить твою астронимически сложную задачу


 
volkafff ©   (2011-01-15 17:31) [2]

Вот есть ряд чисел:
1 2 3 4 5

мне нужен он же,но в другой последовательности:
3 1 5 2 4
или
5 1 4 3 2
и т.д.
Как это можно сделать?


 
Сергей М. ©   (2011-01-15 18:00) [3]

загони ряд в список, например, в TList

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


 
volkafff ©   (2011-01-15 18:08) [4]

Я не то чтобы не очень понял, я ВООБЩЕ ничего не понял.Можно кодом?(желательно всё) и.если возможно, без стандартных компонентов delphi.


 
v_a_belousov   (2011-01-15 18:28) [5]

var i: integer; List: TStringList;
begin
repeat
Randomize;
i := random(92);
if i<>0 then
begin
 if List.IndexOf(IntToStr(i))=-1 then
  List.Add(IntToStr(i));
end;
Application.ProcessMessages;
until List.Count+1=92;
end;


 
volkafff ©   (2011-01-15 18:37) [6]

v_a_belousov
Спасибо! А можно чуть-чуть поподробнее про то,что здесь творится+ответ на первый вопрос?


 
v_a_belousov   (2011-01-15 18:42) [7]


> Мне нужно,чтобы в массиве были  сгенерированные неповторяющиеся
> числа(порядок карт в колоде)


> завис на генерации пяти чисел, а я хотел сгенерировать 92
> числа. Что мне можно сделать?


> что здесь творится


Генерируем тебе 92 числа.


> ответ на первый вопрос?

А что тебе ещё нужно я думаю не только я не понял...


 
volkafff ©   (2011-01-15 18:52) [8]

1)"Что здесь твориться"-всмысле вот так:

"Загружаем bmp-файл в компонент image1. Загружаем его в массив картинок. Очищаем массив цифр."

и т.п. то есть объясните пожалуйста по действиям,что происходит.

2)Вот первый вопрос:

> Здравствуйте!1)Я могу написать во так:z=array[1..10]of integer;
> for i:=1 to 10 dobeginz[i]:=5;end;То есть я циклом присваиваю
> всем элементам массива значение "5".А как мне сделать что-
> то подобное:For i:=1 to 10 dobeginimage[i].visible:=false;
> end;То есть я хочу присвоить 10-ти объектам одно и тоже
> значение одного и того же свойства.Не получается. Пробовал
> и круглые,и квадратные скобки- всё равно.Что сделать?


 
v_a_belousov   (2011-01-15 18:58) [9]


> объясните пожалуйста по действиям,что происходит

var i: integer; List: TStringList; - объявляем переменные
begin
repeat - начинаем цикл
Randomize; - делаем выбор числа случайным...
i := random(92); - генерируем число
if i<>0 then - если не равно 0, то
begin
if List.IndexOf(IntToStr(i))=-1 then - если его ещё нет в списке
 List.Add(IntToStr(i)); - то добавляем его туда
end;
Application.ProcessMessages; - не зависаем
until List.Count+1=92; - цикл закончится когда будут сгенерированы все числа
end;


 
Сергей М. ©   (2011-01-15 19:00) [10]


> Можно кодом?.. без стандартных  компонентов delphi.


Можно если ты вразумительно ответишь на вопрос, где ты увидел хоть намек на компоненты и чем они тебе не угодили


 
v_a_belousov   (2011-01-15 19:00) [11]


> Вот первый вопрос:

чтобы дать тебе ответ на него объясни где у тебя изображения... сколько их... что нужно сделать подробнее...


 
Сергей М. ©   (2011-01-15 19:03) [12]


> v_a_belousov   (15.01.11 18:28) [5]


Забивать гвозди и микроскопом можно)


 
v_a_belousov   (2011-01-15 19:10) [13]


> Сергей М.

ну да)


 
volkafff ©   (2011-01-15 19:19) [14]

Я хочу сделать подобие гастольной игры.Там будет поле из 100 карточек,каждую игру оно генерируется заново.
Есть 100 картинок-полей.
Генерируется массив случайных чисел "Х"-порядок этих карточек.
Потом в массиве "Y" картинки-поля распологаются в соответствии с массивом "Х". И последнее-отображение самого поля:

For Z:=1 to 100 do
begin
image[z].picture:=Y[z];
end;

То есть все сгенерированные картинки встают на свои места. Но такая запись("image[z].")не подходит.Что делать?

2)У меня есть массив:
Pic=array[1..10]of tpicture;

В папке с программой есть картинки.Мне нужно как-то их загрузить в этот массив,но так,чтобы при переносе на другой компьютер всё работало. Как это можно сделать?


 
RWolf ©   (2011-01-15 19:28) [15]


> Но такая запись("image[z].")не подходит.Что делать?

(FindComponent("Image"+IntToStr(i)) as TImage).


 
v_a_belousov   (2011-01-15 19:30) [16]


> volkafff ©

К примеру оставим твою концепцию. Как сгенерировать 100 чисел в разном порядке я тебе показал. Теперь тебе нужно только изображениям задать картинки в нужном порядке... следовательно у тебя на форме находится 100 Image. Image1..Image100

тогда делай так

for i:=1 to Length(Y) do
begin
 TImage(FindComponent("Image"+IntToStr(i))).Picture := Y[x[i-1]];
end;


> В папке с программой есть картинки.Мне нужно как-то их загрузить
> в этот массив,но так,чтобы при переносе на другой компьютер
> всё работало. Как это можно сделать?

сделать ресурс... или загрузить сразу в Image...


 
Anatoly Podgoretsky ©   (2011-01-15 21:38) [17]

Вообще то это конференция для начинающих, а для новичков у нас нет конференции.


 
DiamondShark ©   (2011-01-15 23:23) [18]

Мне понравилось:
-- Как мне продварковать влендишным способом?
Следует описание алгоритма по-русски.
-- Я ничего не понял. Можно кодом?
Следует кусок кода.
- Я ничего не понял. Можно по-русски объяснить?


 
Sha ©   (2011-01-16 09:53) [19]

v_a_belousov   (15.01.11 18:28) [5]

Плохой алгоритм, на троечку.
Попробуйте еще раз, если хотите исправить оценку :)


 
v_a_belousov   (2011-01-16 13:23) [20]


> Sha

Я не старался написать полноценный алгоритм) я показал саму идею...


 
sniknik ©   (2011-01-16 14:18) [21]

> я показал саму идею...
идея "долбится миллион раз пока случайным образом не получишь оставшееся единственным число..." на двоечку. ;)

если нужна "перетасовка" то лучше сделать сортировку по случайному значению. (там где то customsort есть). результат будет тот же, а времени займет много меньше.


 
sniknik ©   (2011-01-16 14:24) [22]

+
идея работать со строковыми представлениями чисел... также на 2
взял бы уж тогда TList и хранил числа.


 
sniknik ©   (2011-01-16 14:41) [23]

вот, "моя идея", если убрать заполнение/просмотр, то все нужное для перемешивания это List.CustomSort(MySort);

function MySort(List: TStringList; Index1, Index2: Integer): Integer;
begin
 result:= Random(3) - 1;
end;

procedure TForm1.Button5Click(Sender: TObject);
var
 i: integer;
 List: TStringList;
 st: string;
begin
 List:= TStringList.Create;
 try
   for i:= 1 to 92 do //это по идее должно быть заполнено 1 раз, при старте например
     List.AddObject("", Tobject(i));
   Randomize;         //тоже достаточно 1 раз, при старте например

   List.CustomSort(MySort); //собственно "перемешивание"

   st:= "";
   for i:= 0 to 92-1 do //посмотрим что получилось
     st:= st + IntToStr(Integer(List.Objects[i])) + #13#10;
   Memo1.Text:= st;
 finally
   List.Free;
 end;
end;


 
v_a_belousov   (2011-01-16 14:43) [24]


> sniknik

да конечно надо делать по другому... как уже писали:


> ...циклами выбираешь из списка элемент со случ.индексом...


да и ещё много как можно... но если у него всего 100 цифр, то ничего страшного не случится и если сделать так как у меня.


 
Inovet ©   (2011-01-16 15:04) [25]

> [21] sniknik ©   (16.01.11 14:18)
> там где то customsort есть

Автор не хотел стандартных компонентов, в это, надо полагать, входят и методы всякие.

Вот наподибие, тько вручную.

Массив на 92 елемента.
Цикл от 91 до 0
Перестановка двух елементов в массиве с индексами текущее_значение_итератора и сенерированного рандомного значения в диапазоне 0-текущее_значение_итератора.


 
MBo ©   (2011-01-16 15:15) [26]

1.  http://www.delphimaster.ru/articles/comparray.html
2.  http://en.wikipedia.org/wiki/Fisher–Yates_shuffle
по сути - то, что уже описал Сергей М. ©   (15.01.11 18:00) [3]


 
sniknik ©   (2011-01-16 15:55) [27]

> Автор не хотел стандартных компонентов, в это, надо полагать, входят и методы всякие.
если не хочет стандартного, то берет только "идею" и реализует все сам.

но честно говоря после (по сути)
> Мне понравилось:
> -- Как мне продварковать влендишным способом?
> Следует описание алгоритма по-русски.
> -- Я ничего не понял. Можно кодом?
> Следует кусок кода.
> - Я ничего не понял. Можно по-русски объяснить?

как то подумалось рановато ему еще чураться стандартного, ему бы хоть как научиться (и лучше правильно).

> Вот наподибие, тько вручную.
можно и так. пишите код. ;) автор вопроса по описанию на это не способен.


 
Servy ©   (2011-01-16 20:31) [28]

Алгоритм из второй части [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.


 
DiamondShark ©   (2011-01-16 22:07) [29]


> Servy ©   (16.01.11 20:31) [28]

Если в функции GetShuffled  K := Random(I + 1) никогда не даст 0, то в Result[0] будет мусорное значение.


 
Servy ©   (2011-01-16 22:32) [30]


> Если в функции 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:44) [31]


> Random(1), очевидно, всегда возвращает 0.

"Семён Семёныч!"


 
Servy ©   (2011-01-16 22:56) [32]


> > 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 23:13) [33]


> Servy ©   (16.01.11 22:56) [32]

Все везде подвох ищут.
Разумеется, первый вариант.


 
Ega23 ©   (2011-01-17 01:14) [34]


> v_a_belousov   (15.01.11 18:28) [5]
>
> var i: integer; List: TStringList;
> begin
> repeat
> Randomize;

Randomize вызывать внутри цикла - мсье знает толк в извращениях.


 
Dennis I. Komarov ©   (2011-01-17 11:17) [35]


> Randomize вызывать внутри цикла - мсье знает толк в извращениях.

А чего?  :) Будет заслучайнее чем просто случайно ;)


 
RWolf ©   (2011-01-17 11:19) [36]


> Dennis I. Komarov ©   (17.01.11 11:17) [35]

Боюсь, что элемент случайности потеряется напрочь.


 
Dennis I. Komarov ©   (2011-01-17 11:57) [37]


> Боюсь, что элемент случайности потеряется напрочь.

Это еще, вдруг, с какого?


 
Ega23 ©   (2011-01-17 12:11) [38]


> А чего?  :) Будет заслучайнее чем просто случайно ;)


Гм.. На 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
и т.п.


 
RWolf ©   (2011-01-17 12:12) [39]


> 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:21) [40]

Удалено модератором


 
Dennis I. Komarov ©   (2011-01-17 12:52) [41]


> RWolf ©   (17.01.11 12:12) [39]

Ну я [35] и написал, и смайлики еще расовал...


 
Anatoly Podgoretsky ©   (2011-01-17 13:49) [42]


> Гм.. На D2010 и вправду сработало. Раньше, помнится, одинаковые
> числа с некоторой периодичностью выдавались. Типа

А ты разве не видишь повторы, по три штуки в ряд. К тебя просто компьютер стал быстрее, только на три штуки и хватает.


 
Ega23 ©   (2011-01-17 13:54) [43]


> А ты разве не видишь повторы, по три штуки в ряд.

Да я пример просто привёл.


 
KSergey ©   (2011-01-17 14:01) [44]

> Dennis I. Komarov ©   (17.01.11 11:57) [37]
> > Боюсь, что элемент случайности потеряется напрочь.
> Это еще, вдруг, с какого?

Из природы генераторов псевдослучайных последовательностей, которыми все эти random и являются.


 
Inovet ©   (2011-01-17 17:10) [45]

> [42] Anatoly Podgoretsky ©   (17.01.11 13:49)
> К тебя просто компьютер стал быстрее, только на три штуки и хватает.

Так чем быстрее, тем больше повторов должно быть.


 
Sha ©   (2011-01-17 21:02) [46]

Процедуры, приведенные в [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;



Страницы: 1 2 вся ветка

Текущий архив: 2011.04.17;
Скачать: CL | DM;

Наверх




Память: 0.61 MB
Время: 0.01 c
1-1251790955
Fr0sT
2009-09-01 11:42
2011.04.17
FastCode и D2009


15-1294155528
Sidak
2011-01-04 18:38
2011.04.17
Выпускная работа


2-1294988529
alexlotov
2011-01-14 10:02
2011.04.17
Delphi 7 ставит точки трассировки куда попало


15-1294066387
KilkennyCat
2011-01-03 17:53
2011.04.17
В разделе "начинающим" есть про акустический резонанс.


15-1293372734
Мимо не прошел
2010-12-26 17:12
2011.04.17
Свое