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;
  17.           Memo1.Lines.Add(inttostr(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;
  24.     Memo1.Lines.Add(inttostr(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;
  25.     Memo1.Lines.Add(inttostr(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;
  10.     Memo1.Lines.Add(inttostr(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.

Thanks for all your help.

**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
  30.     Memo1.Lines.Add(s);
  31. end;
Title: Re: [SOLVED] Randomizing numbers problem
Post by: Slyde on November 22, 2020, 12:10:54 am
@howardpc - Nice code.  I plugged that in and it worked without a glitch.  It's pretty advanced for me, though, so I'll definitely need to study it.  Thanks for the offering.  Much appreciated.
TinyPortal © 2005-2018