Aller au contenu

Image réciproque d'une fonction⚓︎

Nous considérons une fonction \(f\) qui à tout entier naturel \(i\), \(0 \leq i \leq n\), associe un entier naturel \(j\) tel que \(0\leq j\leq m\), avec \(m\) la valeur maximale de \(f(i)\).

Une telle fonction est représentée par le tableau images = [f(0), f(1), ..., f(n)]. Ainsi la valeur de \(f(i)\) est obtenue avec images[i].

L'objectif est d'obtenir pour tout entier \(j\), \(0\leq j\leq m\), la liste de ses antécédents, c'est-à-dire la liste des entiers \(i\), \(0 \leq i \leq n\), pour lesquels \(f(i) = j\).

Pour cela nous construisons deux tableaux, un tableau tetes et un tableau suivants, de la manière suivante:

  • les valeurs des éléments de tetes et de suivantssont initialisées à \(-1\);

  • si j a un unique antécédent i, alors tetes[j] a pour valeur i et suivant[i] a pour valeur -1.

  • si \(i_1, i_2, i_3, ..., i_p\), avec \(p \geq 2\), sont les antécédents de \(j\), alors tetes[j] a pour valeur \(i_p\), chaque élément de suivants d'indice \(i_k\), pour \(2\leq k\leq p\), a pour valeur \(i_{k-1}\) et l'élément de suivants d'indice \(i_1\) a pour valeur \(-1\);

Remarque: en Python, nous pouvons répondre à cette question de manière élégante à l'aide d'un dictionnaire, objet du type construit dict. Mais cette solution nécessite plus d'espace mémoire et l'utilisation de tableaux dynamiques pour stocker les antécédents.

1. Construction des tableaux tetes et suivants

Compléter la fonction image_rec qui prend en paramètres un tableau images représentant une fonction \(f\) et un entier m représentant la valeur maximale des images, et qui construit et renvoie les deux tableaux tetes et suivants.

Exemple
>>> img = [2, 0, 3, 2, 2, 0]
>>> tetes, suivants = image_rec(img, 3)
>>> tetes
[5, -1, 4, 2]
>>> suivants
[-1, -1, -1, 0, 3, 1]

###(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

