estúpidas restricciones y desierto

18

Entonces, estabas sentado en tu escritorio, jugando un programa para calcular los primeros 20 dígitos de pi, y luego viene tu jefe y arroja tu manzana IIe por la ventana. Ahora está trabajando en un nuevo proyecto y esta computadora aún no tiene ninguna capacidad de texto. Ninguna. No hay fuentes Nada.

Ahora terminemos ese programa. Calcule y muestre los primeros 20 caracteres de pi sin usar ninguna fuente que no forme parte de su programa. Su salida se puede mostrar o escribir en un archivo de imagen estándar (jpeg, png, gif, svg (siempre que no use ningún carácter), bmp, xpm). Puede usar cualquier idioma, pero no puede usar las funciones de fuente, visualización de texto o similar de su idioma.

pequeño bono (10 caracteres) si funcionará en una Lisa.

Editar: para aquellos que no lo descubrieron, mi inspiración fue el primer mac, y el título es un juego de palabras. Un gran saludo a @Sukminder cuyo gif animado es genial. El concurso no termina si aparece una mejor respuesta.

hildred
fuente
Me gusta el desafío, pero técnicamente ¿no sería un sistema de este tipo también incapaz de mostrar el código fuente? A excepción de Piet, por supuesto.
ApproachingDarknessFish
2
@ValekHalfHeart puede cargar el código fuente desde una máquina diferente
John Dvorak
1
¿Y cómo define a los humanos legibles? Por ejemplo, mi escritura a mano es legible para algunos humanos (al menos uno) y no para otros. (Por cierto, 2 ^ (2x2) = 16, suficientes glifos para los 11 dígitos.;))
Kendall Frey
44
No entiendo el título en absoluto, no entiendo cómo el arte ASCII puede estar bien cuando no podemos usar la visualización de texto, y la pregunta necesita una definición de "calcular PI".
Peter Taylor
2
¿Qué significa realmente "calcular pi"? ¿Podría codificar un mapa de bits de los primeros 20 decimales? (No utiliza ninguna constante de PI incorporada o similar)
FireFly

Respuestas:

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)

La primera línea calcula los dígitos de pi usando la aproximación pi-3 ~= 277991633/1963319607. Las siguientes tres líneas generan 20 caracteres de pi usando el arte ASCII Nemeth Braille.

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

Aquí estoy empujando los límites en dos direcciones, tanto en el sentido de "cálculo de Pi" como en el de "lectura humana".

Keith Randall
fuente
3
¿Que demonios? Pensé que no debíamos usar ningún resultado de texto. ¿Cómo va a representar tu computadora los *'s y los espacios sin una fuente?
Boothby
@boothby: es el arte ASCII. Piense *en un píxel negro 1x1 y `` como un píxel blanco 1x1.
Keith Randall el
1
Él tiene un punto. No puedes renderizar a *sin usar fuentes, creo que estás descalificado
Sirens
18

Python, 217 bytes

Requiere la biblioteca de imágenes de 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()

El recuento de bytes supone que el carácter escapado \177se reemplaza con su equivalente literal (char 127 ).

La salida aparecerá de la siguiente manera (se abrirá en su visor predeterminado * .bmp):

Tenga en cuenta que esto podría parametrizarse fácilmente para imprimir cualquier número de dígitos que desee. Lo siguiente aceptará una entrada entera de stdin y mostrará esa cantidad de 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()

Salida para n = 80 :


Cálculo de pi

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

SIP eso es. La fórmula utilizada es el resultado de aplicar la Transformada de Euler a la Serie Leibniz y luego deducir cada término del resto de la suma. La fórmula converge linealmente; cada dígito requiere log 2 (10) ≈ 3.32 iteraciones. Para aquellos interesados ​​en la derivación, vea el Apéndice A.

Monitor

PIL se usa para generar imágenes, porque es la biblioteca más conveniente que conozco. Se crea un mapa de bits en blanco y negro 141 × 11 en blanco, y luego se dibujan líneas blancas en forma de siete segmentos, un píxel a la vez. Las posiciones requeridas para dibujar cada segmento se almacenan en una cadena de máscara de bits, con bits correspondientes a las siguientes posiciones:

 000
3   5
3   5
 111
4   6
4   6
 222

