Aller au contenu

Somme d'un sous-ensemble⚓︎

Étant donné un ensemble \(E\) d'entiers positifs et un entier naturel \(s\), on demande s'il existe un sous-ensemble de \(E\) dont la somme des éléments est égale à \(s\).

On appelle ensemble vide l'ensemble qui ne contient aucun élément et on le note en général \(\emptyset\). L'ensemble vide est un sous-ensemble de n'importe quel ensemble \(E\) et la somme de ses éléments vaut \(0\).

Méthode par force brute : on teste tous les sous-ensembles de \(E\). Le problème avec cette méthode est que si \(n\) est le nombre d'éléments de \(E\), alors le nombre de sous-ensembles de \(E\) est \(2^n\). Avec le calcul des sommes de chaque sous-ensemble, on obtient un coût total de l'ordre de \(n\times 2^n\). Ce coût est rédhibitoire. Par exemple, avec \(n=40\), le coût est d'environ \(40\times 2^{40} \simeq 4\times 10^{13}\). Donc si une machine effectue une opération en \(10^{-7}\) s, il faudra environ \(4\times 10^6\) s pour explorer tous les cas, soit environ 1000 heures !

On va donc utiliser la programmation dynamique.

Programmation dynamique⚓︎

Un ensemble de nombres est représenté par une liste en Python, par exemple [4, 1, 8, 2].

Définition des sous-problèmes

Pour chaque élément d'indice i, nous avons une prise de décision entre deux possibilités:

  • soit on choisit cet élément d'indice i et on continue récursivement avec les éléments restants et la somme restante;

  • soit on ne le choisit pas et on continue récursivement avec les éléments restants et la même somme.

Les cas de base:

  • la somme à obtenir est nulle et le sous-ensemble est trouvé,

  • il n'y a pas d'élément à choisir ou la somme à obtenir est négative.

On utilise un dictionnaire pour mémoriser les solutions des sous-problèmes dans une approche descendante. Une clé du dictionnaire est un couple (s, i) qui représente le sous-problème obtenir la somme s en considérant les éléments à partir de l'indice i, la valeur associée étant True ou False.

Compléter le code de la fonction somme_possible qui prend en paramètres une liste ens représentant un ensemble de nombres, un entier positif s, un indice i, un dictionnaire memo et qui renvoie True s'il existe un sous-ensemble de nombres dont la somme des éléments vaut s et False sinon.

Exemple
>>> nombres = [4, 1, 8, 2]
>>> somme_possible(nombres, 7, 0, {})
True

Le sous-ensemble dont la somme des éléments vaut 7 est \(\{ 4, 1, 2 \}\).

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10
.1280135[tf4)+2rFT3,sa-o iug08m1]P6pnl7he=cy:v9(w;S/b_dk050W0I0d0p0t0F0o0s0K0F0p0o0o0J010d0t0D010406050o0u0y0y0p0j0L040S0r0F0u0=0r0E050T0|0~10120`0D041b1i051l0T1l1n1i0`0W0t0N0*0,0.0:0H0t0v0H0F1B0H0d0^050#0U0F0I1w0-0/011A1C1E1C0d1K1M1I0d0U0r0W121J0j1j0d0H0*150o0D0p0E0:0i011O1y010e0%0I0E0p0y0I1I1:1=1`1Q1}1M20220^0a0s0B0j0r0D0r0o0t180E0s0Z1.0j0j0I0K2n1b250E1j0T1,2A0d1*1)1+0W270:1E0E1 2k1I1t1v0+1P2K0t2M0E1$1u1I0D2t1j2y2A2(0{1;2o2S1{2X0j0 0F0^0s0z2x2,0_2+262.1Q2:2=2@0i2`1=2|2y2J01310p2?040s0m352z0`382 0:3b3d0s0f3h372,393n2@0b3r3j3t3l3a0r2;3c2@0C3y2}2-1x303D323e0G3I3k3L3m3N3F3e0x3R3A3T3C3E3o0O3Z2~3#3v040z0w3r1k2$1b2Q2D0W2H390K1$231j3^1m3?2*1c2{053}0Z2%3!2T010X0^0Z0e3;3S4c0Q2@4i4b2/0e0^0o0r0~0I0V2j0.0t1L0I4n3+4c0@040P4C3K4c0E0^1 0o4I394F0n3r0s3J3u4r4P3B4R4T4V3B4L040t4Y3#4!45364U4j2/0^220y0r4+4E0^0g0M3y0s504:4o1Q4e4)4h4.2z524D4=044O583e4$3#0r0^0J0J4#4;1Q0y0t0^3:5f5h4{044~5f06515B5a4J1{552t0d0u0j1a5f5D390X0K0^0l0j0u4B5z5B5v5F0^0t572(5N4%5!5n530:5j04020v0d0R5m5M5Y300U0^2a4`1{4F4H5u5o3m4M0E5e2*63014F0g5+5b1Q0r4l043D6d5E304X5^695.020F5=6k395q5s5~1Q4F5y2(5A5C505_0:5G0!5J5L5%6G4d5Q040k3c0o5V6C5X69555#6u4Z0^61685,3a6n6(6e0:4-6M694(4*626)6b6!5i6h2X0d6`4c6g5!6L2{5(3,4?0I4^6y6.0^6B2{6D6E6N4(0p0N2u0V0I6s0V6?6:6)5.5@7r6-6*5d4t224w2k2l4A7a6a6$7F4(4N7F6/747h6+7N6p0^0q6 5c7K6@7w4F0c7I5*7X6l7b040A4S6o6)6=7F5.0h7F6w3.7L0^7,7v7(7x4@4_7%4Q4|4 6E754K4r1=0o7m7o7q7Q7s5k7U6m7y4u7B4y7E816#4G7#047W6,7}7M4/7O5d7_047{8e7w7/8o5i0^7=8G4c7@2_8K5 7`8h64047 8A6c5W858y8U8O6z0^0c6%466;7P366N8w598y8d8-696b0A8R017t8`7i7k0K8b0d7p8`716i0j8}886691938X6F6X0^5H6K988T78808u82048(8r678*6^8Q7-8E7$9n8p0g8_5z1b480I2A2#9G3@1u3_2D2F2B1#1%2D0p4A2A3^0`0T0Z0#0%0o04.