Dilinizi yorumlayın ama kendiniz değil mi?


21

X'in basit bir dil olduğu "X'i yorumla" diyen birçok zorluk var. Bence bu çok sıkıcı. Tüm erteleyen insanlara internetteki ilginç şeyler yapmak için bu zorluğu deneyebilirsiniz:

Meydan okuma

Bir dil seçiniz $LANG. $LANGherhangi bir turing tam programlama dili veya bir programlama dilinin turing tam bir alt kümesi olabilir. Dilinizi $LANGyorumlama için bir özelliğini atlarsanız , gönderiminiz de yazılı olması gerektiğinden, kendi programınız için kullanmamalısınız $LANG.

İçin $LANGyazılmış bir derleyici / tercüman yazın $LANG. evalBu derleyiciyi yazmak için kullanabileceğiniz dildeki tüm olanakları ( ve arkadaşlarınız dahil ) kullanabilirsiniz. Görevi daha zorlaştırmak için bir kısıtlama var: Programınız $LANG, tercüman / derleyiciniz dışındaki tüm geçerli programları yorumlayabilmeli / derleyebilmelisiniz . Yorumlanacak / derlenecek programın tercümanınız veya derleyicinin kendisi olduğu (dosya adından bağımsız olarak) ortaya çıkarsa, programınız tercüman veya derleyicinin işlevselliği ile tamamen ilgisiz bir şey yapmalıdır (çentikleme veya baskı gibi Hello, world!).

Bu görevi daha da karmaşık hale getirmek için, programınız derlenirken veya yorumlanırken kendi kaynağını okumamalıdır.

Özellikler

  • Bu görev kod golfü. Doğru olan en az karakter içeren gönderim kazanır. Beraberlik durumunda ilk verilen çözüm kazanır.
  • Programınız / betiğiniz bir dosyadan yorumlanacak programı okumalıdır. Yolunu ve adını kodlayabilirsiniz. Dosya okunduğunda, dosyayı başka bir dosyaya (sisteminizde çalıştırılabilir olması gerekir) derleyebilir veya doğrudan çalıştırabilirsiniz. Eğer $LANGdosya okuma yetenekleri yoksun sen uyan bu kodu okumak için başka bir yol seçebilir $LANG. $LANGBaşka bir dilin altkümesi olarak değil, dosya okuma yetenekleri kaldırılmış olarak seçebilirsiniz .
  • Her zamanki kod golf kuralları geçerlidir. Şöyle ki: Sadece bu zorluğu çözmek için oluşturduğunuz kişisel evcil hayvan diliniz, çözümü kullanarak önemsiz hale gelirse (örneğin, çözümü tam olarak uygulayan tek bir char programı tanımlamak gibi) yasaktır. Kuralların kötüye kullanılması teşvik edilir.

Tamamen devam ettiği sürece, bunun için bir dil tanımlamamız mümkün mü?
Cruncher

@Cruncher Evet, sen. Daha fazla ayrıntı için teknik özelliklerin son madde işaretine bakın.
FUZxxl

Yanıtlar:


8

Ruby, 63

b=$<.read
t="b=$<.read\nt=%p\nb!=t%%t&&eval(b)"
b!=t%t&&eval(b)

Daha küçük bir çözüm olmadığı sürece cevap kabul edilmiştir.
FUZxxl

11

Perl, 89 karakter, hile yok

$_=q($_=q(Q);s/Q/$_/;($q=join"",<>)eq$_?die:eval$q);s/Q/$_/;($q=join"",<>)eq$_?die:eval$q

Bu kodun "kendisi" olarak neyin sayılacağı konusunda oldukça seçici olduğuna dikkat edin. Özellikle, girişte takip eden yeni satırlar veya başka fazladan boşluklar varsa, kendisini tanımayacaktır. Test etmek için, (örneğin) adlı bir dosyaya kaydedin unquine.plve şunu yapın:

$ perl unquine.pl unquine.pl
Died at unquine.pl line 1, <> line 1.

