Quine wyprowadza się w postaci binarnej


10

Twoim zadaniem, jeśli chcesz to zaakceptować, jest napisanie programu, który wyświetli własny kod źródłowy w binarnej reprezentacji UTF-8 .

Zasady

  • Źródło musi mieć co najmniej 1 bajt.

  • Twój program nie może przyjmować danych wejściowych (lub mieć nieużywane, puste dane wejściowe).

  • Dane wyjściowe mogą być w dowolnym dogodnym formacie.

  • Opcjonalny końcowy znak nowej linii jest dozwolony.

  • Zauważ, że jeden bajt ma 8 bitów, a długość binarnej reprezentacji UTF-8 jest koniecznie wielokrotnością 8.

  • To jest więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).

  • Standardowe luki są zabronione.

Przykład

Powiedzmy, że twój kod źródłowy to Aä$$€hodpowiadająca mu reprezentacja binarna UTF-8 010000011100001110100100001001000010010011100010100000101010110001101000.

Jeśli uruchomię, Aä$$€hwyjście musi być 010000011100001110100100001001000010010011100010100000101010110001101000.

A      --> 01000001
ä      --> 1100001110100100
$      --> 00100100
$      --> 00100100
€      --> 111000101000001010101100
h      --> 01101000
Aä$$€h --> 010000011100001110100100001001000010010011100010100000101010110001101000

Łańcuch na binarne konwertery UTF-8


1
Przez „binarny” rozumiesz ciąg reprezentujący wartości binarne, tzn. Ciąg składający się tylko z 1 i 0?

1
@mdahmoune Teraz jest już znacznie lepiej. Pozostaje pytanie, jak przedstawić coś jako UTF-8. Zauważ, że reprezentacja Unicode opiera się głównie na wyglądzie znaku (tylko sporadycznie na znaczeniu semantycznym). Co jeśli żaden przypisany glif Unicode nie wygląda jak znak w kodzie źródłowym? Unicode ma również wiele podobnych wyglądów (homoglyphów). Jak decydować, którego użyć? Np. Dyalog APL ma funkcję AND, która może być zakodowana jako 01011110lub 0010011100100010w UTF-8 (wyglądają dość podobnie: ^vs )
Adám

1
Lepszy przykład: 01111100i 0010001100100010koduj |i .
Adám

4
@ Adám Myślę, że sprawiedliwym byłoby wypisanie dowolnej sekwencji binarnej odpowiadającej symbolowi, który skompiluje się / uruchomi w określonej implementacji języka.
qwr

1
Co powiesz na kod maszynowy? (Commodore C64 zajmuje 28 bajtów, zakładając, że sam kod maszynowy jest „źródłem”)
Martin Rosenau

Odpowiedzi:


7

V , 28 (lub 16?) Latin 1 bajtów (35 UTF-8 bajtów)

ñéÑ~"qpx!!xxd -b
ÎdW54|D
Íßó

Wypróbuj online!

Hexdump (po łacinie 1):

00000000: f1e9 d17e 2271 7078 2121 7878 6420 2d62  ...~"qpx!!xxd -b
00000010: 0ace 6457 3534 7c44 0acd dff3            ..dW54|D....

Dane wyjściowe (binarna reprezentacja tego samego kodu w UTF-8, a nie Latin 1):

110000111011000111000011101010011100001110010001011111100010001001110001011100000111100000100001001000010111100001111000011001000010000000101101011000100000110111000011100011100110010001010111001101010011010001111100010001000000110111000011100011011100001110011111110000111011001100001010

Wyjaśnienie:

ñéÑ~"qpx            " Standard quine. Anything after this doesn't affect the
                    " program's 'quine-ness' unless it modifies text in the buffer
        !!xxd -b    " Run xxd in binary mode on the text
Î                   " On every line...
 dW                 "   delete a WORD
   54|              "   Go to the 54'th character on this line
      D             "   And delete everything after the cursor
Í                   " Remove on every line...
  ó                 "   Any whitespace
 ß                  "   Including newlines

Lub...

V , 16 bajtów

ñéÑ~"qpx!!xxd -b

Wypróbuj online!

Wynik:

00000000: 11000011 10110001 11000011 10101001 11000011 10010001  ......
00000006: 01111110 00100010 01110001 01110000 01111000 00100001  ~"qpx!
0000000c: 00100001 01111000 01111000 01100100 00100000 00101101  !xxd -
00000012: 01100010 00001010                                      b.

OP powiedział:

Dane wyjściowe mogą być w dowolnym dogodnym formacie.

Dane wyjściowe są w znacznie wygodniejszym formacie dla V: P (ale nie jestem pewien, czy to rozszerza reguły)



4

05AB1E , 105 bajtów

0"D34çýÇbεDg•Xó•18в@ƶà©i7j0ìëR6ôRíć7®-jšTìJ1®<×ì]ð0:J"D34çýÇbεDg•Xó•18в@ƶà©i7j0ìëR6ôRíć7®-jšTìJ1®<×ì]ð0:J

05AB1E nie ma wbudowanych funkcji konwersji UTF-8, więc muszę zrobić wszystko ręcznie .

Wypróbuj online lub sprawdź, czy jest to quine .

Wyjaśnienie:

-part:

Najkrótsza dla 05AB1E to: 0"D34çý"D34çý( 14 bajtów ) zapewniona przez @OliverNi . Moja odpowiedź wykorzystuje zmodyfikowaną wersję tego Quine'a dodając u ...tutaj: 0"D34çý..."D34çý.... Krótkie wyjaśnienie tego quinu:

0               # Push a 0 to the stack (can be any digit)
 "D34çý"        # Push the string "D34çý" to the stack
        D       # Duplicate this string
         34ç    # Push 34 converted to an ASCII character to the stack: '"'
            ý   # Join everything on the stack (the 0 and both strings) by '"'
                # (output the result implicitly)

Część wyzwania:

Teraz część kodu wyzwania. Jak wspomniałem na górze, 05AB1E nie ma wbudowanych funkcji konwersji UTF-8, więc muszę to zrobić ręcznie. Użyłem tego źródła jako odniesienia do tego, jak to zrobić: Ręczne przekształcanie punktów kodowych Unicode w UTF-8 i UTF-16 . Oto krótkie podsumowanie tego dotyczące konwersji znaków Unicode na UTF-8:

  1. Konwertuj znaki Unicode na ich wartości Unicode (tzn. "dЖ丽"Staje się [100,1046,20029])
  2. Konwertuj te wartości Unicode na binarne (tzn. [100,1046,20029]Staje się ["1100100","10000010110","100111000111101"])
  3. Sprawdź, w którym z poniższych zakresów znajdują się znaki:
    1. 0x00000000 - 0x0000007F (0-127): 0xxxxxxx
    2. 0x00000080 - 0x000007FF (128-2047): 110xxxxx 10xxxxxx
    3. 0x00000800 - 0x0000FFFF (2048-65535): 1110xxxx 10xxxxxx 10xxxxxx
    4. 0x00010000 - 0x001FFFFF (65536-2097151): 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Istnieją również zakresy dla 5 lub 6 bajtów, ale na razie pomińmy je.

Postać dbędzie w pierwszym zakresie, więc 1 bajt w UTF-8; znak Жznajduje się w drugim zakresie, więc 2 bajty w UTF-8; a znak należy do trzeciego zakresu, więc 3 bajty w UTF-8.

xWe wzorcu za to są wypełnione binarnego tych znaków, od prawej do lewej. Tak więc d( 1100100) ze wzorem 0xxxxxxxstaje się 01100100; Ж( 10000010110) z wzór 110xxxxx 10xxxxxxstaje 11010000 10010110; i ( 100111000111101) o wzorze 1110xxxx 10xxxxxx 10xxxxxxsię 1110x100 10111000 10111101, po czym pozostałe xsą zastępowane 0: 11100100 10111000 10111101.

Takie podejście zastosowałem również w moim kodzie. Zamiast sprawdzać rzeczywiste zakresy, po prostu patrzę na długość xpliku binarnego i porównuję go z ilością wzorców, ponieważ pozwala to zaoszczędzić kilka bajtów.

Ç               # Convert each character in the string to its unicode value
 b              # Convert each value to binary
  ε             # Map over these binary strings:
   Dg           #  Duplicate the string, and get its length
     Xó•       #  Push compressed integer 8657
         18в    #  Converted to Base-18 as list: [1,8,12,17]
            @   #  Check for each if the length is >= to this value
                #  (1 if truthy; 0 if falsey)
   ƶ            #  Multiply each by their 1-based index
    à           #  Pop and get its maximum
     ©          #  Store it in the register (without popping)
   i            #  If it is exactly 1 (first range):
    7j          #   Add leading spaces to the binary to make it of length 7
      0ì        #   And prepend a "0"
   ë            #  Else (any of the other ranges):
    R           #   Reverse the binary
     6ô         #   Split it into parts of size 6
       Rí       #   Reverse it (and each individual part) back
    ć           #   Pop, and push the remainder and the head separated to the stack
     7®-        #   Calculate 7 minus the value from the register
        j       #   Add leading spaces to the head binary to make it of that length
         š      #   Add it at the start of the remainder-list again
    Tì          #   Prepend "10" before each part
      J         #   Join the list together
    1®<×        #   Repeat "1" the value from the register - 1 amount of times
        ì       #   Prepend that at the front
  ]             # Close both the if-else statement and map
   ð0:          # Replace all spaces with "0"
      J         # And join all modified binary strings together
                # (which is output implicitly - with trailing newline)

Zobacz moją odpowiedź 05AB1E (sekcje Jak kompresować duże liczby całkowite? I Jak kompresować listy liczb całkowitych? ), Aby zrozumieć, dlaczego tak •Xó•18вjest [1,8,12,17].


3

JavaScript (Node.js) , 60 bajtów

-15 bajtów od @Neil i @Shaggy

f=_=>[...Buffer(`f=`+f)].map(x=>x.toString(2).padStart(8,0))

Wypróbuj online!


padStart(8,0)oszczędza 2 bajty.
Neil

Specyfikacja pozwala, aby dane wyjściowe były w dowolnym dogodnym formacie, dzięki czemu można zachować mapi porzucić, joinaby wyprowadzić tablicę bitów
Shaggy

60 bajtów z wyjściem jako tablicą bajtów.
Kudłaty

Dzięki @Neil i @Shaggy !!
Luis felipe De jesus Munoz

2

Rdza , 187 bajtów

fn f(o:u8){for c in b"go!g)n;t9(zgns!b!ho!c#%#/huds)(zhg!b_n <27zqshou )#z;19c|#-b_n(:|dmrdzg)1(:|||go!l`ho)(zg)0(:|".iter(){if c^o!=36{print!("{:08b}",c^o);}else{f(0);}}}fn main(){f(1);}

Wypróbuj online!


2

Perl 6 , 46 bajtów

<say "<$_>~~.EVAL".ords.fmt("%08b",'')>~~.EVAL

Wypróbuj online!

Standardowy quine z .fmt("%08b",'')formatuje listę wartości porządkowych na binarne o długości 8 i łączy się z pustym łańcuchem.



2

Java 10, 339 308 265 227 225 186 184 bajtów

v->{var s="v->{var s=%c%s%1$c;return 0+new java.math.BigInteger(s.format(s,34,s).getBytes()).toString(2);}";return 0+new java.math.BigInteger(s.format(s,34,s).getBytes()).toString(2);}

-8 bajtów dzięki @NahuelFouilleul usuwających niepotrzebne &255(i dodatkowe -35 za zwrócenie mojej uwagi, że pełna specyfikacja programu wyzwania została odwołana i funkcja jest teraz dozwolona ..)
-41 bajtów dzięki @ OlivierGrégoire .

Wypróbuj online.

Wyjaśnienie:

-part:

  • var s zawiera niesformatowany kod źródłowy String
  • %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 razem

Część wyzwania:

v->{                         //  Method with empty unused parameter and String return-type
  var s="...";               //   Unformatted source code String
  return 0+                  //   Return, with a leading "0":
   new java.math.BigInteger( //    A BigInteger of:
     s.format(s,34,s)        //     The actual source code String
      .getBytes())           //     Converted to a list of bytes (UTF-8 by default)
   .toString(2);}            //    And convert this BigInteger to a binary-String      

1
265 bajtów przy użyciu lambda, również dlatego, że wszystkie źródła są ascii wydaje się niepodpisane int c&255nie jest potrzebne
Nahuel Fouilleul

@NahuelFouilleul Pierwotne pytanie brzmiało: „ Musisz zbudować pełny program. ” I „ Twoje dane wyjściowe muszą być wydrukowane do STDOUT. ”, Stąd pełny kod granicznej tablicy mam zamiast funkcji lambda zwracającej ciąg. Warto &255jednak nie potrzebować, ponieważ nie używamy żadnych znaków spoza ASCII, dzięki!
Kevin Cruijssen

ok, nie jestem jeszcze zbyt dobrze zaznajomiony z zastosowaniami, ale inne języki, takie jak javascript, dają lambda zwracającą ciąg znaków, również nie rozumiem, dlaczego w java nie liczymy typu i ostatniego średnika, gdy używam lambda, gdzie mogę znaleźć zasady?
Nahuel Fouilleul

1
Cóż, tam się zgubiłem. Jednak próbowałem i oto nowy kandydat na 184 bajty . Powiedz mi, czy gdzieś się mylę;)
Olivier Grégoire,

1
@ OlivierGrégoire Ah, ładne podejście! Zupełnie zapomniałem o tym, BigIntegerże jestem dość krótki do konwersji na ciągi binarne. I 2 więcej bajtów, zmieniając return'0'+się return 0+. Hmm, dlaczego to prowadzenie jest 0niezbędne? Myli mnie to, że wszystkie wewnętrzne ciągi binarne mają tę wiodącą 0funkcję, ale ta pierwsza nie jest używana, gdy BigInteger.toString(2)...
Kevin Cruijssen

2

Python 2 , 68 67 bajtów

_="print''.join(bin(256|ord(i))[3:]for i in'_=%r;exec _'%_)";exec _

Wypróbuj online!

Modyfikacja tej odpowiedzi

-1 bajtów poprzez usunięcie spacji po 'in' (dzięki @mdahmoune)


-1 bajt: możesz upuścić miejsce późniejin
mdahmoune

nie zaktualizowałeś swojego łącza TIO. też próbowałem zrobić '%08b'%ord(i)zamiast bin(256|ord(i))[3:], ale z jakiegoś powodu to nie zadziałało
Jo King

2

R , 138 114 bajtów

x=function(){rev(rawToBits(rev(charToRaw(sprintf("x=%s;x()",gsub("\\s","",paste(deparse(x),collapse="")))))))};x()

Wypróbuj online!

Wykorzystuje zdolność R do analizy funkcji do ich reprezentacji postaci. Te revsą potrzebne, ponieważ rawToBitsna pierwszym miejscu stawia najmniej znaczący bit. as.integerjest potrzebne, ponieważ w przeciwnym razie bity są wyświetlane z wiodącym zerem.

Edytowane, gdy zdałem sobie sprawę, że dozwolone są dowolne wygodne wyniki. Został również wyłączony przez jeden na oryginalnej liczbie bajtów.


1

C # (interaktywny kompilator Visual C #) , 221 bajtów

var s="var s={0}{1}{0};Write(string.Concat(string.Format(s,(char)34,s).Select(z=>Convert.ToString(z,2).PadLeft(8,'0'))));";Write(string.Concat(string.Format(s,(char)34,s).Select(z=>Convert.ToString(z,2).PadLeft(8,'0'))));

Wypróbuj online!

C # (interaktywny kompilator Visual C #) z flagą /u:System.String, 193 bajtów

var s="var s={0}{1}{0};Write(Concat(Format(s,(char)34,s).Select(z=>Convert.ToString(z,2).PadLeft(8,'0'))));";Write(Concat(Format(s,(char)34,s).Select(z=>Convert.ToString(z,2).PadLeft(8,'0'))));

Wypróbuj online!


1

Narzędzia Bash + GNU, 48 bajtów

trap -- 'trap|xxd -b|cut -b9-64|tr -dc 01' EXIT

TIO


dzięki, zaktualizowano, to rzeczywiście najkrótsza odmiana, w przeciwnym razie należy usunąć z wyjścia pułapki
Nahuel Fouilleul
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.