Radyasyon Sertleşmiş Kine


39

Bildiğiniz gibi (umarım) radyasyonla sertleştirilmiş bir yüzgeç, herhangi bir karakterden çıkarabileceğiniz ve orijinal, önceden değiştirilmiş kaynağını yazdırabileceğiniz bir yüzgeçtir. Mesele şu ki, bunların çoğunda sadece bir karakter kaldırabilirsin; Aksi halde her şey bozulur. Bunun geldiği yer; Amacınız, mümkün olduğunca çok sayıda karakter kaldırması yapabilen radyasyonla sertleştirilmiş bir keki oluşturmaktır. Kurallara uyan herhangi bir dil iyi.

kurallar

  • Program en az bir karakter uzunluğunda olmalı
  • Kullanılan dil tamamlanmış olmalı (HQ9 + gibi diller kalifiye değil)
  • Normal quine uygulanan diğer tüm kurallar burada da geçerlidir.
  • En birlikte çözüm program_length^(2/n)olan herhangi aynen kümesi nhala orijinal kaynak kodu kazanır Yazdırma sırasında karakterler kaldırılabilir.

1
İçinde bir çözüm bulmaya çalışıyorum Subleq. Bu tür bir meydan okuma için ideal olacağını düşünüyorum!


Belki de ismini değiştir, çünkü bu radyasyonla sertleştirilmiş bir domuz ile aynı değil mi? Belki de "radyasyon geçirmez quine"?
Cyoce

@Cyoce Söyleyebileceğim tek fark, bu zorluğun herhangi bir sayıdaki kaldırma işlemi için olmasıdır, ancak çoğu (tümü değilse) diğer radyasyona karşı sertleştirilmiş çarklar yalnızca bir taneye izin verir.
Takra

Ünlü "mame" den Ruby çözümü. github.com/mame/radiation-hardened-quine
mbomb007

Yanıtlar:


57

Perl, 1116 1124 bayt, n = 3, skor = 1124 ^ (2/3) veya yaklaşık 108.1

Güncelleme : Ben şimdi bunun n = 3 ile çalıştığını doğruladım (birkaç gün sürdü); Bu karmaşık bir programla, radyasyon direncini elle kontrol etmek zor (ve önceki sürümde bir hata yaptım, bu yüzden bayt sayısı arttı). Güncellemeyi sonlandır

Stderr'i görmeyeceğiniz bir yere yönlendirmenizi öneririm; Bu program bile şüpheli sözdizimi hakkında uyarılar bir ton üretir değildir ondan karakterleri silme.

Programın kısaltılması mümkündür. Bunun üzerinde çalışmak oldukça acı verici ve olası mikro optimizasyonları kaçırmayı kolaylaştırıyor. Çoğunlukla silinebilir karakterlerin sayısını olabildiğince yüksek tutmayı hedefliyordum (çünkü bu programın gerçekten zorlu bir parçası) ve tiebreak'ini hedeflemem güzel bir şey olarak kabul etmedim ama optimizasyon için gülünç bir çaba (radyasyon direncini kazayla kırmanın çok kolay olması temelinde).

Program

Not: _Her dört olaydan hemen önce hazır bir Kontrol karakteri (ASCII 31) vardır -+. StackOverflow üzerine kopyalanıp yapıştırıldığını sanmıyorum, bu nedenle programı çalıştırmadan önce yeniden eklemeniz gerekecek.

eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;

Açıklama

Bu program, oldukça açık bir şekilde bir araya getirilmiş dört aynı küçük programdan oluşuyor. Temel fikir, programın her kopyasının çalıştırılmayacak kadar kötü bir şekilde zarar görüp görmediğini doğrulayacağı; eğer öyleyse, hiçbir şey yapmaz (muhtemel uyarılar dışında) ve bir sonraki kopyanın çalışmasına izin verir; yapılmadıysa (yani silinme olmadıysa veya silinen karakter, programın işleyişinde fark yaratmayan bir karakterse), yapmayı istediği şeyi yapacaktır (tam programın kaynak kodunu yazdırarak; kaynak kodunun her birinin kodunu içeren her bir parça ile) ve sonra (diğer hasarsız kopyaların kaynak kodu tekrar yazdırmasını ve böylece çok fazla metin yazdırarak kesimi bozmasını önleyerek) çıkın .

Her bir bölüm, sırayla, etkin bir şekilde işlevsel olarak bağımsız olan iki bölümden oluşur; bir dış sarıcı ve bazı dahili kodlar. Bu nedenle onları ayrı ayrı değerlendirebiliriz.

Dış sarıcı

Dış ambalaj, temel olarak, eval<+eval<+eval< ... >####>####...>###(artı amacı oldukça belirgin olması gereken bir sürü noktalı virgül ve yeni satır; bir noktalı virgül veya onlardan bazılarının silinmemesine bakılmaksızın, programın bölümlerinin ayrı kalmasını sağlamaktır. ). Bu oldukça basit görünebilir, ancak birkaç yönden ince ve bu meydan okuma için Perl'i seçmemin nedeni.

