9
votes

PHP: Trouvez deux numéros ou plus d'une liste de nombres qui s'additionnent vers une quantité donnée

J'essaie de créer un petit script PHP capable de rendre ma vie un peu plus facile. Fondamentalement, je vais avoir 21 champs de texte sur une page où je vais entrer 20 numéros différents. Dans le dernier champ, je vais entrer un numéro, appelons-le le montant total. Tout ce que je veux que le script fasse, c'est signaler quels nombres des 20 champs ajoutés viendront au montant total.

Exemple: xxx

sortie: champ1 + FieldS3 = 81.90

Certains champs peuvent avoir 0 en tant que valeur car parfois, il suffit de saisir 5-15 champs et du maximum sera de 20.

Si quelqu'un peut m'aider Avec le code PHP pour cela, sera grandement apprécié.


4 commentaires

Vous faciliter votre vie ou votre projet universitaire? ;)


Si vous trouvez une réponse à votre question, veuillez accepter cela en cliquant sur la case à cocher à la gauche de cette réponse - vous ne l'avez pas encore fait cela sur vos autres questions, et peut-être parfois, je ne t'élais pas si l'Aren ' t récompensé pour le faire.


Avez-vous essayé ma fonction entre-temps? Quels sont les résultats? serait bien d'entendre si cela vous a aidé ...


Kinda me rappelle une version simplifiée de xkcd.com/287


7 Réponses :


0
votes

Sans savoir s'il s'agit d'une affectation des devoirs ou non, je peux vous donner un pseudo code comme indice pour une solution possible, note que la solution n'est pas très efficace, plus une démonstration.

indice: >

comparer chaque valeur de champ à toutes les valeurs de champ et à chaque vérification de l'itération si leur somme est égale à total_amount .

pseudo code: xxx

MISE À JOUR:

Ce que vous semblez avoir est le Sous-ensemble Sum Problème , indiqué dans la liaison Wiki est pseudo code pour l'algorithme qui pourrait vous aider à pointer dans la bonne direction.


4 commentaires

Cela pourrait être plus de 2 champs


Pas une solution très efficace - mais travaillait pour le petit jeu de données utilisé - une meilleure solution serait d'utiliser les valeurs comme des touches d'index puis de rechercher (total_amount-i), mais cela aurait des problèmes avec des valeurs en double.


@ Nik, @ Symcbean: Ouais Ce n'est pas une solution très efficace, mais je voulais démontrer une comparaison possible pour l'OP. Voyant maintenant qu'une autre exigence est pour plus de 2 champs, je ferai de mon mieux, tout au long du travail, pour mettre à jour ma réponse


Thx pour votre réponse les gars. Juste pour indiquer clairement que ce n'est pas un projet d'école ni ses devoirs. J'essayais de mettre en place un moyen de trouver de la liste des factures que celles-ci additionnent à un Sommet d'argent qui a été transmis au compte de la société. Le logiciel comptable que nous ayons en place n'est pas le plus brillant. Je vais essayer ce soir après le travail voir si je peux comprendre quelque chose.



3
votes
1. Check and eliminate fields values more than 21st field

2. Check highest of the remaining, Add smallest, 

3. if its greater than 21st eliminate highest (iterate this process)

   4. If lower: Highest + second Lowest, if equal show result.

   5. if higher go to step 7

   6. if lower go to step 4

7. if its lower than add second lowest, go to step 3.

8. if its equal show result
This is efficient and will take less execution time.

1 commentaires

Peut-être que ce n'est pas efficace, mais je ne pense pas que cela obtiendra le bon résultat. Consultez mon message pour expliquer - et corrigez-moi si je comprends quelque chose de mal, s'il vous plaît.



0
votes

Je ne pense pas que la réponse n'est pas aussi facile que NIK mentionnée. Vous avez les chiffres suivants: xxx

à la recherche d'une quantité de 10

solution NIKS ferait cela (si je comprends bien. ): xxx

Maintenant, il supprimerait le nombre élevé et recommencerait à prendre la nouvelle valeur la plus élevée xxx

