Nombres sous forme de graphiques circulaires

36

Commencez par étudier ce puzzle pour avoir une idée de ce que vous allez produire.

Votre défi consiste à écrire un programme ou une fonction qui produira un graphique circulaire comme ceux du puzzle, à partir d’un nombre (base 10) compris entre 1 et 100 (inclus). Cela ressemble à ce défi , sauf que vous produirez un graphique plutôt que des chiffres romains. Les cercles suivants représentent les nombres 1 à 10, de gauche à droite:

motif de cercle

Comme l'indique la réponse au puzzle, votre graphique doit se lire comme un chiffre romain vu de l'intérieur vers l'extérieur, l'épaisseur de trait représentant les symboles du chiffre romain et le graphique entier représentant le nombre. Pour votre référence, voici les épaisseurs de lignes dont vous aurez besoin. Chaque ligne doit avoir un remplissage 3px entre elle et la suivante.

Number  Roman Numeral   Line Width
1       I               1px
5       V               3px
10      X               5px
50      L               7px
100     C               9px

S'il vous plaît envoyer un échantillon ou deux de votre sortie. Supposons que la saisie soit correcte, les failles standard , etc., etc. C'est le code de golf, donc le moins d'octets gagnent. En cas d'égalité des voix, la plupart des votes sont gagnants. Bonne chance!

Rip Leeb
la source
3
La taille absolue correcte de l’image est-elle nécessaire ou suffit-il d’avoir les bonnes tailles relatives?
David Zhang
@ DavidZhang Oui, veuillez vous en tenir aux tailles de ligne et de remplissage que j'ai énumérées, par souci d'équité.
Rip Leeb

Réponses:

15

Mathematica - 166 181 octets

Un peu plus concis que les autres réponses de Mathematica, en partie grâce à un style plus simple.

