Saída da fonte, um bit de cada vez

18

Escreva um programa ou função não vazio que, quando chamado, gera um único valor, 1 ou 0, e quando chamado várias vezes, os números de saída produzem a representação binária do código-fonte do seu programa (na mesma página de código da qual seu código é compilado / interpretado).

Por exemplo, se seu código-fonte fosse abc(em ASCII), as saídas seriam:

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.

A representação binária da fonte deve conter pelo menos um bit 0 e um bit 1.

Em vez de 1 e 0, você pode gerar dois valores consistentes e distintos (como truee false).

Os programas de modificação automática que emitem a representação binária da fonte original são permitidos, desde que eles não leiam o código-fonte para descobrir o que imprimir a seguir.

Isso é , então a resposta mais curta em bytes vence.

Steadybox
fonte

Respostas:

8

Funky , 47 41 37 bytes

Retorna um número que representa um pouco.

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

Isso usa o formato quine de f=_=>"f="+f. Ele pega o caractere na posição ⌊i / 8⌋ e , em seguida, pega o bit levando a paridade de n >> 7-i%8onde nestá o valor ascii do caractere atual.

Essa é uma função iterativa que aumenta ia cada chamada, uma vez que está fora do código-fonte, ele escreverá o código para nsempre.

Experimente online!

ATaco
fonte
Isso é poliglota com 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 : Verifique se você não possui um arquivo importante chamado fno diretório em que está testando isso.


Se você quiser testar isso, poderá usar o seguinte comando:

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

Qual deve dar a mesma saída xxd -c1 -b path/to/script.sh|cut -d\ -f2|tr -d \\n.

Explicação

Isso é usar o traptruque - chamar trapdentro da trapação simplesmente imprime essa linha. Em seguida, essa saída é canalizada para a xxdqual a converte em binária (infelizmente xxd -bpnão funciona - portanto, a solução alternativa para cut& tr):

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

A partir disso, estamos interessados ​​apenas em um bit (digamos N) com o qual podemos selecionar cut -cN.

Para descobrir o Nque estamos usando (lembre-se de que é a parte que precisa ser incrementada após cada chamada), tente definir xo conteúdo do arquivo fe, se ele não existir, defina-o como 1:

x=`cat f||echo 1`

A última coisa a fazer é atualizar o arquivo f- escrevendo x+1nele:

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

TI-Basic (série TI-83), 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 tabela é uma referência possível para a representação binária do código fonte da calculadora, embora, no final das contas, eu apenas tenha usado o depurador da TI virtual.

Para comparação e / ou interesse histórico: os primeiros quines escritos em TI-Basic .

Como funciona

Str1armazena o código fonte (agora em glorioso hexadecimal, economizando muito espaço em relação à versão binária anterior), deixando de fora os bits onde o conteúdo em Str1si seria representado.

Estamos assumindo que o programa inicia em uma calculadora cuja memória acabou de ser limpa, o mesmo Xocorre 0. Sempre que o programa é incrementado X.

Geralmente, apenas descobrimos o meio byte do qual estamos tentando extrair um pouco, lemos Str1, convertemos de hexadecimal em binário e imprimi-lo. Se estamos na parte do código-fonte que está armazenando Str1(que é dois terços do comprimento total do programa), então primeiro passo para a parte correspondente da cadeia de armazenamento 31, 32e assim por diante.

Misha Lavrov
fonte
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;}

Desculpe desde já pelas longas explicações. :)

  • Gritante 89 bytes salvos graças ao @Nevay .

Experimente aqui.

Explicação:

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

Explicação adicional:

-part:

  • String s contém o código fonte não formatado
  • %s é usado para colocar essa String em si mesma com s.format(...)
  • %c, %1$cE 34são usados para formatar as aspas duplas ( ")
  • s.format(s,34,s) coloca tudo junto

Experimente aqui com algumas partes removidas / modificadas para verificar as saídas quine do seu próprio código-fonte.

parte :


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

Experimente aqui.

Explicação:

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

Explicação adicional:

-part:

A mesma explicação acima, com a adição de:

  • %%é a forma de escape do sinal do módulo ( %)

Experimente aqui com algumas partes removidas / modificadas para verificar as saídas quine do seu próprio código-fonte.

parte :

  • i/8truncará automaticamente na divisão inteira; portanto, quando ifor 0-7, ele se tornará 0; se ié 8-15, ele se tornará 1; etc.
  • O mesmo s.charAt(i/8)ocorre com o caráter atual do código-fonte, oito vezes um após o outro. Experimente aqui com uma versão modificada.
  • 255é 0xFFou 11111111(o valor máximo para um byte não assinado)
  • 256é 0x100ou 100000000.
  • O &upcasts o caractere ASCII para um número inteiro. Nesse ponto, está em qualquer lugar entre 0e 255( 00000000para 11111111).
  • Long.toString(...,2) converte-o na representação String binária de 9 bits
  • +256e .substring(1)garantirá que haja zeros à esquerda e converterá os 9 bits em 8 bits.

Experimente aqui com algumas partes removidas / modificadas para verificar os bytes inteiros.

Kevin Cruijssen
fonte
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 26/10
@Nevay Whopping 88 bytes salvos. Obrigado! E, como é realmente uma abordagem um pouco diferente da que eu originalmente, mantive a resposta antiga e adicionei a nova. (Se você quiser, eu o removerei novamente e você poderá publicá-lo, mas você me disse no passado que prefere jogar golfe no código de outras pessoas - principalmente o meu XD - em vez de postar sua própria resposta, certo?)
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

Explicação

Repartição do código:

  • o=_=>: define uma função.
  • `o=${o}`: constrói uma string; oé convertido em uma string, que nesse caso é o código fonte da função.
  • .charCodeAt(: obtém um caractere na string como seu código de caractere ASCII.
  • (o.n=1+o.n|0)/8: selecione um caractere. Também é aqui que o contador é incrementado.
  • )>>(7-o.n%8): desloque o código de caractere resultante para que o bit desejado esteja na posição correta.
  • &1: defina todos os outros bits para 0.
RamenChef
fonte
Você pode encurtar isso com um lambda parao=_=>(o+'').charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco 25/10
Isso conta como definindo uma função.
ATaco 25/10
1
Tenteo=_=>('o='+o).charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco 25/10
Em vez de 'n'in top?++n:n=0você pode usar ++n||(n=0)ou ++n?n:n=0ou n=++n||0ou n=1+n||0que todos utilizam o falsiness do NaNque é produzido pelo incrementoundefined
Bergi
1
o=_=>('o='+o).charCodeAt((o.n=1+o.n|0)/8)>>(~o.n&7)&1
tsh 26/10
2

q / kdb + , 45 bytes

Solução:

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

Exemplo:

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"

Explicação:

Eu acho que entendi o breve.

Primeiro configure uma variável global acom o valor inicial de -1. A função fcria a representação binária da representação em cadeia da função (tudo incluindo o {}) precedido pelo a:-1;f:lixo eletrônico e indexa nessa lista binária no índice a (que é incrementado a cada chamada).

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
rua
fonte
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]

Experimente online!

Explicação

Vamos começar com um quine padrão do Python 2.

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

Ok, bem, isso gera exatamente assim. Nós precisamos de binário!

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

Certo, isso apenas converte tudo em binário. Mas o título diz "um pouco de cada vez". Precisamos de algo para persistir através de várias execuções. Eu sei, vamos fazer disso uma função!

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

Espere, isso não ajuda ... Hmm, como podemos acompanhar o índice do bit necessário para a saída? Ooh, ooh, vamos ter um número inteiro para acompanhar.

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

Um ... que sempre gera o primeiro bit. Ah, precisamos incrementar o rastreador! Oh droga, Python não permite que números inteiros como argumentos padrão sejam modificados. E as atribuições não são expressões em Python, então você não pode fazer isso em uma lambda. Welp, isso é impossível em Python, caso encerrado.

... Bem, não exatamente. O Python permite que listas como argumentos padrão sejam modificadas. (E ele morde os programadores Python o tempo todo.) Vamos usar seu comprimento!

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

Isso ainda não modifica o rastreador ... Podemos acrescentar algo a ele para aumentar seu tamanho ... Mas como? Ah, bem, nós temos list.append. lst.append(1)é equivalente a lst += [1]. Ótimo!

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

Opa, isso pula o primeiro bit porque o comprimento do rastreador é 1 antes da saída do bit. Precisamos diminuir o comprimento em que é usado.

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

Aí está pessoal! Golf e você tem a minha solução!

totalmente humano
fonte
2

Perl 5 , 59 bytes

sub{$_=q{unpack(B.++$-,"sub{\$_=q{$_};eval}")=~/.$/g};eval}

Experimente online!

Dom Hastings
fonte