[DELPHI] 220 random waardenmaken maar ongeveer gelijk aantal

Pagina: 1
Acties:
  • 167 views sinds 30-01-2008
  • Reageer

  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
Ik probeer een array te vullen met random getallen die 0 of 1 zijn. Onjuist of juist. Het probleem is nu dat de toets die ik probeer na te maken altijd een ongeveer gelijk aantal juist als onjuist items heeft. Dus allebei ongeveer 110. Er zit wel wat variatie in, dus het kan zeg maar 110+/- 2 zijn voor zowel juist als onjuist

Ik weet niet hoe ik dit moet maken, want nu krijg ik de ene keer wel 109 en 111 maar de andere keer krijg ik dan weer zeg maar 97 en 123.
Nou kan ik wel elke keer controleren als ik er 220 gemaakt heb of # juist ongeveer 110 is, maar dit lijkt me erg omslachtig, zo kan het dan voorkomen dat ik 10 keer achter elkaar de loop moet laten draaien, en aangezien het een statistisch programma moet worden, waarbij ik de mogelijkheid moet hebben om op lange termijn (1000 keer of meer) dit uit te voeren, lijkt het me erg inefficiënt.

Daarom zal ik misschien een willekeurige array moeten maken ofzo en dan op de een of andere manier een set opeenvolgende data moeten plukken die voldoen aan die 110 +/-2 regel. Iemand een idee?


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
procedure vulantwoorden;
var
jo: byte;
i: byte;
begin
  juist := 0;
  onjuist := 0;
    randomize;
  for i := 1 to 220 do
  begin

    jo:= random(2);
    antwoorden[i] := random(2);

    if jo = 1 then
      begin
      inc(juist);
      end
    else if jo = 0 then
      begin
      inc(onjuist);
      end;
  end;

end;


array antwoorden is gewoon van type byte en kan 220 waarden bevatten.

Verwijderd

Waarom moet je toets ongeveer evenveel 'juist' als 'onjuist' antwoorden hebben?

Is de ene random lijst minder random dan een andere random lijst?

.....

Maar goed: een algoritme:
Stop alle genummerde vragen in een array of stack of whatever.
Ga om en om de waarde 'juist' en 'onjuist' toekennen aan vragen die je in willekeurige volgorde van de lijst haalt. Doe dit totdat de 'stack' leeg is, en je hebt alle vragen gehad, dan heb je evenveel juiste als onjuiste antwoorden.

[ Voor 64% gewijzigd door Verwijderd op 28-05-2003 19:36 ]


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Doe het voor de gein es 1000 keer en bepaal het gemiddelde?

  • André
  • Registratie: Maart 2002
  • Laatst online: 19-08 12:30

André

Analytics dude

Je zult zelf die array moeten maken, want met de random functie is het zelfs mogelijk dat je 220 keer 'juist' krijgt...

Wat wel een optie is, is een array van 216 0'len en 1'nen te maken en daar random 4 keer een 0 of 1 aan toe te voegen.

En daarna die array met een random functie te 'schudden'.

[ Voor 51% gewijzigd door André op 28-05-2003 19:40 ]


  • Eskimootje
  • Registratie: Maart 2002
  • Laatst online: 12:21
Een array vullen met evenveel 1 als 0len en die random uitlezen bijhouden welke je gehad hebt. etc.

  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
het aantal keren juist en onjuist is gelijk. Alleen de volgorde die moet random zijn. En niet het complete aantal keren juist of onjuist. Als ik een array maak met 110xjuist en 110x onjuist en ik trek daar random uit, dan nog krijg ik in mijn uiteindelijke array een verschil in het aantal keren dat juist is getrokken en onjuist. Tenzij ik controleer voor al gebruikte getallen.... hmmmmm

Bij kans is het normaal zo dat bijv met munt gooien je na oneindig aantal keren de kans op 0.5 krijgt voor kop. Maar of dit bij random ook opgaat?

Ik probeer een bestaande toets na te maken, dus daarom moet het ongeveer evenveel zijn.

Ja na 1000 keer 220 keer een random waarde krijg ik dus

0,996551411198838 uit voor de deling: juist/onjuist, dus uiteindelijk komt het wel uit ongeveer.


