Quine는 바이너리로 자체 출력


10

작업을 수락하려면 바이너리 UTF-8 표현 으로 자체 소스 코드를 출력하는 프로그램을 작성해야합니다 .

규칙

  • 소스의 길이는 1 바이트 이상이어야합니다.

  • 프로그램은 입력을 받지 않아야합니다 (또는 사용되지 않은 빈 입력이 없어야합니다 ).

  • 출력은 모든 형식이 될 수 있습니다.

  • 선택적 후행 줄 바꿈이 허용됩니다.

  • 1 바이트는 8 비트이며 이진 UTF-8 표현의 길이는 8의 배수 여야합니다.

  • 이것은 이므로 모든 일반적인 골프 규칙이 적용되며 가장 짧은 코드 (바이트)가 이깁니다.

  • 표준 허점 은 금지되어 있습니다.

소스 코드가 Aä$$€h해당 UTF-8 이진 표현 이라고 가정 해 봅시다 010000011100001110100100001001000010010011100010100000101010110001101000.

내가 실행 Aä$$€h하면 출력은이어야합니다 010000011100001110100100001001000010010011100010100000101010110001101000.

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

문자열을 이진 UTF-8 변환기로


1
"이진"이란 이진 값의 문자열 표현, 즉 1과 0만으로 구성된 문자열을 의미합니까?

1
@mdahmoune 이제는 훨씬 나아졌습니다. 문제는 UTF-8로 무언가를 표현하는 방법으로 남아 있습니다. 유니 코드 표현은 주로 문자 모양 을 기반으로합니다 (때로는 의미 적 의미 만 있음). 할당 된 유니 코드 글리프가 소스 코드의 문자처럼 보이지 않으면 어떻게됩니까? 유니 코드에는 많은 모양 (상형 문자)이 있습니다. 어떤 것을 사용할지를 어떻게 결정합니까? 예 Dyalog APL은로 인코딩 할 수있는 AND 기능을 가지고 010111100010011100100010(그들은 꽤 닮았 : UTF-8을 ^)
아담

1
더 나은 예 : 011111000010001100100010인코딩 |.
Adám

4
@ Adám 특정 언어 구현에서 컴파일 / 실행되는 기호에 해당하는 이진 시퀀스를 출력하는 것이 공정하다고 생각합니다.
qwr

1
머신 코드는 어떻습니까? (C64 코머 28 바이트 자체는 "소스"인 머신 코드를 가정 소요)
마틴 Rosenau

답변:


7

V , 28 (또는 16?) 라틴어 1 바이트 (35 UTF-8 바이트)

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

온라인으로 사용해보십시오!

16 진수 덤프 (라틴어 1) :

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

출력 (라틴어 1이 아닌 UTF-8에서 동일한 코드의 이진 표현) :

110000111011000111000011101010011100001110010001011111100010001001110001011100000111100000100001001000010111100001111000011001000010000000101101011000100000110111000011100011100110010001010111001101010011010001111100010001000000110111000011100011011100001110011111110000111011001100001010

설명:

ñéÑ~"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

또는...

V , 16 바이트

ñéÑ~"qpx!!xxd -b

온라인으로 사용해보십시오!

산출:

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는 말했다 :

출력은 편리한 형식 일 수 있습니다.

이것은 V : P에 대해 훨씬 편리한 형식으로 출력됩니다 (그러나 규칙을 확장하는지 확실하지 않습니다)



4

05AB1E , 105 바이트

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에는 UTF-8 변환 내장 기능이 없으므로 모든 작업을 수동으로 수행 해야합니다 .

온라인으로 시도 하거나 quine 인지 확인 하십시오 .

설명:

part :

최단 : 05AB1E 대한이 하나 0"D34çý"D34çý( 14 바이트 ) 에 의해 제공 @OliverNi . 내 대답은 ...여기에 다음 을 추가하여 해당 quine의 수정 된 버전을 사용합니다 0"D34çý..."D34çý.... 이 quine에 대한 간단한 설명 :

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)

도전 과제 :

이제 코드의 챌린지 부분입니다. 위에서 언급했듯이 05AB1E에는 UTF-8 변환 내장 기능이 없으므로 이러한 작업을 수동으로 수행해야합니다. : 그 작업을 수행하는 방법에 대한 참조로이 소스를 사용했습니다 수동으로 UTF-8과 UTF-16으로 유니 코드 코드 포인트로 변환을 . 다음은 유니 코드 문자를 UTF-8로 변환하는 것에 대한 간단한 요약입니다.

  1. (즉, 자신의 유니 코드 값을 유니 코드 문자로 변환 "dЖ丽"됩니다 [100,1046,20029])
  2. (즉, 이진 이러한 유니 코드 값을 변환 [100,1046,20029]된다 ["1100100","10000010110","100111000111101"])
  3. 다음 범위 중 문자 범위를 확인하십시오.
    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

5 또는 6 바이트의 범위도 있지만 지금은 그대로 두겠습니다.

문자 d는 첫 번째 범위에 있으므로 UTF-8의 1 바이트입니다. 문자 Ж는 두 번째 범위에 있으므로 UTF-8의 경우 2 바이트입니다. 문자 는 세 번째 범위에 있으므로 UTF-8의 3 바이트입니다.

x왼쪽에있는 패턴은 오른쪽에서 이러한 문자의 바이너리로 가득 뒤에. 따라서 패턴을 가진 d( 1100100) 0xxxxxxx01100100; 패턴 이 있는 Ж( 10000010110) 110xxxxx 10xxxxxx11010000 10010110; 및 ( 100111000111101패턴)을 1110xxxx 10xxxxxx 10xxxxxx하게 1110x100 10111000 10111101한 후, 나머지는 x치환된다 0: 11100100 10111000 10111101.

그래서 그 접근 방식은 코드에서도 사용되었습니다. 실제 범위를 확인하는 대신 바이너리의 길이를보고 x패턴 의 양과 비교 하면 몇 바이트가 절약됩니다.

Ç               # 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)

내이 05AB1E 대답을 참조하십시오 (섹션 얼마나 큰 정수를 압축하는 방법?압축 정수 목록에 어떻게? ) 이유를 이해하는 •Xó•18в것입니다 [1,8,12,17].


3

자바 스크립트 (Node.js) , 60 바이트

@Neil 및 @Shaggy에서 -15 바이트

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

온라인으로 사용해보십시오!


padStart(8,0)2 바이트를 절약합니다.
Neil

당신이를 유지할 수 있도록 출력이 편리한 형식으로하기위한 사양은 허용 map하고 도랑 join비트의 배열 출력
얽히고 설킨

바이트 배열로 출력되는 60 바이트 .
얽히고 설킨

감사합니다 @Neil과 @Shaggy !!
루이스 펠리페 드 예수님 무 노즈




2

자바 10 339 308 265 227 225 186 184 바이트

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

@NahuelFouilleul 덕분에 -8 바이트 덕분에 불필요 함이 제거되었습니다 &255(그리고 도전에 대한 전체 프로그램 사양이 취소되었으며 기능도 허용됨을주의 깊게 설명 하기 위해 -35 추가). @ OlivierGrégoire
덕분에 -41 바이트 .

온라인으로 사용해보십시오.

설명:

part :

  • var s 형식화되지 않은 소스 코드를 포함합니다.
  • %s 이 문자열을 자체에 넣는 데 사용됩니다. s.format(...)
  • %c, %1$c34(이중 따옴표를 포맷하는 데 사용됩니다 ")
  • s.format(s,34,s) 다 합쳐

도전 과제 :

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 바이트 , 또한 모든 소스가 ASCII이기 때문에 부호없는 int c&255가 필요하지 않은 것 같습니다
Nahuel Fouilleul

@NahuelFouilleul 원래 질문에 " 전체 프로그램을 작성해야합니다. "및 " 출력을 STDOUT에 인쇄 해야합니다. " 라고 말했기 때문에 String을 반환하는 람다 함수 대신 자세한 경계 판 코드가 있습니다. &255그러나 ASCII가 아닌 문자를 사용하지 않기 때문에 필요 하지 않습니다.
케빈 Cruijssen

ok 나는 아직 사용법에 익숙하지 않지만 javascript와 같은 다른 언어는 문자열을 반환하는 람다를 제공합니다. 또한 java에서 왜 람다를 사용할 때 유형과 최종 세미콜론을 계산하지 않는지 이해할 수 없습니다. 규칙을 찾으십니까?
Nahuel Fouilleul

1
내가 잃어버린 곳이야 그러나 나는 시도했고 여기에 184 바이트에 대한 새로운 후보가 있습니다. 내가 어딘가에 틀렸다면 말해줘;)
Olivier Grégoire

1
@ OlivierGrégoire 아, 좋은 접근! BigInteger이진 문자열로 변환하기에 너무 짧다는 것을 완전히 잊었습니다 . 에서 return'0'+를 변경하여 2 바이트를 더 추가합니다 return 0+. 흠, 왜 그 선도가 0필요한가? 모든 내부 바이너리 문자열이이 선행을 가지고 0있지만 BigInteger.toString(2)..을 사용할 때는 처음이 아니라고
혼동합니다

2

파이썬 2 , 68 67 바이트

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

온라인으로 사용해보십시오!

이 답변 의 수정

'in'뒤의 공백을 제거하여 -1 바이트 (@mdahmoune 덕분에)


-1 바이트 : 유 후 공간을 제거 할 수있다in
mdahmoune

TIO 링크를 업데이트하지 않았습니다. 또한, '%08b'%ord(i)대신 하려고했지만 bin(256|ord(i))[3:]어떤 이유로 작동하지 않았습니다.
Jo King

2

R , 138114 바이트

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

온라인으로 사용해보십시오!

R의 기능을 사용하여 함수를 문자 표현으로 분리합니다. rev들 때문에 필요 rawToBits풋 최하위 비트 첫번째. as.integer그렇지 않으면 비트가 선행 0으로 표시되므로 필요합니다.

편리한 출력이 가능하다는 것을 알게되면 편집했습니다. 또한 원래 바이트 수에서 1 씩 나갔습니다.


1

C # (Visual C # 대화식 컴파일러) 221 바이트

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

온라인으로 사용해보십시오!

플래그 /u:System.String가 193 바이트 인 C # (Visual C # Interactive Compiler)

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

온라인으로 사용해보십시오!


1

Bash + GNU 도구, 48 바이트

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

TIO


감사합니다. 실제로 업데이트 된 것은 가장 짧은 변형입니다. 그렇지 않으면 트랩 출력에서 ​​제거되어야합니다
Nahuel Fouilleul
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.