Avatar billede k_jr Nybegynder
26. februar 2004 - 14:01 Der er 15 kommentarer og
2 løsninger

En Regnemaskine/beregner ?

Hejsa kloge hoveder :)

Jeg så et forholdsvis simpelt regnestykke forleden og tænkte om det ikke er muligt at lave en beregner på computeren ... Det er som følger:

Der er 5 tal, og de skal tilsammen give 5. Det gælder om at sætte tegnene imellem de 5 tal (og eventuelle paranteser). Dvs '+', '-', '*', '/'. Kan i hvert fald lykkedes med tal fra 1 til og med 9.
F.eks. :

1 1 1 1 1 = 5  <-- hvordan med tegn ?
1+1+1+1+1 = 5  <-- svar

5 5 5 5 5 = 5  <-- hvordan med tegn ?
(5*5+5-5)/5 = 5  <-- svar

Jeg ville gerne have et script eller meget hjælp til, at lave en beregner i php til dette.

Og nej, det er ikke let ;)
Avatar billede jara06 Nybegynder
26. februar 2004 - 14:02 #1
hmmm! :|
er det overhovedet muligt ?
Avatar billede jpvj Nybegynder
26. februar 2004 - 14:16 #2
Jo da...

Jeg har ikke testet, men du kunne bruge eval() funktionen i php, dvs. du bygger først et udtryk, og så tester det med eval:

altså noget i stil med
$str = "$x = (5*5-5+5)/5"
eval($str)
if $x=5 then {
  // wee - found solution
}

Det andet du skal igennem, er en metode til at finde alle kombinationer af tallene og regnemåderne.

Uden at bruge parenteser vil der være 4 muligheder på 4 pladser, altså (4^4 = 256) muligheder.

Med parenteser er der væsenligt flere, og din rutine til at genere alle muligheder bliver lidt mere komplex, men det skulle stadig være muligt inden for kort tid at lave en "bruteforce" løsning.

Som pseudo kode kunne de se således ud:

procedure lave_alle_parentes_kombinationer
  for each parentes_kombination
    call lav_alle_regnekombinationer
  next
end procedure

procedure lav_alle_regnekombinationer
  // her genereres helt slavisk udtryk med
  // hhv, +-'/ på hver af de 4 pladser
  // og udtrykket evalueres
end procedure

Det er klart at nogle kombinationer vil være overflødige ex. (5*5)+5-5+5, men det betyder nok mindre i dette "legeprojekt".

JP
Avatar billede Slettet bruger
26. februar 2004 - 14:24 #3
Det lyder som om du vil være doven i et opgavehæfte? *G*
Avatar billede jakoba Nybegynder
26. februar 2004 - 14:44 #4
$inddata = $streng_med_tal;
$tallene = explode( " ", $inddata );  // lav til array med eet tal i hver celle

$operander = "+-*/";        // og evt andre 1-bogstav operander der findes i php

$opr = array();                    // vor 'akkumulator'
function proev_alt( $nr, $resultat ) {
    global $operander;
    global $opr;
    global $tallene;
    if ( $nr+1 < count($tallene) ) {
        for ( $i=0; i<strlen($operander); $i++ ) {
            $opr[$nr] = $operander{$i};
            proev_alt( $nr+1, $resultat );
        }
    } else {
        $str = $tallene[0];
        for ( $i=0; $i<count($opr); $i++ ) {
            $str .= $opr[i] .$tallene[$i+1];
            $mitresultat = eval( "return ( " .$str ." );" );
            if ( $mitresultat == $resultat ) {
                echo $str ."<br>";
            }
        }
    }
}

ikke aftestet, så der skal nok være fejl.

mvh JakobA
Avatar billede detox Nybegynder
26. februar 2004 - 15:34 #5
Jeg har testet dette, men den finder ikke løsninger til 8 og 9, hvis resultatet skal være 5. Så det gad jeg godt at se løsningen på ;o)

<?
$tal = 7;
$res = 5;
$tegn = array('+','-','*','/');
for ($a=0;$a<4;$a++) {
    $atmp = regn($a,$tal);
    for ($b=0;$b<4;$b++) {
        $btmp = regn($b,$atmp);
        for ($c=0;$c<4;$c++) {
            $ctmp = regn($c,$btmp);
            for ($d=0;$d<4;$d++) {
                if (regn($d,$ctmp) == $res) {
                    echo $tal.$tegn[$a].$tal.$tegn[$b].$tal.$tegn[$c].$tal.$tegn[$d].$tal."=".$res;
                    exit;
                }
            }
        }
    }
}
echo "Det mislykkedes!";
exit;

function regn($f,$t) {
global $tal;
    switch ($f) {
case 0:
  return $t + $tal;
  break;
case 1:
  return $t - $tal;
  break;
case 2:
  return $t * $tal;
  break;
case 3:
  return $t / $tal;
  break;
}
}
Avatar billede detox Nybegynder
26. februar 2004 - 15:56 #6
Tja, ok. Det er jo så uden brug af parenteser.
Avatar billede detox Nybegynder
27. februar 2004 - 00:16 #7
Nu har jeg leget lidt med eval() og nogle parenteser, men jeg kan stadig ikke få den til at gå op med talet 9 og resultatet 5. Der er nok nogle kombinationer af parenteser i parenteser jeg ikke har prøvet:


<?
$start = 1;    // Mindste resultat - min. 1
$slut = 9;    // Største resultat - max. 9
$tegn = array('+','-','*','/');
$pat = array(
    '/(\d.)(\d.\d)(.\d.\d)/U'        // d+(d+d)+d+d
    ,'/(\d.\d)/U'                    // (d+d)+(d+d)+d
    ,'/(\d.)(\d.\d.\d)(.\d)/U'        // d+(d+d+d)+d
    ,'/(\d.\d.\d)(.\d.\d)/U'        // (d+d+d)+d+d
    ,'/(\d.)(\d.\d).(\d.\d)/U'        // d+(d+d)+(d+d)
    ,'/(\d.\d.)(\d.\d)(.\d)/U'        // d+d+(d+d)+d
    ,'/(\d.\d.\d.\d)(.\d)/U'        // (d+d+d+d)+d
    ,'/(\d.\d)(.\d.)(\d.\d)/U'        // (d+d)+d+(d+d)
    ,'/(\d.\d).(\d.\d)(.\d)/U'        // ((d+d)+(d+d))+d
);
$rep = array('$1($2)$3','($1)','$1($2)$3','($1)$2','$1($2)($3)',
    '$1($2)$3','($1)$2','($1)$2($3)','(($1)($2))$3');
$antalpat = count($pat);
$antal = count($tegn);
for ($res=$start;$res<=$slut;$res++) {
    echo "<h3>Med resultatet = $res</h3>";
    for ($tal=1;$tal<10;$tal++) {
        $stop = false;
        echo "<b>$tal: </b>";
        $a = 0;
        do { $atmp = $tal.$tegn[$a].$tal;
            $b = 0;
            do { $btmp = $atmp.$tegn[$b].$tal;
                $c = 0;
                do { $ctmp = $btmp.$tegn[$c].$tal;
                    $d = 0;
                    do { $dtmp = $ctmp.$tegn[$d].$tal;
                        eval("\$x = $dtmp;");
                        if ($x == $res) {
                            echo $dtmp." = ".$res."<br />";
                            $stop = true;
                            break;
                        }
                        $i = 0;
                        do {
                            $ptmp = preg_replace($pat[$i], $rep[$i], $dtmp);
                            @eval("\$x = $ptmp;");
                            if ($x == $res) {
                                echo $ptmp." = ".$res."<br />";
                                $stop = true;
                                break;
                            }
                        } while (++$i < $antalpat && !$stop);
                    } while (++$d < 4 && !$stop);
                } while (++$c < 4 && !$stop);
            } while (++$b < 4 && !$stop);
        } while (++$a < 4 && !$stop);
        if (!$stop) echo "<br />";
    }
}
?>
Avatar billede detox Nybegynder
27. februar 2004 - 00:27 #8
Der var et par fejl i $pat array'et:

<?
$start = 1;    // Mindste resultat - min.: -9
$slut = 9;    // Største resultat - max.: 9
$tegn = array('+','-','*','/');
$pat = array(
    '/(\d.)(\d.\d)(.\d.\d)/U'        // d+(d+d)+d+d
    ,'/(\d.\d)/U'                    // (d+d)+(d+d)+d
    ,'/(\d.)(\d.\d.\d)(.\d)/U'        // d+(d+d+d)+d
    ,'/(\d.\d.\d)(.\d.\d)/U'        // (d+d+d)+d+d
    ,'/(\d.)(\d.\d)(.)(\d.\d)/U'    // d+(d+d)+(d+d)
    ,'/(\d.\d.)(\d.\d)(.\d)/U'        // d+d+(d+d)+d
    ,'/(\d.\d.\d.\d)(.\d)/U'        // (d+d+d+d)+d
    ,'/(\d.\d)(.\d.)(\d.\d)/U'        // (d+d)+d+(d+d)
    ,'/(\d.\d)(.)(\d.\d)(.\d)/U'    // ((d+d)+(d+d))+d
);
$rep = array('$1($2)$3','($1)','$1($2)$3','($1)$2','$1($2)$3($4)',
    '$1($2)$3','($1)$2','($1)$2($3)','(($1)$2($3))$4');
$antalpat = count($pat);
$antal = count($tegn);
for ($res=$start;$res<=$slut;$res++) {
    echo "<h3>Med resultatet = $res</h3>";
    for ($tal=1;$tal<10;$tal++) {
        $stop = false;
        echo "<b>$tal: </b>";
        $a = 0;
        do { $atmp = $tal.$tegn[$a].$tal;
            $b = 0;
            do { $btmp = $atmp.$tegn[$b].$tal;
                $c = 0;
                do { $ctmp = $btmp.$tegn[$c].$tal;
                    $d = 0;
                    do { $dtmp = $ctmp.$tegn[$d].$tal;
                        eval("\$x = $dtmp;");
                        if ($x == $res) {
                            echo $dtmp." = ".$res."<br />";
                            $stop = true;
                            break;
                        }
                        $i = 0;
                        do {
                            $ptmp = preg_replace($pat[$i], $rep[$i], $dtmp);
                            //echo $ptmp."<br />";
                            @eval("\$x = $ptmp;");
                            if ($x == $res) {
                                echo $ptmp." = ".$res."<br />";
                                $stop = true;
                                break;
                            }
                        } while (++$i < $antalpat && !$stop);
                    } while (++$d < 4 && !$stop);
                } while (++$c < 4 && !$stop);
            } while (++$b < 4 && !$stop);
        } while (++$a < 4 && !$stop);
        if (!$stop) echo "<br />";
    }
}
?>
Avatar billede jakoba Nybegynder
27. februar 2004 - 01:03 #9
den er mulig:
  ((9*9)+9) / (9+9)
