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
.128013ben,49vi[+3mo5_t;PhklpwTf(: cga=ry0FS6]-u/72)s18d050X0c0q0F0i0v0U0C0D0v0F0U0U0G010q0i0w010406050U0P0m0m0F0H0I040L0n0v0P0=0n0d050Q0|0~10120`0w04051i1b1l0Q1i0`0X0i0h0*0,0.0:0t0i0E0t0v1z0t0q0^050#0b0v0c1u0-0/011y1A1C1A0q1I1K1G0q0H1j0q0t0*150U0w0F0d0:0S011M1w010z0%0c0d0F0m0c1G1)1+1:1O1?1K1_1{0^0a0C0s0H0n0w0n0U0i180d0C0Z1%0H0H0c0D2g1b1~0d1j0Q1#2t1Y1!1Z1H0X200:1C0d1^2d1G1r1t0+1N2D0i2F0d0n2J1G0w2m1j2r2t2X0{1*2h2L1;2Q0H0 0v0^0C0V2q2#0_2!1 2%1O2)2+2-0S2:1+2=2r2C012`0F2,040C0l2~2s0`312^0:34360C0f3a302#323g2-0o3k3c3m3e330n2*352-0M3r2?2$1v2_3w2{370R3B3d3E3f3G3y370W3K3t3M3v3x3h0g3S2@3U3o040V0J3k1m2V1b2J2w0X1!2B3u0D2R1|1j3.1k3,2Z1c2;053@0Z2W3T2M010u0^0Z0z3*3L460x2-4c452(0z0^0U0n0~0c0p2c0.0i1J0c4h3!460@040A4w3D460d0^1^0U4C324z0e3k0C3C3n4l4J3u4L4N4P3u4F040i4S3U4U3 2 4O4d2(0^1{0m0n4#4y0^0T0B3r0C4`4*4i1O484Z4b4(2s4|4x4,044I52374W3U0n0^0G0G4V4+1O0m0i0^3)595b4=044^59064{5v544D1;4 2m0q0P0H1a595x320u0D0^0y0H0P4v5t5v5p5z0^0i512X5H4X5U5h4}0:5d04020E0q0r5g5G5S2_0b0^234;1;4z4B5o5i3f4G0d582Z5}014z0T5#551O0n4f043w675y2_4R5/635(020v5,6e325k5m5^1O4z5s2X5u5w4`5:0:5A0!5D5F5X6A475K040K350U5P6w5R634 5V6o4T0^5{625$336h6Y680:4%6G634Y4!5|6Z656U5c6b2Q0q6;466a5U6F2;5Y3#4-0c4/6s6(0^6v2;6x6y6H4Y0F0h2n0p0c6m0p6-6*6Z5(5.7l6%6!574n1{4q2d2e4u74646W7z4Y4H7z6)6~7b6#7H6j0^0O6_567E6.7q4z0j7C5!7R6f75040N4M6i6Z6,7z5(0k7z6q3%7F0^7$7p7Y7r4.4:7X4K4?4_6y6 4E4l1+0U7g7i7k7K7m5e7O6g7s4o7v4s7y7{6V4A7V047Q6$7@7G4)7I577:047=887q7)8i5c0^7,8A467.2/8E5_7;8b5~047_8u665Q7 8s8O8I6t0^0j6X406+7J2 6H8q538s878%63650N8L017n8;7c7e0D850q7j8;6{6c0H8@82608{8}8R6z6R0^5B6E928N727`8o7|048Y8l618!6/8K7%8y7W9h8j0T8:5t1b420c2t2U9A3-1s3/2w2z2u0F4u2t3.0`0Q0Z0#0%0U04.