Unutmayın, unquine.pldosya tam olarak 89 bayt uzunluğunda, daha fazla değil, daha az olmalıdır. Girdi olarak başka bir Perl betiğiyle çalıştırmak sadece diğer betiği de gerektiği gibi çalıştırır:

$ perl unquine.pl hello.pl
Hello, world!

Adından da anlaşılacağı gibi, uygulama bir ineğe dayanıyor - özellikle şu:

$_=q($_=q(Q);s/Q/$_/);s/Q/$_/

Bu kod $_kendine eşittir; Programın geri kalan kısmı (elbette içeride kopyalanmalıdır $_) yalnızca $_girdiyle karşılaştırılır , aksi takdirde girdiyi eşleştirir ve değerlendirirse ölür.


Bunu &&/ ;çiftini bir üçlü ile değiştirebilirsiniz (bir karakter kapalı, sorgulama iki katına çıkar). Harika fikir ve uygulama!
JB

@JB: İyi yakalayın! Şimdi 89 karaktere kadar.
Ilmari Karonen

5

GolfScript, 30 karakter

{`".~"+"#{$<.read}".@=!{~}*}.~

Bu program, komut satırında adlandırılmış bir dosyanın içeriğini okur ve yukarıdaki kodla tam olarak eşit değilse, dosyayı GolfScript olarak yorumlar. Girdi yukarıdaki koda tam olarak eşitse, basitçe değişmeden yazdırılır (sonuna eklenen yeni bir satır hariç).

Bu, kendi kendini tanımlayan programın oldukça basit bir uyarlamasıdır . özellikle:

  • { } GolfScript'te bir kod bloğudur.
  • .~, bir kod bloğuna uygulandığında, bloğu çoğaltır ve kopyayı yürütür.

Kod bloğunun içinde:

  • ` kod bloğunun kopyasını siler.
  • ".~"+.~Programın kaynak kodunu içeren bir dize vererek karakterleri ona ekler .
  • "#{$<.read}"Golf kodları içerisinde Ruby kodunun çalıştırılmasına izin veren belgelenmiş bir bilgisayar korsesidir. Bu durumda, Ruby komutunu $<.read(utanmadan Lowjacker's Ruby çözümünden çalınan) yürütür ve komut satırında belirtilen dosyaların içeriğini okur ve döndürür. Bu kesmek gereklidir, çünkü GolfScript'in kendisi açık bir dosya G / Ç özelliği sunmaz.
  • .@ yığının üstündeki öğeleri çoğaltır ve karıştırır, böylece yığında dosya içeriğinden iki kopya ve ardından bu programın kaynak kodu bulunur.
  • =! Yığındaki en üstteki iki öğeyi (örneğin, dosya içeriği ve kaynak) karşılaştırır, farklıysa 1, aynı ise 0 döndürür.
  • {~}*dosya içeriğinin kalan kopyasını GolfScript kodu olarak değerlendirir, ancak yalnızca karşılaştırmanın sonucu 1 ise (Teknik olarak, kod bloğunu {~}yığındaki sayı ile belirtilen sayıda, yani 0 veya 1 kez yürütür . blok, ~GolfScript eval operatörüdür.)

Ps. Stdin'den çalıştırılacak kodun okunmasına izin veriliyorsa, bu zorluk Ruby'ye zorlanmadan 21 karakterde çözülebilir :

{`".~"+1$=!{""\~}*}.~

Bu program stdin'den bir girdi dizgisini okuyacak ve eğer kendi kaynağına uymuyorsa, onu boş bir girdi ile çalıştırır. Yukarıdaki program gibi, kaynakla eşleşen girdi de basitçe geri çevrilir.


Güzel görünüyor, ancak bir dosyadan girdi okumak gibi görünmüyor.
FUZxxl

Sabit, şimdi Lowjacker'in çözümü gibi bir dosyadan (tam olarak) okuyor.
Ilmari Karonen

5

Python, 167 130 118 bayt

Bu benim ilk golf denemem, işte burada! Kendisi dışındaki herhangi bir programı yorumlar.

Gelişmiş versiyon:

i=open(raw_input()).read();q='i=open(raw_input()).read();q=%s;i==q%%repr(q)and a;exec(i)\n';i==q%repr(q)and a;exec(i)

Kendisi alırsa o zaman ile şunları yapar:

Traceback (most recent call last):
  File "pygolf.py", line 1, in <module>
    i=open(raw_input()).read();q='i=open(raw_input()).read();q=%s;i==q%%repr(q)and a;exec(i)\n';i==q%repr(q)and a;exec(i)
NameError: name 'a' is not defined

Bu çözümün Ilmari Karonen'in yaptığı gibi çalıştığını düşünüyorum, temel fikir şunun gibi:

input = read_some_file()
if input == some_quine()
    barf()
interpret(input)

Kullandığım quine şuydu:

(lambda x: x + repr((x,)))('(lambda x: x + repr((x,)))',)

Ama o zamandan beri çok daha kısa bir quine olduğunu anladım:

q='q=%s;q%%repr(q)';q%repr(q)

Etkileşimli python kabuğuna izin verirseniz, bu durumda daha kısa olabilir, bu durumda şunları yapabilirsiniz:

'%s;_%%repr(_)';_%repr(_)

Python komut satırlarını bulmak için kısa bir yol almadığından, raw_input () ile gittim (bu hala oldukça uzun, ama sürece

import sys;sys.argv[1]

Kullanım:

echo "foobar.py" | python quinterpretter.py

veya

python quinterpretter.py
<type filename and hit enter>

Kullanmak için daha kısa bir çene buldum, fakat işte eski versiyonum (posterity için):

i=open(raw_input()).read();a if i==(lambda x,y:x+repr((x,y))+y)('i=open(raw_input()).read();a if i==(lambda x,y:x+repr((x,y))+y)', ' else 1;exec(i)\n') else 1;exec(i)

% S% r ile değiştirin ve repr öğesini kaldırın. % r, ham anlamına gelir ve temelde aynı şeydir.
Loovjo

4

Javascript kullanarak bir dosyadan tam olarak okuyamıyorum (tamam, yapabilirim, HTML5 FileReader olayını kullanarak, ancak bu işleri ihtiyacımdan daha karmaşık hale getirir). Yani, bu bir Javascript programını string olarak kabul eden ve çalıştıran bir fonksiyondur.

Bu muhtemelen olması gerektiği gibi golf değil, ama yine de burada:

Javascript, 252

function c(p){q='\"';s='\\';a="function c(p){q='\"';s='\\';a=%;a=a.slice(0,17)+s+a.slice(17,24)+a[23]+a.slice(24);a=q+a.replace('%',q+a+q)+q;alert(a);}";a=a.slice(0,17)+s+a.slice(17,24)+a[23]+a.slice(24);a=a.replace('%',q+a+q);alert(a);if(p!=a)eval(p)}

Javascript’te quine oluşturmak için daha iyi bir teknik bilen varsa bana haber verin.


1
Kodunuza ve Perl çözümüme dayalı olarak aşağıda 135 karakterlik bir JS çözümü yayınladım. İlham için +1!
Ilmari Karonen

2
read p<p;read c<c;[ "$p" = "$c" ]||. ./c

45 karakter sh (POSIX kabuğu). Çalıştırılacak kodun dosyada olması gerekir ./c.

Tercüman kodunun dosyada olması gerekiyor ./p, sanırım meydan okumayı yasaklamış gibi görünmese de, aldatmıştım. Yoksa bu, "dilimi" "eksiksiz bir programlama dili" olmaktan diskalifiye eder mi?

Normalde harici bir çalıştırılabilir olan ancak teorik olarak kabuğun içine yerleştirilmiş bir araç kullanarak, kod kısaltılabilir:

cmp -s p c||. ./c

Bu 18 karakter ve -s bit sadece geçerli (kendi kendine olmayan) programlar için yazdırılacak olan bir satırı bastırmak içindir.

Ve sonra her zaman daha kısa ve özlü sözdizimine sahip bir kabuk dili sürümü oluşturabilirsiniz.

Ve sonra giriş, tek bir '.' Den oluştuğunda, her zaman bir program oluşturabilirsiniz. - cehennem, boş dize - başka bir dosyanın içeriğini normal kod olarak değerlendirir ve buna programlama dili der. Yani boş dize, sizin oluşturduğunuz dilde bu zorluğun çözümü olacaktır. Aslında, işte böyle bir dilin tercümanı:

read code; if [ "$code" ]; then eval "$code"; else . ./othercode; fi

Yukarıdaki betiğin yorumladığı dili kullanarak çözüm boş dizedir. Ve kod konumunun artık kodlanmış olmasına gerek yok.

Sorun?


2
Buradaki zorluk "programınız kendi kaynağını okumamalıdır" diyor.
Ilmari Karonen

Kahretsin, biraz zaman boşa. Ve görüyorum ki, atlayacağınız özellikleri kullanmamanız gerektiğini söylüyor. Bu boş dize özelliğine karşı gider. Sonra tekrar, derleyici / tercüman kodunun kendisi yeni dilde farklı davranışa neden oluyorsa, tercümanın işlevselliği atlaması / değiştirmesi gerekir . Her durumda, yanlış yazarken eğlendim.
TaylanUB

@TaylanUB Aslında, tercümanın kendisi dışındaki tüm geçerli $ lang programlarını yorumlamanız gerekiyor.
FUZxxl

@FUZxxl Evet, "sh + boş dize" dil (kod boş dize değilse) ve ayrıca yorumlamaktadır sh kodu (koymak gereken İçinde yazılı boş dize programı sh aksi takdirde eşdeğerdir ./othercode) ve yapar kod boş dize olduğunda hiçbir şey. Dosyayı aramamalıydım. /Othercode, yanıltıcı; sadece boş dize dilinde yazılmış tercümanın yorumlayacağı koddur.
TaylanUB

2

JavaScript, 135 karakter

function c(p){q='function c(p){q=%27Q%27;p!=unescape(q).replace(/Q/,q)?eval(p):alert()}';p!=unescape(q).replace(/Q/,q)?eval(p):alert()}

Peter Olson'ın JavaScript çözümü, Perl çözümümü JS'ye aktarmamda bana ilham verdi. Çözümü gibi, bu kod da cbir dizgeyi kabul eden bir işlevi tanımlar ve yukarıdaki koda eşit değilse onu değiştirir.

JavaScript’te dengeli dize sınırlayıcılarının yokluğuyla başa çıkmanın iyi bir yolunu bulmam biraz zaman aldı, görüntünün ne olduğunu açık bir çözüm bulana kadar: unescape() .

Uygun bir şekilde, kodum ters eğik çizgi veya çift tırnak içermez, bu nedenle çift tırnaklı dizelerde güvenle saklanabilir. Bu, test etmeyi kolaylaştırır:

e = "function c(p){q='function c(p){q=%27Q%27;p!=unescape(q).replace(/Q/,q)?eval(p):alert()}';p!=unescape(q).replace(/Q/,q)?eval(p):alert()}"
h = "alert('Hello, world!')"

eval(e)  // defines the function c()

c(h)     // evaluates h
c(e)     // does not evaluate e, alerts "undefined" instead

Uyarmak yerine hiçbir şey yapmamak için alert()ile değiştirebilir ve 13 karakter kaydedebilirsiniz. 0undefined
Peter Olson

@PeterOlson: Evet, ancak görev kendini algılarsa “programın tamamen ilgisiz bir şey yapması gerektiğini” söylüyor. Bir şey yapması gerektiği anlamına gelir - tercihen kullanıcıya görünür bir şey varsayalım. Ayrıca, daha iyi bu şekilde seviyorum. :) (Ps. Yay, dışarıda kar yağıyor! Kış sonunda burada!)
Ilmari Karonen

1
@Ilmari Hiçbir şey yapmamak, Javascript IMHO yorumlamasıyla ilgili değildir.
FUZxxl

Sen gidip p=>...yerinefunction c(p)
FireCubez

2

Ortak Lisp, 59

#+~ #.(#:a)(defun L(p)(compile-file p))(push :~ *features*)
  • Yeni bir Lisp REPL'de dosyanızı derleyin (örn. sbcl --load)
  • Artık LCommon Lisp dosyalarını derleyebilecek bir fonksiyonunuz var.
  • Ancak, ararsanız (L <your file>), dosyayı okurken bir hata bildirilir .

Niye ya?

Çünkü ilk defa, :~anahtar kelimeyi içine zorladınız *features*. Şimdi, ortamınız ~özellik hakkında bilgi sahibi ve okuyucu makrosu #+, ~ özellik ifadesini değerlendirdikten sonra , ilk kez olduğu gibi atlamak yerine aşağıdaki formu başaracak ve okuyacak. Senin dosyasında aşağıdaki formu #.(#:a)değerlendirmek ister ki (#:a)de okuma-time ve kod okunduğunu olarak ortaya çıkan değeri kullanın. Ancak (#:a), iç sembolü ile ilişkilendirilmiş işlevi çağırır #:a. İnternete #:agirmediğinden, hiçbir fonksiyona bağlı olmayan taze bir simgedir (yanifboundp ) . Hata.


1

Şema, 48 veya 51 karakter

Şema, birçok farklı uygulamaya sahip bir dildir. En son RnRS'ye uymak zorunda olan uygulamalara rağmen, en son çalışma standardı (R6RS) minimalizm olmamasından dolayı popüler değildi. R7RS, dili 2'ye böldüğünde yakında bir çözüm olarak yayınlanacak. İlk dilin güçlü ve minimalist olması ve ikincisi, uygulamalar arasında birlikte çalışabilirlik için özellik uzantıları sağlamayı amaçlayan ilkenin bir süperseti. O zamana kadar, SRFI'lere (Uygulama için Düzenleme İstekleri) güveniyoruz, bu da (ev sahibi uygulamasında veya manuel olarak (düzende ortak olduğu gibi) uygulanırsa) ortak görevleri yerine getirmek için bir araç sağlıyor. Bütün bunlar, ilk kod parçacığının (51 karakter), olabildiğince taşınabilir halde kalırken, komut satırı argümanlarına erişim için SRFI-22'ye (UNIX'te şema komut dosyalarını çalıştırarak) dayandığını söyler:

(define(main x y)(case y(x => error)(else => load)))

veya daha fazla okunabilir şekilde:

(define (main current-file arg)
  (case arg
    [current-file => error]
    [else => load]))

İkincisi (48 karakter), kendisini (boş bir ortamda) değerlendiremeyen yorumu yapmak için dosyasız bir araçtır:

(define(e)(write(eval(read)null-environment))(e))

veya daha fazla okunabilir şekilde:

(define (interpret)
  (write (eval (read) null-environment))
  (interpret))

Tercümanınızı kopyalarsanız, kodunuz çalışmaz.
FUZxxl

1
İç içe parantez içinde nesnesini içerecek şekilde bir şema cevabına bırakın
Cyoce

1

Groovy, 13 bayt

{Eval.me(it)}

Bu bir Groovy alt kümesini yorumlamalıdır.

test durumları:

p={Eval.me(it)}

p'''
    (0..37).each{println"1234567890JIHGFEDCBAKLMNOPQRST!?,.ZYXWVU"[it..it+2]}
'''

p'''
    {Eval.me(it)}
'''

Ne yazık ki kesinlikle engel olsa da, bunu tamamen tercüman gibi yapar ve oldukça fazla giriş yapar.


Yorumlanacak programı hangi satırda okuyorsunuz? Bu görev için geçerli bir başvuru olmasa da kodunuz ilginç.
FUZxxl

Hatanın "özyineleme sınırı aşıldı" gibi bir şey olduğunu varsayıyorum?
Ilmari

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.