Salida de la fuente, un bit a la vez

18

Escriba un programa o función no vacío que, cuando se llama, genera un valor único, 1 o 0, y cuando se lo llama varias veces, los números de salida producen la representación binaria del código fuente de su programa (en la misma página de códigos desde la que se compila su código /interpretado).

Por ejemplo, si su código fuente fuera abc(en ASCII), los resultados serían:

1st call:  0           // ASCII letter 'a'
2nd call:  1
3rd call:  1
4th call:  0
5th call:  0
6th call:  0
7th call:  0
8th call:  1

9th call:  0           // ASCII letter 'b'
10th call: 1
11th call: 1
12th call: 0
13th call: 0
14th call: 0
15th call: 1
16th call: 0

17th call: 0           // ASCII letter 'c'
18th call: 1
19th call: 1
20th call: 0
21st call: 0
22nd call: 0
23rd call: 1
24th call: 1

After the 24th call, the behaviour is undefined.

La representación binaria de la fuente debe contener al menos un bit 0 y un bit 1.

En lugar de 1 y 0, puede generar dos valores distintos y consistentes (como truey false).

Los programas auto modificables que generan la representación binaria de la fuente original están permitidos, siempre que no lean el código fuente para averiguar qué imprimir a continuación.

Este es el , por lo que gana la respuesta más corta en bytes.

Steadybox
fuente

Respuestas:

8

Funky , 47 41 37 bytes

Devuelve un número que representa un bit.

f=_=>1&("%b"%("f="+f)[i//8])>>7-i++%8

Esto usa el formato quine de f=_=>"f="+f. Toma el carácter en la posición ⌊i / 8⌋ , luego, obtiene el bit tomando la paridad de n >> 7-i%8dónde nestá el valor ascii del carácter actual.

Esta es una función iterativa que se incrementa icon cada llamada, una vez que está fuera del código fuente, escribirá el código para nsiempre.

Pruébalo en línea!

Un taco
fuente
¿Es este un políglota con JavaScript?
Stan Strum
9

Bash , 105 bytes

trap -- 'trap|xxd -b -c1|cut -d\  -f2|tr -d \\n|cut -c`x=\`cat f||echo 1\`;echo $((x+1))>f;echo $x`' EXIT

NOTA : Asegúrese de no tener un archivo importante llamado fen el directorio que está probando.


Si desea probar esto, puede usar el siguiente comando:

for i in $(seq 848); do bash path/to/script.sh 2> /dev/null; done | tr -d \\n

Lo que debería dar el mismo resultado xxd -c1 -b path/to/script.sh|cut -d\ -f2|tr -d \\n.

Explicación

Esto está utilizando el traptruco: llamar trapdentro de la trapacción simplemente imprime esa línea. A continuación, ese resultado se canaliza a lo xxdque lo convierte en binario (desafortunadamente xxd -bpno funciona, por lo tanto, la solución con cut& tr):

xxd -c1 -b $0|cut -d\  -f2|tr -d \\n

A partir de eso, solo estamos interesados ​​en un bit (digamos N) con el que podemos seleccionar cut -cN.

Para saber qué Nestamos usando (recuerde que esa es la parte que debe incrementarse después de cada llamada), simplemente intente configurar xel contenido del archivo fy, si no existe, configúrelo en 1:

x=`cat f||echo 1`

Lo último que debe hacer es actualizar el archivo f, escribiéndole x+1:

echo $((x+1))>f
ბიმო
fuente
7

TI-Basic (TI-83 series), 592 357 309 bytes

"123456789ABCDEF02A3132333435363738394142434445463004AA003FB958833404593FB9588338045A3F3230363FDA582B383F303FCE5A405A6B3232333F5A70BB0FAA002BBB0CAA002B5A2B313FB932BA32F01058713459713511BB0FAA002BBB0CAA002B597031377132722B31→Str1
iPart(X/4→Y
iPart(X/8→Z
206
IS>(X,8
0
If Z and Z<223
Z+inString(Str1,sub(Str1,Z,1
iPart(2fPart(2^(X-4Y-5)inString(Str1,sub(Str1,Y+17-2Ans,1

Esta tabla es una posible referencia para la representación binaria de la calculadora del código fuente, aunque finalmente utilicé el depurador de Virtual TI.

Para comparación y / o interés histórico: las primeras citas escritas en TI-Basic .

Cómo funciona

Str1almacena el código fuente (ahora en glorioso hexadecimal, ahorrando mucho espacio sobre la versión binaria anterior), dejando de lado los bits donde se representaría el contenido de Str1sí mismo.

Suponemos que el programa comienza en una calculadora cuya memoria acaba de borrarse, por lo que Xes así 0. Cada vez a través del programa, incrementamos X.

Por lo general, solo descubrimos el medio byte del que estamos tratando de extraer un poco, leerlo Str1, convertirlo de hexadecimal a binario e imprimirlo. Si estamos en la parte del código fuente que está almacenando Str1(que es dos tercios de la longitud total del programa), entonces primer movimiento de la parte correspondiente de la cadena de almacenamiento 31, 32y así sucesivamente.

Misha Lavrov
fuente
4

Java 8, 249 241 237 234 148 bytes

int i;v->{String s="int i;v->{String s=%c%s%1$c;return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}";return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}

Lo siento de antemano por las largas explicaciones. :)

  • La friolera de 89 bytes ahorrados gracias a @Nevay .

Pruébalo aquí

Explicación:

int i;                     // Index-integer on class-level
v->{                       // Method with empty unused parameter and integer return-type
  String s="int i;v->{String s=%c%s%1$c;return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}";
                           //  String containing the unformatted source code
  return s.format(s,34,s)  //    Quine to get the source code,
      .charAt(-i/8)        //     and get the character at index `-i/8`
     >>                    //    And bitwise right-shift it with:
       (--i&7)             //     `i-1` bitwise-AND 7
                           //     by first decreasing `i` by 1 with `--i`
      &1;                  //   Then bitwise-AND everything above with 1
}                          // End of method

Explicación adicional:

-parte:

  • String s contiene el código fuente sin formato
  • %s se utiliza para poner esta cadena en sí misma con s.format(...)
  • %c, %1$cy 34se utilizan para formatear las comillas dobles ( ")
  • s.format(s,34,s) lo pone todo junto

Pruébelo aquí con algunas partes eliminadas / modificadas para verificar que quine genera su propio código fuente.

:


Antigua respuesta de 233 bytes :

int i;v->{String s="int i;v->{String s=%c%s%1$c;return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%%8);}";return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%8);}

Pruébalo aquí

Explicación:

int i;                           // Index-integer on class-level
v->{                             // Method with empty unused parameter and char return-type
  String s="int i;v->{String s=%c%s%1$c;return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%%8);}";
                                 //  String containing the unformatted source code
  return Long.toString(
          (s.format(s,32,s)      //  Quine-formatting
          .charAt(i/8)           //  Take the current character
           &255)+256,2).substring(1)
                                 //  Convert it to an 8-bit binary-String 
         .charAt(i++%8);         //  And return the bit at index `i` modulo-8
                                 //  and increase index `i` by 1 afterwards with `i++`
}                                // End of method

Explicación adicional:

-parte:

Misma explicación que la anterior, con la adición de:

  • %%es la forma escapada del módulo-signo ( %)

Pruébelo aquí con algunas partes eliminadas / modificadas para verificar que quine genera su propio código fuente.

:

  • i/8se truncará automáticamente en la división de enteros, por lo que cuando ies 0-7, se convertirá 0; si ies 8-15, se convertirá 1; etc.
  • Entonces s.charAt(i/8)toma el carácter actual del código fuente, ocho veces uno después del otro. Pruébelo aquí con una versión modificada.
  • 255es 0xFFo 11111111(el valor máximo para un byte sin signo)
  • 256es 0x100o 100000000.
  • La &transmisión del carácter ASCII a un número entero. En ese punto, se encuentra entre 0y 255( 00000000a 11111111).
  • Long.toString(...,2) lo convierte a la representación de cadena binaria de 9 bits
  • +256y .substring(1)se asegurará de que haya ceros a la izquierda, y convertirá el de 9 bits a 8 bits.

Pruébelo aquí con algunas partes eliminadas / modificadas para verificar los bytes completos.

Kevin Cruijssen
fuente
1
149 bytes:int i;v->{String s="int i;v->{String s=%c%s%1$c;return 1&s.format(s,34,s).charAt(-i/8)>>(--i&7);}";return 1&s.format(s,34,s).charAt(-i/8)>>(--i&7);}
Nevay
@Nevay Enorme 88 bytes guardados. ¡Gracias! Y dado que en realidad es un enfoque bastante diferente del que tenía originalmente, conservé la respuesta anterior y agregué la nueva. (Si lo desea, lo eliminaré nuevamente y puede publicarlo usted mismo, pero en el pasado me dijo que prefería jugar al golf, principalmente el mío XD - en lugar de publicar su propia respuesta, ¿verdad?)
Kevin Cruijssen
2

Javascript ES6, 73 58 52 bytes

o=_=>`o=${o}`.charCodeAt((o.n=1+o.n|0)/8)>>(7-o.n%8)&1

Explicación

Desglose del código:

  • o=_=>: define una función.
  • `o=${o}`: construye una cadena; ose convierte en una cadena, que en este caso es el código fuente de la función.
  • .charCodeAt(: obtiene un carácter en la cadena como su código de carácter ASCII.
  • (o.n=1+o.n|0)/8: selecciona un personaje. Aquí también es donde se incrementa el contador.
  • )>>(7-o.n%8): cambia el código de caracteres resultante para que el bit deseado esté en la posición correcta.
  • &1: establece todos los demás bits a 0.
RamenChef
fuente
Puede acortar esto con una lambda eno=_=>(o+'').charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco
Esto cuenta como definir una función.
ATaco
1
Pruebao=_=>('o='+o).charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco
En lugar de 'n'in top?++n:n=0que puede utilizar ++n||(n=0)o ++n?n:n=0, o n=++n||0, o n=1+n||0la que todos utilizar el falsiness de NaNque se produce mediante el incrementoundefined
Bergi
1
o=_=>('o='+o).charCodeAt((o.n=1+o.n|0)/8)>>(~o.n&7)&1
tsh
2

q / kdb + , 45 bytes

Solución:

a:-1;f:{((,/)0b vs'4h$"a:-1;f:",($).z.s)a+:1}

Ejemplo:

q)f[] / call function f with no parameters
0b   
q)f[]
1b   
q)f[]
1b   
q)f[]
0b   
q)f[]
0b   
q)f[]
0b   
q)f[]
0b   
q)f[]
1b   
q)f[]  
q)"c"$0b sv 01100001b / join back to a byte and cast to a character
"a"

Explicación:

Yo creo que entendí el breve.

Primero configure una variable global acon un valor inicial de -1. La función fconstruye la representación binaria de la representación de cadena de la función (todo incluido el {}) antepuesto con la a:-1;f:basura, e indexa en esta lista binaria en el índice a (que se incrementa en cada llamada).

a:-1;f:{(raze 0b vs'4h$"a:-1;f:",string .z.s)a+:1} / ungolfed solution
a:-1;                                              / stick -1 in variable a
     f:{                                         } / define function f
                                             a+:1  / increment a by 1 (:: is required as a is a global variable), indexes into the left
        (                                   )      / do all this together
                                 string .z.s       / z.s is the function, string converts it to a string
                       "a:-1;f:",                  / prepend "a:-1;f:" to the start
                    4h$                            / cast to bytes
              0b vs'                               / convert each byte to binary
         raze                                      / flatten binary into long list
callejero
fuente
2

Python 2 , 164 bytes

lambda s='lambda s=%r,i=[]:i.append(1)or"{:08b}".format(ord((s%%s)[~-len(i)/8]))[~-len(i)%%8]',i=[]:i.append(1)or"{:08b}".format(ord((s%s)[~-len(i)/8]))[~-len(i)%8]

Pruébalo en línea!

Explicación

Comencemos con una quine estándar de Python 2.

s = '...'; print s % s

Bien, bueno, esto lo genera así. ¡Necesitamos binario!

s = '...'; print "\n".join("\n".join("{:08b}".format(ord(i))) for i in s % s)

Correcto, eso simplemente convierte todo a binario. Pero el título dice "un poco a la vez". Necesitamos algo para persistir a través de múltiples ejecuciones. Lo sé, ¡hagámoslo una función!

lambda s = '...': "\n".join("\n".join("{:08b}".format(ord(i))) for i in s % s)

Espera, eso no ayuda ... Hmm, ¿cómo podemos hacer un seguimiento del índice del bit necesario para la salida? Ooh, ooh, tengamos un número entero para hacer un seguimiento.

lambda s = '...', i = 0: "{:08b}".format(ord((s % s)[i / 8]))[i % 8]

Um ... eso siempre genera el primer bit. ¡Oh, necesitamos incrementar el rastreador! Oh, mierda, Python no permite que se modifiquen los enteros como argumentos predeterminados. Y las asignaciones no son expresiones en Python, por lo que no puedes hacer eso en una lambda. Welp, esto es imposible en Python, caso cerrado.

... Bueno, no del todo. Python hace permitir que las listas como argumentos por defecto a ser modificados. (Y muerde a los programadores de Python todo el tiempo.) ¡Usemos su longitud!

lambda s = '...', i = []: "{:08b}".format(ord((s % s)[len(i) / 8]))[len(i) % 8]

Sin embargo, eso todavía no modifica el rastreador ... Podemos agregarle algo para aumentar su longitud ... ¿Pero cómo? Ah, bueno, lo tenemos list.append. lst.append(1)es equivalente a lst += [1]. ¡Excelente!

lambda s = '...', i = []: i.append(1) and "{:08b}".format(ord((s % s)[len(i) / 8]))[len(i) % 8]

Vaya, esto omite el primer bit porque la longitud del rastreador es 1 antes de que salga el bit. Necesitamos disminuir la longitud donde se usa.

lambda s = '...', i = []: i.append(1) and "{:08b}".format(ord((s % s)[(len(i) - 1) / 8]))[(len(i) - 1) % 8]

¡Ahí está, amigos! ¡Golf y tienes mi solución!

totalmente humano
fuente