Moet ik dan eigenlijk voor die variatie een array maken die eigenlijk net iets groter is dan de 220 en dan daaruit 220 waarden trekken, dus bijv. 226 waarden en dan er 220 uit trekken, en een check maken dat zodra een waarde gelezen is, een nieuwe waarde in de array geschreven wordt en die plaats dan met een check niet meer gebruikt wordt.

[ Voor 43% gewijzigd door REDFISH op 28-05-2003 19:43 ]


Verwijderd

Een reden waarom jouw random juist minder goed is dan een echte random lijst:

Stel, je hebt een x aantal waar/niet waar vragen.

Als je y aantal vragen zeker weet, en je hebt al x/2 maal het antwoord 'waar' of x/2 maal het antwoord 'niet waar', dan is kun je alle overgebleven vragen invullen zonder ze uberhaupt te lezen.

Wat mij betreft moet je met kansberekening niet voor god gaan spelen ;)
Laas chaos gewoon zijn werk doen.

  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
André schreef op 28 May 2003 @ 19:35:
Je zult zelf die array moeten maken, want met de random functie is het zelfs mogelijk dat je 220 keer 'juist' krijgt...

Wat wel een optie is, is een array van 216 0'len en 1'nen te maken en daar random 4 keer een 0 of 1 aan toe te voegen.

En daarna die array met een random functie te 'schudden'.
schudden?

  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
Verwijderd schreef op 28 May 2003 @ 19:45:
Een reden waarom jouw random juist minder goed is dan een echte random lijst:

Stel, je hebt een x aantal waar/niet waar vragen.

Als je y aantal vragen zeker weet, en je hebt al x/2 maal het antwoord 'waar' of x/2 maal het antwoord 'niet waar', dan is kun je alle overgebleven vragen invullen zonder ze uberhaupt te lezen.

Wat mij betreft moet je met kansberekening niet voor god gaan spelen ;)
Laas chaos gewoon zijn werk doen.
Volgens mij klopt niks van je redenering.
Alleen als je de helft zeker weet dan kun je de andere helft ook invullen.
Maar stel je weet er maar 50, dan weet je dat er nog 110-het aantal dat je ingevuld hebt als juist vragen juist zijn en 110-het aantal vragen dat je als onjuist ingevuld hebt aan vragen zijn, maar niet welke wanneer.

[ Voor 22% gewijzigd door REDFISH op 28-05-2003 19:55 ]


Verwijderd

REDFISH schreef op 28 May 2003 @ 19:48:

Volgens mij klopt niks van je redenering.
Alleen als je de helft zeker weet dan kun je de andere helft ook invullen.
Maar stel je weet er maar 50, dan weet je dat er nog 110-het aantal dat je ingevuld hebt als juist vragen juist zijn en 110-het aantal vragen dat je als onjuist ingevuld hebt aan vragen zijn, maar niet welke wanneer.
Lees mijn verhaal nu nog eens, en dan wél goed.

  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
Ja dan leg het maar es uit, want volgens mij gaat het alleen op als je x/2 vragen zeker weet. En niet als je er y weet. Stel je weet er 10 zeker. toevallig 10 keer waar. De rest moet je dus op basis van kans gaan invullen. Je weet alleen zeker dat er dan nog 100 waar komen en 110 onwaar. Ik kom er niet uit, wat heeft Y er nu mee te maken?

  • André
  • Registratie: Maart 2002
  • Laatst online: 19-08 12:30

André

Analytics dude

Ja, de waarden in die array verwisselen, swappen, omdraaien, de volgorde veranderen.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Hij zegt dan ook dat die y gelijk is aan x/2 ;)
Verwijderd schreef op 28 mei 2003 @ 19:45:
Als je y aantal vragen zeker weet, en je hebt al x/2 maal het antwoord 'waar' of x/2 maal het antwoord 'niet waar'
't Staat er alleen niet heel duidelijk en in die zin klopt de redenatie ook niet helemaal.

Want als je er x/2 zeker weet, ongeacht of die juist/niet juist zijn kan je al vrij zeker zijn dat je de toets haalt.

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
ofwel snap ik hem niet

ofwel: je roept 110 keer een functie aan die 'juist' plaats op een random plaats - als er op die plaats al iets 'gezet' is (ie == 1) dan probeer nog een random plekje.

ofwel: je vult een array met een 'error' functie (je houdt bij hoevel goede erin zitten en dan laat je de volgende random afhangen van het verschil - dus als goede > gemiddeld dan is de volgende random meer naar de foute kant)

ofwel: je vult een array met 110 goed antwoorden (en de rest staat op nul) en dan ga je ene bepaald aantal keer random plaatsjes swappen (of als je ze allemaal zeker 1 keer wil doen ga je het volledige lijstje af)...

  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
Ok ik heb het gemaakt, maar ik kan het niet helpen dat ik het wat inefficiënt vind dat de while lus telkens tussen de 900 en 1500 keer wordt aangeroepen om 220 waarden door elkaar te husselen. Naarmate ik de 220 nader worden er natuurlijk steeds vaker waarden gekozen die al geweest zijn. Kan dit efficiënter?

het begint namelijk zo:

Het 1e random getal is: 217
Deze index uit evenwicht bevat 1 en wordt geschreven naar positie: 1
Het 2e random getal is: 2
Deze index uit evenwicht bevat 0 en wordt geschreven naar positie: 2
Het 3e random getal is: 71
Deze index uit evenwicht bevat 0 en wordt geschreven naar positie: 3
Het 4e random getal is: 36
Deze index uit evenwicht bevat 0 en wordt geschreven naar positie: 4

En eindigt zo:


Het 679e random getal is: 5
deze waarde (5) is al gekozen, opnieuw random
Het 680e random getal is: 60
deze waarde (60) is al gekozen, opnieuw random

etc.

Heel veel te vaak dus.
Zie ik ook dat een memo een nogal gelimiteerde hoeveelheid text kan bevatten...

vulevenwicht is gewoon de procedure die de array waaruit gekozen wordt vult.

Maak een random getal. Heeft de index geen negen? dan pakt ie dat getal en zet het in de gehusselde array op de positie van het aantal keren valide geproduceerde index. En daarna wordt de betreffende gekozen index de waarde 9 toegekend zodat die niet meer gekozen wordt volgende keer.
Is het wel een 9 opnieuw random.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
procedure tform1.vulantwoorden;
var

temp,totaalkeren,gekozenwaarden : integer;

begin
vulevenwicht;
randomize;
gekozenwaarden := 0;
totaalkeren := 0;

  while gekozenwaarden < 220 do
    begin
      inc(totaalkeren);
      temp := random(220)+1;
      if (evenwicht[temp] = 9) then
        begin
          memo1.lines.add('deze waarde is al gekozen, opnieuw random');
        end

      else
        begin
        inc(gekozenwaarden);
        gekozen[gekozenwaarden]:= evenwicht[temp];
        evenwicht[temp] := 9;
        end;


    end;
   memo1.lines.add('delaatste index gekozen was ' + inttostr(temp));
   memo1.lines.add('De loop was ' + inttostr(totaalkeren) + ' uitgevoerd');

end;

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 22-08 18:12
Redfish, je eerste idee wat volgens mij beste: schudden

vul array met 110x0 en 110x1,
draai dan 440 (ofzo) x Array[Random(220)] en Array[iTeller mod 220] om en je bent er :)

eh...
* Xiphalon hoopt dat het een beetje duidelijk is :)

  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 08-06 11:02
Sorry, ken geen delphi dus C code om mijn idee duidelijk te maken maar dat maakt niet uit voor de echte programmeurs :)
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int tegaan=220;
int kansopnul=110;
while (tegaan>0)
{
   if (random(tegaan)<kansopnul)
   {
      printf("1");
   }
   else
   {
      printf("0");
      kansopnul--;
   }
   tegaan--;
}

random(getal) is niet standaard C geloof ik, maar die geeft een gehele waarde terug van minimaal 0 en maximaal getal-1

edit:
Die manier van darkmage is ook goed met 220 keer een 0 of 1 alleen duurt die wel ff met beginnen als je ipv 220 iets van 220.000.000 zou moeten hebben

[ Voor 19% gewijzigd door PiepPiep op 28-05-2003 21:21 ]

486DX2-50 16MB ECC RAM 4x 500MB Drive array 1.44MB FDD MS-Dos 6.22


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

