[PHP] random nummers

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

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dag allemaal.

Ik moet met PHP een database vullen.
De database heeft 10 records met allemaal een id (1-10 dus)
In iedere record moet ik ergens een nummer (1-10) opslaan.
Ieder nummer mag maar een keer gebruikt worden, en het nummer mag niet hetzelfde zijn als het ID van de record.

Hoe kan ik dit met PHP helamaal random laten gebeuren?

(met andere woorden: iedere record moet naar een andere record verwijzen, er mag geen verwijzing naar zichzelf en er mogen geen dubbele verwijzingen zijn)

Hoop dat het een beetje duidelijk is

Alvast bedankt, Jzzpr

Acties:
  • 0 Henk 'm!

  • Brons
  • Registratie: April 2002
  • Laatst online: 20-09 11:57

Brons

Fail!

Ik weet niet welke database je gebruikt, maar ik neem aan mysql. Ik kan je op het moment de code niet geven, maar google ff op auto_increment.

Trouwens, dit is erg makkelijk met google (en ook op GoT) te vinden.

Acties:
  • 0 Henk 'm!

Verwijderd

Wat je zou kunnen doen:
-Random getallen selecteren van 1-10, in een array stoppen, controleren of het getal er al in staat, zoja: opniew genereren tot alle records vol zijn.

Het nadeel hiervan is, dit kan erg lang duren, aangezien je aan het eind een kleine kans heb (1/10) op een getal wat nog niet in je array zit.

Een andere methode: een array met alle ID's, dan een random element selecteren, in de database zetten en dat element uit je array verwijderen, en de procedure herhalen tot je array leeg is.

En dan zul je zelf nog even moeten nadenken over een oplossing dat het getal niet gelijk mag zijn aan het ID, maar dat is niet al te lastig.

Ik geef hier expres geen code bij omdat: ik al maanden geen php meer heb aangeraakt, het al 2 uur is en /14 geen afhaalchinees is ;). Andere zullen later vandaag best liever zijn op dit gebied neem ik aan.

[ Voor 10% gewijzigd door Verwijderd op 22-10-2005 02:02 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Wat had je zelf in gedachten? Ik kan me niet voorstellen dat je zelf geen enkele manier kan bedenken, aangezien er tientallen manieren zijn om dit op te lossen.

Je kan bijvoorbeeld in een loop een array opbouwen, door steeds random getallen te nemen en als het nog niet in de array voorkomt, het eraan toevoegen op de volgende positie. Of je neemt een array dat opeenvolgend de getallen van 1 tot 10 heeft, en je schrijft er een "sorteerfunctie" voor die het door elkaar husselt. Of je verzint iets zonder arrays.

Met andere woorden: wat heb je zelf al geprobeerd? Wat voor problemen kom je daarbij tegen? Lees ook P&W FAQ - De "quickstart" eens door. :)

Je topic komt op het moment nogal over als een scriptrequest, en die willen we hier eigenlijk niet zien. Ik neem aan dat je dit probleem wel zelf wilt oplossen, en niet van ons verwacht dat wij jouw code voor je schrijven? :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
@ brons:
heeft niks met auto increment te maken, is wel basic

zoek gewoon ff naar de functie die random nummers maakt, hou een arraytje bij van welke nummers je al gehad heb en dan iets in de geest van:

while $randomnummer komtvoorin $array of isniet $index {
$random = doerandomnummerzoeken()
}

This message was sent on 100% recyclable electrons.


Acties:
  • 0 Henk 'm!

  • ripperke
  • Registratie: Augustus 2003
  • Laatst online: 19-08 16:06

ripperke

w00t!

hum blijkbaar al redelijk wat reply's op de tijd dat ik iets ineeen had gestoken
snelle got'ers 8)

anyway:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

$cijfers = array();
while($new = rand(1,10)) {
if(!in_array($new,$cijfers)) { array_push($cijfers,$new); $aant++; }
if($aant == 10) { break; }
}

for($i=0;$i<=count($cijfers)-1;$i++) {
$sql = "UPDATE table SET veld = $cijfers[$i] WHERE id=".($i+1);
echo $sql."<br>";
}

