restrições estúpidas e deserto

18

Então, você estava sentado à sua mesa, jogando golfe em um programa para calcular os primeiros 20 dígitos de pi, e aí vem seu chefe e joga sua maçã pela janela. Agora você está trabalhando em um novo projeto e este computador ainda não possui nenhum recurso de texto. Nenhum. Sem fontes. Nada.

Agora vamos terminar esse programa. Calcular e exibir os 20 primeiros caracteres de pi sem usar nenhuma fonte que não faça parte do seu programa. Sua saída pode ser exibida ou gravada como padrão como um arquivo de imagem (jpeg, png, gif, svg (contanto que você não use caracteres), bmp, xpm). Você pode usar qualquer idioma, mas não pode usar as funções de fonte, exibição de texto ou similares do seu idioma.

bônus pequeno (10 caracteres) Se funcionar em uma Lisa.

Edit: para quem não descobriu, minha inspiração foi o primeiro mac, e o título é um trocadilho. Um grande parabéns para @Sukminder, cujo gif animado é simplesmente legal. O concurso não termina se surgir uma resposta melhor.

hildred
fonte
Eu gosto do desafio, mas tecnicamente esse sistema também não seria capaz de exibir o código-fonte? Exceto Piet, é claro.
ApproachingDarknessFish
2
@ValekHalfHeart você pode carregar o código-fonte de uma máquina diferente
John Dvorak
1
E como você define legível por humanos? Por exemplo, minha letra é legível para alguns humanos (pelo menos um) e não para outros. (By the way, 2 ^ (2x2) = 16, glifos suficientes para todos os 11 dígitos.;))
Kendall Frey
4
Não entendo o título, não entendo como a arte ASCII pode ser boa quando não podemos usar a exibição de texto, e a pergunta precisa muito de uma definição de "calcular PI".
Peter Taylor
2
O que significa "calcular pi" realmente significa? Eu poderia codificar um bitmap das primeiras 20 casas decimais? (Não faz uso de qualquer built-in constante PI ou similar)
FireFly

Respostas:

6

Python, 222 caracteres

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)

A primeira linha calcula os dígitos de pi usando a aproximação pi-3 ~= 277991633/1963319607. As próximas três linhas produzem 20 caracteres de pi usando o ASCII art Nemeth Braille.

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

Estou empurrando os limites em duas direções aqui, tanto nos sentidos "calculando Pi" quanto "legível por humanos".

Keith Randall
fonte
3
Que diabos? Eu pensei que não deveríamos usar nenhuma saída de texto. Como o seu computador processa os *espaços e os espaços sem uma fonte?
usar o seguinte comando
@ boothby: É arte ASCII. Pense *como um pixel preto 1x1 e `` como um pixel branco 1x1.
Keith Randall
1
Ele tem razão. Você não pode tornar um *sem o uso de fontes, eu acho que você está desclassificado
Sirens
18

Python, 217 bytes

Requer a biblioteca de imagens 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()

A contagem de bytes supõe que o caractere de escape \177seja substituído por seu equivalente literal (caractere 127 ).

A saída será exibida da seguinte forma (será aberta no seu visualizador * .bmp padrão):

Observe que isso pode ser facilmente parametrizado para imprimir qualquer número de dígitos que você desejar. A seguir, será aceita uma entrada inteira do stdin e exibirá muitos dígitos:

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

Saída para n = 80 :


Cálculo Pi

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

Sim, é isso. A fórmula usada é o resultado da aplicação da Transformada de Euler à Série Leibniz e, em seguida, fatorando cada termo do restante da soma. A fórmula converge linearmente; cada dígito requer log 2 (10) ≈ 3,32 iterações. Para os interessados ​​na derivação, consulte o Apêndice A.

Exibição

O PIL é usado para geração de imagens, porque é a biblioteca mais conveniente que eu conheço. Um bitmap em branco e preto e branco de 141 × 11 é criado e, em seguida, são desenhadas linhas brancas em uma forma de sete segmentos, um pixel de cada vez. As posições necessárias para desenhar cada segmento são armazenadas em uma sequência de máscaras de bits, com os bits correspondentes às seguintes posições:

 000
3   5
3   5
 111
4   6
4   6
 222

