Hop, une nouvelle version avec la remarque de tbc92 et une version récursive du générateur pour prendre en compte autant de type de cadre que l'on veut :
https://onlinegdb.com/rJtIiF6Fr
Version imprimable
Hop, une nouvelle version avec la remarque de tbc92 et une version récursive du générateur pour prendre en compte autant de type de cadre que l'on veut :
https://onlinegdb.com/rJtIiF6Fr
Variante plus rapide de l'algorithme précédent, un peu sommaire:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 NaMax := Lm DIV La; FOR Ia:= 1 TO NaMax DO BEGIN L1:= Lm - (Ia * La); NbMax = L1 DIV Lb; IF (NbMax>0) THEN FOR Ib:= 1 TO NbMax DO BEGIN L2:= L1 - (Ib * Lb); NcMax := L2 DIV Lc; IF (NcMax>0) THEN FOR Ic:= 1 TO NcMax DO BEGIN L3:= L2 - (Ic * Lc); Nd:= L3 DIV Ld; IF (Nd>0) THEN BEGIN // Ltot:= Ia * La; Inc(Ltot, Ib * Lb); Inc(Ltot, Ic * Lc); Inc(Ltot, Id * Ld); // IF (Ltot<=Lm) THEN condition toujours vraie donc inutile <Examen des critères> END END END END;
Vous êtes trop fort les gars
J'ai pas le temps de me concentrer sur une de vos proposition qu'une autre arrive!
Je prend connaissance de tout ça
...et vous remercie pour votre aimable participation à ce problème existentiel qui me taraude depuis quelques jours, en espérant que ça serve aussi à satisfaire votre curiosité;)
Les différentes versions sont des variantes très proches les unes des autres d'une même idée.
La variante avec la récursivité est la seule vraiment différente, elle a l'avantage de permettre de traiter autant de tailles de tableaux qu'on veut (et pas seulement 4), mais pour un débutant, le code correspondant est totalement illisible.
La dernière variante Python sans récursivité, ou la version que j'avais proposée, c'est quasiment une traduction en 2 langages différents d'une même logique... lire les 2 codes en parallèle peut aider à les décrypter.
Royal.
C'est bien ce que je pensais, je vais finir comme Champollion devant la Pierre de Rosette ahaha
Alors, plusieurs questions:
pour wiwaxia: quel est ce langage?
pour tbc92: le code que tu as proposé est en quel langage?
pour cliffeCSTL: dans ton code, je n'arrive pas à comprendre où est la formule qui permet d'afficher la dimension utilisée.. c'est {}\n ? Pourtant quand
J'essaye de faire apparaître la dimension finale obtenue, c'est à dire la dimension utilisée + 2*e_b je n'y arrive pas...il faut que ce soit sur la même ligne?
ah oui merci, j'avais zappé
ou alors si tu veux formater avec du texte, j'utilise la méthode format :Code:print(2 * e_b)
Code:print("2 * e_b = {}".format(2 * e_b))
okay...ça me donne la somme des deux bordures.
Mais je ne pige toujours pas comment la "dimension utilisée" (somme des différents cadres utilisés) est calculée dans ton code.
Mais je me suis trompé, pour la dimension finale obtenue il faut intégrer les écarts entre les cadres aussi.
La dimension finale obtenue c'est:
dimension utilisée + ((e_c * nombre de cadres utilisés )-1) + 2* e_b
En fait je ne pige pas ou retrouver la valeur ou la formule de la longueur utilisée qui s'affiche avec la solution.
ok j'ai pigé la mise en forme dans le principe
Mais y'a t'il une formule qui calcul le nombre de cadres utilisés dans ton code? ce qui me permettrait de trouver le nombre d'écarts entre les cadres et l'inclure dans le calcul de la dimension totale?Code:print("Dimension obtenue: 2 * e_b = {}".format(best_solution[1] + 2 * e_b))
Après je vous embête plus promis :)
Je croyais que la dimension utilisée était liée à {}\n mais je viens de comprendre que \n c'est juste pour sauter une ligne...
Du coup je capte pas ou se fait le calcul longueur utilisée...ou plutôt je cherche dans quelle partie je peux intervenir pour faire calculer le nombre de cadres utilisés...Bref, je rame quoi ahahha
Dans le code de CliffeCSTL, celui avec la récursivité, si je ne me trompe pas, c'est cette ligne qui calcule la longueur 'utile' :
return sum(s[idx] * cadre[0] for idx, cadre in enumerate(l_cadre))Il faut la remplacer par :
return sum(s[idx] * (cadre[0]+e_c) for idx, cadre in enumerate(l_cadre))
Dans le code que j'avais posté, message n°11, c'est cette ligne :
score = i1* tb_larg[1] + i2* tb_larg[2] + i3* tb_larg[3] + i4* tb_larg[4]qu'il faut remplacer par
score = i1* tb_larg[1] + i2* tb_larg[2] + i3* tb_larg[3] + i4* tb_larg[4] + (i1+i2+i3+i4)*lg_intercalaire
Je comprends pas ce que tu cherches, les solutions de ton problème sont représentées par un vecteur de dimension le nombre de type de cadre.
Chaque composante représente le nombre de cadre pour chaque type, ex :
une solution s = [0, 1, 0, 12] signifie : 0 cadre du premier type, 1 cadre du deuxième, 0 du troisième et 12 du quatrième.
Ensuite, pour comparer des solutions entre elles afin de garder la meilleure, je calcul la longueur totale utilisée par les cadres avec la fonction eval_s.
=> \n c'est juste pour un retour ligne oui.
Je cherche en fait à faire afficher la valeur totale de la solution.
si pour un mur de 500cm, j'ai une solution qui arrive à 498cm, j'aimerai le voir tout de suite poir savoir la différence à combler potentiellement.
Et ça passe par (largeur utilisée + (nombre de cadres -1) * e_c + 2* e_b)
et je crois que dans ton code à aucun endroit je ne peut récupérer le nombre de cadres utilisés (donc le nombre d'écarts entre les cadres à rajouter à l'equation)
désolé si c'est pas clair
Dans mon code, il y avait à la fin du traitement un tableau best_je_ne_sais_plus_quoi, avec le nombre de tableaux de chaque dimension.
Pour trouver la place occupée, il suffit de faire
Dns le code de CliffeCSTL, c'est plus ou mois la même chose.Code:place occupée = best[1] * (70+8) + Best[2]*(60+8) + Best[3]*(50+8) + Best[4]*(40+8)
Mais je le dis et le redis : le code 'Récursif' proposé par CliffeCSTL, il est certainement très bien, mais oublie-le. Il est beaucoup trop compliqué pour un débutant, n'essaie pas de le comprendre. Essaie de comprendre la version précédente proposée par CliffeCSTL, elle est très bien, elle est compréhensible par un débutant, et elle fonctionne parfaitement. Elle a un seul inconvénient : la limitation à 4 tailles de cadres.Mais, c 'est facile d'en faire une variante avec 5 voire 6 tailles de cadres.
C'est good, j'ai mes réponses.
Merci beaucoup en tout cas, j'ai appris beaucoup de choses grâce à vous, je vais classé ce post comme résolu.
Il y a encore la partie "symétrie" mais chaque chose en son temps, c'est déjà top!
Je me dois d'aider à mon tour une âme perdue dans un forum de mon domaine de compétence.
Changez-rien
La partie avec la symétrie c'est pareil, comme déjà dit, on travaille sur la moitié du mur et on essaye pour chaque solution de rajouter une moitié de cadre :
https://onlinegdb.com/SkQGJGg5S
Une solution est représentée par le même vecteur que précédemment plus l’indice du cadre que l'on choisi pour mettre au milieu.
Il n'est peut-être pas souhaitable de faire intervenir des divisions par 2, alors que l'expression des longueurs en centimètres permet d'utiliser des variables entières, et que dénombrer des moitiés de cadre ne conduit pas à un critère simple.
tbc92 a livré dès le début le bon test (#1):
Et rien n'interdit d'exprimer les longueurs en millimètres, si la précision l'exige.
Et bien merci encore.
wiwaxia/tbc92
Je dois être honnête, CliffeCSTL m'ayant donné un moyen rapide de vérifier ses codes, je me suis focalisé sur ses codes/langage, sachant qu'il y a une semaine je ne connaissais rien à tout ça, j'essaye déjà d'assimiler ce que j'aarrive à comprendre.
Mais, cette fois-ci, je ne comprend pas le résultat. il me donne une réponde de type: ([0, 0, 0, 2], 3), longueur utilisée = 175.0
C'est bien une symétrie s'il y a un cadre, ou 2 similaires, ou 2similaires + 1 cadre seul.
Mais là, pour des entrées de cadres 30/40/50/70cm, La dimension utilisée semble fausse
que veut dire le 3?
Et question con:
La solution optimale en symétrie est probablement contenue dans les solutions optimales sans contraintes?
N'est-il pas possible dans ce cas d'afficher dans les meilleurs solutions la solution optimale sans contraintes et la solution symétrie?
En gros de fusionner les 2 codes?
1. Oui à Wiwaxia, pour tester si une solution est symétrique, on teste si les nombres de tableaux par taille sont tous pairs, ou si au maximum, un de ces nombres est impair.
2. Oui, avec cette méthode, on peut adapter le programme pour qu'il fasse le recensement une seule fois, et qu'il affiche à la fin la meilleure combinaison dans l'absolu, et la meilleure combinaison symétrique.
3. J'aimerais bien faire la modification à partir de code Python, mais sur la variante 'récursive', j'en suis incapable.
Si le nombre de tailles de tableaux est limité à 4 ou 5, alors je dois pouvoir adapter la 1ère version du code Python de CliffeCSTL.
Je peux aussi te proposer une version récursive dans mon langage favori.
([0, 0, 0, 2], 3) ça veut dire 2 cadres du dernier type + la moitié du cadre de 3ème type (sachant que l'on commence la numérotation à 0)
Merci tbc92, pour l'instant j'essaye de me focaliser sur un langage pour comprendre le processus, mais il est certain que, ne sachant pas comment (sur quel support) je vais utiliser ça au final, tout code sous différent langage m'intéresse mais je peux pas l'exiger...peut-être que je me ferais faire un petit logiciel perso par mon seul pote programmateur (que j'ai déjà bien sollicité par le passé), et je ne connais pas ses langages de prédilection.
Par défaut j'enregistre tout ce que vous me dites, espérant pouvoir mieux décortiquer ça plus tard.
CliffeCSTL:
ok je comprend mieux. Mais il semble qu'il y a une erreur tout de même:
pour les données suivantes:
L = 300 # Taille de la moitié du mur
e_b = 6 # Espace sur les cotés du mur
e_c = 8 # Espace entre les cadres
# Définition des cadres
l_cadre = [
(30, 999999),
( 40, 999999),
( 50, 999999),
( 70, 999999),]
J'obtiens:
Meilleure solution : ([0, 0, 1, 3], None), longueur utilisée = 260
Ce n'est donc pas une symétrie...
sauf si on considère qu'il faille rentrer comme longueur de mur la moitié du mur?
C'est à dire qu'en rentrant 300cm, je veux remplir un mur de 600cm...c'est bien ça?
heinn...
je suppute qu'il y ait une erreur du fait de travailler sur la moitié d'un mur...car du coup, il y a un écarts entre cadre qui est coupé en 2.
On considère 8cm d'écart (4cm + 4cm par cadre)...
d'où la suggestion de wiwaxia de ne pas travailler sur 1/2 mur?
Quelle enquête à retardement je fais! ahaha
Si ton pote est programmateur, il ne t'aidera pas beaucoup sur cette question. Par contre, s'il est programmeur, ça devrait marcher.
Effectivement, j'ai pas le bon vocabulaire
Si on dit qu'il est développeur ça marche pour tout? algorithme, programme, interface??
Je crois qu'il est loin de votre niveau cela dit...
:)
Oui il faut saisir la moitié du mur, c'est noté dans le commentaire :D
Il y a une petite erreur dans mon code, si on ne prend pas de moitié de cadre il faut rajouter un demi écart supplémentaire dans la solution :
https://onlinegdb.com/SJdyOrx9B
Concernant le langage, pour en avoir tester pas mal, je te conseil vivement python
ah ba oui...c'est sympa de me mettre des petits pièges pour voir si je suis bien concentré :)
CliffeCSTL
après tests, ça semble fonctionner parfaitement! C'est top
Pour pas me gourer dans la saisie, j'ai rajouté une saisie de la taille totale du mur, à la barbare:
Ltotal = 500 # Taille Totale du mur
L = Ltotal/2 # Taille de la moitié du mur
Par curiosité, est-ce que c'est le genre de truc qui alourdi les codes, d'une manière générale?
Je veux dire, de mettre une fonction directe qui rentre dans d'autres fonction, c'est le genre de truc à éviter si possible?
J'ai regardé ce que donnait le programme pour L = 500 et 600 cm.
La largeur totale correspond à la somme des largeurs effectives, la distance résiduelle à l'écart réel séparant le bord du cadre le plus proche de l'extrémité du mur (la distance entre 2 tableaux voisins étant maintenue à 8 cm)
L'algorithme n'a pas présenté de surprises, et s'exécute rapidement.
Le critère de choixCode:
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 PROGRAM Disposition_Tableaux; USES Crt, E_Texte; CONST La0 = 70; Lb0 = 50; Lc0 = 40; Ld0 = 30; Lm0 = 500; // Dimensions intrinsques Et = 8; Em = 6; // Ecarts imposs La = La0 - Et; Lb = Lb0 - Et; // Dimensions effectives Lc = Lc0 - Et; Ld = Ld0 - Et; Lm = (Lm0 + Et) - (2 * Em); X0 = 5; X1 = X0 + 30; // Directives d'affichage Y0 = 10; Y1 = Y0 + 3; o = 5; PROCEDURE AffLtNabcd(Lt, Ka, Kb, Kc,Kd: Word); VAR d: Reel; BEGIN E(0010); We(X1, Y1, Lt, o); E(0014); Write(Ka:o, Kb:o, Kc:o, Kd:o); E(0700); d:= (Lm0 - Lt + Et)/2; Wr(X1, Y1 + 3, d, 502) END; FUNCTION F_Parite(Ka, Kb, Kc, Kd: Word): Bool; VAR s: Byte; BEGIN s:= Ka MOD 2; Inc(s, Kb MOD 2); Inc(s, Kc MOD 2); Inc(s, Kd MOD 2); Result:= (s<2) END; PROCEDURE Comparaison(Lt, Ja, Jb, Jc, Jd: Word; VAR Lt_, Ja_, Jb_, Jc_, Jd_: Word); VAR TestA, TestB, TestC, TestL, TestP, TestLP, TestABC: Bool; BEGIN TestL:= (Lt>Lt_); TestP:= F_Parite(Ja, Jb, Jc, Jd); TestA:= (Ja>Ja_); TestB:= (Jb>Jb_); TestC:= (Jc>Jc_); TestLP:= (TestL AND TestP); TestABC:= TestA AND (TestB AND TestC); IF (TestLP AND TestABC) THEN BEGIN Lt_:= Lt; Ja_:= Ja; Jb_:= Jb; Jc_:= Jc; Jd_:= Jc; AffLtNabcd(Lt, Ja, Jb, Jc, Jd) END END; PROCEDURE AffNq(k: LongInt); BEGIN E(0012); We(X1, Y0, k, o) END; PROCEDURE Enumeration; VAR Iam, Ibm, Icm, Idm, Ia, IaMax, Ib, IbMax, Ic, IcMax, Id, IdMa, L1, L2, L3, Ltot, Ltm: Word; Nq: LongInt; BEGIN Iam:= 0; Ibm:= 0; Icm:= 0; Idm:= 0; Ltm:= 0; Nq:= 0; IaMax:= Lm DIV La; FOR Ia:= 1 TO IaMax DO BEGIN L1:= Lm - (Ia * La); IbMax:= L1 DIV Lb; IF (IbMax>0) THEN FOR Ib:= 1 TO IbMax DO BEGIN L2:= L1 - (Ib * Lb); IcMax:= L2 DIV Lc; IF (IcMax>0) THEN FOR Ic:= 1 TO IcMax DO BEGIN L3:= L2 - (Ic * Lc); Id:= L3 DIV Ld; Ltot:= Ia * La; Inc(Ltot, Ib * Lb); Inc(Ltot, Ic * Lc); Inc(Ltot, Id * Ld); IF (Id>0) THEN BEGIN Inc(Nq); AffNq(Nq); Comparaison(Ltot, Ia, Ib, Ic, Id, Ltm, Iam, Ibm, Icm, Idm) END END END END; A_ END; PROCEDURE AffT; CONST L1 = 10; o = 5; BEGIN E(1015); Wt(X0, Y0 - 3, '( Lm0, La0, Lb0, Lc0, Ld0 )'); Wt(X0, Y0, 'Nombre de quintuplets calculs:'); Wt(X0, Y1, '( Lt, Na, Nb, Nc, Nd ) ='); Wt(X0, Y1 + 3, 'Distance rsiduelle: d = '); E(0009); We(X1, Y0 - 3, Lm0, o); E(0011); Write(La0:o, Lb0:o, Lc0:o, Ld0:o) END; BEGIN AffT; Enumeration END.
n'établit pas de hiérarchie sur la recherche de la plus grande largeur, en ce qui concerne les cadres (A, B, C), et cela ne traduit peut être pas exactement ce que tu souhaitais:Code:
1
2
3
4
5 TestL:= (Lt>Lt_); TestP:= F_Parite(Ja, Jb, Jc, Jd); TestA:= (Ja>Ja_); TestB:= (Jb>Jb_); TestC:= (Jc>Jc_); TestLP:= (TestL AND TestP); TestABC:= TestA AND (TestB AND TestC); IF (TestLP AND TestABC) THEN
Cas3: je veux utiliser en priorité les plus grands cadres (en dernier lieu les plus petits cadres, par exemple A+A+A+A+C+C+C+BB+A) quitte à accepter une solution de 10% moins optimale que la solution du cas 1 (ou*cas2)
=(algorithme glouton/division euclydienne)
Je rectifierai cela; il suffit de reprendre l'expression du booléen TestABC.
Cool Merci
Bon il faut que je fasses des traductions maintenant ;)
J'ai donc repris la sélection des arrangements; la disposition des parenthèses était peu claire, et probablement incorrecte.
Cette nouvelle procédure a conduit aux résultats suivants:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 PROCEDURE Comparaison01(Lt, Ja, Jb, Jc, Jd: Word; VAR Lt_, Ja_, Jb_, Jc_, Jd_: Word); VAR TestP, TestBC, TestABC, TestLABC: Bool; BEGIN TestP:= F_Parite(Ja, Jb, Jc, Jd); TestBC:= (Jb>Jb_) OR ((Jb=Jb_) AND (Jc>Jc_)); TestABC:= (Ja>Ja_) OR ((Ja=Ja_) AND TestBC); TestLABC:= (Lt>Lt_) OR ((Lt=Lt_) AND TestABC); IF (TestLABC AND TestP) THEN BEGIN Lt_:= Lt; Ja_:= Ja; Jb_:= Jb; Jc_:= Jc; Jd_:= Jc; AffLtNabcd(Lt, Ja, Jb, Jc, Jd) END END;
L'étendue couverte est cette fois maximale: (d) est réduite à sa valeur minimale (6 cm); et l'on observe une nette augmentation de (Na).
Yaka voir ce que donne la nouvelle sélection, plus simple:
On obtient pour les mêmes valeurs de la largeur du mur:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 PROCEDURE Comparaison02(Lt, Ja, Jb, Jc, Jd: Word; VAR Lt_, Ja_, Jb_, Jc_, Jd_: Word); VAR TestBC, TestABC, TestLABC: Bool; BEGIN TestBC:= (Jb>Jb_) OR ((Jb=Jb_) AND (Jc>Jc_)); TestABC:= (Ja>Ja_) OR ((Ja=Ja_) AND TestBC); TestLABC:= (Lt>Lt_) OR ((Lt=Lt_) AND TestABC); IF TestLABC THEN BEGIN Lt_:= Lt; Ja_:= Ja; Jb_:= Jb; Jc_:= Jc; Jd_:= Jc; AffLtNabcd(Lt, Ja, Jb, Jc, Jd) END END;
L'étendue de la zone couverte est toujours maximale - il fallait s'y attendre; 3 nombres impairs interviennent dans le second cas, pour lequel (Na) est plus élevé (7 au lieu de 6).
Le nombre de combinaisons est relativement réduit, en raison des contraintes imposées; on observerait probablement des réponses très différentes sur un mur plus long.
Le programme fonctionne encore sur de plus grandes largeurs
et, comme on pouvait s'y attendre, la durée d'exécution est plus grande, et l'étendue couverte maximale que l'on impose (Comparaison01) ou non (Comparaison02) la condition de parité:
Compte tenu du déséquilibre observé en faveur des tableaux de grande dimension, il devient peut-être opportun d'en limiter supérieurement le nombre de chaque sorte, ce qui s'obtient par des corrections mineures.
Le nombre de combinaisons calculées apparaît proportionnel à Lm3 .
dans la realité j'ai un nombre limité de cadres mais je peux en racheter si besoin...Effectivement j'ai pu observer qu'avec un stock limité le calcul est plus rapide
Messieurs, (mesdames?),
je vous remercie pour votre participation généreuse, vous illustrez parfaitement l'idée que dans ce monde de brutes il existent encore des gens prêts à aider son prochain sans attendre en retour.
c'est beau.
vous m'avez fait gagner un temps précieux et je vous en suis très reconnaissant.
Je vais donc classer ce problème comme résolu.
Peace