El bit de magia (j%7/5*4-~j%7/4*~j/7+p,j%7*3%14%8+j%14/10+2)produce cada píxel en el siguiente orden (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

La transformación de Euler es una técnica de aceleración de convergencia que funciona para cualquier serie que muestre una convergencia monotónica absoluta. La serie resultante convergerá linealmente, típicamente a una velocidad de un bit por término (tenga en cuenta que si la serie original ya era superlineal, la serie resultante en realidad convergerá más lentamente). La descripción puramente matemática es un poco difícil de seguir, por lo que adoptaré un enfoque de procedimiento.

Comenzaremos con la serie Leibniz:

Luego divide cada término por la mitad, combinando términos vecinos:

Simplificado:

Generalizado:

Observe que la ½ inicial no tenía un término asociado, y por lo tanto se excluyó del resto de la suma. Este es el primer término de la serie transformada. Para encontrar el siguiente término, repetimos el proceso nuevamente:

Y otra vez:

Y otra vez:

Y una vez más por si acaso:

En este punto tenemos los primeros cinco términos, y el sexto término es evidente. Esto debería ser suficiente para generalizar, así que pararemos aquí. Comenzaremos factorizando los numeradores y denominadores:

Los denominadores evidentemente contienen un Factorial doble de 2n + 1 , por lo que lo repararemos en:

Todo encaja, excepto los dos primeros términos que tienen un 2 no contabilizado en el denominador. Podemos arreglar eso multiplicando la expresión completa por 2 :

2 3 = 2 · 4 , entonces:

El numerador ahora se puede identificar fácilmente como n! .

Observe que el factor agregado a cada término sucesivo, n / (2n + 1) , se aproxima a ½ a medida que n se hace grande, lo que implica una convergencia lineal a una tasa de un bit por término; esto es, de hecho, por diseño. Un buen resultado, pero sería aún mejor sin los factoriales allí. Lo que podemos hacer aquí es factorizar cada término sucesivo del resto de la suma, lo que generará una expresión anidada:



Esto puede reescribirse como una relación de recurrencia:

Donde n cuenta hacia atrás desde ⌈ log 2 (10) · d ⌉ .. 0 , donde d es el número de dígitos requerido.

Puede ser interesante observar que el punto estable de esta recurrencia es exactamente 2 (o 4 si lo ha duplicado, como lo hice en la implicación anterior), por lo que puede guardar una serie de iteraciones inicializando correctamente. Sin embargo, inicializar a un valor aleatorio que necesita en otro lugar y lanzar algunas iteraciones adicionales en la parte superior es generalmente más barato en bytes.

primo
fuente
1
Muy bien, gracias por la lección! Lo que no entiendo es por lo que el pen p/2 * x/p + ...está haciendo .. AIUI Python admite la promoción automática a un tipo de datos BigInteger-ish, por lo que no debe ser una cosa precisión, pero de alguna manera los pes la materia y no cancela fuera como me imagino ellos a ... ¿qué me estoy perdiendo aquí?
FireFly
@FireFly se pinicializó impar, por lo que p/2/pes equivalente, bajo división entera, a ((p-1)/2)/p. Esto produce el 1/3, 2/5, 3/7, etc. términos derivados anteriormente.
primo
12

#C - 777 Personajes

C - 731 caracteres

Imprime GIF en stdout.

  • Quirk: Sin coma después del primero 3.

Unir GIF desde un encabezado preconfigurado + cada dígito representado por una fuente casera (incrustada) de 5x5 píxeles.

Resultado

ingrese la descripción de la imagen aquí

Está ahí --- ^

Tenga en cuenta que GIF desaparece, a veces, en Chrome después de una ejecución.

#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 introducción:

Cálculo de PI

Pi se calcula utilizando una versión ligeramente modificada de la implementación de Dik Winter y Achim Flammenkamp del algoritmo de Rabinowitz y 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);}

Generación de GIF

Las imágenes GIF tienen una canvaspropiedad en el encabezado. Podemos usar esto en combinación con la visualización de múltiples imágenes estableciendo la leftpropiedad para cada dígito en consecuencia, donde cada dígito es una imagen (incrustada) en sí misma.

Documentación.

Ejemplo:

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 ampliado (con muchos comentarios)

Desordenado, pero eso es parte de la minimización :

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

Buscando usar un algoritmo más corto / otro para calcular π.

Runium
fuente
2
No veo el punto después de los primeros 3 en la imagen.
Victor Stafusa
1
¿Tiene un enlace a información sobre el algoritmo de generación de decimales pi? Jugué un poco con su código (después de quitar el material GIF), pero realmente no veo por qué resulta en dígitos de 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>

Esto se puede ver en un navegador web; los números se muestran como rutas SVG.

Captura de pantalla de la salida SVG en un navegador web

  • No calcula pi de una manera interesante, y JS carece de un tipo de número con precisión para mostrar 20 dígitos.

  • Para guardar caracteres, omití los datos de ruta para "0", ya que no aparece en la secuencia.

JustinMimbs
fuente
Ooh, un enfoque basado en vectores. Muy bonito, buen trabajo en la fuente también.
FireFly
5

Java: 866 860 857 853 caracteres, más una versión trampa con 574 caracteres

Usando la fórmula Simon Plouffe de 1996, genera un x.pngarchivo con números blancos tipo reloj digital en un fondo negro:

Pi

Este es el código comprimido:

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