?>


edit:

bugfix :Y)

[ Voor 12% gewijzigd door ripperke op 22-10-2005 02:09 ]

If TCP/IP handshaking was less formal, perhaps SYN/ACK would be YO/WASSUP


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

if (iets) break;? :X

Verder houdt die code geen rekening met het feit dat een record niet naar zichzelf mag wijzen. Die code doet dus lang niet wat de TS wil. ;)

Verder is dit dus niet de bedoeling; ik zou graag willen zien dat de topicstarter eerst meedenkt voordat we heb kant en klare scripts aanbieden, dan leert ie misschien nog wat. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 20-09 08:50

gorgi_19

Kruimeltjes zijn weer op :9

Is het niet makkelijker om de selectie te sorteren op een random nummer en vervolgens de zut in deze volgorde weer toe te voegen aan de database?

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Acties:
  • 0 Henk 'm!

  • ripperke
  • Registratie: Augustus 2003
  • Laatst online: 19-08 16:06

ripperke

w00t!

http://php.belnet.be/manual/nl/control-structures.break.php
als het zelfs als voorbeeld in de manual staat..... imo niks mis met dat statement
Verder houdt die code geen rekening met het feit dat een record niet naar zichzelf mag wijzen. Die code doet dus lang niet wat de TS wil. ;)
dat is imo maar 1 if meer inbouwen
Verder is dit dus niet de bedoeling; ik zou graag willen zien dat de topicstarter eerst meedenkt voordat we heb kant en klare scripts aanbieden, dan leert ie misschien nog wat. ;)
daar heb je wel een punt :) zal het nooit meer doen O-) :)

