# Lazarus

## Programming => General => Topic started by: Slyde on November 21, 2020, 08:04:09 pm

Title: [SOLVED] Randomizing numbers problem
Post by: Slyde on November 21, 2020, 08:04:09 pm
I wrote this

Code: Pascal  [Select][+][-]
1. procedure TForm1.Button1Click(Sender: TObject);
2. var
3.   i, j, f, num : integer;
4.   myArray : array[1..20] of Integer;
5. begin
6.   Randomize;
7.   for i := 1 to 20 do
8.       begin
9.         f := 0;
10.         num := randomrange(0, 19);
11.         for j := 1 to i do
12.           if myArray[j] = num then
13.             f := 1;
14.         if f <> 1 then
15.         begin
16.           myArray[i] := num;
18.         end;
19.       end;
20. end;

and now I'm stuck.  My problem is that I need to subtract from the for-loop i when a random number's in the array, so that it'll dig out all 20 numbers (0 thru 19).
Title: Re: Randomizing numbers problem
Post by: wildfire on November 21, 2020, 08:10:18 pm
If the end requirement is to have an array of randomly stored values 0-19 then you are approaching it from the wrong angle imo.

Fill the array and then randomly swap elements.
Title: Re: Randomizing numbers problem
Post by: Slyde on November 21, 2020, 08:26:07 pm
@wildfire - I wld have to agree with you.  But that's not my endgame.
Title: Re: Randomizing numbers problem
Post by: PascalDragon on November 21, 2020, 08:35:04 pm
and now I'm stuck.  My problem is that I need to subtract from the for-loop i when a random number's in the array, so that it'll dig out all 20 numbers (0 thru 19).

What do you mean with "I need to substract from the for-loop i "? What is the result you want to achieve?

By the way: it's cleaner if you declare your f as a Boolean, initialize it with False, inside the check loop set it to True and later on do if f then. Also you can add a Break statement in your check loop once you've found the number:

Code: Pascal  [Select][+][-]
1.         for j := 1 to i do
2.           if myArray[j] = num then begin
3.             f := True;
4.             Break;
5.           end;
Title: Re: Randomizing numbers problem
Post by: jamie on November 21, 2020, 08:42:46 pm
maybe he wants an array of 0..19 in value then with that have a  1 - 20 counter where as it uses Random(0,19) as an exchange index of the last random that was used..

basically no need to determine if there is a duplication in there list from a random value, just use the random value as swap indexes.
Title: Re: Randomizing numbers problem
Post by: Slyde on November 21, 2020, 08:46:17 pm
I need to have an array of 0 to number of records in my SQLite3 Table(s). Since I don't want to have the same Questions spill out in the same order each time, I'll use this array to seed the form with randomly selected questions, based off the array.

And since i increments each pass through the loop, I need to decrease it ( i := i -1) so that it doesn't leave my array void of all 20 numbers.

The code I posted is for my testing. Nothing more.
Title: Re: Randomizing numbers problem
Post by: lucamar on November 21, 2020, 09:04:36 pm
Try this:

Code: Pascal  [Select][+][-]
1. procedure TForm1.Button1Click(Sender: TObject);
2. var
3.   i, num, Count : integer;
4.   myArray : array[1..20] of Integer;
5.
6.   function InArray(num: Integer): Boolean;
7.   var i: Integer;
8.   begin
9.     Result := False;
10.     for i := 1 to Count do begin
11.       Result := myArray[i] = num;
12.       if Result then Break
13.     end;
14.   end;
15.
16. begin
17.   Randomize;
18.   repeat
19.     repeat
20.       num := randomrange(0, 19);
21.     until not InArray(num);
22.     Inc(Count);
23.     myArray[Count] := num;
25.   until Count = Length(myArray);
26. end;

Title: Re: Randomizing numbers problem
Post by: Slyde on November 21, 2020, 09:11:50 pm
@lucamar - It hangs.  I'll study it and see if I can fix it.  Thank you.
Title: Re: Randomizing numbers problem
Post by: lucamar on November 21, 2020, 09:27:46 pm
@lucamar - It hangs.  I'll study it and see if I can fix it.  Thank you.

