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
1
2
3
>>> 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 : 5/5
.128013it3a;dv,FnT2S5wbcy+14: f-up08)_9eklohrP=[s6(]/mg7050g0H0c0e0b0J0Q0x0r0J0e0Q0Q0O010c0b0B010406050Q0A0V0V0e0M0s040n0K0J0A0=0K0k050U0|0~10120`0B04051i1b1l0U1i0`0g0b0h0*0,0.0:0,0k0W0A0e0W0H0z0B0s0c0L190x0L0b0W0L0J1N0L0c0^050#0q0J0H1u0-0/011M1O1Q1O0c1W1Y1U0c0M1j1I0*150Q0B0e0k0:0m011!1w010y0%0H0k0e0V0H1U1_1{201$231Y26280^0a0x0N0M0K0B0K0Q0b180k0x0Z1@0M0M0H0r2t1b2b0k1j0U1I2G1:1=1;1V0g2d1x0b0k252q1U1r1t0+1#2Q2S0k0K2W1U0B2z1j2E2G2-0{1`2u2Y212$0M0 0J1U0e1L2z0y0:030F0F0r2%0H1Q2#0K0z0u3b0^0x0u1b0e2.2;0_2:2c2?1$2^2`2|2~0H3001323436382T3b0z1~040x0m3h3j1{3l2E2P013q0e2{1j2}0L2 3133350Z3A2$3C0d3e0d3I2D3k0`3M3o0:3P3R053T3V3w3X3z2R3B3c0v3e0v3*1c3,3m2=1v3p0K2_3Q3s3U3u3W3y3Z3|3#3c0o3e0o422-3-2;3N3;4c3^3x3Y374i3a3c0R3e0R4o443.473:493r3S3t3v4w3{393C0X3e0X4F3K4q3n4I3O4K4b4M4d4O3`4h4R3c0D3e0D4W2F4Y462Z4#4a3=3@4e3_4g4y4-0z0G3e0G4=3L4r3/4`4L3?4N4f4x3!4A3b0C0^0u0C571m2+1b2W2J0g1=2O5a4x2V1s1j2*0H2,3k3+3K054x5E2c0b0g0:332E3C0u3s5M5O505h5R1 2h0H5V5g4z5Y2G3i453N0I0^0Z0y5G2F5,5a0p3e5=5K4^2@0y0^0Q0K0~0H0F2p0.0b1X0H5{5@4!0@040S6b4H4_0k0^250Q6h596d0^0i5{0x6c6j606o4Z4_6e6s433K6u6i2@0^0b6y5}1$6B6t6v6H04280V0K6K3N6e0E0w5{0`6D5?3M5U015P2;3C3E5d6)4+513}3D5Z275#6*5W5(3c6.0U3i0x726F6p4_5.040b5;6$3F6P3p6x7b746z210K0^0O0O6O6G1$0V0b0^5n7b7d0:6e6Z7b6#2/6(5N6{5Q3c3%4M6:6|523%0x5!5$4Q6?7I3I737V7h6L0:772z0c0A0M1a7g7w010I0r0^0l0M0A6a7A6V7K7G0z3 7J7E6;5X3~6^287Q4,6?7|7U737+77797o756Q6J7*7p0:7k04020W0c0f7n8h8e3p0q0^2g6V5a6e6g7v8i3O6l0k6n8B8s7x0^0E8d7i1$0K5_04498M7Y8D048G2-7X3N8k020J8o8T3N7r7t8x6q047z4p7^7~0F7`4l7}846=4j0z4l7O6_8{808~1U703F7W728a0^7#7%7)8Y8a7.040j3Q0Q7?8;8H5L8?7`4C8`6{5%524C90839u7R8}9s88998C8b7a9f8C8z8-6w8W9M216N8r8N3:6I9P6M8K8)5a8P0^2$0c9Z4!9#789e3k8Z5a6k6R0H6T9W8J8/6!8=5V7`4T9t7 6}0z4T9y6`a1529 9E7W7+9;0e0h2A0F370c0F8g9J8I018k8qam9T8V6163652q2r699^019L9o8U9;6maA9RaraE7faJ8!0^0z9)9NaGaD6W0^0PaA9;al5F9K0^0T6CaM9:9VaT9!0^0taA8+043ga,8.a(9.ac0^6S6Ua@6A9Y7@aT7_6,4.5T8?9v6?4/a592a24/5*9798a{8W1{0Qah8%akaQ7j7lbq7e8W6228aw67aza 9Q0^8A7CanaF8FaH6rbt9U9ObB9X04a_6EbjaZ5H8C8ka/bO0:a;a?bFasaIa`8C9;a}bJ048Lb2b%2ub41{3C54a07L6?54bc9A858}b`aa7Vbjb-bZaBaVbEa!bGaLccb(bK9SaK78b.0E0TbLaobsci4s0^aeagaibpcr9!8Q8Scy4!9;0QblbnajbU4?9|7Fb55jb7bd525m82a6b|8}cSbgc59G9b0!9dcob,9?a~b=aU040PcbbVcdbNc,8ycha)cDa+c@8.cm9{7v0U5J5p5D5r5A1b0c5ud82M2H0e692G5s6#0Z0#0%0Q04.

crédits : Serge Bays Codex