If TCP/IP handshaking was less formal, perhaps SYN/ACK would be YO/WASSUP


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Nu online
ripperke schreef op zaterdag 22 oktober 2005 @ 02:34:
[...]
http://php.belnet.be/manual/nl/control-structures.break.php
als het zelfs als voorbeeld in de manual staat..... imo niks mis met dat statement
Dat voorbeeld staat in de manual om uit te leggen dat je op deze manier een loop kunt onderbreken. Dat wil niet zeggen dat dit in elk geval netjes is ofzo. In dit geval had de conditie gewoon in de while conditie opgenomen kunnen worden:
PHP:
1
while($new = rand(1,10) && $aant != 10) {


Om 10 random cijfers te krijgen zou mijn voorkeur echter uitgaan naar een for() constructie. Dan maak je tenminste gelijk duidelijk dat het 10x gaat gebeuren. Mja, tis vrij triviaal allemaal...
dat is imo maar 1 if meer inbouwen
En wat als de laatste naar zichzelf wijst?

@hieronder -> "random" wil in principe zeggen willekeurig. Dat houdt voor de meeste toepassingen in dat de kans dat een bepaalde waarde voorkomt bij een key gelijk is aan de kans dat hij voorkomt bij een willekeurige andere key (om het maar in array terminologie te houden). Voor wat betreft het issue van TS geldt dus dat er eigenlijk geen sprake is van randomness. Hij wil de waarde immers niet gelijk hebben aan de key. Dat komt er op neer dat bij een key van zeg 9 een kans is van 0 dat de waarde 9 is, en iets van 0.111 dat de waarde 1-8 of 10 is. Ergo, niet random...
Jouw hardcoded lijstje is verre van random, puur omdat ie vaststaat. TS zou dan net zo goed zelf met de natte vinger wat waarden kunnen mappen. En ik neem aan dat er dan geen topic was geweest...

Je "echte" random code mist de voorwaarde dat een key niet gelijk mag zijn aan zijn waarde, en als je die met een simpele if() inbouwt loop je het risico op een eeuwige loop. Er kan immmers $a[10] = 10 uitkomen...

[ Voor 43% gewijzigd door T-MOB op 22-10-2005 03:06 ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Wim-Bart
  • Registratie: Mei 2004
  • Laatst online: 10-01-2021

Wim-Bart

Zie signature voor een baan.

Volgende code is misschien nog éénvoudiger:

PHP:
1
2
3
4
5
6
$aKey= array();
$iMax= 10;
for ($iKey=0;$iKey<$iMax;$iKey++)
{
  $mysqli->query("INSERT INTO `mytable` SET `value`=".$iMax-$iKey.";");
}

Het is tenslotte maar wat je onder random verstaat.
Je kan ook met echte randoms werken, maar die zijn tijdconsuming.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Init first.
$aRandoms= array();
$iMin= 1;
$iMax= 1000;

for ($i=$iMin;$i<=$iMax;$i++) $aRandoms[$i]=true;
for ($i=$iMin;$i<=$iMax;$i++)
{
  $mysqli->query("INSERT INTO `mytable` SET `key`=".$i.", `value`=".getrandom($iMin,$iMax,$i).";");
}

function getrandom($iBottom,$iTop,$iExclude)
{
  global $aRandoms;
  while ($iReturn===0)
  {
     $iReturn= rand($iBottom,$iTop);
     $iReturn= ($aRandoms[$iReturn]?($iReturn===$iExclude?0:$iReturn):0);
  }
  $aRandoms[$iReturn]=false;
  return $iReturn;
}


Of de zelde code geoptimaliseerd:
PHP:
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
// Init first.
$aRandoms= array();
$iMin= 1;
$iMax= 1000;

for ($i=$iMin;$i<=$iMax;$i++) $aRandoms[$i]=$i;
for ($i=$iMin;$i<=$iMax;$i++)
{
  $mysqli->query("INSERT INTO `mytable` SET `key`=".$i.", `value`=".getrandom($i).";");
}

function getrandom($iExclude)
{
  global $aRandoms;
  // bepaal size van de array
  $iTop= count($aRandoms);
  if ($iTop===1)
  {
    $iReturn= 1;
    unset($aRandoms[$iReturn]);
  }
  else
  {
    if ($iTop===0)
    {
      $iReturn=0;
    }
    else
    {
      $iReturn=$iExclude;
      while ($iReturn===$iExclude)
      {
        $iReturn= $aRandoms[rand(2,$iTop)];
      }
      $aRandoms[$iReturn]= $aRandoms[$iTop];
      unset($aRandoms[$iTop]);
    }
  }
  return $iReturn;
}


De werking is als volgt:

$aRandoms is een array bijvoorbeeld: 1 2 3 4 5 6 7 8 9 10
De eerste pass is getrandom(1) en geeft een waarde van 2 tot en met 10 terug. Bijvoorbeeld 6.
$aRandoms is nu een array: 1 2 3 4 5 10 7 8 9
De tweede pass is getrandom(2) en geeft een waarde tussen 2 en 10 terug. Bijvoorbeeld 10.
$aRandoms is nu een array: 1 2 3 4 5 9 7 8
De derde pass is getrandom(3) en geeft een waarde tussen 2 en 9 terug. Bijvoorbeeld 2.
$aRandoms is nu een array: 1 8 3 4 5 9 7
Pass 4: getrandom(4) geeft 5: $aRandoms is 1 8 3 4 7 9
Pass 5: getrandom(5) geeft 9: $aRandoms is 1 8 3 4 7
Pass 6: getrandom(6) geeft 4: $aRandoms is 1 8 3 7
Pass 7: getrandom(7) geeft 8: $aRandoms is 1 7 3
Pass 8: getrandom(8) geeft 3: $aRandoms is 1 7
Pass 9: getrandom(9) geeft 7: $aRandoms is 1
Pass 10: getrandom(10) geeft 1: $aRandoms is empty

Sneller kan bijna niet.

[ Voor 67% gewijzigd door Wim-Bart op 22-10-2005 03:15 ]

Beheerders, Consultants, Servicedesk medewerkers. We zoeken het allemaal. Stuur mij een PM voor meer info of kijk hier De mooiste ICT'er van Nederland.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Het is tenslotte maar wat je onder random verstaat.
Random betekent letterlijk vertaald "willekeurig". Een aflopende volgorde is niet willekeurig. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

PHP vraagje, random nummers

[ Voor 42% gewijzigd door Verwijderd op 22-10-2005 03:05 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Dus?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

PHP:
1
2
3
4
5
6
7
8
9
for ($i=1; $i <= 10; $i++)
{
    $rand = $i;
    while($rand == $i)
    {
        $rand = rand(1, 10);
    }
    $db->insert("INSERT INTO foobar VALUES($i, $rand)");
}


Probleem is echter dat je hiermee een aantal onnodige iteraties door kunt krijgen, in het wellicht onwaarschijnlijk doch mogelijke geval dat $rand == $i blijft staan; dit wordt steeds reeeler wanneer je de upperbound en lowerbound dichter bij elkaar neemt, waartussen gerandomized wordt. Dit is ook het geval dus bij T-MOB's voorbeeld.
Slimmer is misschien het volgende:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$lowerbound = 1;
$upperbound = 10;

for ($i=$lowerbound; $i < $upperbound+1; $i++)
{
    if ($i == $lowerbound)
    {
        $rand = rand($lowerbound+1, $upperbound);
    }
    else if ($i == $upperbound)
    {
        $rand = rand($lowerbound, $upperbound-1);
    }
    else
    {
        $r[0] = rand($lowerbound, $i-1);
        $r[1] = rand($i+1, $upperbound);
        $rand = $r[rand(0,1)];
    }

    $db->insert("...");
}


De tweede voorbeeld is iig gevrijwaard van infinit loops, en vergt ($upperbound-$lowerbound)+1 itteraties ipv per iteratie nog eventuele sub iteraties. Dit gebeurt door onderscheid te maken tussen 3 situaties:
* De twee randvoorwaarden, dus wanneer i == lowerbound of i == upperbound, dan kan uit de 'rest' gekozen worden.
* De situatie waarin i != lowerbound && i != upperbound is, ofwel in dit geval wanneer i > lowerbound && i < upperbound is. Er wordt dan een random waarde gekozen uit het domein [lowerbound, i-1] en [i+1, upperbound], waarna door 'kop of munt' methode tussen de twee waarde de definitieve random waarde wordt gekozen.

[ Voor 12% gewijzigd door prototype op 22-10-2005 03:43 ]


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Nu online
@wim-bart,
Ook in je aangepaste versies komt het niet goed... Je gooit queries in je loop. Dat kan niet goed gaan aangezien je bij de eerste iteratie nog niet weet of de laatste goed uitkomt. Pas na 9 random nummers weet je of de laatste waarde gelijk gaat zijn aan zijn key. En dan heb jij al 8 queries uitgevoerd...

Het verkrijgen van de nummers kan verder vrij eenvoudig (sorry -NMe-):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$max = 10; //required numbers

$out = array();
for ($i=1; $i<=$max; $i++) {

    //fetch a number that is not equal to $i and not available in $out
    while (!isset($rand) || $rand == $i || in_array($rand, $out)) {
        $rand = rand(1, $max);
    }

    //redo the whole thing when the last number will be equal to its key
    if ($i == ($max - 1) ) {
        if (!in_array($max, $out)) {
            $i = 0;
            $out = array();
        }
    }

    $out[$i] = $rand;

    //clear rand for next iteration
    unset($rand);
}


@prototype: Nummers mogen maar 1x voorkomen. Daarnaast moet je oppassen met het aanpassen van de boundaries van de rand(). Als je die gaat veranderen loop je het risico dat het geheel mider random is dan gewenst...

[ Voor 12% gewijzigd door T-MOB op 22-10-2005 03:52 ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik ken geen ene f*ck van PHP, maar is dit niet nog veel makkelijker?
PHP:
1
2
3
$out = range(1, 20);
srand((float)microtime() * 1000000);
shuffle($out);

Even wat op php.net gebladerd hoor. Ik doe nooit geen zak met PHP, maar misschien is dit een idee?

Mocht ik iets missen:
Ik zie iedereen telkens de array vullen met random nummers en dan eerst zoeken in de bestaande elementen of het nummer al voorkomt in de array. Je kunt toch veel beter de array vullen met de cijfers 1..10 (op volgorde dus) en dan (array_size / 2) maal een tweetal random elementen swappen? Dan vul je je array dus (dat kan met "range" toch?) en dan met een for-lusje van 0..(array_size/2) gewoon element rand_X met element rand_Y swappen. (Volgens mij doet shuffle dat, maar anders kun je het ook makkelijk zelf doen...)
Veel van bovenstaande implementaties lijken mij onnodig vaak te "loop-en" tegen de tijd dat de array bijna vol is, want er worden dan overbodig vaak random getallen gegenereerd en weer weggegooid omdat ze al in de array zitten.

edit:

Sjongejonge... had ik maar gelezen.... :X

NMe: Ik heb je post weer in zijn geheel teruggezet, want wat je zegt klopt wel degelijk, al is het niet 100% een oplossing van wat TS wil. Een beetje eigen verbeelding van de TS kan geen kwaad though. ;)

[ Voor 255% gewijzigd door NMe op 22-10-2005 04:05 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

T-MOB schreef op zaterdag 22 oktober 2005 @ 03:42:


@prototype: Nummers mogen maar 1x voorkomen. Daarnaast moet je oppassen met het aanpassen van de boundaries van de rand(). Als je die gaat veranderen loop je het risico dat het geheel mider random is dan gewenst...
Ah, dat lees ik idd net dat de nummers maar 1x mogen voorkomen, en idd dat heb ik ook als sidenote erbij toegevoegd; verklein je je boundaries dan is het random effect een stuk kleiner, maar dat spreekt eigenlijk voor zich.
Maar ik ga nu slapen ;) Jullie heren komen vast wel tot een oplossing, goedenacht ;)

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Nu online
Er zijn 2 eisen aan de output:
1. Elk nummer mag maar een keer voorkomen
2. Een nummer mag niet gelijk zijn aan zijn key

Zonder 2 was een oplossing met shuffle idd goed te doen...

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

T-MOB schreef op zaterdag 22 oktober 2005 @ 03:59:
Er zijn 2 eisen aan de output:
1. Elk nummer mag maar een keer voorkomen
2. Een nummer mag niet gelijk zijn aan zijn key

Zonder 2 was een oplossing met shuffle idd goed te doen...
Met shuffle ook. Er zal alleen een loop omheen moeten die blijft shufflen zolang er minstens één value gelijk is aan zijn key. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
-NMe- schreef op zaterdag 22 oktober 2005 @ 04:02:
Er zal alleen een loop omheen moeten die blijft shufflen zolang er minstens één value gelijk is aan zijn key. ;)
Jah, maar of dat zo mooi is durf ik te betwijfelen ... Die kans is relatief groot dat 1 op de 10 elementen op z'n eigen plek terecht komt en dan kun je dus wéér shuffelen :P


Overigens: As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand() as this is now done automatically.

[ Voor 36% gewijzigd door RobIII op 22-10-2005 04:19 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Ik denk dat de shuffle-functie van PHP zelf waarschijnlijk sneller werkt dan een zelfgeschreven shuffle-algoritme. :P

Je zal altijd in een loopstructuur bezig blijven die checkt of je huidige gegenereerde getal niet toevallig gelijk is aan zijn key. Ik denk niet dat het in zo'n geval veel uit zal maken of je een loop om die shuffle heen programmeert, of om een theorethisch efficiënter stukje eigen code, dat mogelijk zelfs trager uitpakt omdat het eerst geparsed moet worden. Wat dat betreft zou ik, zeker in een geval als dit met maar 10 keys, gaan voor de duidelijkere code die shuffle biedt. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Nu online
Vind de shuffle idd eleganter, geen zin om te benchen tho
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// checks whether any key value pair in an array is equal
// offset sets the number to be substracted from value
// for a match (default = 1)
function hasEqualKeyValue($array, $offset=1) {
    foreach($array as $key => $value) {
        if ($key == ($value - $offset) ) {
            return TRUE;
        }
    }
    return FALSE;
}


$max = 10; //required numbers

$out = range(1, $max);
while (hasEqualKeyValue($out))
    shuffle($out);
}

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

PHP:
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
<?php
    $LOWERBOUND = 1;
    $UPPERBOUND = 10;

    $options = range($LOWERBOUND, $UPPERBOUND);


    for ($i=$LOWERBOUND; $i <= $UPPERBOUND; $i++)
    {
        switch($i)
        {
            case $LOWERBOUND:
                $k = rand($LOWERBOUND, $UPPERBOUND-1);
            break;
            
            case $UPPERBOUND:
                $k = 0;
            break;

            default:
                $k = rand(0, count($options) - 1);
            break;
        }

        $rand = $options[$k];
        for ($j=$k; $j+1 < count($options); $j++)
        {
            $options[$j] = $options[$j+1];
        }
        unset($options[count($options)-1]);   
    }
?>


Net tijdens het tandenpoetsen bedacht ;) In het geval dat i == 1 (lowerbound), dan moet er gekozen worden uit de nog onaangeraakte array options, die 1..10 bevat, met corresponderende index 0..9. In het bijzonder geldt hierbij dat $lowerbound == $options[0]. De range van de rand is dus 1..9, respectievelijk [$lowerbound, $upperbound-1]. Slechts de eerste iteratie zal gebruik gemaakt worden van deze codeblok. Na een index $k vastgesteld te hebben (en dus een random getal $options[$k]), wordt aan het einde van de eerste iteratie dit element ook uit de array verwijderd om herhaling te voorkomen, en alle elementen die erop volgen, worden 1 index naar links geschoven. Hier zal vast wel een php functie voor zijn, maar ik heb het even met lusje gedaan. Gevolg is dus iig dat de array options nu met 1 element verkleind is, met indexes [0, 8] ipv [0, 9]
Dan voor i > 1 && i < 10 geldt dus dat er uit index [0, 8] gekozen kan worden, en dan [0,7] en dan [0,6] etc... Wanneer het domein gereduceerd is tot [0,0], en dus alleen 0 nog een index is in de array options, geldt de conditie dat i == upperbound, en de random waarde die daarbij hoort is gewoon de laatste waarde uit options, die overgebleven is. ;)