Oops! Forgot to initialize Count :-[
Code: Pascal  [Select][+][-]
1. procedure TForm1.Button1Click(Sender: TObject);
2. var
3.   num, Count : integer;
4.   myArray : array[1..20] of Integer;
5.
6.   function InArray(num: Integer): Boolean;
7.   var i: Integer;
8.   begin
9.     Result := False;
10.     for i := 1 to Count do begin
11.       Result := myArray[i] = num;
12.       if Result then Break
13.     end;
14.   end;
15.
16. begin
17.   Randomize;
18.   Count := 0;
19.   repeat
20.     repeat
21.       num := randomrange(0, 19);
22.     until not InArray(num);
23.     Inc(Count);
24.     myArray[Count] := num;
26.   until Count = Length(myArray);
27. end;

ETA: The attached image seems to show only 10 numbers but that is because I forgot to set the memo's scroll bars :-[
Title: Re: Randomizing numbers problem
Post by: Slyde on November 21, 2020, 09:29:00 pm
Got it.  Had to set Count var to 0:

Code: Pascal  [Select][+][-]
1. begin
2.   Randomize;
3.   Count:=0;
4.   repeat
5.     repeat
6.       num := randomrange(0, 19);
7.     until not InArray(num);
8.     Inc(Count);
9.     myArray[Count] := num;
11.   until Count = Length(myArray);
12. end;

Thanks, lucamar.
Title: Re: Randomizing numbers problem
Post by: winni on November 21, 2020, 09:35:13 pm
Hi!

So often forgotten: Sets.

This is a typical situation where it reduces the code.

Come back later when I fixed my  brandnew USB stick.

Winni

Title: Re: Randomizing numbers problem
Post by: Slyde on November 21, 2020, 10:24:13 pm
Count, initialized to 0, locks it up. But if I initialize it to 1, it skips a number and only gives 19 of the 20.

I see where you (lucamar) increase Count, but it goes to the function as 0 on first try.  So, is the for-loop locking this up?

Code: Pascal  [Select][+][-]
1. for i := 1 to Count do begin
Title: Re: Randomizing numbers problem
Post by: Roland57 on November 21, 2020, 10:31:03 pm
Hello! Another proposition. (I hope I correctly understood what you need.)

Code: Pascal  [Select][+][-]
1. type
2.   TIntArray = array of integer;
3.
4. function Pick(var a: TIntArray): integer;
5. var
6.   i: integer;
7. begin
8.   i := Random(Length(a));
9.   result := a[i];
10.   a[i] := a[Pred(Length(a))];
11.   SetLength(a, Pred(Length(a)));
12. end;
13.
14. var
15.   a: TIntArray;
16.   i: integer;
17.
18. begin
19.   Randomize;
20.   SetLength(a, 20);
21.   for i := 0 to 19 do
22.     a[i] := i;
23.   for i := 0 to 19 do
24.     WriteLn(Pick(a));
25. end.
26.
Title: Re: Randomizing numbers problem
Post by: jamie on November 21, 2020, 10:32:13 pm
this is my version

Code: Pascal  [Select][+][-]
1. procedure TForm1.Button1Click(Sender: TObject);
2. Var
3.   i:integer;
4.   A:Array[0..19]of Integer;
5.      Procedure Exchange(J,K:Integer);
6.       Var
7.         C,D:Integer;
8.       Begin
9.         C := A[J];D:=A[k];
10.         A[J] :=D;
11.         A[K] :=C;
12.       End;
13. begin
14.   Memo1.Lines.Clear;
15.   For I := 0 to 19 do A[I] := I+1; //Test load an array with 1..20 numbers
16.   //--
17.   For I := 0 to 19 Do
18.      Exchange(I,Random(19));
19.
20.   For I := 0 to 19 do memo1.Lines.Add(IntToStr(A[I]));  //display results
21. end;
22.
23.

This does not dead lock because it just takes what it has but the available numbers are predefined so all that needs to be done is mixed up the array of them without searching for duplicates. etc
Title: Re: Randomizing numbers problem
Post by: lucamar on November 21, 2020, 10:40:51 pm
I see where you (lucamar) increase Count, but it goes to the function as 0 on first try.  So, is the for-loop locking this up?

No, in that case the for loop won't execute at all so the function will return False. The "until" test then becomes "not False", which is True, so the execution will go on and add the very first number to the array.

It works as it should here.
Title: Re: Randomizing numbers problem
Post by: Slyde on November 21, 2020, 10:46:48 pm
Perfect, jamie.  Code to study and learn from.  Have it in my app now.  I'll look at yours too, Roland57.  I can't hardly wait to see what winni does with Sets.  You guys/gals have a nice Forum here.  Very, very nice place.

**UPDATE - @jamie - the first button click produces same results each time.  It's not really random.  But thank you for your effort.  I have a lot to build on, thanks to all of you.
Title: Re: Randomizing numbers problem
Post by: jamie on November 21, 2020, 10:58:21 pm
yes, you may need to use the "RadomMize" at first to change the seed value
Title: Re: Randomizing numbers problem
Post by: Slyde on November 21, 2020, 11:10:46 pm
@jamie - Gotcha.  It now randomizes each time.  Many thanks.
Title: Re: [SOLVED] Randomizing numbers problem
Post by: howardpc on November 21, 2020, 11:32:44 pm
I don't know what Jamie had in mind with sets, but it may have been something like this:
Code: Pascal  [Select][+][-]
1. procedure TForm1.Button2Click(Sender: TObject);
2. var
3.   setb: set of Byte = [];
4.   questionList: array[1..100] of string[12];
5.   i: Integer;
6.   idx: Byte;
7.   questionSelection: array[1..20] of string[12];
8.   s: String[12];
9.
10. begin
11.   for i := Low(questionList) to High(questionList) do
12.     questionList[i] := 'Question ' + i.ToString;  // questionList simulates your database of questions
13.
14.   Randomize;
15.   i := 0;
16.   repeat
17.     idx := Succ(Random(100));
18.     case (idx in setb) of
19.       True: ;
20.       False: begin
21.                Include(setb, idx);
22.                Inc(i);
23.                questionSelection[i] := questionList[idx];
24.              end;
25.     end;
26.   until i = 20;
27.
28.   Memo1.Clear;
29.   for s in questionSelection do