Randomize hoef je maar één keer uit te voeren nadat je programma gestart is. Dat kan bijvoorbeeld in de initialization sectie van een unit. Verder is het in Delphi gebruikelijk (want vaak handig) om vanaf 0 te tellen in plaats van 1.

Ook heb je een paar variabelen van het type Byte gedefinieerd. Dat is onverstandig, want de processor moet een paar extra bewerkingen uitvoeren om zijn 32-bits rekenkracht los te laten op een 8-bits getal. Het bespaart ook geen geheugen (alsof een paar bytes belangrijk zouden zijn :P). Je kunt daarom beter de generieke datatypes Integer en Cardinal gebruiken. De compiler kiest dan wel of hij er een 32-bits of (binnenkort?) 64-bits getal van wil maken.

Dit voorbeeld garandeert precies 110 keer een goed antwoord (True) en 110 keer fout (False):
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
type
  TAntwoorden: array[0..219] of Boolean;
var
  Antwoorden: TAntwoorden;

procedure VulAntwoorden;
var
  List: TList;
  i, RandomIndex: Integer;
begin
  List := TList.Create;
  try
    List.Capacity := 220;

    { List vullen }
    for i := 0 to 109 do
      List[i] := Ptr(False);
    for i := 110 to 219 do
      List[i] := Ptr(True);

    { Random True of False in de array zetten }
    for i := 0 to 219 do
    begin
      RandomIndex := Random(List.Count);
      Antwoorden[i] := Boolean(List[RandomIndex]);
      List.Delete(RandomIndex);
    end;
  finally
    List.Free;
  end;
end;

initialization
  Randomize;
end.

[ Voor 5% gewijzigd door Tomatoman op 28-05-2003 21:25 ]

Een goede grap mag vrienden kosten.


Verwijderd

Ik snap niet wat je wilt. Je begint te praten over een array gevuld met nullen en enen, en in je laatste post begin je ineens met andere random getallen te werken :?

Het nullen en enen probleem is rete eenvoudig op te lossen:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var
  nNulTeller: Integer;
  nEenTeller:  Integer;
  nLus:  Integer;
begin 
  nEenTeller := 0;
  nNulTeller := 0;
  for nLus:=0 to 220 do
    begin
      if (nEenTeller<110) and (nNulTeller<110) then // kijken of alle enen en nullen nog niet 'op' zijn
          begin  
             antwoorden[nLus]  := random(2);
             If antwoorden[nLus] = 1 then 
                 Inc(nEenTeller)
               else
                 Inc(nNulTeller);
          end
        else
          begin // alle nullen of enen zijn al gebruikt
            If nNulTeller<110 then 
                begin
                   Inc(nNulTeller);
                   Antwoorden(nLus):=0;
                end
              else 
                begin
                   Inc(nEenTeller);
                   Antwoorden(nLus):=1;
                end
          end;
    end;         
end;


fraai is het niet, maar het werkt wel.

//edit

bovenstaande code van tomatoman komt eigenlijk op exact hetzelfde neer, alleen laat je dan de VCL bijhouden hoeveel waarden al gebruikt zijn of niet. Onderhuids gebeurt min of meer hetzelfde.

[ Voor 14% gewijzigd door Verwijderd op 28-05-2003 21:37 ]


  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
Ik krijg een incompatible types error bij de ptr regel van jou tomatoman. Ik gebruik versie 6 maakt dat iets uit?

Array moet trouwens bij mijn versie onder type met een = ipv :.

Mijn eigen (omslachtige) manier werkt in ieder geval.

Dat C ziet er trouwens er koel uit, lekker efficient.

En nu het afgrijselijke werk van het in een array zetten van input van 660!!!!!!!! radiobuttons ARGH!!!!!!!!!

Effe een opmerking over jouw code hezik:

Op een bepaald moment, stel je hebt pech heeft hij alle 1-en gebruikt. Dan schrijft hij gewoon nog 20 0-en naar de laatste 20 posities van array antwoorden. Dat vind ik niet echt random.
Je code is wel een stuk efficienter, aangezien hij maar 1 keer 220x een waarde maakt.

[ Voor 24% gewijzigd door REDFISH op 28-05-2003 21:53 ]


Verwijderd

Effe een opmerking over jouw code hezik:

Op een bepaald moment, stel je hebt pech heeft hij alle 1-en gebruikt. Dan schrijft hij gewoon nog 20 0-en naar de laatste 20 posities van array antwoorden. Dat vind ik niet echt random.
Je code is wel een stuk efficienter, aangezien hij maar 1 keer 220x een waarde maakt.
Make up your mind, op het moment dat je vaststelde dat je niet wilde dat er bv. 97 keer 1 of 123 keer 1 in die array zou zitten, heb je zelf al bepaald dat je niet met een random waarde wilt werken.

Dan een andere aanpak, in feite dezelfde als die tomatoman voorstelde, maar dan even dirty met een tstringlist (ben je af van het pointer gezeur)

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
type
  TAntwoorden: array[0..219] of Boolean;
var
  Antwoorden: TAntwoorden;

procedure VulAntwoorden;
var
  List: TStringList;
  i, RandomIndex: Integer;
begin
  List := TStringList.Create;
  try
    List.Capacity := 220;

    { List vullen }
    for i := 0 to 109 do
      List[i] := '1';
      for i := 110 to 219 do
      List[i] := '0';

    { Random True of False in de array zetten }
    for i := 0 to 219 do
    begin
      RandomIndex := Random(List.Count);
      Antwoorden[i] := List[RandomIndex] = '1' 
      List.Delete(RandomIndex);
    end;
  finally
    List.Free;
  end;
end;

initialization
  Randomize;
end.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

REDFISH schreef op 28 mei 2003 @ 21:46:
[...]
Ik krijg een incompatible types error bij de ptr regel van jou tomatoman. Ik gebruik versie 6 maakt dat iets uit?
Oeps, foutje omdat ik het ter plekke verzon. Toch maar even Delphi gestart. Verbeterde code:
Delphi:
15
16
17
18
19
20
    { List vullen met 110 keer True en 110 keer False }
    for i := 0 to 109 do
    begin
      List.Add(Ptr(0));  // False
      List.Add(Ptr(1));  // True
    end;
Array moet trouwens bij mijn versie onder type met een = ipv :.
Je hebt helemaal gelijk.
En nu het afgrijselijke werk van het in een array zetten van input van 660!!!!!!!! radiobuttons ARGH!!!!!!!!!
Dat is toch niet zo'n probleem? Je kunt bijvoorbeeld de Tag property van een radiobutton op de bijbehorende vraag zetten. Per vraag heb je twee radiobuttons (goed en fout), waarvan je de OnClick koppelt aan GoedClick of FoutClick:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
procedure TForm1.GoedClick(Sender: TObject);
begin
  if Sender is TRadioButton then
    GegevenAntwoorden[TRadioButton(Sender).Tag] := True;
end;

procedure TForm1.FoutClick(Sender: TObject);
begin
  if Sender is TRadioButton then
    GegevenAntwoorden[TRadioButton(Sender).Tag] := False;
end;

Een goede grap mag vrienden kosten.


  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
Thanx ik ben al een heel stuk verder.

  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
Hmmm, probleem is dat mensen ook de vraag kunnen overslaan, dus dan wordt er niks meegerekend.
Maar dan moet ik van 660 radiobuttons de onclick gaan instellen?? Ik ben nog niet wegwijs in dat sender is etc.
Ik ga het wel effe plakken, maar er zullen wel meer vragen komen. Ander probleem is ook(of niet hierdoor) dat de radiobuttons in runtime gemaakt worden.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

Eerst een paar vragen tussendoor.
  1. Begrijp ik het goed dat je per vraag drie radiobuttons wilt gebruiken (geen antwoord, antwoord A, antwoord B )?
  2. Waar haal je de vragen, de goede antwoorden en de foute antwoorden vandaan? Uit een tekstbestandje of zo?
  3. Wil je alle vragen op één form zetten of misschien wel in een TScrollBox? Zo nee, hoe dan wel?

Een goede grap mag vrienden kosten.


Verwijderd

Ik zou graag zien dat je eens uitlegt wat je nu eigenlijk wilt. Het hele verhaal is een beetje wazig, dat random verhaal al helemaal.

Die onclick , is die voor elke checkbox min of meer hetzelfde? In dat geval kun je bv zoiets doen:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[..]
type
  TMyForm = Class(TForm);
[..]

procedure TMyForm.ZetCheckBoxOnClick;
var
  nLus : Integer;
