Aller au contenu

Messages recommandés

Posté(e)

Suite à ce message, je propose un premier "challenge" en LISP réservé aux "débutants".

 

Il faudrait donc que les lispeurs confirmés s'abstiennent dans un premier temps de répondre pour laisser les autres proposer leurs solutions, disons au moins jusqu'à Lundi soir ou Mardi matin dans la mesure où il y aurait déjà plusieurs réponses.

 

Le but :

- donner une routine qui retourne le centre de gravité d'un triangle défini par ses 3 sommets (p1, p2 et p3).

- que le résultat soit juste (bien sûr)

- essayer de faire le plus concis et élégant possible.

 

 

Exemple : (defun cen-grav (p1 p2 p3) ...) tel que, avec :

 

(setq pt1 '(10.0 5.0))

(setq pt2 '(4.0 15.0))

(setq pt3 '(-2.0 -5.0))

 

(cen-grav pt1 pt2 pt3) retourne (4.0 5.0)

 

Le sujet a, il me semble déjà été traité, mais je le pense qu'il est intéressant pour ceux qui ne connaîtraient pas de solution à priori (encore une fois, les autres s'abstiennent de répondre).

 

 

[Edité le 19/5/2007 par (gile)]

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

Posté(e)

bonjour,

Voila ma reponse avec mes connaissances:

 

(defun c:ctg()

 

(setq P1 '(10 5) P2 '(4 15) P3 '(-2 -5))

(setq XG (* (/ 1.00000000000 3) (+ (car P1) (car p2) (car P3))))

(setq YG (* (/ 1.00000000000 3) (+ (cadr P1) (cadr p2) (cadr P3))))

(setq XYG (list Xg Yg))

 

); fin du defun

 

on peut certainement faire mieux, mais j'ai eu un soucis avec (/ 1 3) qui me retourne 0 d'ou (/ 1.00000000 3)

 

merci de vos commentaires

 

 

Posté(e)

on peut certainement faire mieux

 

Bien sûr, c'est le but du jeu.

 

Et je suis certain que tu vas améliorer ta routine.

Déjà, le résultat est juste, tu semble avoir buté sur la fonction diviser (/) ce qui est le meilleur moyen d'en apréhender la subtilité. En fait il suffit qu'un des termes de la division soit un réel pour que le résultat en soit un, tu n'as donc pas besoins de mettre autant de décimales dans :

(/ 1.00000000000 3)

(/ 1.0 3) est suffisant.

 

quelques pistes pour simplifier :

 

- d'un point de vue arithmétique, multiplier par 1/3 équivaut à diviser par 3

- d'un point de vue code LISP un seul setq peut affecter des valeurs à plusieurs variable (CF (setq pt1 ...) plus bas). Éviter trop de setq est la base de l'allègement d'un code.

 

Une petite remarque générale, tel que, tu définis une fonction/commande (defun c:ctg... ) qui retourne le centre de gravité d'un triangle particulier quand on l'appelle en tapant ctg à la ligne de commande.

Le but que je proposais était de définir une routine avec 3 arguments : (defun ctg (p1 p2 p3) ...) qui retournenrait le centre de gravité de n'importe quel triangle dont les 3 sommets seraient les arguments de la routine.

C'est une manière de créer de nouvelles fonctions LISP qu'on peut appeler dans d'autre routines en faisant (ctg pt1 pt2 pt3) comme on fait avec n'importe quelle autre fonction prédéfinie, par exemple (+ 1 2 3), on parle aussi de "sous routines".

 

Exemple :

 

- avec (setq pt1 '(10.0 5.0) pt2 '(4.0 15.0) pt3 '(-2.0 -5.0))

(ctg pt1 pt2 pt3) retournerait (4.0 5.0)

 

- et (ctg '(0 0) '(1 0) '(0 1)) retournerait (0.333333 0.333333)

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

Posté(e)

Salut,

 

Il n'y a pas de "correspondance anglaise", ctg est le nom qu'a choisi Lovecraft pour sa routine.

On pourrait choisir n'importe quel autre nom qui ne soit pas un nom de fonction LISP prédéfini (comme steq, car, cadr, defun...) ou un symbole protégé (T, pi, pause).

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

Posté(e)

Oups!

 

Désolé gile (je suis vraiment un grand débutant) je pensais qu'il fallait mettre une commande après (defun.

Encore MERCI et bonne journée!

Posté(e)

Bon,

 

Il semble que je me sois "planté" avec ce challenge, plus de 260 visites ce jour, et seulement deux tentatives de réponses.

 

L'exercice est peut-être trop difficile pour ceux qui s'estiment "débutants", ou dénigré par ceux qui auraient pu s'y pencher.

 

L'idée que j'avais derrière la tête était d'amener à découvrir/comprendre la fonction mapcar. Chez moi cette découverte a été un grand pas dans ma compréhension du LISP et des traitements de listes.

 

Je vais tenter de débrousailler un peu pour aider ceux qui voudrait "améliorer la routine proposée par lovecraft.

 

 

mapcar fait passer comme argument à une fonction tous les éléments d'une ou plusieurs listes et retourne une liste dont chaque élément est le résultat de ces évaluations.

 

Exemple :

 

(mapcar '1+ '(3 4 5))

 

La fonction est 1+ qui incrémente de 1 l'argument qui lui est passé.

 

Chaque élément de la liste (3 4 5) sera donc passé comme argument de la fonction 1+

 

ce qui équivaudrait à faire : (list (1+ 3) (1+ 4) (1+ 5)) et retourne donc (4 5 6)

 

avec plusieurs listes, tous les éléments de même rang dans chaque liste sont passés comme argument à la fonction, ce qui permet, entre autre, d'ajouter des points (listes de coordonnées)

 

Exemple :

 

(mapcar '+ '(1 2 3) '(4 5 6) '(7 8 9))

 

ce qui équivaut à : (list (+ 1 4 7) (+ 2 5 8) (+ 3 6 9))

 

et retourne donc (12 15 18)

 

En utilisant la fonction mapcar dans la routine donné par Lovecraft, outre le fait qu'elle serait plus courte et plus élégante, elle pourrait fonctionner aussi bien avec des points 2d (x y) qu'avec des points 3d (x y z).

 

En espérant avoir éclairé quelques lanternes, à vos clavier ...

 

Prochain épisode, l'utilisation de fonctions lambda avec mapcar ...

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

Posté(e)

Salut,

 

J'ai pris l'exercice en cours et j'ai malheureusement lu tout le post pour en savoir plus et donc je n'ai pas cherché. Je ne me sentais pas suffisamment aguerri pour cette routine (simple je sais). J'espère que gile pourra continuer cet exercice vraiment très instructif.

 

 

Posté(e)

Il semble que je me sois "planté" avec ce challenge, plus de 260 visites ce jour, et seulement deux tentatives de réponses.

Comme pour moi avec un niveau intermédiaire ! J'ai bien deux autres propositions de ce niveau, mais je ne suis pas certain qu'il y a beaucoup de réponses. Je pense que l'on a affaire soit à des gros débutants pour lequel c'est trop difficile ou les pros qui répondent en 5mn. Doser le niveau et la difficulté n'est pas aisé. :mad2:

Je pense que le plus simple, c’est que les débutants proposent un challenge à leurs niveaux pour lequel d’ailleurs ils ne peuvent pas répondre, et aux autres de répondre afin que lesdits débutants puissent analyser les réponses, essayer de comprendre, et surtout, n’hésitant pas à poser des questions s’ils ne comprennent telle ou telle fonction ou la manière dont fonctionne la réponse.

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Posté(e)

Bonjour

 

Je ne suis pas tout à fait d'accord Patrick. Je pense plus que nous avons été "un peu timide" et n'avons pas osé. Et je crois aussi tout simplement que pas mal de monde a essayé de son coté.

 

Le fait que vous proposiez des sujets est vraiment "top", vous avez beaucoup d'expérience et pouvez je pense proposer des sujets qui ne nous viennent pas forcément à l'esprit.

 

Je souhaite avoir raison et SVP faites savoir si cet exercice vous intéresse!!!

 

Bonne journée à tous!

Posté(e)

Je pense plus que nous avons été "un peu timide" et n'avons pas osé

Alors allez-y. On n'a rien à perdre, au contraire

Ce qu'il faut savoir, c'est qu'aucune question n'est idiote, seule les réponses peuvent l'être.

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Posté(e)
Ce qu'il faut savoir, c'est qu'aucune question n'est idiote, seule les réponses peuvent l'être.

 

@+

Pas d'accord avec toi, Patrick, dans le cadre d'un challenge de quelque niveau que ce soit, il n'y a pas de réponse idiote, juste des tentatives qu'on peut juste qualifier d'optimisables éventuellement

mais je pense que tes propos ont juste dépassé ta pensée

cordialement

Posté(e)

Ma proposition puisque les réponses sont rares ! :(

 

(defun cen-grav (ptlst / n)
(setq n (float (length ptlst)))
(list (/ (apply '+ (mapcar 'car ptlst)) n) (/ (apply '+ (mapcar 'cadr ptlst)) n))
)

 

Accepte une liste de n éléments sour la forme ((x y) (x1 y1) .....) pas de Z!

 

(cen-grav '((10.0 5.0) (4.0 15.0) (-2.0 -5.0))) -> (4.0 5.0)

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

Posté(e)

La réponse de bonuscad est intéressante, en plus de mapcar, elle utilise la fonction apply, autre fonction majeure pour le traitement des listes.

 

Je vais pour ma part, essayer de finir mon exposé sur l'utilisation de mapcar pour résoudre ce challenge.

 

On avait vu ici comment utiliser mapcar avec une fonction LISP prédéfinie (+).

 

Le problème que nous avons à résoudre demande plus qu'une simple addition de tous les termes de même niveau de chaque point, il faut ensuite diviser chaque résultat par 3. Or, comme il n'existe pas de fonction LISP prédéfinie qui fasse cela, nous allons en créer une.

 

On peut imaginer de faire une autre fonction nommée (defun) qui retournerait la moyenne de 3 nombres :

 

(defun moyenne3	(n1 n2 n3)
 (/ (+ n1 n2 n3) 3)
) 

 

Et ensuite utiliser cette nouvelle fonction avec mapcar :

 

(defun moyenne3	(n1 n2 n3)
 (/ (+ n1 n2 n3) 3)
)

(defun cen-grav (p1 p2 p3)
 (mapcar 'moyenne3 p1 p2 p3)
) 

 

Cette solution exige que la routine moyenne3 soit chargée pour que cen-grav puisse aboutir. C'est celle que j'adopte dans le cas de routines servant dans plusieurs autres LISP.

 

La fonction mapcar accepte, comme on l'a vu, les fonctions prédéfinies, les fonctions définies par l'utilisateur (defun) elle accepte aussi les fonctions anonymes : lambda

 

Une fonction lambda n'a pas de nom et retourne son résultat là où elle est définie.

Comme un defun elle peut nécessiter des arguments.

 

Dans le cas présent, la fonction lambda remplacerait la fonction moyenne3 :

 

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

 

Voilà, c'est lidée que j'avais derrrière la tête en lançant ce challenge, faire découvrir à ceux qui ne les connaissaient pas ces fonctions, si faciles à comprendre mais puissantes dans le traitement des listes (tout comme la fonction apply utilisée par Bonuscad).

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

  • 2 semaines après...
Posté(e)

je voulais vous remerciez pour l'aide que vous nous donnez. Donc comme vous le suggerez j'ai une p'tite demande a vous faire. Est ilpossible de lancer un nouveau challenge? le sujet serait:

trier une liste de bloc avec un attribut (style numero du bloc) Pour ensuite avoir une nouvelle liste suivant l'attribut.

Merci de votre aide.

@plus

  • 3 mois après...
Posté(e)

Désolé pour le temps de réponse, mais j'avais pas vu ces challenges !! Vachement bien ça didon !!

 
(defun cen-grav (pt1 pt2 pt3)
    (mapcar '(lambda (div) (/ div 3))(mapcar '+ pt1 pt2 pt3))
)

 

Ma réponse diffère un peu de celle de Gile, mais c'est pas loin...

A quand un autre chalenge de ce type ??? ;)

A bientot !

Matt.

"Chacun compte pour un, et nul ne compte pour plus d'un."

  • 4 semaines après...
Posté(e)

Il y a une autre solution qui est plus géométrique :

 

(defun cen-grav (p1 p2 p3)
 (setq milieu (polar pt1 (angle pt1 pt2) (/(distance pt1 pt2)2)))
 (setq solution (polar milieu (angle milieu pt3) (/(distance milieu pt3)3)))
 )

 

Pour ceux qui ne connaisse pas la fonction polar

 

( polar point_de_départ direction_en_radians distance)

 

[Edité le 11/10/2007 par saamreivax2]

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é