Eso, con identificación y algunos espacios en blanco sería esto:

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

Hacer trampa en las reglas y considerar que el cálculo de PI se puede hacer como "la representación numérica de la Cadena 3.1415926535897934384", esto se puede reducir a 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
fuente
4

Java - 642 622 caracteres

Copiando de mi respuesta anterior, usando la fórmula Simon Plouffe de 1996. Pero en cambio saca el arte ASCII:

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

Todo eso, con algunas identificaciones y espacios, y un poco de ayuda para que el lector entienda el significado de los 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));
    }
}

Salida:

###         #  # #    #  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  ###  # #  
  #         #  # #    #  #    # #    #  #    #      #  #    # #  # #    #  # #    #    #    #  # #  # #  
###         #  ###    #  ###  ###  ###  ###  ###  ###  ###  ###  ###    #  ###  ###  ###  ###  ###  ###  
  #         #    #    #    #    #  #    # #    #    #    #  # #    #    #    #    #  #      #  # #    #  
###   #     #    #    #  ###  ###  ###  ###  ###  ###  ###  ###  ###    #  ###  ###  ###  ###  ###    # 
Victor Stafusa
fuente
4

C, 253 250 caracteres

Aproxima pi usando el algoritmo en el código de @ Sukminder (tomando prestado y refactorizando su código un poco descaradamente). Emite una imagen binaria PBM , que luego podría, por ejemplo, convertirse con 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);}

Así es como se ve la salida con mi renderizador PPM basado en Braille:

Captura de pantalla de salida

Tiene el mismo capricho que la respuesta de @ Sukminder, ya que carece de un separador decimal. Además, la producción mía es vertical, y si es legible para los humanos es discutible ...

Editar: se aplicaron las sugerencias de @ ugoren.

Luciérnaga
fuente
Pequeñas mejoras: pasar putsa la for inicialización, definir L[5]y omitir ,0. Haga dun parámetro para main(guardar una coma).
Ugoren
4

PHP 380

requiere gd habilitado para salida de imagen

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

ingrese la descripción de la imagen aquí

cálculo pi: dado que la base php tiene una precisión predeterminada de 14 y no quería volver a compilar el servidor con las extensiones de precisión arbitrarias habilitadas, ni siquiera pude aproximar PI con los decimales requeridos, por lo que calcula tau / 2 y luego el resto de los decimales

Como el gráfico está hecho de 0 y 1, puedo intentar usar WBMP como formato más adelante para ver si puedo eliminar gd

Einacio
fuente
esa imagen es roja sobre negro y realmente pequeña, pero al 500% puedes leerla si miras de cerca. (y no son daltónicos)
hildred
@hildred cada personaje es 3x5 with 1 px between chars. el color es rojo solo para reducir 4 caracteres, pero teniendo en cuenta que no ganaré, lo cambiaré a blanco para
facilitar la
Mi comentario no pretendía ser una crítica, sino una explicación, para alentar los votos.
hildred
¿Imagecreateindex salvaría algún personaje? ¿existe tal función?
hildred
@hildred cuando se trabaja con una imagen de paleta ( imagecreate), la primera invocación de imagecolorallocateestablece el color de fondo, y se necesita una segunda para establecer el color de escritura. así que termina más tiempo
Einacio
4

Impresora C + LaserWriter 599-10 = 589

¡Canalice la salida a su LaserWriter! :) Esto debería funcionar en una Lisa (con un compilador de C).

Calcula pien la impresora calculando la suma de las longitudes de los segmentos de línea que se aproximan a una secuencia de curva de Bezier que se aproxima a un semicírculo, dividido por el diámetro, multiplicado por 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");
}

PostScript Ungolfed Nivel-1 (compatible con 1985):

%!
/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

Salida:

ps_pi

luser droog
fuente
Supongo que también necesito hacer una fuente.
luser droog
Hmm Nunca obtendré suficientes dígitos de esta manera. PS solo tiene flotantes de 32 bits.
luser droog
buena idea, me gusta la posdata para jugar al golf.
hildred
¡Tengo una fuente de mapa de bits para los dígitos, pero el golf lo arruinará!
luser droog
2

Java, 1574 2643 1934 caracteres

Caracteres comprimidos de 1934 :

    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 recopilado de: /programming/8343977/calculate-pi-on-an-android-phone?rq=1

Clayton
fuente
Parece que usaste una constante en lugar de calcular PI.
hildred
Ese es un buen giro. Trabajando en eso ahora.
Clayton
Es posible comprimir un poco más agregando throws Exceptionen mainy retirar el bloque try-catch. Además, es posible cambiar el nombre piy sqrtlos métodos y los loc, args, SCALE, x0y x1las variables a 1 identificadores de carbonilla. Y, por cierto , debe agregar la clase completa, esto incluye la class Foo{declaración y las importaciones.
Victor Stafusa