begin
  For nLus:=0 to Self.ComponentCount-1 do 
     if Self.Component[nLus] is TCheckBox then
       TCheckBox(Self.Components[nLus]).onClick := MyOnClick;
end;

end;


//edit
even de self. erbij gezet, zodat het duidelijker is wat ik doe. Ik maak dus gebruik van de components property van een form, dit is een array met daarin alle componenten op dat form. Die doorloop ik allemaal, en indien het een checkbox is koppel ik de onclick.

Een andere optie is een eigen class afleiden van de TCustomCheckbox en daar je onclick in implementeren.. de mogelijkheden zijn legio, maar dan moet eerst duidelijker zijn wat je nu eigenlijk wilt.

[ Voor 33% gewijzigd door Verwijderd op 28-05-2003 23:34 ]


  • REDFISH
  • Registratie: Augustus 2001
  • Laatst online: 13-07 15:20

REDFISH

beetje vreemd en niet lekker

Topicstarter
Ik verlang van jullie niet dat jullie een heel programma schrijven, ik hoef alleen maar wat tips en uitleg over hoe het moet.

Uitleg voor Hezik

Het wordt een form met 220 x 3 radiobuttons. Elk 3tal correspondeert met een vraag. De waarde van elk 3 tal radiobuttons moet in een array gezet worden(ingevulde waarden). Als geen waarde is geselecteerd wordt automatisch waarde 2 aan het positienummer van die array toegekend. 0 voor onjuist, 1 voor juist en 2 voor geen invoer of weet niet.

normaal zou je dan die input gaan vergelijken met de correcte antwoorden. Maar in dit geval worden die correcte antwoorden verzonnen door het programma. Die verzonnen 'correcte antwoorden' moeten random gemaakt worden met een verdeling waarbij er 109 juist en 109 onjuist zijn. de 2 laatsten worden random bepaald. Dus ik heb een array die er zo uitziet:


Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure vulevenwicht;
var
 i: integer;
begin
  for i := 1 to 109 do
  begin
   evenwicht[i] := 0;
  end;
  for i:= 110 to 218 do
  begin
    evenwicht[i]:=1;
  end;
  evenwicht[219] := random(2);
  evenwicht[220] := random(2);

end;


De waarden in deze array(evenwicht) zijn bijna helemaal in evenwicht, aangezien er evenveel waarden 0 en 1 zijn met uitzondering van de 2 laatste random waarden. En ook is deze array mooi verdeeld in eerst 0-en en dan 1-en. Dit wordt dan door elkaar gehusseld met

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
procedure tform1.vulantwoorden;
var

temp,gekozenwaarden : integer;

begin
vulevenwicht;
randomize;
gekozenwaarden := 0;

  while gekozenwaarden < 220 do
    begin
      temp := random(220)+1;

      if (evenwicht[temp] = 9) then
        begin
          //doe niks :P
        end

      else
        begin
        inc(gekozenwaarden);
        antwoorden[gekozenwaarden]:= evenwicht[temp];
        evenwicht[temp] := 9;
        end;

    end;
end;


(Jouw stringlist heb ik nog effe niet uitgeplozen)


Nou is het aan de gebruiker, om strategieën te verzinnen waarmee hij toch een redelijke score zou behalen. Dit kan zijn :

1. Hij vult echt gewoon maar iets in (bijvoorbeeld 2x juist, 2x onjuist, en zo alle 220 waarden lang) dus hierbij moeten zijn 4 waarden voor de rest van de ingevuld array gebruikt woorden. JJOOJJOO etc.

2. of hij heeft al kennis, en bijvoorbeeld 30 vragen ingevuld, en probeert dan de rest ook in te vullen met een strategie (JJOO) om te kijken hoe hij dan scoort op de lange termijn als hij bijvoorbeeld 10 keer de toets zou doen.

Uiteindelijk is het belangrijkste punt, om op basis van de al ingevulde vragen en het aantal juist en onjuist in de gaten houdend een goede strategie te bedenken die rekening houdt met deze feiten.


Vragen van tomatos
1: correct.