c = Characters; r = Riffle;
Graphics[r[{0, 0}~Disk~# & /@ Reverse@Accumulate[
    l = {3} ~Join~ r[2 Position[c@"IVXLC", #][[1, 1]] - 1 & /@ 
        c@IntegerString[#, "Roman"], 3]], {White, Black}],
    ImageSize -> 2 Total@l] &

Tous les espaces sont uniquement à des fins de clarté. Ceci définit une fonction anonyme qui renvoie le graphique souhaité.

Animation

Cercles animés

Générer un GIF animé des nombres décimaux est trivial dans Mathematica, qui intègre des fonctions permettant d’animer et d’exporter des séquences d’objets arbitraires. En supposant que le code ci-dessus vient d'être exécuté,

Table[Show[%@n, PlotRange -> {{-100, 100}, {-100, 100}}, 
    ImageSize -> 200], {n, 1, 399, 1}];
Export["animcircles.gif", %]

Exemple de sortie

Exemple de sortie

David Zhang
la source
S'il vous plaît poster quelques résultats. Désolé de ne pas demander c'est la première place. J'ai également changé la question pour accepter les fonctions.
Rip Leeb
Merci pour les suggestions @ MartinBüttner. Le code a été corrigé pour produire des images de taille correcte et un exemple de sortie a été ajouté.
David Zhang
3
Votre animation bouge. Pas que je puisse faire mieux.
CorsiKa
Hmm, vous avez raison. Je ne sais vraiment pas pourquoi, alors que j'ai spécifié explicitement la plage de l'intrigue pour Mathematica.
David Zhang
Peut-être liée au wiggling: mathematica.stackexchange.com/q/134272
coredump
15

Common Lisp - 376 331 304 octets

(use-package(car(ql:quickload'vecto)))(lambda(n o &aux(r 3)l p)(map()(lambda(c)(setf l(position c" I V X L C D M")p(append`((set-line-width,l)(centered-circle-path 0 0,(+(/ l 2)r))(stroke))p)r(+ r l 3)))(format()"~@R"n))(with-canvas(:width(* 2 r):height(* 2 r))(translate r r)(map()'eval p)(save-png o)))

Exemples

entrez la description de l'image ici(1) entrez la description de l'image ici(24)

entrez la description de l'image ici(104) entrez la description de l'image ici(1903) entrez la description de l'image ici(3999)

Animation

Pour les nombres de 1 à 400:

Nouveau

NB: Pour l'anecdote, cette animation se fait comme suit:

J'ai une version modifiée du code, nommée ringsqui renvoie la largeur de l'image produite. Par conséquent, le résultat de la boucle suivante est la taille maximale, ici 182 :

 (loop for x from 1 to 400
       maximize (rings x (format nil "/tmp/rings/ring~3,'0d.png" x)))

La boucle entière prend 9.573 secondes. Cela donne environ 24 ms pour chaque entier. Ensuite, dans une coquille:

 convert -delay 5 -loop 0 -gravity center -extent 182x182 ring*png anim.gif

Ungolfed

(ql:quickload :vecto)
(use-package :vecto)

(lambda (n o)
  (loop with r = 3
        for c across (format nil "~@R" n)
        for l = (1+ (* 2(position c"IVXLCDM")))
        for h = (/ l 2)
        collect `(,(incf r h),l) into p
        do (incf r (+ h 3))
        finally (with-canvas(:width (* 2 r) :height (* 2 r))
                  (loop for (x y) in p
                        do (set-line-width y)
                           (centered-circle-path r r x)
                           (stroke))
                  (save-png o))))

Des explications

  • La fonction prend un entier Ncompris entre 1 et 3999 et un nom de fichier

  • J'utilise (format nil "~@R" N)pour convertir décimal en romain. Par exemple:

     (format nil "~@R" 34) => "XXXIV"
    

    La ~@R chaîne de contrôle de format est spécifiée pour fonctionner avec des nombres entiers compris entre 1 et 3999. C'est pourquoi il existe une limitation pour la plage d'entrées autorisées.

  • Je parcours la chaîne résultante pour construire une liste Pcontenant des (radius width)couples, pour chaque chiffre C.

    • La largeur est un simple mappage linéaire: j'utilise la chaîne constante "IVXLCDM" pour calculer la position de C dans celle-ci. En multipliant par deux et en ajoutant un, nous obtenons la valeur souhaitée:

             (1+ (* 2 (position c "IVXLCDM")))
      

      Ceci est cependant fait légèrement différemment dans la version avec golf:

             (position c " I V X L C D M")
      
    • Le calcul de chaque rayon prend en compte la largeur de chaque anneau ainsi que les espaces vides entre les anneaux. Sans optimisation de la vitesse, les calculs restent précis car ils ne sont pas basés sur des flottants, mais sur des nombres rationnels.

      Edit : J'ai modifié les paramètres pour se conformer aux règles de remplissage.

  • Une fois que cela est fait, je connais la taille requise de la toile résultante (deux fois le dernier rayon calculé).

  • Enfin, je trace un cercle pour chaque élément de Pet sauve la toile.
coredump
la source
1
"Ce code prend en charge tous les chiffres romains (IVXLCDM)". Cela signifie-t-il que votre programme prend des chiffres romains en entrée? Ce n'est pas ce que je voulais, mais plutôt cool. Les accessoires pour l'animation aussi.
Rip Leeb
1
Non, non, désolé si cela n'est pas clair: cela fonctionne pour tout nombre entier compris entre 1 et 3999. Dans votre question, vous n'avez requis que des entrées de 1 à 100, et votre tableau ne mentionne pas D ou M ... Je vais éditer ça partie.
Coredump
8

HTML + JQuery, 288

HTML

<canvas>

JS

    r=3;w=9;c=$('canvas').get(0).getContext('2d')
    for(i=prompt(),e=100;e-.1;e/=10){
    if((x=Math.floor(i/e)%10)==4)d(w)+d(w+2)
    else if(x==9)d(w)+d(w+4)
    else{if(x>4)d(w+2)
    for(j=x%5;j;j--)d(w)}
    w-=4}
    function d(R){c.lineWidth=R
    c.beginPath()
    c.arc(150,75,r+=R/2,0,7)
    c.stroke()
    r+=R/2+3}

Violon

TwiNight
la source
Pas d'extrait de pile?
Optimiseur
@Optimizer Totalement oublié que nous avons que maintenant
TwiNight
5

Java, 565

import java.awt.*;class Z{public static void main(String[]s){int i=new Byte(s[0]),j=i/10,k=i%10;String t="",u;if(j>8)t="59";if(j>9)t="9";if(j==4)t="57";else if(j<9){t=j>4?"7":"";j-=j>4?5:0;if(j>0)t+="5";if(j>1)t+="5";if(j>2)t+="5";}if(k>8)t+="15";if(k==4)t+="13";else if(k<9){t+=k>4?"3":"";k-=k>4?5:0;if(k>0)t+="1";if(k>1)t+="1";if(k>2)t+="1";}u=t;Frame f=new Frame(){public void paint(Graphics g){g.setColor(Color.BLACK);int x=0;for(char c:u.toCharArray()){int z=c-48,q=x;for(;x<q+z;)g.drawOval(99-x,99-x,x*2,x++*2);x+=3;}}};f.setSize(200,200);f.setVisible(1>0);}}

Exemples

15

15

84

84

93

93

Bien formaté:

import java.awt.*;    
class Z {    
    public static void main(String[] s) {
        int i = new Byte(s[0]), j = i / 10, k = i % 10;
        String t = "", u;
        if (j > 8)
            t = "59";
        if (j > 9)
            t = "9";
        if (j == 4) {
            t = "57";
        } else if (j < 9) {
            t = j > 4 ? "7" : "";
            j -= j > 4 ? 5 : 0;
            if (j > 0)
                t += "5";
            if (j > 1)
                t += "5";
            if (j > 2)
                t += "5";
        }
        if (k > 8)
            t += "15";
        if (k == 4) {
            t += "13";
        } else if (k < 9) {
            t += k > 4 ? "3" : "";
            k -= k > 4 ? 5 : 0;
            if (k > 0)
                t += "1";
            if (k > 1)
                t += "1";
            if (k > 2)
                t += "1";
        }
        u = t;
        Frame f = new Frame() {
            public void paint(Graphics g) {
                g.setColor(Color.BLACK);
                int x = 0;
                for (char c : u.toCharArray()) {
                    int z = c - 48, q = x;
                    for (; x < q + z;) {
                        g.drawOval(99 - x, 99 - x, x * 2, x++ * 2);
                    }
                    x += 3;
                }
            }
        };
        f.setSize(200, 200);
        f.setVisible(1 > 0);
    }
}
Ypnypn
la source
S'il vous plaît poster quelques résultats. Désolé de ne pas demander c'est la première place.
Rip Leeb
3

Mathematica 9 - 301 249 octets

: D On se sent triste d'utiliser la conversion intégrée en chiffres romains, mais bon.

l=Length;k=Characters;r@n_:=(w=Flatten[Position[k@"IVXLC",#]*2-1&/@k@IntegerString[n,"Roman"]];Show[Table[Graphics@{AbsoluteThickness@w[[i]],Circle[{0,0},(Join[{0},Accumulate[3+w]]+3)[[i]]+w[[i]]/2]},{i,Range@l@w}],ImageSize->{(Total@w+(l@w)*3)*2}])

(Quand j'ai fait ça hier soir, je n'avais pas beaucoup de temps, mais j'ai réalisé que le golf pouvait être joué beaucoup plus loin. Et j'ai aussi pris des allusions de David Zhang ...: D Merci!)

Un peu plus clairement:

l=Length;
k=Characters;
r@n_:=
    (
    w=Flatten[Position[k@"IVXLC",#]*2-1&/@k@IntegerString[n,"Roman"]];
    Show[Table[Graphics@{AbsoluteThickness@w[[i]],Circle[{0,0},(Join[{0},Accumulate[3+w]]+3)[[i]]+w[[i]]/2]},{i,Range@l@w}],ImageSize->{(Total@w+(l@w)*3)*2}]
    )

C'est une fonction que vous pouvez appeler comme ceci:

r[144]

entrez la description de l'image ici

Vous pouvez aussi afficher les résultats des valeurs a à b avec:Table[r[i],{i,a,b}]

Remarque : cela ne fonctionne que pour des valeurs allant jusqu'à 399.

kukac67
la source
1

Python 2, 322 296

Le script lit le numéro à convertir à partir de stdin et génère l'image sous forme de balisage SVG.

.. J'utilise 'rouge' au lieu de 'noir', car il enregistre 2 caractères :)

Voici quelques exemples: pour 23: http://jsfiddle.net/39xmpq49/ pour 42: http://jsfiddle.net/7Ls24q9e/1/

i=input();r=9
def R(n,p):
 global r,i;i-=n;print '<circle r="{0}" stroke-width="{1}"/>'.format(r,p);r+=p+3
print '<svg viewBox="-50 -50 99 99" fill="none" stroke="red">',[[R(n,int(p)) for p in s*int(i/n)] for n,s in zip([100,90,50,40,10,9,5,4,1],'9/59/7/57/5/15/3/13/1'.split('/'))]and'','</svg>'
dieter
la source
1

JavaScript 342 334 308

function R(n){var v=document,o=[],x=1,c=v.body.appendChild(v.createElement('canvas')).getContext('2d')
while(n)v=n%10,y=x+2,o=[[],[x],[x,x],[x,x,x],[x,y],[y],[y,x],[y,x,x],[y,x,x,x],[x,x+=4]][v].concat(o),n=(n-v)/10
v=3
while(x=o.shift())c.lineWidth=x,c.beginPath(),c.arc(150,75,v+x/2,0,7),c.stroke(),v+=x+3}

for (var i = 1; i <= 100; i++) {
  R(i);
}

wolfhammer
la source