... et Donc, où la réponse parfaite serait simplement être 8 + 2 = 10 ... Je pense que la seule solution est toute la combinaison possible de Numéros et arrêtez-vous si l'AMAISTE que vous recherchez est trouvée (ou de calculer réellement tout, s'il existe différentes solutions et épargne laquelle on utilise le moins de chiffres).

EDIT: Calculez vraiment toutes les mbieurs possibles de 21 numéros se retrouvera vraiment, vraiment, vraiment beaucoup de calculs - il doit donc y avoir une solution "intelligente" pour ajouter des chiffres dans une commande spéciale (comme une post de post-NIKS - avec certaines améliorations, peut-être que cela nous amènera à une solution fiable)


2 commentaires

Hey Oezi, tu étais rite. J'ai fait des changements, veuillez vérifier. J'espère que cela fonctionnera par better pour plus de valeurs telles que vous avez pris 1 2 3 6 8, Wat s'il y a 15 valeurs de plus de valeurs que 10, cet algo les annulera en une seule fois des contrôles exponentiels.


HM ... Je ne pense pas que ce soit correct, mais je ne suis pas sûr de cela). Je suis assis, je suis une conférence pour le moment, alors j'ai beaucoup de temps à essayer une idée de votre réponse, je vais télécharger map maintenant et essayer quelque chose.



1
votes

La méthode suivante vous donnera une réponse ... presque tout le temps. Augmentez la variable d'itérations à votre goût.

[1] + 8.99 = 8.99
[4] + 8.16 = 17.15
[5] + 2.53 = 19.68
[6] + 0.28 = 19.96
[8] + 0.34 = 20.3
[10] + 8.24 = 28.54
[11] + 4.35 = 32.89
[13] + 1.69 = 34.58
[14] + 5.64 = 40.22
[15] + 0.27 = 40.49
[16] + 2.73 = 43.22
[17] + 1.63 = 44.85
[18] + 4.07 = 48.92
[19] + 9.04 = 57.96


6 commentaires

+1 pour une solution fonctionnerait maintenant et encore, mais ce n'est pas 100% fiable - ce qui est vraiment gentil de stupide.


La logique de cette méthode de calcul est loin d'être stupide.


mais c'est une mauvaise habitude que (seulement dans certains moments rarement), ce script se retrouvera sans solution, tandis que l'on n'aurait tout simplement pas été trouvée - vous devez donc faire plus d'itérations pour être plus fiable (et aussi dans ce cas pourrait le script ne trouve rien) ... avec les chiffres que vous avez pris pour tester il y a 338 solutions possibles, que s'il n'y en ait qu'un? Combien de fois ce script ne trouve pas cette solution - et combien de temps cela prendra-t-il?


C'est l'une des nombreuses méthodes de trouver des solutions, pas une mauvaise habitude. Bien sûr, dans l'extrême cas, s'il n'y avait qu'une solution particulière, le code ne trouverait pas une solution la plupart du temps. Ceci est un problème complet NP. Plus vous connaissez les méthodes, mieux vous ferez gérer cette classe de problèmes. Quoi qu'il en soit, je ne suis pas capable de répondre à vos questions spécifiques (je ne suis pas un mathématicien), vous pouvez peut-être demander à mathoverflow.net i Je viens de voir votre dernière réponse - laissez-moi vérifier.


Je viens de commenter le code de mon message, vous pourrez peut-être examiner cela à nouveau - et merci pour l'indice de Mathoverflow ... à une première dizaine, il ressemble à un endroit plein de monsus absolus O.0


+1 Je pense que c'est une très bonne méthode si vous n'avez besoin que d'un match.



4
votes

Désolé d'avoir ajouté une nouvelle réponse, mais c'est une nouvelle solution complète pour résoudre tous les problèmes de vie, univers et tout ...: xxx