O bit de mágica (j%7/5*4-~j%7/4*~j/7+p,j%7*3%14%8+j%14/10+2)produz cada pixel na seguinte ordem (base-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

Apêndice A

A transformação de Euler é uma técnica de aceleração de convergência que funciona para qualquer série que exibe convergência monotônica absoluta. A série resultante convergirá linearmente, normalmente na taxa de um bit por termo (observe que, se a série original já era super-linear, a série resultante realmente convergirá mais lentamente). A descrição puramente matemática é um pouco difícil de seguir, portanto, adotarei uma abordagem processual.

Vamos começar com a série Leibniz:

Em seguida, divida cada termo ao meio, combinando termos vizinhos:

Simplificado:

Generalizado:

Observe que o líder ½ não tinha um termo de parceiro e, portanto, foi excluído do restante da soma. Este é o primeiro termo da série transformada. Para encontrar o próximo termo, repetimos o processo novamente:

E de novo:

E de novo:

E mais uma vez, para uma boa medida:

Neste ponto, temos os cinco primeiros termos e o sexto termo é evidente. Isso deve ser suficiente para generalizar, então vamos parar por aqui. Começaremos fatorando os numeradores e denominadores:

Os denominadores evidentemente contêm um fatorial duplo de 2n + 1 ; portanto, corrigiremos isso em:

Tudo se encaixa, exceto os dois primeiros termos que não são contabilizados como 2 no denominador. Podemos corrigir isso multiplicando a expressão inteira por 2 :

2 3 = 2 , 4 , então:

O numerador agora pode ser facilmente identificado como n! .

Observe que o fator adicionado a cada termo sucessivo, n / (2n + 1) , se aproxima de ½ quando n se torna grande, implicando uma convergência linear na taxa de um bit por termo - isso é de fato por design. Um bom resultado, mas seria ainda melhor sem os fatoriais presentes. O que podemos fazer aqui é fatorar cada termo sucessivo do restante da soma, o que gerará uma expressão aninhada:



Isso pode ser reescrito como uma relação de recorrência:

Onde n conta inversamente a partir de ⌈ log 2 (10) · d ⌉ .. 0 , onde d é o número de dígitos necessários.

Pode ser interessante notar que o ponto estável dessa recorrência é exatamente 2 (ou 4, se você o dobrou, como eu fiz na implementação acima), para que você possa salvar várias iterações ao inicializar corretamente. No entanto, inicializar com um valor aleatório necessário em outro lugar e lançar algumas iterações extras no topo geralmente são mais baratas em bytes.

primo
fonte
1
Muito bom, obrigado pela lição! O que eu não entendo é o que o pem p/2 * x/p + ...está fazendo .. AIUI Python suporta promoção automática para um tipo de dados BigInteger-ish, por isso não deve ser uma coisa precisão, mas de alguma forma aqueles pé matéria e não cancelar fora, como eu imagino eles para ... o que estou perdendo aqui?
FireFly 21/01
O @FireFly pinicializou ímpar, de modo que p/2/pé equivalente - na divisão inteira - a ((p-1)/2)/p. Isto produz o 1/3, 2/5, 3/7, etc. termos derivado acima.
primo 21/01
12

#C - 777 caracteres

C - 731 caracteres

Imprime GIF para stdout.

  • Peculiaridade: sem vírgula após o primeiro 3.

Costurando GIF a partir do cabeçalho pré-configurado + cada dígito representado pela fonte caseira (incorporada) de 5x5 pixels.

Resultado

insira a descrição da imagem aqui

Está lá --- ^

Observe que o GIF desaparece, às vezes, no Chrome após uma execução.

#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);}

Breve introdução:

Cálculo de PI

O Pi é calculado usando uma versão ligeiramente modificada da implementação de Din Winter e Achim Flammenkamp do algoritmo de Rabinowitz e Wagon para calcular dígitos de π.

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

Geração de GIF

Imagens GIF tem uma canvaspropriedade no cabeçalho. Podemos usar isso em combinação com a exibição de várias imagens, configurando a leftpropriedade para cada dígito de acordo - onde cada dígito é uma imagem (incorporada) em si mesma.

Documentação.

Exemplo:

Header: Canvas Width  100 pixels
        Canvas Height   5 pixels

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

Código expandido (com muitos comentários)

Confuso, mas isso faz parte da minimização :

#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);
}

Procurando usar um algoritmo mais curto / outro para calcular π.

Runium
fonte
2
Não vejo o ponto após os três primeiros na imagem.
Victor Stafusa
1
Você tem um link para informações sobre o algoritmo de geração de decimais pi? Eu brinquei com seu código um pouco (após a remoção do material GIF out), mas eu realmente não vejo por que isso resulta em dígitos do pi ...
FireFly
7

JavaScript, 680 caracteres

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

Isso pode ser visualizado em um navegador da web; os números são exibidos como caminhos SVG.

Captura de tela da saída SVG em um navegador da web

  • Ele não calcula pi de uma maneira interessante, e JS não possui um tipo de número com precisão para exibir 20 dígitos.

  • Para salvar os caracteres, omiti os dados do caminho para "0", pois eles não aparecem na sequência.

JustinMimbs
fonte
Ooh, uma abordagem baseada em vetor. Muito bom, bom trabalho na fonte também.
FireFly
5

Java - 866 860 857 853 caracteres, além de uma versão fraudulenta com 574 caracteres

Usando a fórmula de Simon Plouffe de 1996, gera um x.pngarquivo com números brancos do tipo relógio digital em fundo preto:

pi

