Liczby jako grafika okrągła

36

Najpierw przestudiuj tę łamigłówkę, aby poczuć, co będziesz produkować.

Wyzwanie polega na napisaniu programu lub funkcji, która wyświetli okrągłą grafikę podobną do układanki, podając (podstawa 10) liczbę od 1 do 100 (włącznie). Jest to podobne do tego wyzwania , z tym wyjątkiem, że będziesz tworzył grafikę zamiast cyfr rzymskich. Poniższe kółka przedstawiają liczby 1-10, od lewej do prawej:

wzór koła

Jak wynika z odpowiedzi na układankę, twoja grafika powinna wyglądać jak cyfra rzymska od wewnątrz, gdzie grubość linii reprezentuje symbole rzymskie, a cała grafika reprezentuje liczbę. Dla odniesienia, oto grubości linii, których będziesz potrzebować. Każda linia powinna mieć wypełnienie 3px między nią a następną.

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

Proszę zamieścić próbkę lub dwie z twoich wyników. Załóżmy, że dane wejściowe są prawidłowe, standardowe luki itp. To jest kod golfowy, więc wygrywa najmniej bajtów. W przypadku remisu większość głosów wygrywa. Powodzenia!

Rip Leeb
źródło
3
Czy konieczny jest prawidłowy bezwzględny rozmiar obrazu, czy wystarczające są odpowiednie rozmiary względne?
David Zhang,
@DavidZhang Tak, proszę, trzymaj się wymienionych przeze mnie rozmiarów linii i wypełnień, dla zachowania uczciwości.
Zgrać Leeba

Odpowiedzi:

15

Mathematica - 166 181 bajtów

Trochę bardziej zwięzłe niż inne odpowiedzi Mathematica, po części dzięki bardziej punktowemu stylowi.

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

Cała biała spacja służy wyłącznie przejrzystości. Definiuje to anonimową funkcję, która zwraca żądaną grafikę.

Animacja

Animowane kręgi

Generowanie animowanego pliku GIF z kręgów liczb jest banalne w Mathematica, która ma wbudowane funkcje do animowania i eksportowania sekwencji dowolnych obiektów. Zakładając, że powyższy kod został właśnie wykonany,

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

Przykładowy wynik

Przykładowe dane wyjściowe

David Zhang
źródło
Proszę zamieścić kilka wyników. Przepraszam, że nie pytam o to. Zmieniłem również pytanie, aby zaakceptować funkcje.
Zgrać Leeba
Dzięki za sugestie @ MartinBüttner. Poprawiono kod wyświetlający obrazy o prawidłowych rozmiarach i dodano przykładowe dane wyjściowe.
David Zhang
3
Twoja animacja porusza się. Nie żebym mógł zrobić lepiej.
corsiKa
Hmm, masz rację. Naprawdę nie jestem pewien, dlaczego tak się dzieje, biorąc pod uwagę, że wyraźnie podałem zakres wykresu dla Mathematica.
David Zhang
Być może związane z poruszaniem się: mathematica.stackexchange.com/q/134272
coredump
15

Common Lisp - 376 331 304 bajty

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

Przykłady

wprowadź opis zdjęcia tutaj(1) wprowadź opis zdjęcia tutaj(24)

wprowadź opis zdjęcia tutaj(104) wprowadź opis zdjęcia tutaj(1903) wprowadź opis zdjęcia tutaj(3999)

Animacja

Dla liczb od 1 do 400:

Nowy

NB: Dla przypomnienia animacja ta jest wykonywana w następujący sposób:

Mam zmodyfikowaną wersję kodu o nazwie, ringsktóra zwraca szerokość wygenerowanego obrazu. Dlatego wynikiem następującej pętli jest maksymalny rozmiar, tutaj 182 :

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

Cała pętla zajmuje 9.573 sekundy. To daje około 24 ms dla każdej liczby całkowitej. Następnie w powłoce:

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

Bez golfa

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

Objaśnienia

  • Funkcja przyjmuje liczbę całkowitą Nod 1 do 3999 i nazwę pliku

  • Używam (format nil "~@R" N)do konwersji z dziesiętnego na rzymski. Na przykład:

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

    ~@R Ciąg kontroli formatu jest określony do pracy dla liczb całkowitych między 1 i 3999. Dlatego istnieje ograniczenie dla zakresu dozwolonych nakładów.

  • Ieruję wynikowy ciąg, aby zbudować listę Pzawierającą (radius width)pary dla każdej cyfry C.

    • Szerokość jest prostym odwzorowaniem liniowym: używam stałego ciągu „IVXLCDM”, aby obliczyć w nim pozycję C. Mnożąc przez dwa i dodając jeden, otrzymujemy pożądaną wartość:

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

      W wersji golfowej dzieje się to jednak nieco inaczej:

             (position c " I V X L C D M")
      
    • Obliczenia każdego promienia uwzględniają szerokość każdego pierścienia, a także puste przestrzenie między pierścieniami. Bez optymalizacji prędkości obliczenia pozostają precyzyjne, ponieważ nie są oparte na liczbach zmiennoprzecinkowych, ale liczbach wymiernych.

      Edycja : Zmieniłem parametry, aby były zgodne z regułami wypełniania.

  • Po wykonaniu tej czynności znam wymagany rozmiar wynikowego płótna (dwukrotność ostatniego obliczonego promienia).

  • Na koniec rysuję okrąg dla każdego elementu Pi zapisuję płótno.
rdzeń rdzeniowy
źródło
1
„Ten kod obsługuje wszystkie cyfry rzymskie (IVXLCDM)”. Czy to oznacza, że ​​twój program przyjmuje cyfry rzymskie jako dane wejściowe? Nie o to mi chodziło, ale całkiem fajnie. Rekwizyty do animacji też.
Zgrać Leeba
1
Nie, nie, przepraszam, jeśli jest to niejasne: działa na dowolnej liczbie całkowitej od 1 do 3999. W twoim pytaniu potrzebujesz tylko danych wejściowych od 1 do 100, a twoja tabela nie wspomina o D lub M ... Zedytuję to część.
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}

Skrzypce

TwiNight
źródło
Brak fragmentu stosu?
Optymalizator
@Optimizer Całkowicie zapomniałem, że już to mamy
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);}}

Przykłady

15

15

84

84

93

93

Ładnie sformatowane:

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
źródło
Proszę zamieścić kilka wyników. Przepraszam, że nie pytam o to.
Zgrać Leeba
3

Matematyka 9 - 301 249 bajtów

: D Używanie wbudowanej konwersji na cyfry rzymskie jest oszukiwane, ale hej.

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

(Kiedy robiłem to ostatniej nocy, nie miałem zbyt wiele czasu, ale zdałem sobie sprawę, że można grać w golfa o wiele bardziej. I wziąłem też kilka wskazówek od Davida Zhanga ...: D Dzięki!)

Trochę jaśniej:

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

Jest to funkcja, którą można wywołać w następujący sposób:

r[144]

wprowadź opis zdjęcia tutaj

Lub możesz pokazać wyniki od wartości a do b za pomocą:Table[r[i],{i,a,b}]

Uwaga : Działa to tylko dla wartości do 399.

kukac67
źródło
1

Python 2, 322 296

Skrypt odczytuje liczbę do konwersji ze standardowego wejścia i wysyła obraz jako znacznik SVG.

.. Używam „czerwonego” zamiast „czarnego”, ponieważ oszczędza 2 znaki :)

Oto kilka przykładów: dla 23: http://jsfiddle.net/39xmpq49/ dla 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
źródło
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
źródło