Avatar billede detox Nybegynder
27. februar 2004 - 01:41 #10
Ja, der var den jo. Har tilføjet regexp her:

<?
$start = 0;    // Mindste resultat - min. 1
$slut = 9;    // Største resultat - max. 9
$tegn = array('+','-','*','/');
$pat = array(
    '/(\d.)(\d.\d)(.\d.\d)/U'        // d+(d+d)+d+d
    ,'/(\d.\d)/U'                    // (d+d)+(d+d)+d
    ,'/(\d.)(\d.\d.\d)(.\d)/U'        // d+(d+d+d)+d
    ,'/(\d.\d.\d)(.\d.\d)/U'        // (d+d+d)+d+d
    ,'/(\d.)(\d.\d)(.)(\d.\d)/U'    // d+(d+d)+(d+d)
    ,'/(\d.\d.)(\d.\d)(.\d)/U'        // d+d+(d+d)+d
    ,'/(\d.\d.\d.\d)(.\d)/U'        // (d+d+d+d)+d
    ,'/(\d.\d)(.\d.)(\d.\d)/U'        // (d+d)+d+(d+d)
    ,'/(\d.\d)(.)(\d.\d)(.\d)/U'    // ((d+d)+(d+d))+d
    ,'/(\d.\d)(.\d)(.)(\d.\d)/U'
);
$rep = array('$1($2)$3','($1)','$1($2)$3','($1)$2','$1($2)$3($4)',
    '$1($2)$3','($1)$2','($1)$2($3)','(($1)$2($3))$4','(($1)$2)$3($4)');
$antalpat = count($pat);
$antal = count($tegn);
for ($res=$start;$res<=$slut;$res++) {
    echo "<h3>Med resultatet = $res</h3>";
    for ($tal=1;$tal<10;$tal++) {
        $stop = false;
        echo "<b>$tal: </b>";
        $a = 0;
        do { $atmp = $tal.$tegn[$a].$tal;
            $b = 0;
            do { $btmp = $atmp.$tegn[$b].$tal;
                $c = 0;
                do { $ctmp = $btmp.$tegn[$c].$tal;
                    $d = 0;
                    do { $dtmp = $ctmp.$tegn[$d].$tal;
                        eval("\$x = $dtmp;");
                        if ($x == $res) {
                            echo $dtmp." = ".$res."<br />";
                            $stop = true;
                            break;
                        }
                        $i = 0;
                        do {
                            $ptmp = preg_replace($pat[$i], $rep[$i], $dtmp);
                            //echo $ptmp."<br />";
                            @eval("\$x = $ptmp;");
                            if ($x == $res) {
                                echo $ptmp." = ".$res."<br />";
                                $stop = true;
                                break;
                            }
                        } while (++$i < $antalpat && !$stop);
                    } while (++$d < 4 && !$stop);
                } while (++$c < 4 && !$stop);
            } while (++$b < 4 && !$stop);
        } while (++$a < 4 && !$stop);
        if (!$stop) echo "<br />";
    }
}
?>
Avatar billede k_jr Nybegynder
27. februar 2004 - 10:59 #11
jpvj og detox .. smid svar :)
Det virker fint med din kode detox, og jpvj gav godt råd/vejledning.
Avatar billede detox Nybegynder
27. februar 2004 - 11:04 #12
Værsgo'
Avatar billede jpvj Nybegynder
29. februar 2004 - 15:14 #13
Det må vist være de fleste points til detox :-)
Avatar billede jpvj Nybegynder
29. februar 2004 - 15:15 #14
detox> Du har vist for megen tid *G*
Avatar billede k_jr Nybegynder
29. februar 2004 - 15:18 #15
hehe, tak for det :)
havde ikke regnet med en komplet løsning men bare hjælp .. men takker :)

og, sandbox, Ja, ideen kom rent faktisk fra et opgavehæfte til en HH klasse, jeg så da jeg var ifærd med at ordne deres computere ... Så det er ikke 'snyd til mig' ;)
Avatar billede Slettet bruger
29. februar 2004 - 15:25 #16
Jeg tænkte faktisk ikke på skoleopgaver men på kryds-og-tværs-blade. Et ef de små til ca. 12 kr. har ofte opgaver af denne type.
Avatar billede k_jr Nybegynder
29. februar 2004 - 15:36 #17
okay. hehe, didnt know ;)
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