Este é o código compactado:

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

Isso, com identing e alguns espaços em branco, seria este:

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

Trapaceando as regras e considerando que o cálculo do PI pode ser feito como "a representação numérica da String 3.1415926535897934384", isso pode ser reduzido para 574 caracteres:

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
fonte
4

Java - 642 622 caracteres

Copiando da minha resposta anterior, usando a fórmula de Simon Plouffe de 1996. Mas produz 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));}}

Tudo isso, com algumas identificações e espaços, e um pouco de ajuda para o leitor entender o significado dos números mágicos:

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

Resultado:

###         #  # #    #  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  # #  
  #         #  # #    #  #    # #    #  #    #      #  #    # #  # #    #  # #    #    #    #  # #  # #  
###         #  ###    #  ###  ###  ###  ###  ###  ###  ###  ###  ###    #  ###  ###  ###  ###  ###  ###  
  #         #    #    #    #    #  #    # #    #    #    #  # #    #    #    #    #  #      #  # #    #  
###   #     #    #    #  ###  ###  ###  ###  ###  ###  ###  ###  ###    #  ###  ###  ###  ###  ###    # 
Victor Stafusa
fonte
4

C, 253 250 caracteres

Aproxima pi usando o algoritmo no código do @ Sukminder (emprestando e refatorando descaradamente o código deles um pouco). Produz uma imagem PBM binária , que pode, por exemplo, ser convertida com o 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);}

Veja como é a saída do meu renderizador PPM baseado em Braille:

Captura de tela da saída

Tem a mesma peculiaridade da resposta de @ Sukminder, na medida em que falta um separador decimal. Além disso, a saída da minha é vertical, e se é legível por humanos é discutível ...

Editar: aplicou as sugestões de @ ugoren.

FireFly
fonte
Pequenas melhorias: passe putspara a for inicialização, defina L[5]e omita ,0. Faça dum parâmetro para main(salve uma vírgula).
ugoren
4

PHP 380

requer gd ativado para saída de imagem

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

insira a descrição da imagem aqui

cálculo do pi: como o php base tem uma precisão padrão de 14 e eu não queria recompilar o servidor com as extensões de precisão arbitrárias ativadas, eu não conseguia nem aproximar o PI com as casas decimais necessárias, portanto, calcula tau / 2 e depois o resto das casas decimais

como o gráfico é composto de 0 e 1, posso tentar usar o WBMP como o formato mais tarde para ver se consigo remover o gd

Einacio
fonte
essa imagem é vermelha no preto e muito pequena, mas a 500% você pode lê-la se olhar de perto. (e não são daltônicos).
hildred
@hildred cada personagem é 3x5 with 1 px between chars. a cor é vermelha apenas para reduzir de 4 caracteres, mas considerando que eu não vou ganhar, eu vou mudá-lo para branco para facilitar a leitura
Einacio
Meu comentário não foi uma crítica, mas uma explicação, para encorajar votos.
Hildred
O imagecreateindex salvaria algum personagem? existe essa função?
Hildred
@hildred ao trabalhar com uma imagem pallete ( imagecreate), a primeira chamada de imagecolorallocatedefine a cor do plano de fundo e uma segunda é necessária para definir a cor da escrita. para que termine mais tempo
Einacio 21/01
4

Impressora C + LaserWriter 599 - 10 = 589

Canalize a saída para o seu LaserWriter! :) Isso deve funcionar em uma Lisa (com um compilador C).

Ele calcula pina impressora calculando a soma dos comprimentos dos segmentos de linha que se aproximam de uma sequência da curva de Bezier que se aproxima de um semicírculo, dividido pelo diâmetro, vezes 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 (compatível com 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

Resultado:

ps_pi

luser droog
fonte
Suponho que preciso criar uma fonte também.
Luser droog
Hmm. Nunca vai conseguir dígitos suficientes dessa maneira. O PS possui apenas flutuadores de 32 bits.
Luser droog
ideia legal, eu gosto de postscript para jogar golfe.
Hildred 28/02
Eu tenho uma fonte de bitmap para os dígitos, mas o golfe apenas a arruinará!
Luser droog
2

Java, 1574 2643 1934 caracteres

1934 caracteres compactados :

    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;}}

2643 caracteres expandidos :

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;
}

Método Pi reunido em: /programming/8343977/calculate-pi-on-an-android-phone?rq=1

Clayton
fonte
Parece que você usou uma constante em vez de calcular o PI.
Hildred
Essa é uma bela reviravolta. Trabalhando nisso agora.
Clayton
Você pode comprimi-lo um pouco mais adicionando throws Exceptionem maine remover o bloco try-catch. Além disso, você pode renomear pie sqrtmétodos e loc, args, SCALE, x0e x1variáveis para 1 identificadores de char. E, a propósito, você deve adicionar a classe completa, isso inclui a class Foo{declaração e as importações.
precisa saber é o seguinte