Quine kendisini ikili olarak çıkarır


10

Göreviniz, kabul etmek isterseniz, ikili UTF-8 sunumunda kendi kaynak kodunu çıkaran bir program yazmaktır .

kurallar

  • Kaynak en az 1 bayt uzunluğunda olmalıdır.

  • Programınız girdi almamalıdır (veya kullanılmayan, boş bir girdi içermemelidir ).

  • Çıktı herhangi bir formatta olabilir.

  • İsteğe bağlı sondaki yeni satıra izin verilir.

  • Bir baytın 8 bit olduğuna ve ikili UTF-8 gösteriminin uzunluğunun mutlaka 8'in katı olduğuna dikkat edin.

  • Bu bu nedenle her zamanki golf kuralları geçerlidir ve en kısa kod (bayt cinsinden) kazanır.

  • Standart boşluklar yasaktır.

Misal

Diyelim ki kaynak kodunuz, Aä$$€hkarşılık gelen UTF-8 ikili gösterimi 010000011100001110100100001001000010010011100010100000101010110001101000.

Çalıştırırsam Aä$$€hçıkış olması gerekir 010000011100001110100100001001000010010011100010100000101010110001101000.

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

Dize - ikili UTF-8 dönüştürücüler


1
"İkili" ile, ikili değerlerin dize gösterimi, yani yalnızca 1 ve 0'lardan oluşan bir dize mi demek istediniz?

1
@mdahmoune Şimdi zaten çok daha iyi. Soru, UTF-8 olarak bir şeyin nasıl temsil edileceği sorusu devam ediyor. Unicode gösteriminin temel olarak bir karakterin görünümlerine dayandığına dikkat edin (sadece ara sıra anlamsal anlam üzerinde). Atanmış Unicode glifi kaynak kodunda bir karaktere benzemiyorsa ne olur? Unicode ayrıca birçok benzer görünüme (homoglif) sahiptir. Hangisini kullanacağına nasıl karar verilir? Örneğin, Dyalog APL, UTF-8 olarak 01011110veya kodlanmış olabilen bir AND fonksiyonuna sahiptir 0010011100100010(oldukça benziyorlar: ^vs )
Adám

1
Daha iyi bir örnek: 01111100ve 0010001100100010kodlamak |ve .
Adám

4
@ Adám Bir dilin belirli bir uygulamasında derlenecek / çalıştırılacak bir sembole karşılık gelen herhangi bir ikili dizinin çıktısının adil olacağını düşünüyorum.
qwr

1
Makine kodu hakkında nasıl? (Commodore C64, makine kodunun kendisinin "kaynak" olduğunu varsayarak 28 bayt alır)
Martin Rosenau

Yanıtlar:


7

V , 28 (veya 16?) Latin 1 bayt (35 UTF-8 bayt)

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

Çevrimiçi deneyin!