2. de vragen worden nergens opgehaald, alleen de antwoorden, die krijg ik in een word document, met vraagnummer en juist en onjuist, maar dat type ik wel handmatig in, dat maakt niet uit.
In het kader van toetsingsanalyse en verbetering wil ik dit onderzoeken. Het is een statistisch programma dat random een ongeveer gelijk aantal goed en fout maakt zodat strategieën geprobeerd kunnen worden onder bepaalde aannames, als er bijvoorbeeld al 30 zijn ingevuld. Dan met een bepaalde strategie, steeds 2x goed, 2x fout ofzo de rest invullen die je niet weet.

3. niet echt van toepassing, dit zou later wel kunnen toegevoegd worden en de toets electronisch zo aanbieden(de huidige potloodinvul formulieren zijn nog altijd niet foutloos), maar het gaat nu eerst om de strategieën en de score die je daarmee zou halen. Een vraag goed is score + 1 een vraag fout score -1.
Bedankt voor je hulp in ieder geval. Je kunt me ook op msn bereiken.

zo heb ik het maken van radiobuttons gedaan

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
procedure TForm1.Button1Click(Sender: TObject);
const
kolommen = 22;

var
  row, column , grotekolom : integer;
  rb : tradiobutton;
  lb : tlabel;
  gb : tgroupbox;
  totaal : integer;

begin
  vulantwoorden;
  totaal := 0;
  for grotekolom := 0 to 9 do

    begin
     //labels met Juist onjuist
       lb := Tlabel.create(self);
       lb.parent := self;
       lb.left := 56+ grotekolom*90;
       lb.Top := 24;
       lb.caption := 'J   X   O';

      for row := 1 to kolommen do


       begin
           //labels met vraag nummer
             lb := Tlabel.create(self);
             lb.parent := self;
             lb.left := 22+ grotekolom*90;
             lb.Top := 18 + row*25;
             lb.caption := inttostr(kolommen*grotekolom+(kolommen-(kolommen-row))); //lekka

           // Groupbox settings

             gb := tgroupbox.create (self);
             gb.top := 10+25*row;
             gb.height := 25;
             gb.Left := 50 + grotekolom * 90;
             gb.width := 50;
             gb.parent := self;
             gb.caption := '';


         for column := 0 to 2 do

           begin

           //Radiobutton settings

             rb := TRadioButton.Create (self);
             rb.width := 15;
             rb.Height:= 15;
             rb.top := 7;
             rb.left := 2+15*column;
             rb.parent := gb; //this line to assign the groupbox as parent?
             rb.caption := '';

           end;
             inc(totaal);
             progressbar1.position := totaal;
       end;
     end;
    button1.enabled := false;
end;


ik weet alleen niet hoe ik die radiobuttons later dan weer aanspreek.

edit: effe labels met vraagnummer verzet> snelheidswinst.

Ik hoop dat het een beetje duidelijk is.