İlk olarak, paketleyicinin programın hasarsız bir kopyasında nasıl çalıştığına bakalım. evalBir argüman alan yerleşik bir işlev olarak ayrıştırır. Bir argüman beklendiğinden, +burada bir birlik vardır +(şu anda Perl golfçülerine çok aşina olacak; şaşırtıcı şekilde sıkça faydalı olacaklardır). Hala bir argüman bekliyoruz (daha önce bir unary operatörü gördük), bu nedenle bir <sonraki adım operatörün başlangıcı olarak yorumlanır <>(önek veya postfix argümanları almaz ve bu nedenle operand konumunda kullanılabilir).

<>oldukça garip bir operatör. Onun her zamanki amaç filehandles okumaktır ve dt adı yerleştirilmesi açılı ayraçlar. Alternatif olarak, ifade bir dosya askısı adı olarak geçerli değilse, genelleme (temel olarak, UNIX'in kabuklarının, kullanıcı tarafından girilen metni komut satırı argümanlarının bir sırasına çevirmek için kullandığı işlem; bunun için kabuk, ancak bugünlerde Perl globbing'i içten ele alır). Bu nedenle amaçlanan kullanım, <*.c>tipik olarak bir liste döndürecek olan çizgiler boyuncadır ("foo.c", "bar.c"). Skaler bir bağlamda (argüman gibieval), sadece ilk çalıştırıldığında bulduğu ilk girişi döndürür (ilk argümanın eşdeğeridir) ve asla gerçekleşmeyen varsayımsal gelecekteki çalışmalarda diğer girdileri döndürür.

Şimdi, kabuklar genellikle komut satırı argümanlarını ele alır; Eğer -rtartışmasız bir şey verirseniz , bu isimde bir dosya olup olmadığına bakılmaksızın, sadece programa iletilir. Perl de aynı şekilde hareket eder, kabuk için veya karakter <ile eşleşen arasında Perl'e özel karakter olmadığından emin olduğumuz sürece, bunu >gerçekten garip bir dize değişkeni gibi kullanabiliriz. Daha da iyisi, Perl'in alıntı benzeri operatörler için ayrıştırıcısı, anlam ifade etmeyen bu gibi durumlarda bile parantezleri eşleştirme zorunluluğu vardır, bu yüzden <>güvenli bir şekilde yuvalayabiliriz (bu programın mümkün olması için gerekli olanıdır ). Bu iç içe <>geçmişlerin en büyük dezavantajı , içeriğinden kaçmaktır.<>neredeyse imkansız; her biriyle birlikte açılmayan iki katman var gibi gözüküyor <>, bu yüzden her üçünün de içindeki bir şeyden kaçmak için, önce 63 ters eğik çizgiyle gelmek gerekiyor. Kod büyüklüğünün bu problemde sadece ikincil bir değerlendirme olmasına rağmen, puanım için bu tür bir ceza ödemeye değmeyeceğine karar verdim, bu yüzden rahatsız edici karakterleri kullanmadan programın geri kalanını yazmaya karar verdim.

