Zahlen als Kreisgrafiken

36

Studieren Sie zuerst dieses Puzzle , um ein Gefühl dafür zu bekommen, was Sie produzieren werden.

Ihre Herausforderung besteht darin, ein Programm oder eine Funktion zu schreiben, die eine kreisförmige Grafik wie die des Puzzles mit einer Zahl (Basis 10) zwischen 1 und 100 (einschließlich) ausgibt. Dies ähnelt dieser Herausforderung , mit der Ausnahme, dass Sie eine Grafik anstelle von römischen Ziffern erstellen. Die folgenden Kreise stehen für die Nummern 1-10 von links nach rechts:

Kreismuster

Wie die Antwort auf das Rätsel besagt, sollte Ihre Grafik von innen nach außen wie eine römische Ziffer gelesen werden, wobei die Linienstärke die Symbole der römischen Ziffer und die gesamte Grafik die Zahl darstellt. Zu Ihrer Information, hier sind die Strichstärken, die Sie benötigen. Jede Zeile sollte einen 3px-Abstand zwischen der nächsten und der nächsten haben.

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

Bitte posten Sie ein oder zwei Beispiele Ihrer Ausgabe. Angenommen, die Eingabe ist korrekt, es gibt Standardlücken usw. Das ist Codegolf, also gewinnen die wenigsten Bytes. Bei Stimmengleichheit gewinnen die meisten Stimmen. Viel Glück!

Rip Leeb
quelle
3
Ist die richtige absolute Größe des Bildes erforderlich oder ist es ausreichend, die richtigen relativen Größen zu haben?
David Zhang
@DavidZhang Ja, bitte halten Sie sich aus Gründen der Fairness an die angegebenen Zeilen- und Polstergrößen.
Rip Leeb

Antworten:

15

Mathematica - 166 181 Bytes

Ein bisschen prägnanter als die andere Mathematica-Antwort, auch dank eines punktloseren Stils.

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] &

Alle Leerzeichen dienen nur der Übersichtlichkeit. Dies definiert eine anonyme Funktion, die die gewünschte Grafik zurückgibt.

Animation

Animierte Kreise

Das Erzeugen eines animierten GIF der Zahlenkreise ist in Mathematica, das integrierte Funktionen zum Animieren und Exportieren von Sequenzen beliebiger Objekte enthält, trivial. Angenommen, der obige Code wurde gerade ausgeführt,

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

Beispielausgabe

Beispielausgabe

David Zhang
quelle
Bitte posten Sie ein paar Ergebnisse. Entschuldigung, dass Sie nicht gefragt haben, dies ist der erste Ort. Ich habe auch die Frage geändert, um Funktionen zu akzeptieren.
Rip Leeb
Danke für die Vorschläge @ MartinBüttner. Der Code wurde korrigiert, um Bilder in der richtigen Größe auszugeben, und eine Beispielausgabe wurde hinzugefügt.
David Zhang
3
Ihre Animation wackelt. Nicht, dass ich es besser machen könnte.
corsiKa
Hmm, du hast recht. Ich bin mir wirklich nicht sicher, warum das so ist, wenn man bedenkt, dass ich den Plotbereich explizit für Mathematica festgelegt habe.
David Zhang
Vielleicht im Zusammenhang mit dem Wackeln: mathematica.stackexchange.com/q/134272
coredump
15

Gemeines Lisp - 376 331 304 Bytes

(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)))

Beispiele

Bildbeschreibung hier eingeben(1) Bildbeschreibung hier eingeben(24)

Bildbeschreibung hier eingeben(104) Bildbeschreibung hier eingeben(1903) Bildbeschreibung hier eingeben(3999)

Animation

Für Zahlen von 1 bis 400:

Neu

NB: Für die Aufzeichnung wird diese Animation wie folgt durchgeführt:

Ich habe eine modifizierte Version des Codes, ringsder die Breite des erzeugten Bildes zurückgibt. Das Ergebnis der folgenden Schleife ist daher die maximale Größe, hier 182 :

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

Die gesamte Schleife dauert 9,573 Sekunden. Das ergibt ungefähr 24 ms für jede ganze Zahl. Dann in einer Shell:

 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))))

Erklärungen

  • Die Funktion akzeptiert eine Ganzzahl Nzwischen 1 und 3999 und einen Dateinamen

  • Ich benutze (format nil "~@R" N), um von dezimal zu römisch zu konvertieren. Beispielsweise:

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

    Die ~@R Formatsteuerzeichenfolge ist für Ganzzahlen zwischen 1 und 3999 angegeben. Aus diesem Grund gibt es eine Einschränkung für den Bereich der zulässigen Eingaben.

  • Ich iteriere über die resultierende Zeichenfolge, um eine Liste Pmit (radius width)Paaren für jede Ziffer C zu erstellen .

    • Die Breite ist eine einfache lineare Abbildung: Ich verwende die konstante Zeichenfolge "IVXLCDM", um die Position von C darin zu berechnen. Multipliziert man mit zwei und addiert eins, erhält man den gewünschten Wert:

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

      Dies wird jedoch in der Golfversion etwas anders gemacht:

             (position c " I V X L C D M")
      
    • Die Berechnung jedes Radius berücksichtigt die Breite jedes Rings sowie die Leerstellen zwischen den Ringen. Ohne Geschwindigkeitsoptimierung bleiben Berechnungen präzise, ​​da sie nicht auf Gleitkommazahlen basieren, sondern auf rationalen Zahlen.

      Bearbeiten : Ich habe die Parameter geändert, um den Auffüllregeln zu entsprechen.

  • Sobald dies erledigt ist, kenne ich die erforderliche Größe der resultierenden Leinwand (das Doppelte des zuletzt berechneten Radius).

  • Zuletzt zeichne ich für jedes Element einen Kreis Pund speichere die Leinwand.
Core-Dump
quelle
1
"Dieser Code unterstützt alle römischen Ziffern (IVXLCDM)". Bedeutet das, dass Ihr Programm römische Ziffern als Eingabe verwendet? Das war nicht meine Absicht, aber ziemlich cool. Requisiten für die Animation auch.
Rip Leeb
1
Nein, nein, tut mir leid, wenn dies unklar ist: Es funktioniert für eine beliebige Ganzzahl zwischen 1 und 3999. In Ihrer Frage haben Sie nur Eingaben von 1 bis 100 benötigt, und in Ihrer Tabelle wird weder D noch M erwähnt ... das werde ich bearbeiten Teil.
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}

Geige

TwiNight
quelle
Kein Stack-Snippet?
Optimierer
@Optimizer Völlig vergessen, dass wir das jetzt haben
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);}}

Beispiele

15

15

84

84

93

93

Schön formatiert:

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
quelle
Bitte posten Sie ein paar Ergebnisse. Entschuldigung, dass Sie nicht gefragt haben, dies ist der erste Ort.
Rip Leeb
3

Mathematica 9 - 301 249 Bytes

: D Es fühlt sich mies an, die eingebaute Umwandlung in römische Ziffern zu verwenden, aber hey.

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}])

(Als ich dies letzte Nacht tat, hatte ich nicht viel Zeit, aber ich erkannte, dass es viel mehr Golf spielen könnte. Und ich nahm auch einige Hinweise von David Zhang ...: D Danke!)

Ein bisschen klarer:

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}]
    )

Dies ist eine Funktion, die Sie folgendermaßen aufrufen können:

r[144]

Bildbeschreibung hier eingeben

Oder Sie können die Ergebnisse von den Werten a bis b anzeigen mit:Table[r[i],{i,a,b}]

Hinweis : Dies funktioniert nur für Werte bis 399.

kukac67
quelle
1

Python 2, 322 296

Das Skript liest die zu konvertierende Zahl aus stdin und gibt das Bild als SVG-Markup aus.

.. Ich benutze 'rot' anstelle von 'schwarz', weil es 2 Zeichen spart :)

Hier einige Beispiele: für 23: http://jsfiddle.net/39xmpq49/ für 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
quelle
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
quelle