Si vous n'utilisez pas le troisième Paramètre, il renvoie le meilleur (avec les chiffres de la moindre quantité utilisés) en tant que tableau (Whith Touches du tableau d'entrée) - Si vous définissez le troisième paramètre sur true , toutes les solutions sont renvoyées (pour les tests J'ai utilisé les mêmes numéros que Zaf dans son poste - il y a 338 solutions dans ce cas, trouvées dans ~ 10Sec sur ma machine).

EDIT: Si vous obtenez tout, vous obtenez les résultats commandés par lesquels est "meilleur" - sans ceci, vous obtenez seulement la première solution trouvée (ce qui n'est pas nécessairement le meilleur).

EDIT2: Pour confier le désir de certaines explications, j'ai commenté les parties essentielles du code. Si quelqu'un a besoin de plus d'explications, veuillez demander


5 commentaires

Thx Oezi, je vais essayer ce soir. Postera le résultat. Cristian.


Avant I +1, pourriez-vous donner une explication à cet algorithme?


J'ai commenté le code ci-dessus, en espérant que cela vous aidera à comprendre - sinon, veuillez demander à nouveau.


Pour que les calculs totaux ne sont pas la factorielle de 20 (20!)? Quelle seconde, je vois ce que tu fais. D'ACCORD.


Ravi de voir combien d'utilisateurs allemands il y a sur Stackoverflow: D Je vois de nombreux extraits de code avec Varnames Likes $ loesung ou $ anzahl . @oezi: Vous devriez changer vos <= comparaisons sur SO SLOW. Je comprendrais que ma mise en œuvre est deux ou trois fois plus rapide, car elle tombe des chèques, mais je ne m'attendais pas à ce qu'elle soit environ 20 fois plus rapide.



1
votes

une solution probablement inefficace mais simple avec de la backtracking xxx

exemple xxx

résultat xxx


0 commentaires

8
votes

Si vous regardez Algorithme d'Oézis Un inconvénient est immédiatement effacé: il passe beaucoup de temps à résumer des chiffres qui sont déjà connus de ne pas travailler. (Par exemple, si 1 + 2 est déjà trop gros, il n'a aucun sens d'essayer 1 + 2 + 3, 1 + 2 + 3 + 3 + 4, 1 + 2 + 3 + 4 + 5, ..., aussi .)

Ainsi, j'ai écrit une version améliorée. Il n'utilise pas Bit Magic, il fait tout le manuel. Un inconvénient est que les valeurs d'entrée doivent être triées (utilisez lsort code>). Mais cela ne devrait pas être un gros problème;) p> xxx pré>

version modifiée du programme de test OEZIS (voir fin) sorties: p>

// Inputs
$n = array();
$n[0]  = 6.56;
$n[1]  = 8.99;
$n[2]  = 1.45;
$n[3]  = 4.83;
$n[4]  = 8.16;
$n[5]  = 2.53;
$n[6]  = 0.28;
$n[7]  = 9.37;
$n[8]  = 0.34;
$n[9]  = 5.82;
$n[10] = 8.24;
$n[11] = 4.35;
$n[12] = 9.67;
$n[13] = 1.69;
$n[14] = 5.64;
$n[15] = 0.27;
$n[16] = 2.73;
$n[17] = 1.63;
$n[18] = 4.07;
$n[19] = 9.04;
$n[20] = 6.32;

// Convert to Integers
foreach ($n as &$num) {
    $num *= 100;
}
$sum = 57.96 * 100;

// Sort from High to Low
rsort($n);

// Measure time
$start = microtime(true);
echo 'possibilities: ', count($result = array_sum_parts($n, $sum)), '<br />';
echo 'took: ', microtime(true) - $start;

// Check that the result is correct
foreach ($result as $element) {
    $s = 0;
    foreach ($element as $i) {
        $s += $n[$i];
    }
    if ($s != $sum) echo '<br />FAIL!';
}

var_dump($result);


3 commentaires

+1 vraiment génial! Je connaissais aussi ce problème dans mon code et je voulais trocher, mais je n'ai jamais trouvé de temps et d'espace pour faire ça ... et Splash n'était pas en ligne depuis mon poste, il ne le reconnaîtra même pas. Une question plus qui ne sera jamais traitée officiellement (et celle-ci est la réponse)


@oezi: C'est toujours le risque lorsque vous répondez à de vieilles questions. Mais bon, l'écriture d'algorithmes est amusant même si vous ne pouvez pas vous attendre à la réputation pour eux;)


Absolument - et j'ai écrit ma fonction lors d'une conférence d'économie d'entreprise qui s'ennuie aux larmes - questions comme celle-ci sont super pour ces situations