Peki, sargının parçaları silinirse ne olur?

  • Kelimedeki silme, evalbir korkaklığa , anlamsız bir dizeye dönüşmesine neden olur . Perl bunlardan hoşlanmıyor, ama onlara tırnaklarla çevrilmiş gibi davranıyor; Böylece eal<+eval<+...yorumlanır"eal" < +eval<+.... Bunun programın çalışması üzerinde hiçbir etkisi yoktur, çünkü temelde sadece yoğun şekilde iç içe geçmiş (zaten kullanmadığımız) evrelerin sonucunu almak, bir tam sayıya dönüştürmek ve üzerinde bazı anlamsız karşılaştırmalar yapmaktır. (Bu tür bir şey, normal şartlar altında yapılması açıkça yararlı olmayan bir şey olduğundan çok fazla uyarı spamına neden olur; yalnızca silme işlemlerini absorbe etmek için kullanıyoruz.) Bu, ihtiyaç duyduğumuz kapanma açısı dirseklerinin sayısını değiştirir (çünkü açılış braketi şu anda bunun yerine bir karşılaştırma operatörü olarak yorumlanmaktadır), ancak sondaki yorum zinciri, kaç kez iç içe olursa olsun dizenin güvenli bir şekilde bitmesini sağlar. (Burada #kesinlikle gerekenden çok daha fazla işaret var; programı daha sıkıştırılabilir kılmak için yaptığım gibi yazdım, quin'i depolamak için daha az veri kullanmama izin verdim.)
  • Bir <silinirse, kod şimdi ayrıştırılır eval(eval<...>). İkincil, dışarının evalhiçbir etkisi yoktur, çünkü değerlendirmekte olduğumuz programlar, program olarak herhangi bir gerçek etkisi olan hiçbir şey döndürmezler (eğer normal şekilde dönüyorlarsa, normalde boş bir dize veya bir korkak; evalBir boş dize döndürmeye neden olan istisna, ya da exithiç döndürmemek için kullanılır.
  • Bir +silinirse, bitişik kodun sağlam olması durumunda bunun hemen bir etkisi olmaz; unary +program üzerinde hiçbir etkisi yoktur. (Orijinal +belgenin orda olması sebebi, hasarı onarmaya yardım etmektir; bunlar ilişkisel bir operatör olarak değil <, bir birleşik olarak yorumlanan durumların sayısını arttırır <>, yani geçersiz bir program üretmek için daha fazla silmeye ihtiyacınız vardır.)

Sarıcı , yeterli silme işlemiyle zarar görebilir, ancak ayrıştırmayan bir şey üretmek için bir dizi silme işlemi yapmanız gerekir. Dört silme ile bunu yapabilirsiniz:

eal<evl<eval+<...

Perl'de ilişkisel işleç ilişkisizdir <ve bu nedenle bir sözdizimi hatası alırsınız (bununla aynı 1<2<3). Bu haliyle, program için yazılan başlık n = 3'tür. Daha fazla unary eklenmesi +, onu arttırmanın umut verici bir yolu gibi görünüyor, ancak programın yeni sürümünün çok zor olabileceğini doğrulamak için, sargının iç kısmının da kırılması olasılığını artırıyor.

Paketleyicinin bu kadar değerli olmasının nedeni, evalPerl'de bir sözdizimi hatası derlemeye çalıştığınızda aldığınız istisnalar gibi (örneğin) istisnaları yakalamasıdır. Bu evalbir dizgenin değişmezi olduğundan, dizginin derlemesi çalışma zamanında gerçekleşir ve değişmez derlenemezse ortaya çıkan istisna yakalanır. Bu, evalboş bir dize döndürmeye ve hata göstergesini ayarlamasına neden olur $@, ancak hiçbirini kontrol etmiyoruz (zaman zaman döndürülen boş dizeyi programın değiştirilmiş birkaç sürümünde yürütmek dışında). Önemli olan, bu, içindeki koda bir şey olması gerektiği anlamına gelir.Bir sözdizimi hatasına neden olan sarmalayıcı, daha sonra sarmalayıcı yalnızca kodun yerine hiçbir şey yapmamasına neden olur (ve program bozulmamış bir kopyasını bulma girişiminde çalışmaya devam eder). Bu nedenle, iç kodun sarıcı kadar radyasyona karşı dayanıklı olması gerekmez; Tek umursadığımız şey, eğer hasar görürse, programın zarar görmemiş sürümüyle aynı şekilde hareket edeceği veya başka bir şey yapmadan çökeceği ( evalistisnayı yakalama ve devam etme izni veren ) veya normal olarak herhangi bir şey basmadan çıkacak olmasıdır .

Sarıcı içinde

Paketleyicinin içindeki kod temel olarak şöyle görünür (yine, _Stack Exchange'in hemen önce göstermeyeceği bir Kontrol vardır -+):

eval+(q(...)=~y=A-Z=-+;-AZz-~=r)

(Biz kullanamaz Bu kod glob güvenli karakterlerle tamamen yazılır, ve amacı transliterating ve bir dize değerlendirmek yoluyla, mümkün gerçek programı yazmak için yapmak noktalama işaretlerinden yeni bir alfabe eklemektir 'veya "bizim alıntı olarak işaretler, ancak q()ayrıca Perl'de bir dize oluşturmak için geçerli bir yoldur). (Yazdırılamayan karakterin nedeni, programda değişmez bir boşluk karakteri olmadan bir şeyi boşluk karakterine çevirmemiz gerektiği, böylece ASCII 31'den başlayan bir aralık oluşturmamız ve alanı aralığın ikinci elemanı olarak yakalamamızdır.) Belli ki, eğer harf çevirisi yoluyla bazı karakterler üretiyorsak, karakterleri kopyalamak için karakterleri feda etmeliyiz ., ancak büyük harfler çok kullanışlı değildir ve noktalama işaretlerine erişime sahip olmayanlara yazmaksızın yazmak çok daha kolaydır.

Burada, glob sonucu elde edilebilen noktalama işaretlerinin alfabesi bulunur (üst satır kodlamayı gösterir, alt satır kodladığı karakter):

BCDEFGHIJKLMNOPQRSTUVWXYZ
 ! "# $% & '() * +; <? => @ Azz {|} ~ 

En önemlisi, dünya güvenliği açısından güvenli olmayan ancak Perl programlarını boşluk karakteriyle birlikte yazmakta yararlı olan bir sürü noktalama işaretimiz var. Ayrıca değişmez harfler büyük iki kaydedilir Ave Z(kodlama kendileri için, ama Tve Uçünkü, Abir üst sıra ve bir alt sınıfı için bir son nokta olarak gerekli); bu, yeni kodlanmış karakter setini kullanarak harf çevirisi talimatını yazmamıza izin verir (büyük harfler o kadar kullanışlı olmasa da, büyük harflerde değişiklik belirlemede kullanışlıdır). Elimizdeki olmadığını en önemli karakterlerdir [, \ve ], ama çıktıda bir yeni satır gerektiğinde hiçbiri (ihtiyaç vardır, ben örtülü yeni satır gelen kullanarak üretilensayyazmaya ihtiyaç duymak yerine \n; chr 10Ayrıca işe yarayacaktı ama daha ayrıntılı.

Her zaman olduğu gibi, sargının iç kısmı telin dışına zarar verirse ne olacağı konusunda endişelenmemiz gerekir. Bozuk evalherhangi bir şeyin çalışmasını önler; biz bununla iyiyiz. Alıntı işaretleri zarar görürse, dizginin içi geçerli Perl değildir ve dolayısıyla sarıcı yakalar (ve dizelerdeki sayısız çıkarma, geçerli Perl yapsanız bile hiçbir şey yapmaz. kabul edilebilir bir sonuçtur). Harf çevirisinde oluşacak hasar sözdizimi hatası değilse, değerlendirilmekte olan dizgiyi karıştıracak ve genellikle sözdizimi hatası oluşmasına neden olacaktır ; Bunun kırıldığı hiçbir durum olmadığından% 100 emin değilim, ancak şu anda emin olmak için kaba bir şekilde zorluyorum ve varsa düzeltmek için yeterince kolay olmalı.

Kodlanmış program

Dize değişmezine baktığımda, kullandığım kodlamayı tersine çevirip daha okunaklı hale getirmek için boşluk ekleyerek şunu elde ediyoruz (yine, -+olarak kodlanandan önce kontrol alt çizgisini düşünün A):

$o=q<
  length$o  ==181 || zzzz((()));
  do {
    chop ($t = "eval+<"x4);
    $r = '=-+;-AZz-~=';
    $s = '$o=q<' . $o . '>;eval$o';
    eval '$s=~y' . $r . 'A-Z=';
    say "$t(q($s)=~y=A-Z${r}r)" . "####>"x6;
    say ";" for 1..4
  } for 1..4;
  exit>;
eval $o

Kuyruklara alışkın olan insanlar bu genel yapıyı tanıyacaktır. En önemli kısım, başlangıçta, $ o'nun hasarsız olduğunu doğruladığımız yer; karakterleri silinmiş olsa bile, uzunluğu maç olmayacak 181Yürüttüğümüz bu yüzden, zzzz((()))bunun nedeni eşsiz parantez bir sözdizimi hatası değilse, hangi nedeniyle hiçbiri arasında herhangi üç karakteri silseniz dahi bir çalışma zamanı hatası olacaktır zzzz, zzz, zz, ve zbir işlevdir ve silme (((ve karmaşık bir sözdizimi hatasına neden olmaktan başka bir işlev olarak ayrıştırmasını engellemenin bir yolu yoktur . Kontrolün kendisi de hasara karşı bağışıklık kazanır; ||için zarar görebilir |ama bu neden olacaktır zzzz((()))koşulsuz çalıştırmak için çağrı; Değişkenlere veya sabitlere zarar vermek uyumsuzluğa neden olacaktır, çünkü bunlardan birini karşılaştırıyorsanız 0,180, 179, 178Basamak bazı alt eşitlik için 181; ve birinin kaldırılması =ayrıştırma hatasına neden olur ve ikisi =kaçınılmaz olarak LHS'nin her ikisi de falsey olan 0 tamsayısı veya boş bir dize olarak değerlendirmesine neden olur.

Güncelleme : Bu kontrol, programın önceki bir sürümünde biraz yanlıştı, bu yüzden sorunu çözmek için düzenlemek zorunda kaldım. Kodun çözülmesinden sonra önceki sürüm şöyle görünüyordu:

length$o==179||zzzz((()))

ve bunu almak için ilk üç noktalama işaretini silmek mümkündü:

lengtho179||zzz((()))

lengtho179, bir korkak olmak, kaba ve bu nedenle çeki bozar. Bunu, ilave iki Bkarakter ekleyerek (boşluk karakterlerini kodlayan) ekledim, yani sıranın en son sürümü şöyle:

length$o  ==181||zzzz((()))

Artık hem =işaretleri hem de işaretleri $bir sözdizimi hatası üretmeden gizlemek imkansızdır . (Biri yerine iki boşluk eklemek zorunda kaldım, çünkü uzunluğu sıfır olan bir korkakla başarılı bir karakterle karşılaştırmak için bu bağlamda kötüye kullanılabilecek 180bir 0karakter niteliği taşıyordu.) Son güncelleme

Uzunluk kontrolü geçtikten sonra, kopyanın hasarsız olduğunu, en azından ondan karakter silmeleri açısından biliyoruz, bu yüzden hepsi oradan kolayca anlaşılıyor (bozuk bir kod çözme tablosundan dolayı noktalama işaretlerinin değişimleri bu çekle yakalanmayacaktı) , ancak, sadece kod çözme tablosundan üç silinme işleminin kaleyi kırmadığını, muhtemelen çoğunun sözdizimi hatalarına neden olduğunu) zorla zorlama yoluyla zaten doğruladım . $oZaten bir değişkene sahibiz , bu yüzden tek yapmamız gereken dış paketleyicileri (küçük bir sıkıştırma derecesiyle; sorunun kısmını tamamen atlamamıştım ). Bir hile, kodlama tablosunun büyük bölümünü içinde sakladığımızdır.$r; biz ya içeride sargının kodlama tablosu bölümünü üretmek için tam anlamıyla yazdırabilir veya çevresinde bazı kodlar birleştirmek ve olabilir evalbize ne olduğunu anlamaya izin (ters deşifreleme işlemini çalıştırmak için kodlanmış $ sürümünü o is bu noktada sadece kodu çözülmüş versiyona sahip ).

Son olarak, sağlam bir kopya olsaydık ve böylece tüm orijinal programı çıkartabilseydik exit, diğer kopyaların da programı yazdırmaya çalışmasını önlemek için ararız .

Doğrulama betiği

Çok hoş değil, ama birileri sorduğu için gönderiyorum. Bunu çeşitli ayarlarla birkaç kez koştum (genellikle değişen $minve $maxçeşitli ilgi alanlarını kontrol etmek için); tam otomatik bir işlem değildi. Başka bir yerde ağır CPU yükü nedeniyle çalışmayı durdurma eğilimi vardır; bu olduğunda, sadece $minilk değeri $xtamamen kontrol edilmedi ve senaryoyu çalıştırmaya devam ettim (bu yüzden aralıktaki tüm programların sonunda kontrol edilmesini sağladım). Yalnızca programın ilk kopyasındaki silme işlemlerini kontrol ettim, çünkü diğer kopyalardan yapılan silme işlemlerinin daha fazlasını yapamayacağı açıktır.

use 5.010;
use IPC::Run qw/run/;
undef $/;
my $program = <>;
my $min = 1;
my $max = (length $program) / 4 - 3;
for my $x ($min .. $max) {
    for my $y ($x .. $max) {
        for my $z ($y .. $max) {
            print "$x, $y, $z\n";
            my $p = $program;
            substr $p, $x, 1, "";
            substr $p, $y, 1, "";
            substr $p, $z, 1, "";
            alarm 4;
            run [$^X, '-M5.010'], '<', \$p, '>', \my $out, '2>', \my $err;
            if ($out ne $program) {
                print "Failed deleting at $x, $y, $z\n";
                print "Output: {{{\n$out}}}\n";
                exit;
            }
        }
    }
}

say "All OK!";

3
OP biraz belirsiz; ancak skorun (1116 * 1116) / 3 olacağını düşündüm.
Greg Martin

@GregMartin: (1116 * 1116) / 3 415152, bu yüzden bu giriş bu koşullar altında kazanmaya devam ediyor. Bununla birlikte, OP'nin bunun anlamına gelebileceğini sanmıyorum, çünkü birden fazla karakterin kaldırılması için çok az teşvik veriyordu. Bu karakter, sadece bir karakter kaldırmayı işlemesi için ihtiyacınız varsa, uzunluktan yarıdan daha az olabilir; Bu, eğer böyle yorumlarsak, n = 3'ten aldığım ÷3'ü geçecek ve böylece daha az ilginç olan n = 1 girişin gerçekten daha iyi puan aldığı anlamına gelir.

2
Skorlamayı netleştirdim. Neyse, bu kesinlikle inanılmaz; kimsenin n> 1 olacağını düşünmüyordu
takra

1
Perl hakkında, harfsiz bir program yazmanın noktalama işaretinden daha kolay olduğunu söylüyor
Robert Fraser

35

Befunge-98 , 884, n = 14, puan ≈ 2.636

f00f00f00f00f00f00f00f00f00f00f00f00f00f00f0xxxxxxxxxxxxxxx"""""""""""""""fffffffffffffff'''''''''''''''000000000000000\\\\\\\\\\\\\\\'''''''''''''''000000000000000\\\\\\\\\\\\\\\'''''''''''''''fffffffffffffff\\\\\\\\\\\\\\\111111111111111---------------:::::::::::::::!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!000000000000000aaaaaaaaaaaaaaa---------------bbbbbbbbbbbbbbb---------------***************jjjjjjjjjjjjjjj$$$$$$$$$$$$$$$'''''''''''''''+++++++++++++++kkkkkkkkkkkkkkk,,,,,,,,,,,,,,,333333333333333kkkkkkkkkkkkkkk$$$$$$$$$$$$$$$000000000000000{{{{{{{{{{{{{{{'''''''''''''''888888888888888uuuuuuuuuuuuuuu'''''''''''''''!!!!!!!!!!!!!!!111111111111111+++++++++++++++'''''''''''''''xxxxxxxxxxxxxxx###############;;;;;;;;;;;;;;;:::::::::::::::!!!!!!!!!!!!!!!kkkkkkkkkkkkkkk@@@@@@@@@@@@@@@dddddddddddddddkkkkkkkkkkkkkkk:::::::::::::::eeeeeeeeeeeeeeekkkkkkkkkkkkkkk,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;

Çevrimiçi deneyin!

Bu yalnızca tam olarak 14 karakteri kaldırdığınızda değil , 14 karaktere kadar olan herhangi bir miktarı kaldırdığınızda da işe yarar .

n = 14çok keyfi bir seçim gibi görünebilir, ancak kullandığım teknik aslında sadece 1-14 arası radyasyon sertleştirme için kullanılabilir, ancak bunun ötesinde kolayca kullanılamaz (mümkün olabilir ama nasıl bir ipucu yok). Order-1 quine sadece 73 byte (daha büyükler için geçerli olmayan bazı golf hileleri kullanmasına rağmen n):

200 20 xx""''ÈÈ..aa22**..33kk$$00{{''!!uu''!!11++''xx##;;::!!kk@@::,,,,;;

açıklama

Bu cevap üzerinde çalışırken , talimat göstergesinin deltasını (2,0)radyasyonla sertleştirilmiş koşullar altında aşağıdaki pasaj ile ayarlamanın mümkün olduğunu buldum :

20020xx

Bunun neden işe yaradığını görmek için bu cevaba bakınız. Bunu sadece biraz elle oynaşırken buldum, ancak bu, birden fazla karakterin kaldırılması altında sağlam olan benzer kalıpların olup olmadığı sorusunu gündeme getirdi. Bu yüzden kaba kuvvetle bunları aramak için kısa bir Mathematica betiği yazdım:

n = 14;
m = 4;
Print @ FromDigits @ {
      m + 1, 0, 
      ## & @@ ((m + 1) IntegerDigits[#, 2, n - 4]),
      m + 1, 0
} & /@ Select[
   Range[0, 2^(n - 4) - 1], 
   AllTrue[
     Subsets[{
         m + 1, 0, 
         ## & @@ ((m + 1) IntegerDigits[#, 2, n - 4]),
         m + 1, 0
       }, 
       {n - m, n - 1}
     ] //. {a___, _, m + 1} | {a___, 0, _} :> {a}, 
     MatchQ@{___, m + 1, 0}
  ] &
];

Bu çok çabuk bir model ortaya koydu. İçin yukarı kaldırılması için çalışan bir gelen pasajı almak için nkarakterler kullanabilirsiniz (m0x){n}m0nerede molduğunu n+1ve xya bir mya 0. Bu nedenle, aşağıdakilerin tümü iki karaktere kadar çıkarmaya çalışır:

30030030
30030330
30330030
30330330

Ben bu kanıtlamak mümkün olduğuna emin değilim, ama basitçe doğruladıktan niçin yukarı 7. Elbette, bu sadece n+1tek bir rakam olarak temsil edebildiğimiz sürece çalışır ve Befunge 98'deki en büyük rakam f15 olanı temsil eder. Bu yüzden yaklaşımım bununla sınırlı n = 14. Birisi deltayı güvenilir şekilde daha büyük bir değere ayarlamanın bir yolunu bulursa n+1, bu radyasyonla sertleştirilmiş kinin sırasını süresiz olarak artırmak mümkün olabilir.

Gerçek koda bakalım. Temelde iki bölüm var. Önce deltayı (15,0)az önce söylediğim gibi ayarladık :

f00f00f00f00f00f00f00f00f00f00f00f00f00f00f0xxxxxxxxxxxxxxx

Ve kodun geri kalanında her komut 15 defa tekrarlanır ve kaynak yazdırılır. Tekrarı kaldırırsak, şöyle görünür:

"f'0\'0\'f\1-:!!0a-b-*j$'+k,3k$0{'8u'!1+'x#;:!k@dk:ek,;

"Bu dize modunu başlatır etrafında tamamlamasından sonra tekrar yığını ve uçları dize modu üzerine (kendisi hariç) tüm karakterleri iter: Standart 2D quining tekniğidir. Bu, ikinci yarının tüm kod noktalarını almamıza yardımcı olur, ancak ilk yarıdan yararlı bir şey elde etmemize neden olmaz, çünkü f00f00...f0bit boyunca yalnızca iki karakter kaydeder (hangi karakterlerin fveya 0hangi karakterlerin silindiğine bağlı olabilir) ). Ancak bu kısım 15 kez tekrarlanan karakterlerden oluşmadığından, yine de ayrı olarak yazdırmamız gerekir.

Daha uygun, modifiye edilmemiş Quine'ın içinde, bir şeridinin uzunluğu daha önce "olduğu -1 (mod 15). Bu garanti ki (14 kadar) birçok karakter o, kaldırma nasıl olursa olsun numarası kayıtlı karakterlerin daima 3 (tane var xve iki fve 0). Bu aslında 14'e kadar herhangi bir radyasyon emri için geçerlidir.

Şimdi f00f00...f0parçayı yazdırarak başlıyoruz :

f'0\'0\'f\1-:!!0a-b-*j$'+k,

f          Push 15, a loop counter.
'0\'0\'f\  Put "00f" underneath the loop counter.
1-         Decrement the loop counter.
:!!        Copy it, and turn it into a 1 if it's positive.
0a-b-      Push -21.
*          Multiply by 0 if the loop counter is zero, or by 1 otherwise.
j          Jump that many steps. If the value was 0, this is a no-op and
           the loop ends. Otherwise, this brings us back after the f.
$          Pop the loop counter (which is now 0).
'+k,       Print the top of the stack 43 times, which gives us all of
           the "f00f00...f0" and leaves one "0" on top of the stack.

Bir sonraki 3k$basitçe bunu programın başından itibaren 0itilen üç karakterin yanı sıra atıyor ". Yığın şimdi yalnızca karakterlerden sonra, hangi karakterlerin silindiğine bağlı olarak "orijinalin altındaki bazı önemsiz öğeleri f00f00...f0içerir.

Şimdi sadece yığının üst kısmını (kalan karakterleri içeren) ters çevirip her birini 15 kez basmamız gerekiyor.

0{     Start a new, empty stack. This pushes two zeros onto the original stack.
'8u    Move the top 56 values from the original stack to the new one, which
       is the 54 characters after the " as well as those two zeros. This is
       implemented as pop-push loop, so it reverses the order of those elements.
'!1+   Push a " by incrementing a !.
'x     Push an x. Now we've got all the characters that are repeated 15 times.
#;     Enter a loop. This is a standard technique for Befunge-98: the ; is
       a bit like a comment character, that ignores everything until the next
       ;, but we jump over the first one with #, so that from now on only
       the code inside will be executed (over and over).
  :!     Copy the top of the stack, and compute logical NOT (1 if 0, 0 otherwise).
  k@     Terminate the program that many times (i.e. when the top of the
         stack is zero).
  dk:    Make 14 copies of the top of the stack.
  ek,    Print 15 characters from the top of the stack.
;

Ve bu kadar. :)


16

JavaScript (ES6), 927 bayt, n = 1, puan = 859329

Not: Bunu çalıştırmak için bir REPL (tarayıcı konsolu gibi) kullanmayın.

Bu, kod uzunluğu bir etken olmadan yazılmıştı, bu yüzden henüz golf oynamadı.

Bu çok zordu ve ayrıntılı bir açıklamayı hak ediyor. Daha sonra yazacağım, bu mücadeleyi biraz daha keşfettikten sonra!

etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;
setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

not: Sonunda yeni bir satır var.

Temel olarak, ilk satır, tüm yanlış yazımları setTimeoutgeçerli fonksiyonlarla yeniden adlandırmak için dikkatlice yapılandırılmıştır , böylece bir karakter birinden setTimeoutsilinirse, kod hata vermez ve kopyalanmamış sürüm çalışabilir. Ayrıca, herhangi bir karakter ilk satırdan kaldırılırsa hata oluşmayacak ve kodun geri kalanının etkilenmeden çalışabileceği şekilde yazılmıştır.

İkinci ve üçüncü bloklar tam olarak eşdeğerdir. Biri tamamlanmaya çalışırsa, _değişkeni diğerinin sırayı kopyalamamasını bilecek şekilde ayarlar . Bu bloklardan biri hata verirse, diğer bloku etkilemez, çünkü zaman uyumsuz olarak kullanıldı setTimeout. Hata _ayarlanmamasına neden olur , böylece diğer blok başarılı bir şekilde sonlandırılır. Ana kod, kaldırma işlemi olmadığından emin olmak için her blokta uzunluk kontrolü yapılan bir dizedir.

Bir sonraki satırdaki şablon dizileri, şablon dizelerinin sonundaki bazı yorumlar ile birlikte, şablon dizesini oluşturan geri tepmelerden birinin çıkarılması durumunda, kodun hata yapmalarını önler. Bitiş backtick kaldırılırsa, şablon dizesi yorumdaki backtick tarafından sonlandırılır. Başlangıç ​​backtick'i kaldırılırsa, setTimeout atanmamış bir işlev olarak değerlendirilir (no-op) ve kod, setTimeout olmadan normal şekilde çalışır. Bitiş backtick başka bir yorum tarafından geçersiz kılındı.


Ne dedin sen? Denemek ister misin? Daha fazla konuşma!

Tam sayfa modu önerilir.

Giriş kutusunu yoksay, bu pasaj giriş yapmaz.

Herhangi bir karakteri koddan çıkarmayı deneyin!

İnanmıyor musun? Normal kod hala çalışmaya devam edecek (ancak bu işe yaramayacak ...) Gibi bir şey deneyin console.log(5)!

not: REPL özelliğini devre dışı bırakmak için pasajın hafifçe değiştirilmesi gerekiyordu, bu yüzden yalnızca bu yanıt için birden fazla çıktı özelliğini kaldırdım.

etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;
setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`
<!--                               Try the test suite below!                              --><strong id="bytecount" style="display:inline; font-size:32px; font-family:Helvetica"></strong><strong id="bytediff" style="display:inline; margin-left:10px; font-size:32px; font-family:Helvetica; color:lightgray"></strong><br><br><pre style="margin:0">Code:</pre><textarea id="textbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><pre style="margin:0">Input:</pre><textarea id="inputbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><button id="testbtn">Test!</button><button id="resetbtn">Reset</button><br><p><strong id="origheader" style="font-family:Helvetica; display:none">Original Code Output:</strong><p><div id="origoutput" style="margin-left:15px"></div><p><strong id="newheader" style="font-family:Helvetica; display:none">New Code Output:</strong><p><div id="newoutput" style="margin-left:15px"></div><script type="text/javascript" id="golfsnippet">var bytecount=document.getElementById("bytecount");var bytediff=document.getElementById("bytediff");var textbox=document.getElementById("textbox");var inputbox=document.getElementById("inputbox");var testbtn=document.getElementById("testbtn");var resetbtn=document.getElementById("resetbtn");var origheader=document.getElementById("origheader");var newheader=document.getElementById("newheader");var origoutput=document.getElementById("origoutput");var newoutput=document.getElementById("newoutput");textbox.style.width=inputbox.style.width=window.innerWidth-50+"px";var _originalCode=null;function getOriginalCode(){if(_originalCode!=null)return _originalCode;var allScripts=document.getElementsByTagName("script");for(var i=0;i<allScripts.length;i++){var script=allScripts[i];if(script.id!="golfsnippet"){originalCode=script.textContent.trim();return originalCode}}}function getNewCode(){return textbox.value.trim()}function getInput(){try{var inputText=inputbox.value.trim();var input=eval("["+inputText+"]");return input}catch(e){return null}}function setTextbox(s){textbox.value=s;onTextboxChange()}function setOutput(output,s){output.innerHTML=s}function addOutput(output,data){output.innerHTML='<pre style="background-color:'+(data.type=="err"?"lightcoral":"lightgray")+'">'+escape(data.content)+"</pre>"}function getByteCount(s){return(new Blob([s],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"})).size}function onTextboxChange(){var newLength=getByteCount(getNewCode());var oldLength=getByteCount(getOriginalCode());bytecount.innerHTML=newLength+" bytes";var diff=newLength-oldLength;if(diff>0){bytediff.innerHTML="(+"+diff+")";bytediff.style.color="lightcoral"}else if(diff<0){bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgreen"}else{bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgray"}}function onTestBtn(evt){origheader.style.display="inline";newheader.style.display="inline";setOutput(newoutput,"");setOutput(origoutput,"");var input=getInput();if(input===null){addOutput(origoutput,{type:"err",content:"Input is malformed. Using no input."});addOutput(newoutput,{type:"err",content:"Input is malformed. Using no input."});input=[]}doInterpret(getNewCode(),input,function(data){addOutput(newoutput,data)});doInterpret(getOriginalCode(),input,function(data){addOutput(origoutput,data)});evt.stopPropagation();return false}function onResetBtn(evt){setTextbox(getOriginalCode());origheader.style.display="none";newheader.style.display="none";setOutput(origoutput,"");setOutput(newoutput,"")}function escape(s){return s.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}window.alert=function(){};window.prompt=function(){};function doInterpret(code,input,cb){var workerCode=interpret.toString()+";function stdout(s){ self.postMessage( {'type': 'out', 'content': s} ); }"+" function stderr(s){ self.postMessage( {'type': 'err', 'content': s} ); }"+" function kill(){ self.close(); }"+" self.addEventListener('message', function(msg){ interpret(msg.data.code, msg.data.input); });";var interpreter=new Worker(URL.createObjectURL(new Blob([workerCode])));interpreter.addEventListener("message",function(msg){cb(msg.data)});interpreter.postMessage({"code":code,"input":input});setTimeout(function(){interpreter.terminate()},1E4)}setTimeout(function(){getOriginalCode();textbox.addEventListener("input",onTextboxChange);testbtn.addEventListener("click",onTestBtn);resetbtn.addEventListener("click",onResetBtn);setTextbox(getOriginalCode())},100);function interpret(code,input){_=undefined;window={};alert=function(s){stdout(s)};window.alert=alert;console.log=alert;prompt=function(s){if(input.length<1)stderr("not enough input");else{var nextInput=input[0];input=input.slice(1);return nextInput.toString()}};window.prompt=prompt;(function(){try{_=undefined;eval(code);if(typeof evalResult=="disabled_function_evaluation"){var callResult=evalResult.apply(this,input);if(typeof callResult!="undefined")stdout(callResult)}}catch(e){stderr(e.message)}})()};</script>

Daha iyi bir açıklama gelecek. Bu arada, beni herhangi bir yorum / soru / eleştiri ile jrich sohbete atmaktan çekinmeyin!


ah tamam, boğmaca: |
Downgoat

4
Yerine thiskullanın window.
Mama Fun Roll

3
Hayatın anlamını kaynak kodunuza dahil etmek için +1
Cyoce
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.