1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
| # -*- coding:Utf-8 -*-
# Enoncé de l'exercice : Forum développer.com, message posté par petitours:
# http://www.developpez.net/forums/d1600384-2/general-developpement/algorithme-mathematiques/general-algorithmique/regroupements-d-objets-adresse/
#
def ff_lire_data(fic ) :
" Lit le fichier de data, ligne 1 = timeout, lignes suivantes = pour chaque paquet, 2 colonnes (adesse,longueur)"
nf = open(fic, 'r')
# Traitement des erreurs ...
lig = nf.readline()
xx = lig.split(',')
timeout = int( xx[0] )
ok = 1
i = 0
les_addd= [] # Les adresses de tous les paquets
les_lggg = [] # et leur longueur
lig = nf.readline()
while ok == 1 :
i=i+1
xx = lig.split(',')
les_addd.append( int(xx[0]) ) # Adresse
les_lggg.append( int(xx[1]) ) # Longueur
lig = nf.readline()
if lig == "" :
print (' fin de fichier ')
ok = 0
nf.close
return ( [ timeout , i , les_addd, les_lggg ] ) # Timeout, nbre de paquets, plus 2 tableaux addr et longueurs.
# **********************************************************************************************************
# **********************************************************************************************************
def ff_calcule_cout( add_debut, add_fin, qtimeout) :
" Calcul du coût de transmission d'un groupe de données. ---------------------------------------"
ii1 = add_fin - add_debut +1
ii1 = 12 + 1.04 * ( 5+ ii1 )
ii2 = 12 + qtimeout
if ii2 > ii1 :
ii1 = ii2 # le max des 2 calculs. ------------------------------------------------
return ii1
# **********************************************************************************************************
# **********************************************************************************************************
def ff_duplique ( tb ) :
"Fonction pour dupliquer un tableau"
# petite fonction , car quand on fait tb_svg = tb, ça ne duplique pas les données...
# J'imagine qu'il existe une fct standard, mais je ne la connais pas, donc je la crée.
tb2 = []
for un in tb :
tb2.append(un)
return tb2
# **********************************************************************************************************
# **********************************************************************************************************
def affiche_en_clair(qscenar, tb_add, tb_lg) :
"Fonction qui va afficher en clair les endroits où il faut séparer les paquets "
les_0_1 = qscenar[0]
print ( "$$$$$ $$$$$ $$$$$ Syntèse scénario $$$$$ $$$$$ $$$$$")
for i in range(len(les_0_1) ) :
if les_0_1[i] == 1 :
print ( " Coupure après le paquet qui débute à l'adresse ", str( tb_add[i] ) , sep = " : " )
for i in range(len(les_0_1) ) :
if les_0_1[i] == 1 :
print ( str( tb_add[i] ) , end = " // " )
# **********************************************************************************************************
# Programme principal ************************************************************************************
# 1. Initialisation des données --------------------------------------------------------------------
[ timeout , nb_paquets, les_addd, les_lggg ] = ff_lire_data( "c:\prj\petitours.csv" )
lg_max = 250
nb_paquets = nb_paquets+1
les_addd.append ( 99999999)
les_lggg.append ( 0)
# J'ajoute un paquet bidon très loin, ainsi on va s'obliger à 'fermer' après le dernier paquet, dans la boucle générale.(pas besoin de code particulier pour la fin de tableau).
tb_scenar = []
un_scenar = ( [], les_addd[0], 0 ,0 ) # 1=liste des 0 ou 1 , 2= addresse du 1er paquet après le dernier mur, 3=Cout cumulé 4= Redondant avec 2 , valeur du dernier 0/1
tb_scenar.append(un_scenar )
# 2. Boucle sur les paquets --------------------------------------------------------------------------
for i in range( nb_paquets-1) :
tb_scenar2 = []
fin_paquet_a_venir = les_addd[i+1] + les_lggg[i+1] - 1
best_cout = 9999999999
for un_scenar in tb_scenar :
les_0_1_svg = un_scenar[0]
addr_prem_paquet = un_scenar[1]
cout_cumule = un_scenar[2]
#if fin_paquet_a_venir - addr_prem_paquet <= lg_max :
for k in range ( 2) :
# on ajoute 2 scenarios
# k=0 : pas de mur après i, k=1 : avec un mur après i
les_0_1 = ff_duplique ( les_0_1_svg)
les_0_1.append(k)
if k == 0 :
if fin_paquet_a_venir - addr_prem_paquet <= lg_max :
# pas de mur après i, ossible uniquement si i+1 n'est pas trop loin.
un_scenar = ( les_0_1, addr_prem_paquet, cout_cumule, k )
tb_scenar2.append(un_scenar)
# Fin du test : if futur-paquet 'compatible
else :
cout_incremental = ff_calcule_cout ( addr_prem_paquet , fin_paquet_a_venir , timeout )
nv_cout = cout_cumule + cout_incremental
un_scenar = ( les_0_1, les_addd[i+1], nv_cout , k )
if nv_cout < best_cout :
best_cout = nv_cout # Je mémorise le coût minimal parmi les scénarios qui finnissent par un mur à cet endroit.
tb_scenar2.append(un_scenar)
# fin de la boucle for k in 0,1
# Fin de la boucle : Pour tous les scénarios qui étaient en attente
# Suppression de tous les scénarios 'périmés'
nj = len(tb_scenar)
for j in range(nj) :
del ( tb_scenar[0] )
# Nettoyage des scenarios trop couteux, et on re-transfère vers tb_scenar au lieu de tb_scenar2
for un_scenar in tb_scenar2 :
if un_scenar[3] == 0 : # Les scenar 'ouverts'
tb_scenar.append(un_scenar)
else : # Les scénar fermés par un mur.
cout_cumule = un_scenar[2]
if cout_cumule == best_cout :
tb_scenar.append(un_scenar)
best_cout = -1 # Je viens de copier un scénario, les autres scénarios ex-aequo ne m'intéressent plus.
print ( "Fin du step i= ", str( i ), " Nb scénar dans le tuyau = ", str( len( tb_scenar) ), " Addr/lg du paquet à venir = ", str(les_addd[i+1]), " ; " , str ( les_lggg[i+1] ) )
# Fin de la boucle sur i
# Affichage du résultat
for un_scenar in tb_scenar :
affiche_en_clair ( un_scenar, les_addd, les_lggg ) |
Partager