[ Voor 4% gewijzigd door prototype op 22-10-2005 04:36 . Reden: verkeerde variabele naam ;) ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
T-MOB schreef op zaterdag 22 oktober 2005 @ 04:26:
Vind de shuffle idd eleganter, geen zin om te benchen tho
En toch vind ik dit ook niks (ja het was wel mijn suggestie, maar ik had dan ook niet alles goed gelezen). Het heeft de potentie om ontzettend vaak te itereren voor niks... Kun je misschien nog beter een kruising maken: eerst vullen met range, dan shufflen, en dan er door heen jassen en kijken of value == index. Zo ja, swappen met een ander element (!=value) en doorgaan...

ofzo :P

enniewee: * RobIII gaat pitten. Tenzij er binnen nu en (tandenpoetsen==klaar) nog een lekkere chick van een jaar of 18-26 spontaan op de deurbel staat te duwen :P
(Oh, en als IlseIII dat dan maar goed vindt :P )
-NMe- schreef op zaterdag 22 oktober 2005 @ 04:32:
Dat is inderdaad eleganter en in principe ook nog wel leesbaar te houden. Go Rob! :P
Who da man? :P ;)
Truste!

[ Voor 46% gewijzigd door RobIII op 22-10-2005 04:34 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Dat is inderdaad eleganter en in principe ook nog wel leesbaar te houden. Go Rob! :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

RobIII's manier lijkt me ook het meest efficient en levert ook een redelijk homogene verdeling op:
PHP:
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
$aantal = 10;

$check = array_fill(0, $aantal, array_fill(0, $aantal, 0));

$do = 1000;

while ($do--)
{
    $array = range(0, $aantal - 1);
    shuffle($array);

    $i = $j = count($array);

    while ($i--)
    {
        if ($array[$i] == $i)
        {
            $swap = mt_rand(1, $j) - 1;
            while ($array[$swap] == $i || $array[$i] == $swap)
            {
                $swap++;
                if ($swap == $j) $swap = 0;
            }
        
            $temp = $array[$swap];
            $array[$swap] = $array[$i];
            $array[$i] = $temp;
        }
    }

    while ($j--)
    {
        $check[$j][$array[$j]]++;
    }
}

echo '<pre>', print_r($check, true), '</pre>';

Intentionally left blank

Pagina: 1