Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2011.04.17;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.59 MB
Время: 0.005 c
15-1293625833
dmk
2010-12-29 15:30
2011.04.17
Можно ли сделать общий загрузчик


2-1295205120
v_a_belousov
2011-01-16 22:12
2011.04.17
Перемещение объектов по дробной координате


15-1293983270
Aleks
2011-01-02 18:47
2011.04.17
Сеть и базы данных


2-1294828261
Студент
2011-01-12 13:31
2011.04.17
Насколько я неправильно использую SetLength?


2-1294441804
Студент
2011-01-08 02:10
2011.04.17
Как открыть своё окно как бы "модальным" поверх чужого?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский