Dessin de filets 3D - solides platoniciens

14

Ceci est une version de base des réseaux 3D de dessin plutôt plus difficiles - solides d'Archimède .

J'ai un faible pour les filets 3D qui, une fois découpés et pliés, vous permettent de créer des formes 3D en papier ou en carte. La tâche est simple, écrivez le programme le plus court possible qui dessine des filets pour les 5 solides platoniciens. La sortie doit être un fichier image dans n'importe quel format sensible de votre choix (png, jpg, etc.).

Les cinq formes sont décrites sur http://en.wikipedia.org/wiki/Platonic_solid . Leurs filets ressemblent à ceci (extrait de http://www.newscientist.com/gallery/unfolding-the-earth/2 ).

entrez la description de l'image ici

Entrée: Un entier de 1 à 5. Supposons que les formes sont numérotées dans l'ordre du nombre de côtés qu'elles ont. Donc, 1 serait un tétraèdre et 5 l'icosaèdre.

Sortie: un fichier image contenant le filet pour cette forme. Seul le contour, y compris les lignes internes, est OK. Il n'est pas nécessaire de le remplir de couleurs

Vous pouvez utiliser n'importe quel langage de programmation que vous aimez ainsi que n'importe quelle bibliothèque qui n'a pas été spécialement conçue pour ce concours. Les deux devraient cependant être disponibles gratuitement (dans les deux sens) en ligne.

J'accepterai la réponse avec le plus petit nombre de caractères dans exactement une semaine.

Gagnant.Un seul participant mais c'était merveilleux. Le gagnant est ... Raufio pour ce qui est mon morceau de golf préféré.

Felipa
la source

Réponses:

8

Python, 456 429 381

import turtle as t
L="fl"
R="fr"
d=L*3+R*3
b=(d+R)*3
a=[b,120,L*3+"fflflffflflfrflflfffl"+R*4+"flf",90,b+"ffrfrflffrffrfrfrflflf",120,(R*5+L*5+R+L)*5+"rrfr"+L*5+R*2+L*2+R*4+"f",72,(d+"f")*5+"rfl"+((d+"b")*5)[:-1],120]
l=t.lt
f=t.fd
b=t.bk
r=t.rt
p=input()*2-2 
t.setup(.9,.9)
t.goto(-200,150)
t.clear()
for c in a[p]:exec c+"(a[p+1])"
t.getscreen().getcanvas().postscript(file="o")

J'ai implémenté un interprète primitif avec l r f b comme opérateurs qui déplacent le curseur de la tortue à l'angle des formes. À un moment donné, il ne tourne que d'un angle. J'ai compressé les chaînes en réutilisant des chaînes (un peu comme des pseudo-sous-programmes), à part ça, je n'ai pas vérifié si j'utilisais le meilleur chemin. Il sort dans un fichier postscript.

Une petite explication du code non golfé:

import turtle as t
Left="fl"
Right="fr"
diamond= Left*3 + Right*3
tetrahedron=(d+R)*3 #used to be b

Importe le module de tortue intégré et définit les macros qui raccourcissent les chaînes. Le module tortue utilise des commandes pour déplacer une «tortue» autour de l'écran (c'est-à-dire vers l'avant (100), gauche (90))

netList=[
   #tetrahedron
   tetrahedron,120,
   #cube
   Left*3+"fflflffflflfrflflfffl"+Right*4+"flf",90,
   #octohedron, builds off the tetrahedron
   tetrahedron+"ffrfrflffrffrfrfrflflf",120,
   #dodecahedron
   (Right*5 + Left*5 + Right + Left)*5
    +"rrfr"+
    Left*5 + Right*2 + Left*2 + Right*4 + "f",72,
   #icosahedron
   (diamond+"f")*5 +"rfl"+((diamond+"b")*5)[:-1],120
]

Cette liste contient les angles et les séquences de mouvement. Le tétraèdre a été conservé pour être réutilisé avec les octoèdres.

l=t.left
f=t.forward
b=t.back
r=t.right

C'est la partie que j'aime, elle fait des fonctions locales à un seul caractère afin que les appels puissent être raccourcis et automatisés via des chaînes prédéfinies.

input=int(raw_input())*2-2 
t.setup(.9,.9)
t.goto(-200,150)
t.clear()

Cela commence par prendre l'entrée (entre 1 et 5) et la convertir en un index qui pointe vers la chaîne de forme dans la netList. Ces tortues d'installation pour montrer l'ensemble du net. Ceux-ci pourraient être omis si la tâche consistait simplement à les dessiner, mais comme nous avons besoin d'une sortie d'image, ils sont nécessaires.

for command in netList[input]:
    exec command+"(netList[input+1])"
t.getscreen().getcanvas().postscript(file="o")

La boucle for prend les commandes dans la chaîne de séquence de commandes et les exécute, donc pour une chaîne comme "fl", cela exécute "avant (angle); gauche (angle);" en appelant les fonctions locales nouvellement créées. la dernière ligne génère un fichier appelé «o» au format postscript utilisant la fonction tortue.

Pour exécuter :

Copiez-le dans un fichier et exécutez-le à partir de là. Lorsque vous l'exécutez, il attendra une entrée de nombre entre 1 et 5 (je viens de le changer pour qu'il demande avant de configurer la tortue). Lorsque vous entrez un nombre, une fenêtre apparaît et dessine le filet. si vous voulez que ça aille plus vite, vous pouvez ajouter t.speed(200)avantsetup .

Vous pouvez le copier-coller dans l'interpréteur, mais lorsqu'il raw_input()est appelé, il consomme la chaîne suivante que vous saisissez "t.setup(.9,.9)"au lieu d'un nombre. Donc, si vous faites cela, copiez jusqu'à raw_input(), entrez un nombre, puis copiez-collez le reste. Il est destiné à être exécuté dans son ensemble. Ou vous pouvez le copier dans une fonction et l'appeler.

Voici ses sorties (converties à partir de postscript):

Remarque: la position de ceux-ci dans la fenêtre a changé, mais leur forme générale est la même.

tétraèdre cube octaèdre dodécaèdre icosaèdre

C'est une petite force brute pour le golf de code, mais je me suis fatigué d'essayer de trouver un motif cohérent entre les formes.

Raufio
la source
Très proche. Le dodécaèdre est définitivement plus délicat.
felipa
@Raufio C'est très sympa. N'est-il pas possible de définir un triangle (ou carré ou pentagone) puis de le faire pivoter / déplacer? Ou est-ce effectivement ce que vous avez fait?
felipa
Effectivement, c'est ce que j'ai fait, mais avec des formes plus grandes. Par exemple, l'icosaèdre est dessiné en dessinant deux triangles, l'un au-dessus de l'autre, et en avançant 5 fois, puis en réinitialisant à un nouvel emplacement, en tirant à nouveau le diamant en reculant puis en répétant 5 fois. dest la chaîne qui fait les deux triangles, donc c'est(d+'f')*5+setupPosition+(d+'b')*5
Raufio
@Raufio Le code golfé ne fonctionne pas pour moi. Il ouvre une fenêtre presque vide. Si j'appuie ensuite sur retour, j'obtiens p = (ord (raw_input ()) - 49) * 2 TypeError: ord () attendait un caractère, mais une chaîne de longueur 0 trouvée
felipa
1
@felipa setupfait que la fenêtre de la tortue est suffisamment grande pour contenir le filet. Même chose avec goto, il déplace la «tortue» à -200, 150. clearefface la ligne tracée par goto. Leurs seules commandes pour configurer le dessin. p=(ord(raw_input())-49)*2prend un nombre, de 1 à 5, correspondant à la forme souhaitée.
Raufio
6

Mathematica

Hors compétition, pas une langue gratuite (sauf si un essai gratuit compte comme gratuit)

f[n_] := PolyhedronData[ Sort[PolyhedronData["Platonic", {"FaceCount","StandardName"}]][[n,2]],
                                                                                       "NetImage"]

Usage:

f /@ Range@5

Graphiques Mathematica

Dr. belisarius
la source
1
Mathematica n'est certainement pas gratuit dans les deux sens. Très belle réponse cependant.
felipa
@felipa c'est gratuit comme dans la bière sur le Raspberry Pi.
shrx
vous savez, sur cet ordinateur gratuit, le raspberry pi
undergroundmonorail
6

Python 2 (avec le Caire) - 239

from cairo import*
s=PSSurface(None,99,99)
g=Context(s)
g.move_to(30,20)
a=str([34,456,3455,568788,3454445555][input()-1])
f=6.28
for c in a+a[::-1]:exec'g.rel_line_to(8,0);g.rotate(f/int(a[0]));'*int(c);f=-f
g.stroke()
s.write_to_png('o')

Résultats:

résultats

aditsu quitte parce que SE est MAL
la source
3

Logo, 199 octets

TO p:d:n:s
rt :n*45 for[i 1 :n/8][pu setxy :d*:i 0 pd repeat 2[for[k 1 :s*2+2][fd 40 rt (360-720*(:k>:s))/:s] rt 720/:s]]END
TO q:j
apply "p item :j [[70 9 3][56 23 4][70 16 3][105 26 5][40 42 3]]END

En lisant ceci, je vois que ma version originale n'était pas conforme à la spécification telle qu'écrite (prendre un argument numérique et dessiner une forme) mais plutôt telle qu'interprétée par certaines des autres réponses (dessiner toutes les formes.) La nouvelle version corrige cela. Il s'attend à être appelé comme par exemple q 5. csdoit être fait avant pour effacer l'écran et pointer la tortue vers le nord.

qappelle la fonction principale pavec 3 arguments. La syntaxe pour cela est assez gonflée, donc pour battre mon score précédent, j'ai dû raser les octets ailleurs.

la nouvelle version de pprend 3 arguments. Il n'y a pas besoin de xet yparce que nous ne traçons qu'un seul filet, mais dle pas entre les sous-unités demeure. s est toujours le nombre de côtés par polygone, et nencode maintenant pour deux choses différentes>n/8 est le nombre de sous-unités à tracer, et n*45est un angle par lequel la tortue doit être tournée avant de commencer (en profitant du mod naturel 360 pour les rotations. )

Le bouclage amélioré permet de dessiner des slignes avec une rotation à droite ets+2 lignes avec une rotation à gauche dans une seule boucle.

l'interprète calormen semble être moins tolérant à l'égard des espaces manquants maintenant qu'au moment de mon premier post, mais le code fonctionne bien sur http://turtleacademy.com/playground/en

Logo, 200 octets

TO p:x:y:d:n:s
for[i 1:n][pu setxy:x:y-:d*:i if:i<>6[pd]repeat 2[repeat:s[fd 40 rt 360/:s]repeat:s+2[fd 40 lt 360/:s]rt 720/:s]]END
p 0 200 40 7 3
p 70 0 80 2 3
p -200 200 105 3 5
rt 45
p 90 90 56 2 4

Interprète sur http://www.calormen.com/jslogo/# Il est supposé que la tortue pointe vers le nord avant l'exécution du programme. Utilisez la cscommande pour effacer l'écran, pointez la tortue vers le nord et placez-la à l'origine au centre de l'écran.

entrez la description de l'image ici

L'unité de base de tous les filets ci-dessus est une paire de polygones dos à dos. Ceux-ci sont disposés en 2 rangées décalées, formant une sous-unité de 4 polygones qui peuvent être translatés verticalement pour faire tous les filets (sauf l'octaèdre, qui fait un tour sur le dessin de l'icosaèdre et du tétraèdre). La sous-unité forme 1 filet de tétraèdre, 1/5 du filet d'icosaèdre, 1/3 du filet de dodécaèdre et 2/3 du filet de cube (deux sous-unités sont dessinées, les deux carrés du milieu se chevauchant.)

Code non golfé

TO p :x :y :d :n :s                 ;x,y=starting point d=negative vertical offset for each iteration n=#of iterations s=# of sides on polygon
  for[i 1 :n][                      ;iterate n times 
    pu                              ;pen up
    setxy :x :y- :d* :i             ;move pen to start of iteration
    if :i<>6[pd]                    ;pen down (supressed for i=6 to enable part of octahedron to be drawn with icosahedron)
    repeat 2[                       ;draw lower row of 2 polygons, then upper row of 2 polygons
      repeat :s[fd 40 rt 360/ :s]   ;starting at lower left of polygon facing up, draw righthand polygon
      repeat :s+2[fd 40 lt 360/ :s] ;starting at lower right of polygon facing up, draw lefthand polygon, duplicating last two sides
      rt 720/ :s                    ;return turtle to upwards facing in order to draw second row
    ]
  ]
END
cs
p 0 200 40 7 3                      ;draw icosahedron and left side of octahedron (6th iteration is suppressed)
p 70 0 80 2 3                       ;draw right side of octahedron, and tetrahedron
p -200 200 105 3 5                  ;draw dodecahedron
rt 45                               ;turn turtle in preparation for drawing cube
p 90 90 56 2 4                      ;draw cube
Level River St
la source
@phase haha, merci, j'ai pensé à faire un htpour le cacher pour l'image. Je suis content de ne pas l'avoir fait!
Level River St