Wyjście źródła, jeden bit na raz

18

Napisz niepusty program lub funkcję, która po wywołaniu generuje pojedynczą wartość 1 lub 0, a po wielokrotnym wywołaniu liczby wyjściowe tworzą binarną reprezentację kodu źródłowego programu (na tej samej stronie kodowej, z której skompilowany jest kod / interpretowane).

Na przykład, jeśli kod źródłowy to abc(w ASCII), dane wyjściowe byłyby:

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.

Binarna reprezentacja źródła musi zawierać co najmniej jeden bit 0 i jeden 1 bit.

Zamiast 1 i 0 można wygenerować dowolne dwie różne, spójne wartości (takie jak truei false).

Dozwolone są programy samomodyfikujące, które generują binarną reprezentację oryginalnego źródła, pod warunkiem, że nie czytają kodu źródłowego, aby dowiedzieć się, co wydrukować w następnej kolejności.

To jest , więc wygrywa najkrótsza odpowiedź w bajtach.

Steadybox
źródło

Odpowiedzi:

8

Funky , 47 41 37 bajtów

Zwraca liczbę reprezentującą bit.

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

To używa formatu quine f=_=>"f="+f. Przyjmuje postać w pozycji ⌊i / 8⌋ , a następnie dostaje bit, biorąc parzystość n >> 7-i%8gdzie njest wartością ascii bieżącego znaku.

Jest to funkcja iteracyjna, która zwiększa się iz każdym wywołaniem, gdy tylko skończy się kod źródłowy, zapisze kod na nzawsze.

Wypróbuj online!

ATaco
źródło
Czy to jest poliglota z JavaScriptem?
Stan Strum
9

Bash , 105 bajtów

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

UWAGA : Upewnij się, że nie ma ważnego pliku o nazwie fw katalogu, który to testujesz.


Jeśli chcesz to przetestować, możesz użyć następującego polecenia:

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

Co powinno dać taką samą wydajność xxd -c1 -b path/to/script.sh|cut -d\ -f2|tr -d \\n.

Wyjaśnienie

Korzysta z tej trapsztuczki - wywołanie trapw trapakcji po prostu wypisuje tę linię. Następnie dane wyjściowe są przesyłane potokowo, do xxdktórego konwertuje je na binarne (niestety xxd -bpnie działa - dlatego obejście z cut& tr):

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

Od tego interesuje nas tylko jeden bit (powiedzmy N), który możemy wybrać cut -cN.

Aby dowiedzieć się N, z czego korzystamy (pamiętaj, że jest to część, którą należy zwiększyć po każdym wywołaniu), po prostu spróbuj ustawić xzawartość pliku, fa jeśli nie istnieje, ustaw go na 1:

x=`cat f||echo 1`

Ostatnią rzeczą do zrobienia jest aktualizacja pliku f- napisanie x+1do niego:

echo $((x+1))>f
ბიმო
źródło
7

TI-Basic (seria TI-83), 592 357 309 bajtów

"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

Ta tabela jest możliwym odniesieniem do binarnej reprezentacji kalkulatora kodu źródłowego, chociaż ostatecznie użyłem debuggera Virtual TI.

Dla porównania i / lub zainteresowania historycznego: pierwsze quiny napisane w TI-Basic .

Jak to działa

Str1przechowuje kod źródłowy (teraz w chwalebnym systemie szesnastkowym, oszczędzając dużo miejsca w stosunku do poprzedniej wersji binarnej), pomijając bity, w których treść Str1byłaby reprezentowana.

Zakładamy, że program uruchamia się na kalkulatorze, którego pamięć została właśnie wyczyszczone, tak Xjest 0. Za każdym razem poprzez program zwiększamy X.

Zwykle po prostu wymyślamy pół bajta, z którego próbujemy trochę wydobyć, odczytać Str1, przekonwertować z szesnastkowego na binarny i wydrukować. Jeśli jesteśmy na części kodu źródłowego, który jest przechowującej Str1(czyli dwie trzecie całkowitej długości programu), to pierwszy ruch do odpowiedniej części łańcucha przechowywania 31, 32i tak dalej.

Misza Ławrow
źródło
4

Java 8, 249 241 237 234 148 bajtów

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

Z góry przepraszam za długie wyjaśnienia. :)

  • Oszczędność 89 bajtów dzięki @Nevay .

Wypróbuj tutaj.

Wyjaśnienie:

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

Dodatkowe wyjaśnienie:

-part:

  • String s zawiera niesformatowany kod źródłowy
  • %s służy do umieszczenia tego ciągu w sobie s.format(...)
  • %c, %1$cI 34są wykorzystywane do formatowania cudzysłowia ( ")
  • s.format(s,34,s) łączy to wszystko

Wypróbuj to tutaj, gdy niektóre części zostały usunięte / zmodyfikowane, aby zweryfikować, że wyjście Quine'a ma własny kod źródłowy.

:


Odpowiedź na stare 233 bajty :

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

Wypróbuj tutaj.

Wyjaśnienie:

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

Dodatkowe wyjaśnienie:

-part:

To samo wyjaśnienie, co powyżej, z dodatkiem:

  • %%jest ucieczką postaci znaku modulo ( %)

Wypróbuj to tutaj, gdy niektóre części zostały usunięte / zmodyfikowane, aby zweryfikować, że wyjście Quine'a ma własny kod źródłowy.

:

  • i/8będzie automatycznie obcinany przy dzieleniu liczb całkowitych, więc gdy iwynosi 0-7, stanie się 0; jeśli ijest 8-15, stanie się 1; itp.
  • s.charAt(i/8)Bierze więc bieżący znak kodu źródłowego, osiem razy po sobie. Wypróbuj tutaj ze zmodyfikowaną wersją.
  • 255to 0xFFlub 11111111(maksymalna wartość dla bajtu bez znaku)
  • 256jest 0x100lub 100000000.
  • &Upcasts ASCII-znakowy do liczby całkowitej. W tym momencie jest to gdzieś pomiędzy 0i 255( 00000000do 11111111).
  • Long.toString(...,2) konwertuje go na 9-bitową reprezentację ciągu binarnego
  • +256i .substring(1)upewni się, że są wiodące zera, i przekonwertuje 9-bit na 8-bit.

Wypróbuj tutaj, gdy niektóre części zostały usunięte / zmodyfikowane, aby zweryfikować całe bajty.

Kevin Cruijssen
źródło
1
149 bajtów: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 Oszczędność 88 bajtów zapisanych. Dzięki! A ponieważ jest to trochę inne podejście niż pierwotnie, zachowałem starą odpowiedź i dodałem nową. (Jeśli chcesz, usunę go ponownie i sam możesz go opublikować, ale w przeszłości powiedziałeś mi, że wolisz grać w golfa innych ludzi - głównie mój kod XD zamiast publikować własną odpowiedź, prawda?)
Kevin Cruijssen
2

JavaScript ES6, 73 58 52 bajtów

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

Wyjaśnienie

Podział kodu:

  • o=_=>: zdefiniuj funkcję.
  • `o=${o}`: skonstruuj ciąg; ojest konwertowany na ciąg znaków, który w tym przypadku jest kodem źródłowym funkcji.
  • .charCodeAt(: pobierz znak w ciągu jako kod znaku ASCII.
  • (o.n=1+o.n|0)/8: wybierz postać. Jest to również miejsce, w którym licznik jest zwiększany.
  • )>>(7-o.n%8): przesuń wynikowy kod znaku, aby żądany bit znalazł się we właściwej pozycji.
  • &1: ustaw wszystkie inne bity na 0.
RamenChef
źródło
Możesz to skrócić za pomocą lambda doo=_=>(o+'').charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco
Jest to liczone jako definiowanie funkcji.
ATaco
1
Spróbujo=_=>('o='+o).charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco,
Zamiast 'n'in top?++n:n=0można użyć ++n||(n=0)lub ++n?n:n=0lub n=++n||0lub n=1+n||0które wykorzystują falsiness z NaNktóry jest produkowany przez inkrementacjiundefined
BERGI
1
o=_=>('o='+o).charCodeAt((o.n=1+o.n|0)/8)>>(~o.n&7)&1
tsh
2

q / kdb + , 45 bajtów

Rozwiązanie:

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

Przykład:

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"

Wyjaśnienie:

Myślę , że zrozumiałem krótki opis.

Najpierw ustaw zmienną globalną ao wartości początkowej wynoszącej -1. Funkcja fbuduje binarną reprezentację ciągu reprezentującego funkcję (wszystko łącznie z {}) poprzedzoną a:-1;f:śmieciami i indeksuje do tej listy binarnej o indeksie a (który jest zwiększany przy każdym wywołaniu).

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
streetster
źródło
2

Python 2 , 164 bajty

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]

Wypróbuj online!

Wyjaśnienie

Zacznijmy od standardowej quine Python 2.

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

Okej, cóż, tak to wygląda. Potrzebujemy pliku binarnego!

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

Racja, to wszystko konwertuje wszystko na binarne. Ale tytuł mówi „po trochu”. Potrzebujemy czegoś, aby przetrwać przez wiele przebiegów. Wiem, zróbmy to funkcją!

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

Czekaj, to nie pomaga ... Hmm, w jaki sposób możemy śledzić indeks bitu potrzebnego do wyjścia? Ooh, ooh, miejmy liczbę całkowitą do śledzenia.

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

Um ... to zawsze wyprowadza pierwszy bit. Och, musimy zwiększyć moduł śledzący! O cholera, Python nie pozwala na modyfikowanie liczb całkowitych jako domyślnych argumentów. A przypisania nie są wyrażeniami w Pythonie, więc nie możesz tego zrobić w lambda. Welp, w Pythonie jest to niemożliwe, sprawa zamknięta.

... Niezupełnie. Python nie pozwalają list jako domyślne argumenty mają być modyfikowane. (I cały czas gryzie programistów Pythona.) Wykorzystajmy jego długość!

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

To wciąż nie modyfikuje modułu śledzącego ... Możemy do niego dołączyć, aby zwiększyć jego długość ... Ale jak? Ach, cóż, mamy list.append. lst.append(1)jest równoważne z lst += [1]. Świetny!

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

Ups, pomija to pierwszy bit, ponieważ długość modułu śledzącego wynosi 1 przed wysłaniem bitu. Musimy zmniejszyć długość, w której jest używany.

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

Oto ludzie! Zagraj w golfa i masz moje rozwiązanie!

całkowicie ludzki
źródło
2

Perl 5 , 59 bajtów

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

Wypróbuj online!

Dom Hastings
źródło