Avatar billede nicklasb Nybegynder
01. juli 2004 - 19:54 Der er 8 kommentarer og
1 løsning

Beregne den maksimale gengangerværdi i to intervalarrays.

Hej,

Jeg har to arrays ($start og $slut), der sideløbbende danner en masse (ukendt antal) intervaller.
Indekseringen af arrayene sker ved hjælp af php's autonummerering, og arrayene danner derfor parvist intervallerne med samme indeks.
Et eksempel er følgende to arrays:

$start = array(1, 2, 4, 7, 4, 3);
$slut  = array(4, 14, 7, 11, 6, 7);

Altså dannes intervallerne ved 1 til 4, 2 til 14, 4 til 7 osv.
Tallene opgivet i arrayene (både start og slut) er en del af intervallet (den lukkede ring i matematikkens verden).


Det jeg ønsker er nu en funktion der på HURTIGSTE og MINDST KRÆVENDE måde beregner hvor mange gange den maksimale gengangerværdi optræder. Altså skal den i situationen ovenfor blot returnere 5, idet tallet 4 optræder ialt 5 gange i ovenstående intervaller (er ligeglad om tallet ER 4, blot at der er et tal der optræder 5 gange!).

Tilmed kunne jeg godt tænke mig at man i funktionen kunne angive et maksimum og et minimum for hvor i arrayet der skal søges. Her mener jeg hvis der forekspempel havde været en masse intervaller med start over 10, og denne mængde gengangere af tal ville overstige 4, skulle det i funktionen alligevel være muligt kun at tjekke på de "lave" tal ved foreksempel at sætte en nedre grænse på 2 og en øvre grænse på for eksempel 7.. (intervaller der ligger over grænserne skal beregnes med, blot de har et enkelt tal eller flere i "grænsefladen").

Altså ønsker jeg en funktion
$antal = stoerst_antal_gengangere($start, $slut, $minimum, $maksimum);

Har forsøgt at beskrive mig så godt som muligt, men skriv endeligt hvis der er noget du er i tvivl om!

Jeg takker på forhånd for jeres bud!
/Nicklas B.
Avatar billede jakoba Nybegynder
01. juli 2004 - 20:25 #1
$start = array(1, 2, 4, 7, 4, 3);
$slut  = array(4, 14, 7, 11, 6, 7);

$benyttet = array();            // et tomt array til optællinger

function interval( $fra, $til, $min, $max ) {
    global $benyttet;
    for( $i=$fra; $i<=$til; $i++ ) {
        if ( $i>=$min && $i<=$max ) {
            if (isset($benyttet[$i]) {
                $benyttet[$i]++;
            } else {
                $benyttet[$i] = 1;
            }
        }
    }
}

function storst_antal_gengangere( $start, $slut, $minimum, $maksimum ) {
    global $benyttet;
    for( $i=0; $i<count($start); i+=2 ) {
        interval( $start[$i], $start[$i+1], $minimum, $maksimum );
    }
    for( $i=0; $i<count($slut); i+=2 ) {
        interval( $slut[$i], $slut[$i+1], $minimum, $maksimum );
    }
    $maxcount = 0;
    foreach ( $benyttet as $index => $count ) {
        if ( $count > $maxcount ) {
            $maxcount = $count;
        }
    }
    return $maxcount;
}

Den kan utvivlsomt gøres hurtigere, men det må du selv hitte ud af.

mvh JakobA
Avatar billede jakoba Nybegynder
01. juli 2004 - 20:31 #2
Ups. jeg misforstod dine 'start/slut array

    for( $i=0; $i<count($start); i++ ) {
        interval( $start[$i], $slut[$i], $minimum, $maksimum );
    }

bemærk at der er nul og niks fejlhåndtering, (fx hvis $slut er for kort)
Avatar billede coderdk Praktikant
01. juli 2004 - 20:58 #3
Her:

<?php

    function tael( $tal, $key )
    {
        global $nums, $minimum, $maximum;
        $nums[ $tal ]++;
        if ( !isset( $minimum ) || $minimum > $tal )
        {
            $minimum = $tal;
        }
        if ( !isset( $maximum ) || $maximum < $tal )
        {
            $maximum = $tal;
        }
    }

    function stoerst_antal_gengangere( $start, $slut )
    {
        global $nums;
        $n = count( $start );
        for ($i = 0; $i < $n; $i++ )
        {
            array_walk( range( $start[$i], $slut[$i] ), 'tael' );
        }

        return max( $nums );
    }
   
    $start = array(1, 2, 4, 7, 4, 3);
    $slut  = array(4, 14, 7, 11, 6, 7);

    $antal = stoerst_antal_gengangere( $start, $slut );

    echo "Minimum: $minimum, Maximum: $maximum, største antal gengangere: $antal";

?>
Avatar billede nicklasb Nybegynder
01. juli 2004 - 21:31 #4
jakoba -> Har selv lavet noget lignende, dog med lidt flere (men efter lige at have dobbelttjekket det med dit) overflødige foreach-løkker. Den er dog blevet lidt kortere end min egen, med din hjælp, så jeg har vel fået hvad jeg kom efter :)

Gider du smide et svar, så jeg kan "belønne" dig for din hjælp?

coderdk -> får et par fejl på din kode, men har ikke fået kigget den nærmere igennem for fejl. Har dog fundet en løsning ovenfor, men vil højst sandsynligt lige kigge din igennem og se om der er noget "revolutionerende" deri, jeg kan bruge til min optimering..
Avatar billede coderdk Praktikant
01. juli 2004 - 21:33 #5
Hvad får du af fejl? Det kører fint her ;)
Avatar billede nicklasb Nybegynder
01. juli 2004 - 21:37 #6
Notice: Undefined offset: 1 in D:\webserver\Apache2\htdocs\projekt\hm\temp\kalender\~scp.php on line 6

og så bare med offsetene 1 til 14
Avatar billede coderdk Praktikant
01. juli 2004 - 21:39 #7
Ah:

  if ( isset( $nums[$tal] ) )
  {
    $nums[ $tal ]++;
  }
  else
  {
    $nums[ $tal ] = 1;
  }
Avatar billede jakoba Nybegynder
01. juli 2004 - 21:56 #8
nej tak.
Avatar billede nicklasb Nybegynder
07. juli 2004 - 22:00 #9
mig der huskede galt. Var selvfølgelig et par ekstra for-løkker jeg havde i min..
Men min version ser således ud;

function calendar_day_rows($start, $end, $min, $max) {
    $line = array_fill($min, $max - $min + 1, 0);
    for($i = 0; $i < count($start); $i++) {
        for($j = $start[$i]; $j <= $end[$i]; $j++) {
            if ($j >= $min && $j <= $max) {
                $line[$j]++;
            }
        }
    }
    return max($line);
}

Jeg lukker her, da du (jakob) åbenbart ikke vil have dine ellers fortjente :S point!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester