Aller au contenu

Messages recommandés

Posté(e)

Bonjour à tous,

 

En continuant ma lecture assidue du forum, j’ai pris la peine de m’attarder 5 mn sur ce post,que je conseil aux autres débutants qui n’auraient pas encore pris soin de le consulter...

 

Après relecture de la consigne je me suis permis cette légère modification (3 => 3.0)

(defun cen-grav (p1 p2 p3) 
 (mapcar '(lambda (x1 x2 x3) (/ (+ x1 x2 x3) 3.0)) p1 p2 p3) 
) 

Plus un clin d’œil reconnaissant à l’auteur pour son partage qu’autre chose... que je me permets ici plutôt que sur son post initial, étant donné « ma jeunesse sur le forum » et mon niveau en Lisp.

Histoire ne pas rester passif vis-à-vis de mes lectures , j’ai essayé de varianter le code :

 

 

L’objectif : Généraliser ce code pour n points. (que j’ai à tord cru simple)

Pour ce faire j’ai détecté 2 difficultées :

 

1ere difficulté : Le passage de n arguments (facile)

Bon comme la fonction defun ne support qu’un nombre d’arguments prédéfinis, pas de problème je vais lui soumettre les arguments sous forme de liste.

 (setq lstpt ‘(pt1 pt2 pt3 .. ptn)) 

 

2ème difficulté : Elle découle de la première, soumettre à mapcar non plus une liste de points, mais bien plusieurs listes de coordonnés de points. (Ce qui revient à supprimer un niveau de parenthèse).

 

Hé la je sèche totalement, malgré tout mes tests je n’arrive pas à trouver l’expression qui me permettrais de passer de cette forme :

((x1 y1) (x2 y2) (x3 y3) … (xn yn))

À la suivante pour la soumettre à mapcar:

(x1 y1) (x2 y2) (x3 y3) … (xn yn)

 

 

D’une manière générale :

 

Mais là je conclu peut être hâtivement, j’espère que vous me contredirez, ce que je cherche à obtenir n’est plus vraiment une liste, n’y même une liste de sous listes.. Et donc plus interprétable (n’y réalisable) en AutoLISP.

 

Ce qui revient à dire que l’opération

(list '(2 8) '(-4 9) '(20 -2)) qui retourne ((2 8) (-4 9) (20 -2))

Ne serai pas réversible avec une expression du type :

(expression ‘((2 8) (-4 9) (20 -2))) qui retournerai (2 8) (-4 9) (20 -2)

Ce qui serai je pense une erreur au regard de la syntaxe du LISP. Et donc que mon résonnement de départ conduit à une impasse..

 

 

Les questions posées sont les suivantes :

 

Y a-t-il une solution autre que de remanier totalement le code pour surmonter la 2ème difficultés?

Ma conclusion est elle juste ?

 

En espérant avoir été suffisamment clair.

Cordialement

 

Ps1: Pour un code remanier totalement ce n’est trop pas la peine de plancher à moins que vous ayez un lien tout fait, j’espère avoir les moyens d’y parvenir si il fallait en passer par là.

 

Ps2: Au passage dans mes évaluations de fonctions, j’ai trouvé très intéressant (sur le plan de la réflexion) le comportement de la fonction diviser (/) avec l’introduction d’un réel sur un 3ème terme et non les 2 premiers au regard de la définition donné par l’aide.

 

 

 

[Edité le 26/10/2010 par VDH-Bruno]

Apprendre => Prendre => Rendre

Posté(e)

Bonjour,

 

N'ayant pas autocad sur mon poste actuellement, je ne peux pas essayer ce que j'avance mais je pense que la fonction apply peut t'aider.

 

Cette fonction permet de passer une liste d'argument à une fonction.

 

ex:

(apply 'min '(-5 3 2 6))

est équivalent à

(min -5 3 2 6)

 

avec une liste lstpt de type ((x1 y1 z1) (x2 y2 z2) ... (xn yn zn))

on pourrait faire ceci

 

(mapcar '(lambda (x) (/ x (float (length lstpt)))) (apply 'mapcar (list '+ lstpt)))

 

(apply 'mapcar '(+ lstpt)) permet de récupérer la liste des sommes respectives de chaque coordonnée

 

(mapcar '(lambda (x) (/ x (float (length lstpt)))) (apply 'mapcar '(+ lstpt))) divise chaque somme par le nombre de points présent dans la liste lstpt

 

Tout cela est à vérifier

 

 

[Edité le 26/10/2010 par Titifonky]

www.le-metal.net, sur la métallerie
Posté(e)

Salut,

 

Là, tu as mis le barre plus haut !

Si tu le veux, je déplacerais ce message vers le forum "Pour aller plus loin en LISP" où il sera, à mon avis, mieux à sa place.

C'est fait.

 

Pour compléter/préciser ce que dit titifonky.

 

Je commencerais par un petit rappel théorique : en LISP, il n'y a pas de distinction syntaxique entre les données et les programmes. Autrement dit, un programme (ou appel de fonction) est une liste tout comme une liste de données et on peut construire un appel de fonction de la même façon qu'on construit une liste.

 

Ce à quoi tu voudrais arriver est une expression du type :

(mapcar 'fun l1 l2 l3 ... ln)

(où fun représente une fonction qui accepte un nombre indétermié d'arguments)

en partant d'une liste de données contenant l1, l2 l3, ... ln :

(setq lst (list l1 l2 l3 ... ln)) -> (L1 L2 L3 ... Ln)

Si on regarde l'expression ci-dessus comme une liste, on voit que c'est la liste de données à laquelle est ajoutée au début un symbole 'quoté' : 'fun et la fonction appelée : mapcar.

 

Pour ajouter 'fun à la liste de données, il suffit d'employer la fonction cons (puisque fun n'est pas évaluée)

(cons 'fun lst) retourne (FUN L1 L2 L3 ...Ln)

Pour mapcar, il en va un peu différemment puisque c'est la fonction appelée.

L'utilisation de apply permet de résoudre ceci.

(apply 'mapcar (cons 'fun lst))

est équivalent à :

(mapcar 'fun l1 l2 l3 ... ln)

(voir ou revoir ici).

 

Reste le problème de fun qui doit être une fonction acceptant un nombre indéterminé d'arguments (comme +, -, *, /, list, etc.) et ne peut donc pas être un defun ou une fonction lambda.

Pour en revenir à ton exemple, il s'agit de faire la moyenne d'un nombre indéterminé de points, autrement dit la moyenne des X, celle des Y et éventuellement celle des Z.

Il va donc falloir procéder en "deux temps" : utiliser la méthode ci-dessus pour réduire la liste de points en une liste utilisable avec une fonction defun ou lambda.

 

Par exemple en ajoutant tous les points (somme vectorielle) puis en divisant chaque coordonnée du vecteur résultant par la longueur de la liste (nombre de points) :

(mapcar	'(lambda (x) (/ x (float (length lst)))) ; division par le nombre de points
(apply 'mapcar (cons '+ lst))            ; somme vectorielle
)

 

Ou encore en transformant la liste de points en liste de listes de coordonnées (transposition d'une matrice) :

(mapcar	'(lambda (l) (/ (apply '+ l) (float (length l)))) ; moyenne des coordonnées
(apply 'mapcar (cons 'list lst))                  ; transposition
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonsoir,

 

Merci à tout les deux pour vos réponses très intéressante, qui devraient occuper mes prochaines soirées :D

 

A la première lecture, je pense en avoir saisi le contenu dans les grandes lignes. Je vais étudier vos réponses plus en détail.. . Je donnerai suite à mon retour (en déplacement pour la semaine).

 

Ps : (gile) j’apprécie grandement le soin et la pédagogie apporté à ta réponse, et effectivement tu peux déplacer le message dans la rubrique "Pour aller plus loin en LISP".

Apprendre => Prendre => Rendre

Posté(e)

Bonsoir,

 

Bon j’ai regardé plus dans le détail vos réponses, c’est impeccable.. à la première comme à la seconde lecture , merci encore

 

(gile) en plus de tes excellentes explications, je suis impressionné par la façon avec laquelle tu as réussi en quelques lignes à expliquer ce à quoi je voulais arriver :

Ce à quoi tu voudrais arriver est une expression du type :

 (mapcar 'fun l1 l2 l3 ... ln)

(où fun représente une fonction qui accepte un nombre indétermié d'arguments)

 

Et comment tu as pointé l’approche qui me faisais défaut :

Si on regarde l'expression ci-dessus comme une liste, on voit que c'est la liste de données à laquelle est ajoutée au début un symbole 'quoté' : 'fun et la fonction appelée : mapcar.

 

 

Pour conclure ce post et pour ceux qui auraient encore quelques difficultés avec, je vous livre les codes mis en forme ainsi que leurs déroulements sous forme de pas pas.

 

 

Les codes :

 ;; centre de gravité (version somme vectorielle)
(defun cen-grav	(lst)
 (mapcar '(lambda (x) (/ x (float (length lst))))
  (apply 'mapcar (cons '+ lst))
 )
)

;; centre de gravité (transposition d'une matrice)
(defun cen-grav	(lst)
 (mapcar '(lambda (l) (/ (apply '+ l) (float (length l))))
  (apply 'mapcar (cons 'list lst))
 )
)

 

 

Pour tester

 ;; liste de point représentant une forme pyramidale
(setq lstpt '((17 0 17) (0 17 17) (17 34 17) (34 17 17) (17 17 34)))
(cen-grav lstpt)

 

 

- Version somme vectorielle – Pas à pas "simplifié"

 (mapcar
 '(lambda (x) (/ x (float (length '((17 0 17) (0 17 17) (17 34 17) (34 17 17) (17 17 34))))))
 (apply 'mapcar (cons '+ '((17 0 17) (0 17 17) (17 34 17) (34 17 17) (17 17 34))))
)

 

Etape 1

 (mapcar '(lambda (x) (/ x (float 5)))
      (apply 'mapcar '(+ (17 0 17) (0 17 17) (17 34 17) (34 17 17) (17 17 34)))
)

 

Etape 2: ce qui revient à écrire:

 (mapcar '(lambda (x) (/ x 5.0))
(list (+ 17 0 17 34 17) (+ 0 17 34 17 17) (+ 17 17 17 17 34))
)

 

Etape 3

 (mapcar '(lambda (x) (/ x 5.0))
'(85 85 102)
)

 

Etape 4: qui peut ce traduire par:

 (list (/ 85 5.0) (/ 85 5.0) (/ 102 5.0))

 

Valeur de retour

'(17.0 17.0 20.4)

 

 

 

- Transposition d'une matrice - Pas à pas "simplifié"

 (mapcar
 '(lambda (l) (/ (apply '+ l) (float (length l))))
 (apply 'mapcar (cons 'list '((17 0 17) (0 17 17) (17 34 17) (34 17 17) (17 17 34))))
)

 

Etape 1

 (mapcar
 '(lambda (l) (/ (apply '+ l) (float (length l))))
 (apply 'mapcar '(LIST (17 0 17) (0 17 17) (17 34 17) (34 17 17) (17 17 34)))
)

 

Etape 2

 (mapcar
 '(lambda (l) (/ (apply '+ l) (float (length l))))
 '((17 0 17 34 17) (0 17 34 17 17) (17 17 17 17 34))
)

 

Etape 3: ce qui revient à écrire:

 (list (/ (apply '+ '(17 0 17 34 17)) (float (length '(17 0 17 34 17))))
     (/ (apply '+ '(0 17 34 17 17)) (float (length '(0 17 34 17 17))))
     (/ (apply '+ '(17 17 17 17 34)) (float (length '(17 17 17 17 34))))
)

 

Etape 4

 (list (/ 85 (float 5))
     (/ 85 (float 5))
     (/ 102 (float 5))
)

 

Valeur de retour

'(17.0 17.0 20.4)

 

Apprendre => Prendre => Rendre

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité