głupie ograniczenia i pustynia

18

Siedziałeś więc przy biurku i grałeś w program, aby obliczyć pierwsze 20 cyfr pi, a następnie podszedł twój szef i wyrzucił twoje jabłko IIe przez okno. Pracujesz teraz nad nowym projektem, a ten komputer nie ma jeszcze możliwości obsługi tekstu. Żaden. Brak czcionek. Nic.

Teraz zakończmy ten program. Oblicz i wyświetl pierwsze 20 znaków liczby pi bez użycia czcionek, które nie są częścią twojego programu. Twoje dane wyjściowe mogą być wyświetlane lub zapisywane w postaci standardowej jako plik obrazu (jpeg, png, gif, svg (o ile nie używasz żadnych znaków), bmp, xpm). Możesz używać dowolnego języka, ale nie możesz korzystać z funkcji czcionek, wyświetlania tekstu itp.

mały bonus (10 znaków) Jeśli zadziała na Lirze.

Edycja: dla tych, którzy tego nie zrozumieli, moją inspiracją był pierwszy Mac, a tytuł to gra słów. Wielkie uznanie dla @Sukmindera, którego animowany gif jest po prostu fajny. Konkurs się nie kończy, jeśli pojawi się lepsza odpowiedź.

Hildred
źródło
Podoba mi się wyzwanie, ale technicznie nie byłby też w stanie wyświetlać kodu źródłowego? Oczywiście z wyjątkiem Piet.
ApproachingDarknessFish
2
@ValekHalfHeart możesz załadować kod źródłowy z innej maszyny
John Dvorak
1
A jak definiujesz ludzi jako czytelnych? Na przykład moje pismo jest czytelne dla niektórych ludzi (przynajmniej jednego), a nie dla innych. (Nawiasem mówiąc, 2 ^ (2x2) = 16, wystarczająca liczba glifów dla wszystkich 11 cyfr.;))
Kendall Frey
4
W ogóle nie rozumiem tytułu, nie rozumiem, jak sztuka ASCII może być dobra, gdy nie możemy korzystać z wyświetlania tekstu, a pytanie bardzo potrzebuje definicji „oblicz PI”.
Peter Taylor
2
Co tak naprawdę oznacza „obliczyć pi”? Czy mogę na stałe zapisać mapę bitową pierwszych 20 miejsc po przecinku? (Nie korzysta z żadnej wbudowanej stałej PI lub podobnej)
FireFly

Odpowiedzi:

6

Python, 222 znaki

n=[10**20*277991633/1963319607/10**i%10 for i in range(19,1,-1)]
print' *     *'
print' * **    '+' '.join(' ** * ***** *****  *'[2*d:2*d+2]for d in n)
print'**     * '+' '.join('**  *    * ** ***** '[2*d:2*d+2]for d in n)

Pierwszy wiersz oblicza cyfry pi przy użyciu przybliżenia pi-3 ~= 277991633/1963319607. Następne trzy wiersze generują 20 znaków liczby pi przy użyciu sztuki ASCII Nemeth Braille.

 *     *
 * **    *  ** *  *   * *  ** *  ** *  *   * **  * ** *  ** * 
**     *     *     * *  *  *   *     * ** *  ** *     *     **

Przesuwam tutaj granice w dwóch kierunkach, zarówno w sensie „obliczania Pi”, jak i „czytelności ludzkiej”.

Keith Randall
źródło
3
Co za cholera? Myślałem, że nie powinniśmy używać żadnego tekstu wyjściowego. Jak twój komputer będzie renderował *znaki i spacje bez czcionki?
stoisko
@boothby: To sztuka ASCII. Pomyśl o tym *jak o czarnym pikselu 1x1 i `` jak o białym pikselu 1x1.
Keith Randall
1
Ma rację. Nie możesz renderować *bez użycia czcionek, myślę, że jesteś zdyskwalifikowany
Syreny
18

Python, 217 bajtów

Wymaga biblioteki obrazów Python

import Image
x=p=141
i=Image.new('1',(x,11))
while~-p:x=p/2*x/p+2*10**19;p-=2
for c in str(x):[i.putpixel((j%7/5*4-~j%7/4*~j/7+p,j%7*3%14%8+j%14/10+2),1&ord('}`7gjO_a\177o'[int(c)])>>j%7)for j in range(17)];p+=7
i.show()

Liczba bajtów zakłada, że ​​znak ucieczki \177jest zastępowany jego dosłownym odpowiednikiem (char 127 ).

Dane wyjściowe będą wyglądać następująco (otworzą się w domyślnej przeglądarce * .bmp):

Pamiętaj, że można to łatwo sparametryzować, aby wydrukować dowolną liczbę cyfr, które lubisz. Poniższe zaakceptuje liczbę całkowitą ze standardowego wejścia i wyświetli tyle cyfr:

import Image
n=input()
x=p=n*7|1
i=Image.new('1',(x,11))
while~-p:x=p/2*x/p+2*10**(n-1);p-=2
for c in str(x):[i.putpixel((j%7/5*4-~j%7/4*~j/7+p,j%7*3%14%8+j%14/10+2),1&ord('}`7gjO_a\177o'[int(c)])>>j%7)for j in range(17)];p+=7
i.show()

Wyjście dla n = 80 :


Obliczanie Pi

while~-p:x=p/2*x/p+2*10**19;p-=2

Tak, to wszystko. Zastosowana formuła jest wynikiem zastosowania transformacji Eulera do serii Leibniza , a następnie uwzględnienia każdego terminu z pozostałej części sumy. Formuła jest zbieżna liniowo; każda cyfra wymaga dziennika 2 (10) ≈ 3,32 iteracji. Dla osób zainteresowanych pochodną, ​​patrz załącznik A.

Pokaz

PIL służy do generowania obrazów, ponieważ jest to najwygodniejsza biblioteka, jaką znam. Tworzona jest pusta czarno-biała bitmapa 141 × 11 , a następnie narysowane są na niej białe linie w sposób siedmiosegmentowy, jeden piksel na raz. Pozycje wymagane do narysowania każdego segmentu są przechowywane w łańcuchu maski bitowej, z bitami odpowiadającymi następującym pozycjom:

 000
3   5
3   5
 111
4   6
4   6
 222

Trochę magii (j%7/5*4-~j%7/4*~j/7+p,j%7*3%14%8+j%14/10+2)wytwarza każdy piksel w następującej kolejności (podstawa-18):

(2, 2), (2, 5), (2, 8), (1, 3), (1, 6), (5, 3), (5, 6),
(3, 2), (3, 5), (3, 8), (1, 4), (1, 7), (5, 4), (5, 7),
(4, 2), (4, 5), (4, 8)

 07e
3   5
a   c
 18f
4   6
b   d
 29g

załącznik A

Transformacja Eulera to technika przyspieszania zbieżności, która działa dla dowolnej serii, która wykazuje absolutną zbieżność monotoniczną. Powstała seria będzie zbiegać się liniowo, zwykle z szybkością jednego bitu na termin (zauważ, że jeśli pierwotna seria była już superliniowa, to uzyskana seria faktycznie zbiegnie się wolniej). Opis czysto matematyczny jest nieco trudne do naśladowania, więc będę biorąc podejścia proceduralnego.

Zaczniemy od serii Leibniz:

Następnie podziel każdy termin na pół, łącząc sąsiednie wyrażenia:

Uproszczony:

Uogólnione:

Zauważ, że wiodący ½ nie miał terminu partnera, a zatem został wykluczony z reszty sumy. To jest pierwszy termin serii przekształconej. Aby znaleźć następny termin, powtarzamy ten proces ponownie:

I ponownie:

I ponownie:

I jeszcze raz na wszelki wypadek:

W tym momencie mamy pięć pierwszych terminów, a szósty termin jest oczywisty. To powinno wystarczyć do uogólnienia, więc zatrzymamy się tutaj. Zaczniemy od faktorów liczników i mianowników:

Mianowniki ewidentnie zawierają podwójne silnia z 2n + 1 , więc będziemy łatać, że:

Wszystko pasuje, z wyjątkiem dwóch pierwszych warunków, które mają nierozliczony 2 w mianowniku. Możemy to naprawić, mnożąc całe wyrażenie przez 2 :

2 3 = 2,4 , więc:

Licznik można teraz łatwo zidentyfikować jako n! .

Zauważ, że współczynnik dodawany do każdego kolejnego składnika, n / (2n + 1) , zbliża się do ½, gdy n staje się duży, co sugeruje liniową zbieżność w tempie jednego bitu na termin - jest to w rzeczywistości z założenia. Dobry wynik, ale byłby jeszcze ładniejszy, gdyby nie istniały czynniki. Możemy tutaj odjąć każdy kolejny termin od reszty sumy, co wygeneruje zagnieżdżone wyrażenie:



Można to przepisać jako relację powtarzalności:

Gdzie n liczy się wstecz od ⌈ log 2 (10) · d ⌉ .. 0 , gdzie d jest liczbą wymaganych cyfr.

Ciekawe może być to, że stabilny punkt tego nawrotu wynosi dokładnie 2 (lub 4, jeśli podwoiłeś go, jak mam to w powyższym opisie), więc możesz zapisać kilka iteracji, poprawnie inicjując. Jednak inicjowanie do losowej wartości, której potrzebujesz gdzie indziej, i rzucenie kilku dodatkowych iteracji na górę jest ogólnie tańsze bajtowo.

primo
źródło
1
Bardzo miło, dziękuję za lekcję! Co mi się nie dostać to, co psię p/2 * x/p + ...robi .. AIUI Python obsługuje automatyczny awans do BigInteger-owski typu danych, więc nie powinno być precyzyjne rzeczy, ale jakoś te ps sprawa i nie znoszą się jak mogę sobie wyobrazić je do ... czego tu brakuje?
FireFly,
@FireFly pzainicjował nieparzyste, więc p/2/pjest to odpowiednik - w ramach podziału liczb całkowitych - na ((p-1)/2)/p. To produkuje 1/3, 2/5, 3/7, itd terminy pochodzące powyżej.
primo
12

#C - 777 znaków

C - 731 znaków

Drukuje GIF do stdout.

  • Dziwactwo: Po pierwszym nie ma przecinka 3.

Łączenie GIF-a ze wstępnie skonfigurowanego nagłówka + każda cyfra reprezentowana przez domową (osadzoną) czcionkę 5x5 pikseli.

Wynik

wprowadź opis zdjęcia tutaj

Jest tam --- ^

Pamiętaj, że GIF czasami znika w Chrome po jednym uruchomieniu.

#include <stdio.h>
#define G 68,30
#define F(e,i)for(i=0;i<e;++i)
#define B w[++k]
unsigned char r[][10]={{4,18,150,199,188,159,10,0},{4,18,102,169,188,122,64,1},{G,160,166,104,217,80,1},{G,160,166,184,140,66,1},{68,96,153,193,135,138,66,1},{G,6,107,199,155,80,40},{68,128,150,22,173,218,90,1},{G,160,182,169,254,84,1},{G,6,138,153,140,10,0},{G,6,138,185,250,66,1},{0,0,0,5,0,5,0,0,2,8}},w[440]={71,73,70,56,57,97,100,0,5,0,144,0,0,255,255,255,0,0,0};int main(){int a=10000,b=0,c=70,d,e=0,f[71],g;int i,j,k=18,s=0;char m[5];for(;b<c;)f[b++]=a/5;for(;d=0,g=c*2;c-=14,e=d%a){for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);sprintf(m,"%d",e+d/a);F(4,i){B=44;B=s++*5;F(10,j)B=r[10][j];F(8,j)B=r[m[i]-'0'][j];B=0;}}B=59;fwrite(w,1,k,stdout);}

Krótkie wprowadzenie:

Obliczanie PI

Pi jest obliczane przy użyciu nieco zmodyfikowanej wersji implementacji Rabinowitza i algorytmu Wagona do obliczania cyfr π przez Dika Wintera i Achima Flammenkampa.

int a=10000,b,c=2800,d,e,f[2801],g;main(){for(;b-c;)f[b++]=a/5;for(;d=0,g=c*2;c
-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}

Generowanie GIF

Obrazy GIF mają canvaswłaściwość w nagłówku. Możemy użyć tego w połączeniu z wyświetlaniem wielu obrazów, ustawiając odpowiednio leftwłaściwość dla każdej cyfry - gdzie każda cyfra jest (osadzonym) obrazem samym w sobie.

Dokumentacja.

Przykład:

Header: Canvas Width  100 pixels
        Canvas Height   5 pixels

3 : left  0 pixels
1 : left  5 pixels
4 : left 10 pixels
… and so on.

Rozszerzony kod (z mnóstwem komentarzy)

Bałagan, ale to część minimalizacji :

#include <stdio.h>
#define G 68,30
#define F(e,i)for(i=0;i<e;++i)
#define B w[++k]

/* Font + Image Descriptor + Start of Image Data. 
 *
 * Font glyphs are black and white pixels making a 5x5 picture.
 * Each glyph has its own entry in array.
 * Pixels (White,White,Black,Black ...) are further compressed using LZW
 * compression.
 *
 * Next entry in array is Image Descriptor which is added before each glyph.
 * Last entry is start of Image Data.
 *
 * - "0" and comma are 7 and 5 bytes, but hacked to fill 8 bytes to make it 
 * easier to handle in minified code.
 * */
unsigned char r[][10]={
        /* Images representing glyphs. */
        { 4,   18, 150, 199, 188, 159, 10,  0}, /* 0 */
        { 4,   18, 102, 169, 188, 122, 64,  1}, /* 1 */
        { 68,  30, 160, 166, 104, 217, 80,  1}, /* 2 */
        { 68,  30, 160, 166, 184, 140, 66,  1}, /* 3 */
        { 68,  96, 153, 193, 135, 138, 66,  1}, /* 4 */
        { 68,  30,   6, 107, 199, 155, 80, 40}, /* 5 */
        { 68, 128, 150,  22, 173, 218, 90,  1}, /* 6 */
        { 68,  30, 160, 182, 169, 254, 84,  1}, /* 7 */
        { 68,  30,   6, 138, 153, 140, 10,  0}, /* 8 */
        { 68,  30,   6, 138, 185, 250, 66,  1}, /* 9 */
        {132, 143, 121, 177,  92,   0,  0,  0}, /* , (removed as not used) */
        {
        /* Image Descriptor */
        /* 0x2C    Image separator (Embedded in code)   */
           0,   /* Image Left   (LSB embedded in code.  */
        0, 0,   /* Image top    (16-bit Little endian)  */
        5, 0,   /* Image Width  (16-bit Little endian)  */
        5, 0,   /* Image Height (16-bit Little endian)  */
        0,      /* Packed byte  (Local color table (not used, etc.)) */
        /* Start of Image Data */
        2,      /* Starting size of LZW 2 + 1 = 3 */
        8       /* Number of bytes in data */
        }
};
/* GIF Header + Global Color table. 
 *
 * GIF's has a standard header.
 * Canvas size is the are on which to paint.
 * Usually this is size of whole image, but in this code I've spanned it out
 * and paint glyphs by rendering pictures on a canvas of size:
 * 20 * width_of_1_image (5 * 20 = 100)
 *
 * Each image can have an optional color table, but if not present the global
 * color table is used. In this code only global color table is used. It
 * consist of only black and white. (Though very easy to change if wanted.)
 * */
unsigned char buf[440] = {
        71, 73, 70,     /* Signature     "GIF" */
        56, 57, 97,     /* Version       "89a" */
        100, 0,         /* Canvas width  (16-bit Little endian) 5 * 20 = 100*/
          5, 0,         /* Canvas height (16-bit Little endian) 5 pixels.   */
        144,            /* Packed byte: 1 001 0 000
                                  1 : Has global color table.
                                001 : Color resolution.
                                  0 : Sorted Color Table (No)
                                000 : Size of Global Color table (2^(value+1))
                                        or 2 << value ...
                        */
        0,              /* Background Color index. */
        0,              /* Pixel aspect ratio. */
        /* Global color table. */
        255, 255, 255,  /* Index 0: White */
          0,   0,   0   /* Index 1: Black */
};

int main(void){
        /* PI generation variables. */
        int a = 10000, 
            b = 0,
            c = 70,
            d,
            e = 0,
            f[71],
            g;
        /* General purpose variables */
        int i,
            j,
            k = 18,     /* Current Index in out buffer. */
            s = 0;      /* Image counter:
                           (Tells us what "left/x" value should be). */
        char m[5];      /* Print next 4 digits of PI to this buffer. */
        /* Prepare / pre-fill for PI math. */
        for(;b < c;)
                f[b++] = a/5;
        /* Calculate 4 and 4 digits of PI and push onto out buffer. */
        for(; d = 0, g = c * 2; c -= 14 , e = d % a) { 
                for (b = c; d += f[b] * a, f[b] = d % --g, d /= g--, --b; d *= b);
                /* sprintf next 4 digits to temprary buffer.     */
                sprintf(m, "%d", e + d/a);
                /* We are served 4 and 4 digits. 
                 * Here we transalte them to glyphs and push onto out buffer*/
                for (i = 0; i < 4; ++i) {  
                        buf[++k] = 0x2C;     /* 0x2C : Image separator.        */
                        buf[++k] = s++ * 5;  /* xx   : Image left (x) on canvas.*/
                        for (j = 0; j < 10; ++j) {
                                /* Push "Start of Image Data" onto buffer      */
                                buf[++k] = r[11][j];
                        }
                        for (j = 0; j < 8; ++j) {
                                /* Push data of glyph (LZW-compressed) onto buffer. */
                                buf[++k] = r[m[i]-'0'][j];
                        }
                        /* Start of image data informs how big the image data 
                         * is. End with zero to mark that this is EOI. */
                        buf[++k] = 0;       
                }
        }
        /* 0x3b is Trailer, marking end of file. */
        buf[k] = 0x3b;
        /* Write buffer to standard output. 
         * 'k' holds length of data, though as we know this image is 
         * 100x5 etc. we can pre-define it as well.
         * */
        fwrite(buf, 1, k, stdout);
}

Chciałbym użyć krótszego / innego algorytmu do obliczania π.

Runium
źródło
2
Nie widzę kropki po pierwszych 3 obrazach.
Victor Stafusa,
1
Czy masz link do informacji o algorytmie generowania liczb dziesiętnych pi? Bawiłem się trochę z twoim kodem (po usunięciu rzeczy z GIF-ów), ale tak naprawdę nie rozumiem, dlaczego to powoduje cyfry pi ...
FireFly
7

JavaScript, 680 znaków

<html><body></body><script>v=["","41L70L7e","24C223060Ca0b587C592b2eLae","30L90L55L65C95a7a9Cac9e6eC5e3e2c","aaL2aL80L8e","90L40L36C455565C95a7a9Cac9e6eC5e3e2c","70C52272aC2c3e6eC9eacaaCa89666C36282a","20La0C745a5e","60C202435C465666C96a8aaCac9e6eC3e2c2aC283666C768695Ca4a060","a4Ca69868C382624C223060C90a2a4Ca77c5e","6dC7d7e6eC5e5d6d"];v["."]=v[10];a=(""+(4*Math.atan(1))).split("");s="";for(i in a)s+="<path d='M "+v[a[i]].split("").map(function(c){return+-c||c>"Z"?parseInt(c,16):c;}).join(" ")+"'transform='translate("+i*33+".5,10.5)scale(3,3)'fill='none'stroke='#333'stroke-linecap='round'stroke-linejoin='round'/>";document.body.innerHTML="<svg>"+s+"</svg>";</script></html>

Można to wyświetlić w przeglądarce internetowej; liczby są wyprowadzane jako ścieżki SVG.

Zrzut ekranu wyjścia SVG w przeglądarce internetowej

  • Nie oblicza pi w ciekawy sposób, a JS nie ma typu liczbowego z dokładnością do wyświetlania 20 cyfr.

  • Aby zapisać znaki, pominąłem dane ścieżki dla „0”, ponieważ nie pojawia się ona w sekwencji.

JustinMimbs
źródło
Ooh, podejście oparte na wektorze. Bardzo fajna, dobra robota na czcionce.
FireFly
5

Java - 866 860 857 853 znaków, a także oszustwo z 574 znakami

Korzystając ze wzoru Simona Plouffe z 1996 roku, wyświetla x.pngplik z białymi cyframi cyfrowymi na czarnym tle:

Liczba Pi

To jest skompresowany kod:

import java.math.BigDecimal;class E{static java.awt.Graphics g;public static void main(String[]h)throws Exception{java.awt.image.BufferedImage i=new java.awt.image.BufferedImage(213,17,1);g=i.getGraphics();BigDecimal y=v(-3);for(int n=1;n<99;n++)y=y.add(v(n).multiply(v(2).pow(n)).multiply(f(n).pow(2)).divide(f(2*n),42,0));int j=2;for(char c:y.toPlainString().substring(0,21).toCharArray()){if(j!=12){c-=48;boolean b=c!=1&c!=4;t(b,j,2,8,3);t(c<1|c>3&c!=7,j,2,3,8);t(c<5|c>6,j+5,2,3,8);t(c>1&c!=7,j,7,8,3);t(c%2==0&b,j,7,3,8);t(c!=2,j+5,7,3,8);t(b&c!=7,j,12,8,3);}j+=10;}t(true,17,12,3,3);javax.imageio.ImageIO.write(i,"png",new java.io.File("x.png"));}static BigDecimal v(int k){return BigDecimal.valueOf(k);}static BigDecimal f(int k){return k<2?v(1):f(k-1).multiply(v(k));}static void t(boolean x,int a,int b,int c,int d){if(x)g.fillRect(a,b,c,d);}}

To z identyfikacją i niektórymi białymi znakami byłoby:

import java.math.BigDecimal;

class E {

    static java.awt.Graphics g;

    public static void main(String[] h) throws Exception {
        java.awt.image.BufferedImage i = new java.awt.image.BufferedImage(213, 17, 1);
        g = i.getGraphics();
        BigDecimal y = v(-3);

        // Calculate PI using the Simon Plouffe formula, 1996.
        for (int n = 1; n < 99; n++)
            y = y.add(v(n).multiply(v(2).pow(n)).multiply(f(n).pow(2)).divide(f(2 * n), 42, 0));

        int j = 2;
        for (char c : y.toPlainString().substring(0, 21).toCharArray()) {
            if (j != 12) {
                c -= 48;
                boolean b = c != 1 & c != 4;
                t(b, j, 2, 8, 3);
                t(c < 1 | c > 3 & c != 7, j, 2, 3, 8);
                t(c < 5 | c > 6, j + 5, 2, 3, 8);
                t(c > 1 & c != 7, j, 7, 8, 3);
                t(c % 2 == 0 & b, j, 7, 3, 8);
                t(c != 2, j + 5, 7, 3, 8);
                t(b & c != 7, j, 12, 8, 3);
            }
            j += 10;
        }
        t(true, 17, 12, 3, 3);
        javax.imageio.ImageIO.write(i, "png", new java.io.File("x.png"));
    }

    static BigDecimal v(int k) {
        return BigDecimal.valueOf(k);
    }

    static BigDecimal f(int k) {
        return k < 2 ? v(1) : f(k - 1).multiply(v(k));
    }

    static void t(boolean x, int a, int b, int c, int d) {
        if (x) g.fillRect(a, b, c, d);
    }
}

Oszukując reguły i biorąc pod uwagę, że obliczenia PI można dokonać jako „reprezentację liczbową ciągu 3.1415926535897934384”, można to zmniejszyć do 574 znaków:

class F{static java.awt.Graphics g;public static void main(String[]h)throws Exception{java.awt.image.BufferedImage i=new java.awt.image.BufferedImage(213,17,1);g=i.getGraphics();int j=2;for(char c:"3.1415926535897932384".toCharArray()){if(j!=12){c-=48;boolean b=c!=1&c!=4;t(b,j,2,8,3);t(c<1|c>3&c!=7,j,2,3,8);t(c<5|c>6,j+5,2,3,8);t(c>1&c!=7,j,7,8,3);t(c%2==0&b,j,7,3,8);t(c!=2,j+5,7,3,8);t(b&c!=7,j,12,8,3);}j+=10;}t(true,17,12,3,3);javax.imageio.ImageIO.write(i,"png",new java.io.File("x.png"));}static void t(boolean x,int a,int b,int c,int d){if(x)g.fillRect(a,b,c,d);}}
Victor Stafusa
źródło
4

Java - 642 622 znaków

Kopiowanie z mojej poprzedniej odpowiedzi, używając formuły Simona Plouffe z 1996 roku. Zamiast tego generuje ASCII-art:

import java.math.BigDecimal;class H{public static void main(String[]h)throws Exception{int[]t={31599,4681,31183,29647,5101,29671,31719,4687,31727,29679,8192};BigDecimal y=v(-3);for(int n=1;n<99;n++)y=y.add(v(n).multiply(v(2).pow(n)).multiply(f(n).pow(2)).divide(f(2*n),42,0));for(int z=0;z<5;z++){for(char c:y.toPlainString().substring(0,21).toCharArray()){if(c<48)c=58;int a=(t[c-48]>>>z*3)&7;e(a/4);e(a/2&1);e(a&1);e(0);e(0);}e(10);}}static void e(int c){System.out.print((char)(c<2?c*3+32:c));}static BigDecimal v(int k){return BigDecimal.valueOf(k);}static BigDecimal f(int k){return k<2?v(1):f(k-1).multiply(v(k));}}

Wszystko to, z pewnymi identyfikatorami i spacjami oraz odrobiną pomocy czytelnikowi w zrozumieniu znaczenia magicznych liczb:

import java.math.BigDecimal;

class H {

    public static void main(String[] h) throws Exception {
        // Each block corresponds to a line. Each char has 5 lines with a 3-char width.
        int[] t = {
            0b111_101_101_101_111,
            0b001_001_001_001_001,
            0b111_100_111_001_111,
            0b111_001_111_001_111,
            0b001_001_111_101_101,
            0b111_001_111_100_111,
            0b111_101_111_100_111,
            0b001_001_001_001_111,
            0b111_101_111_101_111,
            0b111_001_111_101_111,
            0b010_000_000_000_000
        };

        // Calculate PI using the Simon Plouffe formula, 1996.
        BigDecimal y = v(-3);
        for (int n = 1; n < 99; n++)
            y = y.add(v(n).multiply(v(2).pow(n)).multiply(f(n).pow(2)).divide(f(2 * n), 42, 0));

        for (int z = 0; z < 5; z++) {
            for (char c : y.toPlainString().substring(0, 21).toCharArray()) {
                if (c < 48) c = 58;
                int a = (t[c - 48] >>> z * 3) & 7;
                e(a / 4);
                e(a / 2 & 2);
                e(a & 1);
                e(0);
                e(0); // Not needed, but makes a better art with the cost of 5 chars.
            }
            e(10);
        }
    }

    static void e(int c) {
        System.out.print((char) (c < 2 ? c * 3 + 32 : c));
    }

    static BigDecimal v(int k) {
        return BigDecimal.valueOf(k);
    }

    static BigDecimal f(int k) {
        return k < 2 ? v(1) : f(k - 1).multiply(v(k));
    }
}

Wynik:

###         #  # #    #  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  # #  
  #         #  # #    #  #    # #    #  #    #      #  #    # #  # #    #  # #    #    #    #  # #  # #  
###         #  ###    #  ###  ###  ###  ###  ###  ###  ###  ###  ###    #  ###  ###  ###  ###  ###  ###  
  #         #    #    #    #    #  #    # #    #    #    #  # #    #    #    #    #  #      #  # #    #  
###   #     #    #    #  ###  ###  ###  ###  ###  ###  ###  ###  ###    #  ###  ###  ###  ###  ###    # 
Victor Stafusa
źródło
4

C, 253 250 znaków

Przybliża liczbę pi przy użyciu algorytmu zawartego w kodzie @ Sukmindera (bezwstydnie pożycza i refaktoryzuje swój kod). Wysyła binarny obraz PBM , który można następnie np. Przekonwertować za pomocą ImageMagick.

b,c=70,e,f[71],g;v[71],j,k;L[5]={1072684944,792425072,492082832,256581624};
main(d){for(puts("P4\n8 100");b<c;)f[b++]=2;for(;d=0,g=--c*2;e=d%10){
for(b=c;d+=f[b]*10,f[b]=d%--g,d/=g--,--b;d*=b);v[j++]=e+d/10;}
for(;k<100;k++)putchar(L[k%5]>>3*v[k/5]&7);}

Oto, jak wygląda wyjście z moim rendererem PPM opartym na alfabecie Braille'a:

Zrzut ekranu wyjścia

Ma to samo dziwactwo, co odpowiedź @ Sukmindera, ponieważ nie ma separatora dziesiętnego. Ponadto mój wynik jest pionowy, a kwestia, czy jest on czytelny dla człowieka, jest dyskusyjna ...

Edycja: zastosowano sugestie @ ugoren.

Robaczek świętojański
źródło
Małe ulepszenia: przejdź putsdo for inicjalizacji, zdefiniuj L[5]i pomiń ,0. Ustaw dparametr na main(zapisz przecinek).
ugoren
4

PHP 380

wymaga włączenia gd dla wyjścia obrazu

<? header('Content-Type: image/png');$i=imagecreatetruecolor(84,5);$n=['71775777770','51115441550','51777771770','51411151510','71771771712'];$c=imagecolorallocate($i,255,255,255);$m=(6.28318/2).(5307*5).(28060387*32);$k=5;while($k--)for($j=0;$j<21;$j++){$p=str_pad(decbin($n[$k][($m[$j]!='.')?$m[$j]:10]),3,'0',0);$l=3;while($l--)$p[$l]&&imagesetpixel($i,$l+$j*4,$k,$c);}imagepng($i);

wprowadź opis zdjęcia tutaj

obliczenia pi: ponieważ podstawowy php ma domyślną precyzję 14 i nie chciałem ponownie kompilować serwera z włączonymi dowolnymi rozszerzeniami dokładności, nie mogłem nawet oszacować PI z wymaganymi miejscami dziesiętnymi, więc zamiast tego oblicza tau / 2, a następnie reszta miejsc po przecinku

ponieważ grafika składa się z zer i jedynek, mogę spróbować użyć WBMP jako formatu, aby sprawdzić, czy mogę usunąć gd

Einacio
źródło
ten obraz jest czerwony na czarnym i bardzo mały, ale przy 500% możesz go odczytać, jeśli spojrzysz z bliska. (i nie są ślepi na kolory.)
hildred
@ Hildred każda postać jest 3x5 with 1 px between chars. kolor jest czerwony, aby zmniejszyć 4 znaki, ale biorąc pod uwagę, że nie wygram, zmienię go na biały dla czytelności
Einacio 21.01.2014
Mój komentarz nie miał na celu krytyki, ale wyjaśnienia, aby zachęcić do głosowania.
hildred
Czy imagecreateindex uratuje jakieś postacie? czy taka funkcja istnieje?
hildred
@hildred podczas pracy z obrazem pallete ( imagecreate), pierwsze wywołanie imagecolorallocateustawia kolor tła, a drugie jest potrzebne, aby ustawić kolor pisania. więc kończy się dłużej
Einacio
4

Drukarka C + LaserWriter 599–10 = 589

Przesyłaj dane wyjściowe do LaserWriter! :) To powinno działać na Lisa (z kompilatorem C).

Oblicza piw drukarce, obliczając sumę długości odcinków linii, które przybliżają sekwencję krzywej Beziera, która przybliża półkole podzielone przez średnicę, razy 2.

main(){
printf("/dist{dtransform dup mul exch dup mul add sqrt}def");
printf("/len{3 2 roll sub 3 1 roll exch sub dist}def");
printf("/pi{0 0 2 index 0 180 arc closepath flattenpath");
printf("[{2 copy}{2 copy 6 2 roll len 3 1 roll}{}{counttomark -2 roll len\n");
printf("counttomark 2 add 1 roll counttomark 1 sub{add}repeat\n");
printf("exch pop exch pop exch div 2 mul}pathforall}def\n");
printf("matrix setmatrix 100 dup scale 10 setflat 100 pi 10 string cvs\n");
printf("matrix defaultmatrix setmatrix/Palatino-Roman findfont 10 scalefont setfont\n");
printf("100 700 moveto show showpage");
}

Ungolfed Level-1 (kompatybilny z 1985) PostScript:

%!
/dist { % dx dy  .  dz  
    dtransform
    dup mul exch dup mul add sqrt
} def 

/len { % x1 y1 x2 y2  .  dist(y2-y1,x2-x1)
    3 2 roll % x1 x2 y2 y1
    sub 3 1 roll exch sub % y2-y1 x2-x1
    dist
} def 

