Emette l'origine, un bit alla volta


18

Scrivi un programma o una funzione non vuota che quando chiamato genera un singolo valore, 1 o 0, e quando chiamato più volte, i numeri di output producono la rappresentazione binaria del codice sorgente del programma (nella stessa tabella codici da cui viene compilato il codice /interpretato).

Ad esempio, se il codice sorgente fosse abc(in ASCII), gli output sarebbero:

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 rappresentazione binaria della sorgente deve contenere almeno uno 0 bit e un 1 bit.

Invece di 1 e 0, è possibile generare due valori distinti e coerenti (come truee false).

Sono consentiti programmi di modifica automatica che producono la rappresentazione binaria della fonte originale, a condizione che non leggano il codice sorgente per scoprire cosa stampare dopo.

Questo è , quindi vince la risposta più breve in byte.

Risposte:


8

Funky , 47 41 37 byte

Restituisce un numero che rappresenta un bit.

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

Questo utilizza il formato Quine di f=_=>"f="+f. Prende il personaggio nella posizione ⌊i / 8⌋ , quindi ottiene il bit prendendo la coppia di n >> 7-i%8dove nè il valore ASCII del carattere corrente.

Questa è una funzione iterativa che aumenta icon ogni chiamata, una volta che è fuori dal codice sorgente, scriverà il codice per nsempre.

Provalo online!


È un poliglotta con JavaScript?
Stan Strum,

9

Bash , 105 byte

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 : assicurati di non avere un file importante chiamato fnella directory che stai testando.


Se vuoi testarlo, puoi usare il seguente comando:

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

Che dovrebbe dare lo stesso risultato xxd -c1 -b path/to/script.sh|cut -d\ -f2|tr -d \\n.

Spiegazione

Questo sta usando il traptrucco: chiamare trapall'interno trapdell'azione stampa semplicemente quella linea. Successivamente l'output viene reindirizzato in xxdcui lo converte in binario (purtroppo xxd -bpnon funziona, quindi la soluzione alternativa con cut& tr):

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

Da ciò ci interessa solo un bit (diciamo N) con cui possiamo selezionare cut -cN.

Per scoprire cosa Nstiamo usando (ricorda che è la parte che deve essere incrementata dopo ogni chiamata), prova semplicemente a impostare xil contenuto del file fe se non esiste impostalo su 1:

x=`cat f||echo 1`

L'ultima cosa da fare è aggiornare il file fscrivendolo x+1:

echo $((x+1))>f

7

TI-Basic (serie TI-83), 592 357 309 byte

"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

Questa tabella è un possibile riferimento per la rappresentazione binaria del codice sorgente della calcolatrice, anche se alla fine ho appena usato il debugger di Virtual TI.

Per confronto e / o interesse storico: i primi quines scritti in TI-Basic .

Come funziona

Str1memorizza il codice sorgente (ora in glorioso esadecimale, risparmiando molto spazio rispetto alla precedente versione binaria), tralasciando i bit in cui Str1sarebbe rappresentato il contenuto stesso.

Partiamo dal presupposto che il programma inizia su una calcolatrice la cui memoria è stata appena cancellata, così Xè 0. Ogni volta che attraverso il programma, incrementiamo X.

Di solito, scopriamo solo il mezzo byte dal quale stiamo provando a estrarre un po ', a leggerlo Str1, a convertirlo da esadecimale a binario e a stamparlo. Se siamo sulla parte del codice sorgente che sta memorizzando Str1(che è due terzi della lunghezza totale del programma), allora prima mossa per la parte corrispondente della stringa memorizzazione 31, 32e così via.


4

Java 8, 249 241 237 234 148 byte

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

Scusa in anticipo per le lunghe spiegazioni. :)

  • Whopping 89 byte salvati grazie a @Nevay .

Provalo qui.

Spiegazione:

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

Spiegazione aggiuntiva:

parte:

  • String s contiene il codice sorgente non formattato
  • %s è usato per mettere questa stringa in sé con s.format(...)
  • %c, %1$cE 34vengono utilizzati per formattare le virgolette ( ")
  • s.format(s,34,s) mette tutto insieme

Provalo qui con alcune parti rimosse / modificate per verificare che l'output sia il proprio codice sorgente.

:


233 byte vecchi rispondono:

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

Provalo qui.

Spiegazione:

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

Spiegazione aggiuntiva:

parte:

Stessa spiegazione di cui sopra, con l'aggiunta di:

  • %%è la forma di escape del modulo-sign ( %)

Provalo qui con alcune parti rimosse / modificate per verificare che l'output sia il proprio codice sorgente.

:

  • i/8troncerà automaticamente sulla divisione intera, quindi quando iè 0-7, diventerà 0; se iè 8-15, diventerà 1; eccetera.
  • Quindi s.charAt(i/8)prende l'attuale carattere del codice sorgente, otto volte uno dopo l'altro. Provalo qui con una versione modificata.
  • 255è 0xFFo 11111111(il valore massimo per un byte senza segno)
  • 256è 0x100o 100000000.
  • Il &upcasts il carattere ASCII a un numero intero. A quel punto, è ovunque tra 0e 255( 00000000a 11111111).
  • Long.toString(...,2) lo converte nella rappresentazione String binaria a 9 bit
  • +256e .substring(1)assicurerà la presenza di zero iniziali e convertirà i 9 bit in 8 bit.

Provalo qui con alcune parti rimosse / modificate per verificare l'intero byte.


1
149 byte: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 Whopping 88 byte salvati. Grazie! E dal momento che in realtà è un approccio un po 'diverso rispetto a quello che avevo originariamente, ho mantenuto la vecchia risposta e ho aggiunto il nuovo. (Se vuoi lo rimuoverò di nuovo e puoi pubblicarlo tu stesso, ma in passato mi hai detto che preferisci giocare a golf ad altre persone - principalmente il mio XD - invece di pubblicare la tua risposta, giusto?)
Kevin Cruijssen

2

Javascript ES6, 73 58 52 byte

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

Spiegazione

Analisi del codice:

  • o=_=>: definisce una funzione.
  • `o=${o}`: costruisce una stringa; oviene convertito in una stringa, che in questo caso è il codice sorgente della funzione.
  • .charCodeAt(: ottiene un carattere nella stringa come suo codice di carattere ASCII.
  • (o.n=1+o.n|0)/8: seleziona un personaggio. Questo è anche il punto in cui il contatore viene incrementato.
  • )>>(7-o.n%8): sposta il codice carattere risultante in modo che il bit desiderato sia nella posizione corretta.
  • &1: imposta tutti gli altri bit su 0.

Puoi accorciarlo con un lambda ino=_=>(o+'').charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco,

Questo conta come definire una funzione.
ATaco,

1
Provao=_=>('o='+o).charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco,

Invece di 'n'in top?++n:n=0te puoi usare ++n||(n=0)o ++n?n:n=0o n=++n||0o n=1+n||0che tutti utilizzano la falsità di NaNciò che viene prodotto incrementandoundefined
Bergi,

1
o=_=>('o='+o).charCodeAt((o.n=1+o.n|0)/8)>>(~o.n&7)&1
TSH

2

q / kdb + , 45 byte

Soluzione:

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

Esempio:

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"

Spiegazione:

Io penso che ho capito la breve.

Innanzitutto imposta una variabile globale acon valore iniziale di -1. La funzione fcrea la rappresentazione binaria della rappresentazione in formato stringa della funzione (tutto compreso il {}) anteposto alla a:-1;f:posta indesiderata e indicizza in questo elenco binario all'indice a (che viene incrementato ad ogni chiamata).

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

2

Python 2 , 164 byte

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]

Provalo online!

Spiegazione

Iniziamo con un quine standard di Python 2.

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

Va bene, questo lo emette proprio così. Abbiamo bisogno del binario!

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

Bene, questo converte tutto in binario. Ma il titolo dice "un po 'alla volta". Abbiamo bisogno di qualcosa per persistere attraverso più corse. Lo so, facciamolo funzione!

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

Aspetta, questo non aiuta ... Hmm, come possiamo tenere traccia dell'indice del bit necessario per essere emesso? Ooh, ooh, facciamo un numero intero per tenere traccia.

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

Um ... che emette sempre il primo bit. Oh, dobbiamo incrementare il tracker! Oh merda, Python non consente di modificare numeri interi come argomenti predefiniti. E i compiti non sono espressioni in Python, quindi non puoi farlo in una lambda. Welp, questo è impossibile in Python, caso chiuso.

... Beh, non proprio. Python fa permettere liste come argomenti predefiniti da modificare. (E morde continuamente i programmatori Python.) Usiamo la sua lunghezza!

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

Questo comunque non modifica il tracker ... Possiamo aggiungere qualcosa per aumentarne la lunghezza ... Ma come? Ah, beh, abbiamo list.append. lst.append(1)è equivalente a lst += [1]. Grande!

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

Spiacenti, questo salta il primo bit perché la lunghezza del tracker è 1 prima che il bit venga emesso. Dobbiamo ridurre la lunghezza in cui viene utilizzata.

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

Eccolo, gente! Golf e hai la mia soluzione!


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.