Hexdump (Latince 1'de):

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

Çıktı (aynı kodun Latin 1 değil UTF-8'de ikili gösterimi):

110000111011000111000011101010011100001110010001011111100010001001110001011100000111100000100001001000010111100001111000011001000010000000101101011000100000110111000011100011100110010001010111001101010011010001111100010001000000110111000011100011011100001110011111110000111011001100001010

Açıklama:

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

Veya...

V , 16 bayt

ñéÑ~"qpx!!xxd -b

Çevrimiçi deneyin!

Çıktı:

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 dedi:

Çıktı herhangi bir uygun formatta olabilir.

Bu, V: P için çok daha uygun bir formatta çıktı (ancak kuralları genişletip genişletmediğinden emin değilim)



4

05AB1E , 105 bayt

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'de UTF-8 dönüşüm yerleşikleri yoktur, bu yüzden her şeyi manuel olarak yapmak zorundayım ..

Çevrimiçi deneyin veya bunun bir quine olduğunu doğrulayın .

Açıklama:

-part:

Kısa : 05AB1E için bu bir 0"D34çý"D34çý( 14 bayt ) tarafından sağlanan @OliverNi . Benim cevabım de ekleyerek o Quine'ın değiştirilmiş bir sürümünü kullanır ...burada: 0"D34çý..."D34çý.... Bu kinin kısa bir açıklaması:

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)

Zorluk bölümü:

Şimdi kodun meydan okuma kısmı için. Yukarıda da bahsettiğim gibi, 05AB1E'nin UTF-8 dönüşüm yerleşikleri yoktur, bu yüzden bunları elle yapmak zorundayım. Bu kaynağı nasıl yapılacağı konusunda referans olarak kullandım: Unicode kod noktalarını elle UTF-8 ve UTF-16'ya dönüştürme . Unicode karakterlerin UTF-8'e dönüştürülmesiyle ilgili kısa bir özet:

  1. Unicode karakterleri unicode değerlerine dönüştürün (yani "dЖ丽"olur [100,1046,20029])
  2. Bu unicode değerlerini ikili biçime dönüştürün (yani [100,1046,20029]olur ["1100100","10000010110","100111000111101"])
  3. Aşağıdaki aralıklardan hangilerinin karakter olduğunu kontrol edin:
    1. 0x00000000 - 0x0000007F (0-127) 0xxxxxxx
    2. 0x00000080 - 0x000007FF (128-2047): 110xxxxx 10xxxxxx
    3. 0x00000800 - 0x0000FFFF (2.048-65.535): 1110xxxx 10xxxxxx 10xxxxxx
    4. 0x00010000 - 0x001FFFFF (65536-2097151): 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

5 veya 6 baytlık aralıklar da var, ancak şimdilik onları dışarıda bırakalım.

Karakter dilk aralıkta olacak, bu yüzden UTF-8'de 1 bayt; karakter Жikinci aralıktadır, dolayısıyla UTF-8'de 2 bayt; ve karakter üçüncü aralıktadır, yani UTF-8'de 3 bayt.

xSola desende o sağdan, bu karakterlerin ikili ile doldurulur arkasında. Böylece desenli d( 1100100) 0xxxxxxxolur 01100100; Ж( 10000010110) paterni ile 110xxxxx 10xxxxxxolur 11010000 10010110; ve ( 100111000111101desenli) 1110xxxx 10xxxxxx 10xxxxxxolur 1110x100 10111000 10111101, bundan sonra geriye kalan, xile değiştirilir 0: 11100100 10111000 10111101.

Bu yaklaşımı kodumda da kullandım. Gerçek aralıkları kontrol etmek yerine, sadece ikilinin uzunluğuna bakarım ve bunu xdesenlerin miktarıyla karşılaştırırım , çünkü bu birkaç bayt kazandırır.

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

Bu 05AB1E cevabımın neden •Xó•18вolduğunu anlamak için ( Büyük tamsayılar nasıl sıkıştırılır ? Ve Tamsayı listeleri nasıl sıkıştırılır? ) Bölümlerine bakın[1,8,12,17] .



2

Pas , 187 bayt

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

Çevrimiçi deneyin!


2

Perl 6 , 46 bayt

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

Çevrimiçi deneyin!

Standart kınama .fmt("%08b",''), sıra sayıları listesini uzunluk 8 ikilik biçime dönüştürür ve boş bir dize ile birleşir.



2

Java 10, 339 308 265 227 225 186 184 bayt

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 sayesinde gereksizler kaldırılıyor &255(ve ek bir -35 zorluğun tüm program özelliklerinin iptal edildiğini ve şimdi de bir işleve izin verildiğini dikkatimi
çekmek için ..) -41 bytes @ OlivierGrégoire sayesinde .

Çevrimiçi deneyin.

Açıklama:

-part:

  • var s biçimlendirilmemiş kaynak kodunu içerir Dize
  • %s bu String'i kendi içine koymak için kullanılır s.format(...)
  • %c, %1$cve 34çift ​​tırnak işaretlerini ( ") biçimlendirmek için kullanılır
  • s.format(s,34,s) hepsini bir araya getirir

Zorluk bölümü:

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
Lamda kullanarak 265 bayt , ayrıca tüm kaynak ascii imzasız görünüyor çünkü int c&255gerekli değildir
Nahuel Fouilleul

@NahuelFouilleul Orijinal soru " Tam bir program oluşturmak gerekir. " Ve " Çıktı STDOUT yazdırılmalıdır. ", Bu nedenle bir String döndüren lambda işlevi yerine sahip ayrıntılı sınır plakası kodu. &255ASCII olmayan karakterler kullanmadığımız için ihtiyaç duymamanız iyi bir nokta , teşekkürler!
Kevin Cruijssen

Tamam ben henüz kullanımları ile çok familar değilim, ancak javascript gibi diğer diller bir dize dönen bir lambda vermek, ayrıca neden java'da lambda kullanırken türü ve son noktalı virgül saymıyoruz anlamıyorum kurallar?
Nahuel Fouilleul

1
Ben kayboldum. Ancak denedim ve 184 bayt için yeni bir aday . Bana bir yerde yanılıyorsam söyle;)
Olivier Grégoire

1
@ OlivierGrégoire Ah, hoş bir yaklaşım! BigIntegerİkili dizelere dönüştürmek için oldukça kısa olmayı tamamen unuttum . Ve return'0'+değerini değiştirerek 2 bayt daha return 0+. Hmm, bu neden 0gerekli btw? Bana tüm iç ikili-Dizeleri bu lider var 0, ama ilk değil kullanırken BigInteger.toString(2)
kafa karıştırıyor

2

Python 2 , 68 67 bayt

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

Çevrimiçi deneyin!

Bir değişiklik , bu cevap

'İn' sonrası boşluğu kaldırarak -1 bayt (teşekkürler mdahmoune)


-1 bayt: u sonra boşluk bırakabilirsinizin
mdahmoune

TIO bağlantınızı güncellemediniz. Ayrıca, '%08b'%ord(i)bunun yerine yapmaya çalıştım bin(256|ord(i))[3:], ama bir sebepten dolayı işe yaramadı
Jo King

2

R , 138114 bayt

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

Çevrimiçi deneyin!

R'nin işlevleri karakter temsillerine yönlendirme yeteneğini kullanır. revS nedeniyle ihtiyaç vardır rawToBitskoyar az anlamlı bit ilk. as.integergereklidir, aksi takdirde bitler önünde sıfır ile gösterilir.

Herhangi bir uygun çıktıya izin verildiğini anladıktan sonra düzenlendi. Ayrıca orijinal bayt sayısı bir tarafından dışarı edildi.


1

C # (Visual C # Etkileşimli Derleyici) , 221 bayt

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

Çevrimiçi deneyin!

C # (Visual C # Etkileşimli Derleyici) bayrağı /u:System.String, 193 bayt

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

Çevrimiçi deneyin!


1

Bash + GNU araçları, 48 bayt

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

TIO


teşekkürler, gerçekten güncellenen bu en kısa varyasyon yoksa tuzak çıkışından kaldırılmalıdır
Nahuel Fouilleul
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.