/pi { % rad 
    0 0 2 index 0 180 arc closepath % rad 
    flattenpath
    [   
    { % rad [ x(0) y(0)     (m)print
        2 copy 
    } %moveto proc
    { % rad [ ... x(n-1) y(n-1) x(n) y(n)     (l)print
        2 copy 6 2 roll len % rad [ ... x(n) y(n) dist
        3 1 roll % rad [ ... dist x(n) y(n)
    } %lineto proc
    {} %curveto proc % n.b. flattenpath leaves no curve segments
    { % rad [ x(0) y(0) dist(1) dist(2) ... dist(n-1) x(n) y(n)     (c)print
        counttomark -2 roll len % rad [ dist(1) dist(2) ... dist(n)
        counttomark 2 add 1 roll % dist(n) rad [ dist...
        counttomark 1 sub { add } repeat % dist(n) rad [ sum_dist
        exch pop % dist(n) rad sum_dist
        exch pop % dist(n) sum_dist
        exch % sum_dist dist(n)
        div  % length_of_half_circle/diameter
        2 mul % C/d 
    } %closepath proc
    pathforall
} def 

matrix setmatrix
100 dup scale
10 setflat
100 pi 10 string cvs 
matrix defaultmatrix setmatrix
/Palatino-Roman findfont 10 scalefont setfont
100 700 moveto show

Wynik:

ps_pi

luser droog
źródło
Przypuszczam, że muszę też stworzyć czcionkę.
luser droog
Hmm Nigdy nie otrzymam wystarczającej liczby cyfr w ten sposób. PS ma tylko 32-bitowe zmiennoprzecinkowe.
luser droog
fajny pomysł, lubię postscriptum do gry w golfa.
hildred
Mam czcionkę bitmapową dla cyfr, ale gra w golfa zepsuje ją!
luser droog
2

Java, 1574 2643 1934 znaków

Skompresowane 1934 znaki:

    public static void main(String[] args){int[][][]num={{{1,1,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1}},{{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1}},{{1,1,1},{0,0,1},{1,1,1},{1,0,0},{1,1,1}},{{1,1,1},{0,0,1},{1,1,1},{0,0,1},{1,1,1}},{{1,0,1},{1,0,1},{1,1,1},{0,0,1},{0,0,1}},{{1,1,1},{1,0,0},{1,1,1},{0,0,1},{1,1,1}},{{1,1,1},{1,0,0},{1,1,1},{1,0,1},{1,1,1}},{{1,1,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1}},{{1,1,1},{1,0,1},{1,1,1},{1,0,1},{1,1,1}},{{1,1,1},{1,0,1},{1,1,1},{0,0,1},{0,0,1}},{{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,1}}};BufferedImage image=new BufferedImage(103,5,BufferedImage.TYPE_3BYTE_BGR);for(int q=0;q<103;q++){for(int w=0;w<5;w++){image.setRGB(q,w,0xFFFFFF);}}int loc = 0;String g=String.valueOf(pi(20));for(int w=0;w<g.length()-1;w++){Integer n=0;if(g.charAt(w)=='.'){n=10;}else{n=Integer.parseInt(String.valueOf(g.charAt(w)));}for(int t=0;t<5;t++){for(int q=0;q<3;q++){int c=num[n][t][q]==1?0x000000:0xFFFFFF;image.setRGB(loc+q,t,c);}}loc+=5;}try{BufferedImage bi=image;File f=new File("o.png");ImageIO.write(bi,"png",f);}catch(IOException e){}}public static BigDecimal pi(final int SCALE){BigDecimal a=BigDecimal.ONE;BigDecimal b=BigDecimal.ONE.divide(sqrt(new BigDecimal(2),SCALE),SCALE,BigDecimal.ROUND_HALF_UP);BigDecimal t=new BigDecimal(0.25);BigDecimal x=BigDecimal.ONE;BigDecimal y;while(!a.equals(b)){y=a;a=a.add(b).divide(new BigDecimal(2),SCALE,BigDecimal.ROUND_HALF_UP);b=sqrt(b.multiply(y),SCALE);t=t.subtract(x.multiply(y.subtract(a).multiply(y.subtract(a))));x=x.multiply(new BigDecimal(2));}return a.add(b).multiply(a.add(b)).divide(t.multiply(new BigDecimal(4)),SCALE,BigDecimal.ROUND_HALF_UP);}public static BigDecimal sqrt(BigDecimal A,final int SCALE){BigDecimal x0=new BigDecimal("0");BigDecimal x1=new BigDecimal(Math.sqrt(A.doubleValue()));while(!x0.equals(x1)){x0=x1;x1=A.divide(x0,SCALE,BigDecimal.ROUND_HALF_UP);x1=x1.add(x0);x1=x1.divide(new BigDecimal(2),SCALE,BigDecimal.ROUND_HALF_UP);}return x1;}}

Rozszerzone 2643 znaki:

public static void main(String[] args) {
    int[][][] num = { { { 1, 1, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 } },
            { { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 } },
            { { 1, 1, 1 }, { 0, 0, 1 }, { 1, 1, 1 }, { 1, 0, 0 }, { 1, 1, 1 } },
            { { 1, 1, 1 }, { 0, 0, 1 }, { 1, 1, 1 }, { 0, 0, 1 }, { 1, 1, 1 } },
            { { 1, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 0, 1 }, { 0, 0, 1 } },
            { { 1, 1, 1 }, { 1, 0, 0 }, { 1, 1, 1 }, { 0, 0, 1 }, { 1, 1, 1 } },
            { { 1, 1, 1 }, { 1, 0, 0 }, { 1, 1, 1 }, { 1, 0, 1 }, { 1, 1, 1 } },
            { { 1, 1, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 } },
            { { 1, 1, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 1, 0, 1 }, { 1, 1, 1 } },
            { { 1, 1, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 0, 1 }, { 0, 0, 1 } },
            { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 1 } } };

    BufferedImage image = new BufferedImage(103, 5, BufferedImage.TYPE_3BYTE_BGR);

    for (int q = 0; q < 103; q++) {
        for (int w = 0; w < 5; w++) {
            image.setRGB(q, w, 0xFFFFFF);
        }
    }

    int loc = 0;

    String g = String.valueOf(pi(20));
    for (int w = 0; w < g.length()-1; w++) {
        Integer n = 0;
        if (g.charAt(w) == '.') {
            n = 10;
        } else {
            n = Integer.parseInt(String.valueOf(g.charAt(w)));
        }
        for (int t = 0; t < 5; t++) {
            for (int q = 0; q < 3; q++) {
                int c = num[n][t][q] == 1 ? 0x000000 : 0xFFFFFF;
                image.setRGB(loc + q, t, c);
            }
        }
        loc += 5;
    }
    try {
        BufferedImage bi = image;
        File outputfile = new File("out2.png");
        ImageIO.write(bi, "png", outputfile);
    } catch (IOException e) {

    }
}

public static BigDecimal pi(final int SCALE) {
    BigDecimal a = BigDecimal.ONE;
    BigDecimal b = BigDecimal.ONE.divide(sqrt(new BigDecimal(2), SCALE), SCALE, BigDecimal.ROUND_HALF_UP);
    BigDecimal t = new BigDecimal(0.25);
    BigDecimal x = BigDecimal.ONE;
    BigDecimal y;

    while (!a.equals(b)) {
        y = a;
        a = a.add(b).divide(new BigDecimal(2), SCALE, BigDecimal.ROUND_HALF_UP);
        b = sqrt(b.multiply(y), SCALE);
        t = t.subtract(x.multiply(y.subtract(a).multiply(y.subtract(a))));
        x = x.multiply(new BigDecimal(2));
    }
    return a.add(b).multiply(a.add(b)).divide(t.multiply(new BigDecimal(4)), SCALE, BigDecimal.ROUND_HALF_UP);

}

public static BigDecimal sqrt(BigDecimal A, final int SCALE) {
    BigDecimal x0 = new BigDecimal("0");
    BigDecimal x1 = new BigDecimal(Math.sqrt(A.doubleValue()));
    while (!x0.equals(x1)) {
        x0 = x1;
        x1 = A.divide(x0, SCALE, BigDecimal.ROUND_HALF_UP);
        x1 = x1.add(x0);
        x1 = x1.divide(new BigDecimal(2), SCALE, BigDecimal.ROUND_HALF_UP);
    }
    return x1;
}

Metoda Pi zebrana z: /programming/8343977/calculate-pi-on-an-android-phone?rq=1

Clayton
źródło
Wygląda na to, że użyłeś stałej zamiast obliczania PI.
hildred
To niezły zwrot akcji. Pracuję teraz nad tym.
Clayton
Można go skompresować trochę więcej poprzez dodanie throws Exceptionw maini wyjmowania blok try-catch. Ponadto, można zmienić nazwę pii sqrtmetod oraz loc, args, SCALE, x0i x1zmienne do 1 identyfikatorów Char. Nawiasem mówiąc , musisz dodać pełną klasę, w tym class Foo{deklarację i import.
Victor Stafusa,