[ Voor 104% gewijzigd door REDFISH op 29-05-2003 00:04 ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

Die group boxen moet je in een TList of TObjectList bijhouden. Je voegt iedere group box die je maakt aan de list toe: MijnList.Add(DeNieuweGroupBox). Vervolgens kun je ze weer terughalen uit de list. Het derde item is bijvoorbeeld:
GezochteGroupBox := TGroupBox(MijnList[2])
je telt immers vanaf nul. Zie de Help van Delphi voor uitleg en voorbeelden. De eerste radio button in groep 5 is:
GezochteRadioButton := TGroupBox(MijnList[4]).Components[0] as TRadioButton

Verder kun je veel snelheidswinst boeken bij het creëren van al die componenten door ze op een TPanel te plaatsen dat tijdelijk onzichtbaar is. Hier heet dat ding Panel1. De try.. finally constructie verzekert dat het panel weer zichtbaar wordt, zelfs als er tussentijds een fout optreedt.
Delphi:
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
begin
  Panel1.Visible := False;
  Panel1.DoubleBuffered := True;
  try
    VulAntwoorden;
    totaal := 0;
    for grotekolom := 0 to 9 do

      begin
       //labels met Juist onjuist
         lb := Tlabel.create(self);
         lb.parent := Panel1;
...
               lb.parent := Panel1;
...
               gb.parent := Panel1;
...
               rb.parent := gb;...
...
  finally
    Panel1.Visible := True;
  end;
end;

Een goede grap mag vrienden kosten.


Verwijderd

Ik verlang van jullie niet dat jullie een heel programma schrijven, ik hoef alleen maar wat tips en uitleg over hoe het moet.
dat begrijp ik, maar om je probleem te begrijpen (en dus je te kunnen helpen) moet ik eerst weten wat het probleem is.

Ik splits even mijn antwoord, eerst het 'theoretische' deel en dan de code
Uiteindelijk is het belangrijkste punt, om op basis van de al ingevulde vragen en het aantal juist en onjuist in de gaten houdend een goede strategie te bedenken die rekening houdt met deze feiten.
Ben je niet bezig met een overbodig onderzoek? Of iig. je onderzoek verkeerd aan te pakken? Door zulke specifieke eisen te stellen aan je array, maar je er in feite gewoon 'kop-of-munt' gooien van, met een munt waarbij de kansen 50/50 zijn. Je doelstelling is om de toekomstige score van de kandidaat te verbeteren, op basis van zijn/haar resultaten in het verleden. Juist doordat je de kans kunstmatig op 50/50 houdt, maak je deze exercitie nutteloos. Immers de kans is 50/50 elke 'gooi' weer, en het verzinnen van een strategie daarvoor is volslagen nutteloos. Of zie ik iets over het hoofd?

Je procedure vulevenwicht is zo al een stuk korter:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
procedure maakrandomarray;
var
  i:  integer;
begin
var
  i:  integer;
begin
  for i := 1 to 218 do
    evenwicht[i] := Integer(i > 109);
  evenwicht[219] := random(2);
  evenwicht[220] := random(2);
end;


Uitleg: zolang i <= 109 zal de expressie (i > 109) evalueren naar false, oftewel 0 in integervorm. Daarboven evalueert hij naar true, oftewel 1.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var
  temp,gekozenwaarden : integer;
begin
  vulevenwicht;
  randomize;
  gekozenwaarden := 0;
  while gekozenwaarden < 220 do
    begin
      temp := random(220)+1;
      if (evenwicht[temp] <> 9) then
        begin
          inc(gekozenwaarden);
          antwoorden[gekozenwaarden]:= evenwicht[temp];
          evenwicht[temp] := 9;
        end;
    end;
end;


De code is zo al korter, maar nog steeds inefficient, doordat hij 'al gebruikte' waarde in de array laat zitten. Het mooist is dus om deze waarden gewoon uit je array te halen, op die manier pak je per stap een random waarde mee, zonder omwegen. Twee voorbeelden (1 m.b.v. een stringlist, en 1 mbv een tlist) staan hier al boven. Let vooral op de t(string)list.delete, deze verwijderd een gebruit item per direct.

Ik persoonlijk vind de Tlist al netter, maar helemaal ideaal is het nog niet, omdat je in feite wel je boolean loopt te casten de hele tijd.

Je code wordt dan (zou de funtie weer tot 1 samenbrengen):

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Function MaakRandomArray: Array [ 0 .. 217] of integer;
  var
    i:  integer;
    oStamlijst : TList;
    nStamIndex: Integer;
  begin
    // lijst aanmaken
    oStamLijst := TList.Create;
    try
      for i := 0 to 217 do
        oStamlijst[i] .add(Integer(i > 109));
      oStamlijst.add(random(2));
      oStamlijst.add(random(2));
      // lijst husselen
      for i := 0 to 217 do
        begin  
           nStamIndex := Random(oStamlijst.Count-1);
           Result[i]:=Integer(oStamlijst[nStamIndex]);
           oStamlijst.delete(nStamIndex);
        end
     finally
       oStamlijst.free;   
     end;
  end;


Als je goed kijkt zie je dat dit praktisch dezelfde code is als welke tomatoman al gepost had.
ik weet alleen niet hoe ik die radiobuttons later dan weer aanspreek.
dat heb ik hierboven al aangegeven. Een ander optie is om ze bij aanmaken in een Tlist te stoppen, op die manier heb je ze bij de hand.

Overigens valt me op dat je al je arrays etc. begint te tellen bij 1. In delphi is het gebruikelijk te tellen bij 0. dus: 4 items in een array --> array [ 0 .. 3] of integer, het 4e item uit deze array --> array[3]. Let wel op dat de itemcount van deze array 4 is!

[ Voor 10% gewijzigd door Verwijderd op 29-05-2003 03:03 ]

Pagina: 1