.128013s3_8ufvy n7aêS1me(P2C4:jtwi][hE*)6o;bcdgx/0lîàqp.rL-,}=+k95R{é050N0r0z0m0B0S0b0j0M0S0m0b0b0%010z0B0W010406050b0f0q0q0m0Y0i040o0J0S0f120J0k0j020m0q0W0K0j0,0r1c0Y0V0f0r0b050Q191b1d1f170W041D1K051N0Q1N1P1K170N0B0h0`0|0~100E0B0O0E0S1%0E0z15050=0L0S0r1Y0}0 011$1(1*1(0z1:1=1.0z0L0J0N1f1/0Y1L0z0E0`1i0b0W0m0k100u011@1!010g0@0r0k1q0r1.2f2h2m1_2p1=2s0q2u040a0j0t0Y0J0W0J0b0B1l1n0:2d0Y0Y0r0M2P1D2w0k1L0Q2b2#0z29282a0N2y101*0k2r2M1.1V1X0{1^2/0B2;0k251W1.0W2U1L2Z2#36182g1n2`2n2 0Y1c0S150j0p2Y3a16392x3c1_3e3g3i0u3l2h3n2Z2.013s0m3h040j0c3w2!173z3q103C3E0j0w3I3y3a3A3O3i0+3S3K3U3M3B0J3f3D3i0I3Z3o3b1Z3r3(3t3F0l3-3L3:3N3=3*3F0e3_3#3{3%3)3P0*413p433W040p0R483/2{443?0p3k1E3m1M341D2^2(0N2,3A0M252E0/1W1L330r354n4m3x054w0:4E494h0)150:0g3S3.3A0A3i4S3`4h0k0g150B1c0O0r0d2U0M4X424h14040s4.4M3d4$4(1B4@4g2n4;0#3S0j4T3$0k150q4}3A4;0H0x3Z0j5f534Y2n0M0p15030j1=0j200r0m0f0j4%0m4)0_1B0z5o0m5o0B0b0z1?0:0_5w5y5e5g54435k5m0j0q0j5A5o005L1?1c0P5w1=5N5f5P4Z150k525+2n0J150%5/5i3r0L152B593$4;4?4G2!5:3r4`5x4|624L4~1_5b5)5h4/4_045H5H1C696f4^1_5=045@6m64104;0D5~436q0!6y4h0q0B154l385_6v150C5^6g6p150G6N6o6K4=6C6h58696u016q0(6W1_6E6G6(6U0H6e6!5604191W2h0z6l366n6b106q6s6{6!6w6,6#156B6Z6J016*4c744;6M6t796q6R7g6O3N5-6/794O040g3(6S6}3B4$7u3A0J4V042}7y555{040Y2h4)7d15616I7l7w045.787P5b5d69065g7Z6|3V150y7E6z5?7)5,7C4{6`4n79737T6T7Q0B7L047f367Y7!5*796;6?0h6^7:4H7=156x7@7v6;7`8c5a6L7,5;7+7k7^6;6j687O7^7?8r8d7%7{7}3m7 806:158p876389048b8u7$047(8g5 8i8m7v6 8j657C7o7P7q2U0z0f0Y7S71828D0;8q7;7U15518R8L84863-0Q4J4D4o8|0Q4r1D0z4t912*2$24262(0m1;8~4r1J6a3A2U0q0d0g0m0)4*0E0c151v1x1z1B0j7W381Q3n1K0Z5D1*5G5I9u6^0.0M0.0:0k6_0j2R0M0E0m9t5V9M0B0r0Y7#3$1d2O0E1c5H0P15090s0y096.6m5W4w0k5G0Y0f2O1?0m0h2V5o1?332}0M135I000f2;5E9E0`9R0T0k0.0r0x9Z439#2b9(0r9*049,0y0j090Y1+0=2T7A5v0d0)atav1~1d2J0AaA0-0)0!0p0$aDawaGaz0XaTaPaFayaI0B0d0uaV1,aRaY0d0pa$axaH0jaM9/4S9y9e0F1n0t0i2b1m0#9U0j1k0@5F6^b02Q0B2W0B1m2s0B2U5V5B5J5q9a1=5t0P9O0i2C0B9t0ba~1m0j2L8$7I2O0j9Iavbd0|0j7s0kb8bt0?9@0B7W1T4z2_431{1)aw2v7P2A2r2t152G0o0Mav0W5Ba`a|8(4n4C6a374n8{9f3$7q4Q747B538O4a4#7.674+2V7{7N8.8n665Mb}4:155c8Xc7041V4w8U6~8l8)8/040-0$ce7v7q7s0Ycj7_cw7A4$b,3xaj4Z7G7I0k7Kca4 7M740k7G5}cJ6ccLcQ7mc0c98K8P040Hcd7X80818Y4$4R8=55c88-88cn8Jc68v8WcT017ecy7B2 0zc|cAcw6;ch0J7{9w8zc%7!8Ccgb7d5c_8tc?8L5Z8Fb?43dgc:cf8fcXdm6L8ycC6!8Tc,ds8IcM7xdf8Q7~d96!7q0r0^0rd66edG8*dccidDdAc_8e7/7{c=doc@dqdhcY0Cdu8G7P6q0XdB040m0W0W2r0Nc4d.d#dZ8hcZcr3A8Z0;8$cB2!cD6hd48_b=8}2#9d1O040va12J0O7I1b1?b19D9F0_5rbk531wcgbn1qbp1A6leta~0semb32P9O1?bD0q0.a|2R4I4xd/d;d?1Db=0Ha~bv9Y5G0J0M9m9Y1=0_9H9J9L9N0Na71n2r129Xd-a?ed9B0j9^0f2W8$5!0n2DeG9Ob72Pbbbd5W4%0W0S0.2D9Mag0j0U5X0?2R2Rfa0f2N0r8$epbi5s0fbl0;2d9@0Jekbu1j0_e-1B2g0M5!fc0Jbc1?9TbD0b1ib1bt332K2Mff9}9 e%eGfubh9bereN4K8EeSeObe53b=8@9M6lb=e?bN8 0;0?0^04.

Il s'agit maintenant avec les deux tableaux tetes et suivants de parcourir la liste des antécédents d'un entier \(j\), \(0\leq j\leq m\), \(m\) étant la valeur maximale de \(f\) qu'on peut obtenir si nécessaire avec len(tetes)-1. Le coût pour chaque entier \(j\) est de l'ordre du nombre d'antécédents de \(j\).

Remarque: on pourrait parcourir la liste des images et noter les indices des éléments de valeur \(j\), mais dans ce cas le coût pour obtenir la liste des antécédents d'un entier \(j\) serait de l'ordre de \(n\).

Ce parcours permet de traiter chaque antécédent d'un entier \(j\). Ici, il est demandé de construire une liste liste initialement vide et complétée à chaque étape du parcours par l'antécédent de \(j\) obtenu.

2. Antécédents d'un élément

Compléter la fonction antecedents qui prend en paramètres deux tableaux tetes et suivants, un entier j, et renvoie la liste des antécédents de j.

Exemple
>>> tetes = [5, -1, 4, 2]
>>> suivants = [-1, -1, -1, 0, 3, 1]
>>> antecedents(tetes, suivants, 2)
[4, 3, 0]
>>> antecedents(tetes, suivants, 1)
[]

###(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

.128013s3obcdufvg/ly n7apS!.r1-me,(P2=4:jtwki][5h)6050g0A0J0r0M0m0b0o0f0m0r0b0b0F010J0M0s010406050b0h0z0z0r0w0n040t0d0m0h0-0d0p050l0@0_0{0}0=0s04161d051g0l1g1i1d0=0g0M0j0#0%0)0+0Q0M0k0Q0m1w0Q0J0:050W0e0m0A1r0(0*011v1x1z1x0J1F1H1D0J0e0d0g0}1E0w1e0J0Q0#100b0s0r0p0+0E011J1t010i0Y0A0p0r0z0A1D1+1-1=1L1^1H1{1}0:0a0o0D0w0d0s0d0b0M130p0o0U1)0w0w0A0f2i16200p1e0l1%2v0J1#1!1$0g220+1z0p1`2f1D1o1q0$1K2F0M2H0p1X1p1D0s2o1e2t2v2Z0?1,2j2N1?2S0w0`0m0:0x2s2%0;2$212)1L2+2-0:0E2;1-2?2t2E012{0r2.040c2 2u0=322_0+35370G3a312%333g0:0P3j3c3l3e340d2,360:0S3q2@2(1s2`3v2|040q3j1f2X162L2y0g2C330f1X1~1e3N1h3L2#172=053S0U2Y3s3D0+0L0:0U0i3J3d3+010K0:0o3;3*2O340i0:1-0J2p0A0U0p0J0b3{2^3?0/040C493C3}0p0:4242483!303B334c0B3j3`3=4h0:0@1p414m2#4v1?4r4t4p3t4i040I4f4q0:0R0H3q0o4S4u3|2*0:0M4G4D1L0d0:0F4Z4V2`4j0V0A4B3#4!0+4c0O4M4I0:4L4n2u4H4b0:0N4R4T4~4w041z0b424)4a3}4$044(4|044U5b4E0:0O515g064T5i4g1?3-040K1v1H5a5s4+044Y5g5r335d0u5f2Z5F3t5d0y4^3?0z0M2/5P3}4c4Q5o5q5q544W560M580A5U1?5d0v5+5B0r0s0s1`0g5/4=0:4e5g5#5B5D4C4*5`040R525Z5L3?4J602=685c4%5z3m4x0h4z464/4o4;014?5_344X6r4c5n2Z5p536o5u2o0J0h0w155E5~3f0:57595o163%0A2v2W6Q3M1p3O2y2A2w1W1Y2y0r1G6T0l3N0=6*0V0X0Z04.

La méthode décrite ci-dessus n'est pas du tout adaptée pour certaines valeurs de \(n\) et \(m\). Un exemple extrème est par exemple images = [0, 100]. Le tableau tetes contient alors \(101\) valeurs dont \(99\) sont égales à \(-1\).

L'idée qui apparaît déjà avec les tableaux tetes et suivants est d'utiliser des listes chainées. Un maillon contient un entier et un accès au maillon suivant.

3. Avec une liste chaînée

Dans la suite, un objet maillon sera une instance de la classe Entier:

🐍 Script Python
class Entier:
    def __init__(self, i):
        self.i = i
        self.suivant = None

    def __str__(self):
        return str(self.i)

Compléter les méthodes __init__ et ajouter de la classe ImageRec. Une instance de cette classe, ImageRec(images, j) est une liste chainée composée des antécédents de \(j\).

Exemple d'utilisation
>>> images = [2, 0, 3, 2, 2, 0]
>>> for i in range(3):
        print(f"pour j = {images[i]}")
        imrecj = ImageRec(images, images[i])
        print(imjrecj)
pour j = 2
0, 3, 4
pour j = 0
1, 5
pour j = 3
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

.128013s3o_8bcdufvgI/0ly n7apS.r1-meR,(P2=4:+Njtwki9][5hE)6050i0D0P0v0S0q0b0s0h0q0v0b0b0J010P0S0w010406050b0j0C0C0v0z0r040x0d0q0j0^0d0t050o0 1113150}0w041e1l051o0o1o1q1l0}0i0S0l0-0/0;0?0X0S0m0X0q1E0X0P0{050(0g0q0D1z0:0=011D1F1H1F0P1N1P1L0P0g0d0i151M0z1m0P0X0-180b0w0v0t0?0I011R1B010k0*0D0t0v0C0D1L1?1^1}1T201P23250{0a0s0H0z0d0w0d0b0S1b0t0s0$1;0z0z0D0h2q1e280t1m0o1/2D0P1-1,1.0i2a0?1H0t222n1L1w1y0.1S2N0S2P0t1)1x1L0w2w1m2B2D2+0~1@2r2V1~2!0z120q0{0s0A2A2/0|2.292;1T2?2^2`0I2}1^2 2B2M01340v2_040s0c382C0}3b320?3e3g0s0K3k3a2/3c3q2`0W3u3m3w3o3d0d2@3f2`0!3B302:1A333G353h0u3L3n3O3p3Q3I3h0f3U3D3W3F3H3r0T3$313(3y040A0p3-3N2W3)3R0A2|1f2~3C3.3_3:0A373~39403^2=3Y3g0A3j463l3M3x4b0{0A3t4f3v414a3*4k3A4n484i4r3;3K4u4h3E433T4A3V424j3;3#4F3%4H4x0A3,4L4p3P4x0I3?4R494T3R0I3}2+4v4C4I0I454%4B3/4*4e2-1r2)1e2T2G0i2K3c0h1)261m4_1p4@4=2-4~0$2*4M1~0R0{323u4.3_0Q2`5f4G2=0h0{0n120m0D0E2x5k5a1T0`040L3B0s5C0s5g5b0{0$0k5v4S0?5i3h5K4Y0?0k0C0{0e0e2Y2p5V5P3c5y0G5!3E0g5y0b0D0q5J4n5F5x0{0F3u5E5l330{0S5q0D0b5(3(5y5@4n5_5w3p0{0O613_5y0Z5A4u5D6h665L015*0{5,5.6b1~0d0{0y6q5{040$0g1a5^5;0?6s040J6B5`0?0R5n040N1c0D5B6i5C6C6l5+5-5/2-6I016E6u5:6Z0t5d0d0j0z1^0P6H676!0{6G656T6K0{6N2P6Q6R6_0{0k3G6:6k6)040S745Q6!5N2Y793x0g0{6-0t5r6v0?5$7l3d7g042d7o7n6%6;765}0v5r607v6k6d6e6~6R5D70776X2~6j7a766a6^6Z6E0J6@2+7N3x5|5~7B6Y6;5y0V7o7x7t0{0U6f4%7H7;7X4C0{120*0q1c7e3E7T7}3/0{0Y0t0^0D0z7,045%7C7O5|880Z7G7=7I6Z6m046o7L396T6#7*0{0v0O6+0P86888a7$757^0)0q7{1d8b5#0{8f4u066h7J5I7o5N5E8H4C0k8s8u1a8x8T620{8z2~6T8k8m88647W6T767_8E7|8!6c8J7/3 7;7J0S8n2C7?3(8*6W7o8q8@2=5H0D6z6/975=5z8g7H8)6V6p9d6D6t8r044~6,6.959n9l3d6n0j1x9s7R6;7 9B8B048;8F9g6S6Z5c045-5,888`478h9K6;939k8A7a969Y7Y6x9a6A9E9Z6?80428C7`8?7:9h8j9j8 596k9!8(6(6*9r849-6r9,9*9$9H9;3 8M8i6;9M8P9v8R7o5S5U0e0b2H5Z9v7u9#5)9^8e9R3l8|9~9p0Xa21T9D8.6Z0b1{0401019J919.9G8D9Ia57~a4aD9Vas9v9|8oax6y9)9=6 9L0{0Q1D1PaA68aN9:8Gaq8#9f6g9T8/5dazaQ3(6E0M7V7M8/7qal87ao8$9oa7a;9}7%8Ja-6=040MbfaF0{010F0saJa^8ha`a/8=bb39aLa36Fbf8:aOa8aY9C9ua=aM0 9za1bq6i7J2w0P6,bv90bs0ha|bH1~7(7o0C0S0{4WbX9eau9`7O7q7sb7899obV8e9t040Bb!b$044,bc7D7-3L0o570D2D2(c54^1x4`2G2I2E1(1*2G0v1Oc80o4_0}cl0%8D0b04.