Mutant pangolin


28

Bu, makine öğrenmesini göstermek için kendini değiştiren bir quine veya quine gibi çalışan bir program tasarlamanız gereken bir kod-golf mücadelesidir.

Arka fon

Burada tarif edilen 'pangolin oyunu' adı verilen temel bir yapay zeka programı var . Temel fikir şudur: Program ilk kez çalıştırıldığında şunu sorar:

Tamam, lütfen bir şey düşün

Bir pangolin mi?

Daha sonra her ikisine de cevap verebilirsiniz:

Evet

Bu durumda diyor ki:

İyi. Bu çok kolaydı.

Ya da değilse:

Ah. O zaman sen kazandın - Ne düşünüyordun?

Söyleyeceğiniz şey:

bir köpek

Söyleyeceği şey

Lütfen bana bir köpek hakkında bir soru verin, böylece bir köpekle pangolin arasındaki farkı anlatabilirim

cevap verebilirsin

Karıncaları yer mi?

Sonra soracaktı:

Bir köpeğin cevabı nedir?

Söyleyeceğin şey

yok hayır

Ve söylerdi

Teşekkürler

Bir dahaki sefere çalıştığında, yukarıdaki soruyu soracak ve bu gibi sorulardan oluşan bir ikili ağacı oluşturacaktı.

Meydan okuma

Arka plan yeterli. Bu zorluk kendi kendini değiştiren bir pangolin programı yazmaktır. Kurallar aşağıdaki gibidir:

  1. Program çıktısı (yukarıda açıklandığı gibi) olmalıdır STDERR. Nihai yanıt her zaman "İyi. Bu çok kolaydı." Olacaktır. veya "Teşekkürler". Bundan sonra, programın geçerli sürümünü veya soruyu içeren programın yeni bir sürümünü çıkarmalıdır STDOUT. Yazmayı STDOUTve STDERRokumayı desteklemeyen bir dilde yazılmış hiçbir cevap STDINgeçerli olmayacaktır.

  2. Başka bir deyişle UNIX’in altındaki programı şu şekilde çağırabilirsiniz:

örnek:

$ mylanguage myprogram > myprogram.1
[dialog goes here]
$ mylanguage myprogram1 > myprogram.2
[dialog goes here]
  1. Program tam olarak belirtilen istemleri kullanmak zorundadır (çünkü istemleri kısaltmak beceri gerektirmez). Bilgi istemleri (tırnak işaretleri olmadan ve% s'nin yerine kullanıldığı yerde) aşağıdaki gibidir:

liste:

"OK, please think of something"
"Is it %s?"
"Good. That was soooo easy."
"Oh. Well you win then -- What were you thinking of?"
"Please give me a question about %s, so I can tell the difference between %s and %s"
"What is the answer for %s?"
"Thanks"
  1. Evet / hayır cevabı bekliyor zaman, programın kabul etmeli yya da yes'evet' için her durumda, ve nya no'hayır' için her durumda. Uygun olmayan girişlerle yaptığınız işlem size bağlıdır. Örneğin , 'evet' ile başlayan yveya Yhayır olarak başlayan herhangi bir cevabı almaya karar verebilirsiniz .

  2. Verilen şeylerin adlarının ve soruların yalnızca ASCII harfleri, sayıları, boşlukları, kısa çizgileri, soru işaretlerini, virgülleri, tam durakları, iki noktalı virgülleri ve noktalı virgülleri içerdiğini, yani regex'i takip ettiklerini varsayabilirsiniz ^[-?,.;: a-zA-Z]+$. Bundan daha fazlasıyla başa çıkabiliyorsanız (özellikle seçtiğiniz dilde alıntı karakterleri), kendini beğenmiş gibi görünüyorsun ama fazladan puan kazanmıyorsun.

  3. Herhangi bir dosyayı okumak veya yazamayabilir Programınız (hariç STDIN, STDOUTve STDERRya ağdan,); özellikle diskten kendi kodunu okuyabilir veya yazamaz. Durumu program kodunun kendisine kaydedilmelidir.

  4. Program çalıştırmak ve düzgün yanıtı tahmin edildiğinde, gereken , bir Quine'ın tam olarak gerçekleştirmek o kadar yazmalıdır yani STDOUTtam olarak kendi kod değişmeden.

  5. Program çalıştırın ve hatalı yanıtı tahmin edildiğinde, gereken onu kendi kodu içinde sağlanan yeni bir soru-cevap kodlamak ve yazmak STDOUTkendi özgün tahmin ve sağlanan yeni nesne arasındaki ayrım yapabilen bu yüzden de, kendi kodunda önceden verilen tüm nesneler arasında ayrım yapmaya ek olarak.

  6. Yazılımın birden fazla sıralı çalışmasıyla başa çıkabilmeniz gerekir, böylece birçok nesneyi öğrenir. Çoklu çalışma örnekleri için buraya bakınız .

  7. Test çalışmaları kafadaki bağlantıda verilmiştir (açıkçası sadece STDINve STDERRdiyaloğu kapsar).

  8. Standart boşluklar hariçtir.


Program birden fazla kez mutasyona uğramalı ve 2'den fazla hayvanı destekleyebilmeli mi? Öyleyse , programın bildiği iki veya daha fazla hayvan olduğunda diyalogda "Lütfen bana bir soru verin ..." diyaloğu verebilir misiniz ?
Cristian Lupascu

Kullanıcı sadece "bir köpek" yerine "köpek" diyorsa? "A / an" ı belirleme cümlesini çözümleyelim mi yoksa cevabı tam anlamıyla ele alabilir miyiz? Sanırım verdiğin bilgiler verildiğinde (% s).
coredump

1
@ Coredump kullanıcı "köpek" değil "köpek" diyorsa, o zaman cevaplar dilbilgisi olmayacak. Bu bir sorun değil.
saat

1
Oof. Runic'te bunu yapmaya çalışmak bir kabus olurdu. Birincil neden, tüm bitlerin isteğe bağlı giriş dizileriyle başa çıkmak için kablolanmasının (sonuçta ortaya çıkan çıktı programında dizgenin değişmezleri olması gerekir) temelde imkansız olurdu. Oh ve Runic STDERR'ye çıkış yapamıyor.
Draco18

1
Bu eğlenceli bir oyun gibi gözüküyor, golf oynamak yerine, Pangolin Oyununu kalbinizin içeriğine göre çalabileceğiniz bir codepen hazırladım . Keyfini çıkarın!
Skidsdev

Yanıtlar:


20

Ortak Lisp, 631 576

(let((X"a pangolin"))#1=(labels((U(M &AUX(S *QUERY-IO*))(IF(STRINGP M)(IF(Y-OR-N-P"Is it ~A?"M)(PROG1 M(FORMAT S"Good. That was soooo easy.~%"))(LET*((N(PROGN(FORMAT S"Oh. Well you win then -- What were you thinking of?~%")#2=(READ-LINE S)))(Q(PROGN(FORMAT S"Please give me a question about ~A, so I can tell the difference between ~A and ~A~%"N N M)#2#)))(PROG1(IF(Y-OR-N-P"What is the answer for ~A?"N)`(,Q ,N ,M)`(,Q ,M ,N))(FORMAT S"Thanks~%"))))(DESTRUCTURING-BIND(Q Y N)M(IF(Y-OR-N-P Q)`(,Q ,(U Y),N)`(,Q ,Y,(U N)))))))(write(list'let(list`(X',(U x)))'#1#):circle t)()))

Örnek oturum

Komut dosyasını adlandırın pango1.lispve şu şekilde çalıştırın (SBCL kullanarak):

~$ sbcl --noinform --quit --load pango1.lisp > pango2.lisp
Is it a pangolin? (y or n) n
Oh. Well you win then -- What were you thinking of?
a cat
Please give me a question about a cat, so I can tell the difference between a cat and a pangolin
Does it sleep a lot?
What is the answer for a cat? (y or n) y
Thanks

Ayıyı ekleyen başka bir raunt:

~$ sbcl --noinform --quit --load pango2.lisp > pango3.lisp
Does it sleep a lot? (y or n) y

Is it a cat? (y or n) n
Oh. Well you win then -- What were you thinking of?
a bear
Please give me a question about a bear, so I can tell the difference between a bear and a cat
Does it hibernate?
What is the answer for a bear? (y or n) y
Thanks

Bir tembellik eklemek (cevabın "hayır" olduğu durumu test ederiz):

~$ sbcl --noinform --quit --load pango3.lisp > pango4.lisp
Does it sleep a lot? (y or n) y

Does it hibernate? (y or n) n

Is it a cat? (y or n) n
Oh. Well you win then -- What were you thinking of?
a sloth
Please give me a question about a sloth, so I can tell the difference between a sloth and a cat
Does it move fast?
What is the answer for a sloth? (y or n) n
Thanks

Son dosyayı test etmek:

~$ sbcl --noinform --quit --load pango4.lisp > pango5.lisp
Does it sleep a lot? (y or n) y

Does it hibernate? (y or n) n

Does it move fast? (y or n) y

Is it a cat? (y or n) y
Good. That was soooo easy.

Uyarılar

  • İlk önce baskıyı unuttum "Thanks", işte burada.
  • Gördüğünüz gibi soruları takip ediyor (y or n) ediyorum, bunun nedeni mevcut y-or-n-pfonksiyonu kullanıyorum . Gerekirse bu çıktıyı kaldırmak için cevabı güncelleyebilirim.
  • Common Lisp'in iki yönlü olduğu *QUERY-IO* kullanıcı etkileşimi ile ilgili akışa sahip, burada ne kullanıyorum. Standart çıktı ve kullanıcı etkileşimi karışıklık yaratmaz; bu da IMHO'yu sorunun özüdür.
  • SAVE-LISP-AND-DIEUygulamada pratik kullanmak daha iyi bir yaklaşım olacaktır.

Oluşturulan çıkış

İşte en son oluşturulan komut dosyası:

(LET ((X
       '("Does it sleep a lot?"
              ("Does it hibernate?" "a bear"
               ("Does it move fast?" "a cat" "a sloth"))
              "a pangolin")))
  #1=(LABELS ((U (M &AUX (S *QUERY-IO*))
                (IF (STRINGP M)
                    (IF (Y-OR-N-P "Is it ~A?" M)
                        (PROG1 M (FORMAT S "Good. That was soooo easy.~%"))
                        (LET* ((N
                                (PROGN
                                 (FORMAT S
                                         "Oh. Well you win then -- What were you thinking of?~%")
                                 #2=(READ-LINE S)))
                               (Q
                                (PROGN
                                 (FORMAT S
                                         "Please give me a question about ~A, so I can tell the difference between ~A and ~A~%" 
                                         N N M)
                                 #2#)))
                          (PROG1
                              (IF (Y-OR-N-P "What is the answer for ~A?" N)
                                  `(,Q ,N ,M)
                                  `(,Q ,M ,N))
                            (FORMAT S "Thanks~%"))))
                    (DESTRUCTURING-BIND
                        (Q Y N)
                        M
                      (IF (Y-OR-N-P Q)
                          `(,Q ,(U Y) ,N)
                          `(,Q ,Y ,(U N)))))))
       (WRITE (LIST 'LET (LIST `(X ',(U X))) '#1#) :CIRCLE T)
       NIL))

açıklamalar

Bir karar ağacı olabilir:

  • bir dize gibi "a pangolin" yaprağı temsil eden .
  • üç unsurdan bir listesi: kapalı olduğunu evet / hayır , soru bir dize olarak ve ve soruyla ilişkili iki olası altağaçlara vardır.(question if-true if-false)questionif-trueif-false

UFonksiyon yürür ve döner bir olasılıkla değiştirilmiş ağaç. Her soru sırayla, kullanıcı ile etkileşime girdiğinde kökten başlayarak bir yaprağa ulaşana kadar sorulur.

  • Bir ara düğüm için döndürülen değer (Q Y N)olan (Q (U Y) N)(sırasıyla. (Q Y (U N))Sorunun cevabı ise) Qolduğu Evet (sırasıyla. Yok ).

  • Bir yaprağın döndürülen değeri, programın cevabı doğru tahmin etmesi durumunda yaprağın kendisidir ya da kullanıcının aldığı değerlere göre yaprağın bir soru ve iki olası sonucu ile değiştirildiği rafine bir ağaçtır.

Bu kısım oldukça basitti. Kaynak kodu yazdırmak için kendinden referanslı kod oluşturmak için okuyucu değişkenleri kullanıyoruz.Ayarlayarak *PRINT-CIRCLE*True olarak , güzel baskı sırasında sonsuz özyinelemeden kaçınırız.Kullanarak hile WRITEile :print-circle Tolması da yazma son şeklidir ve bağlı olarak repl için değer döndürür belki işlevi böylece, bu standart varsayılan değer ile tanımlanır gibi REPL, dairesel yapılar ele etmezse *PRINT-CIRCLE*, sonsuz bir özyineleme olacak. Dairesel yapının REPL'e döndürülmediğinden emin olmamız gerekiyor, bu yüzden LET'in son konumunda bir NIL var. Bu yaklaşım sorunu büyük ölçüde azaltır.


İyi görünüyor! (y or n)Gerekli değildir, ama bu hali daha iyi olarak buna izin için cazip.
saat

@ abligh Teşekkürler. Y / n hakkında, bu iyi olurdu, yardımcı olur ve IMHO, istemleri kısaltmaktan kaçınmak üzere # 3 ile gerçekten çelişmez.
coredump

9

Python 2.7.6, 820 728 bayt

(Farklı sürümlerde çalışabilir, ancak emin değilim)

def r(O,R):
 import sys,marshal as m;w=sys.stderr.write;i=sys.stdin.readline;t=O;w("OK, please think of something\n");u=[]
 def y(s):w(s);return i()[0]=='y'
 while t:
  if type(t)==str:
   if y("Is it %s?"%t):w("Good. That was soooo easy.")
   else:w("Oh. Well you win then -- What were you thinking of?");I=i().strip();w("Please give me a question about %s, so I can tell the difference between %s and %s"%(I,t,I));q=i().strip();a=y("What is the answer for %s?"%q);w("Thanks");p=[q,t];p.insert(a+1,I);z=locals();exec"O"+"".join(["[%s]"%j for j in u])+"=p"in z,z;O=z["O"]
   t=0
  else:u+=[y(t[0])+1];t=t[u[-1]]
 print"import marshal as m;c=%r;d=lambda:0;d.__code__=m.loads(c);d(%r,d)"%(m.dumps(R.__code__),O)
r('a pangolin',r)

Common Lisp'in cevabı kadar kısa değil, ama işte bazı kodlar!


4

Python 3, 544 bayt

q="""
d=['a pangolin'];i=input;p=print
p("OK, Please think of something")
while len(d)!=1:
    d=d[1+(i(d[0])[0]=="n")]
x=i("Is it "+d[0]+"?")
if x[0]=="n":
    m=i("Oh. Well you win then -- What were you thinking of?")
    n=[i("Please give me a question about "+m+", so I can tell the difference between "+d[0]+" and "+m),*[[d[0]],[m]][::(i("What is the answer for "+m+"?")[0]=="n")*2-1]]
    p("Thanks")
    q=repr(n).join(q.split(repr(d)))
else:
    p("Good. That was soooo easy.")
q='q=""'+'"'+q+'""'+'"'+chr(10)+'exec(q)'
p(q)
"""
exec(q)

Çevrimiçi Deneyin!

Sorular / cevaplar / cevaplar, bir dizide saklanır, eğer dizi üç maddeyi (örn. ['Does it eat ants',['a pangolin'],['a dog']]) Saklarsa, soruyu cevaplar ve cevaba bağlı olarak sadece ikinci veya üçüncü öğenin içeriğini tekrar eder. Sadece bir maddeye sahip bir diziye ulaştığında, soruyu sorar ve kaynak kodunun tamamı bir dizgeye sahip olduğundan, yeni dal eklemek için diziye uzantı eklemek için split-join yöntemini kullanabilir. .

Ben aslında bunu gereklilik sırasındaki gerekliliği yerine getirmediğim için yazdım, bu yüzden soruyu tekrar okumak ve hem kodu yürütmek hem de onu bir dize olarak kullanmak için bir yol bulmak zorunda kalmak zorunda kaldım, ancak nihayetinde güzel bir şekilde genişletilebilir ince biçim biçimi fikrine tövbe ettim:

q="""
print("Some actual stuff")
q='q=""'+'"'+q+'""'+'"'+chr(10)+'exec()'
print(q)
"""
exec(q)

1

Python 3 , 497 bayt

t=["a pangolin"];c='''p=print;i=input;a=lambda q:i(q)[0]in"Yy"
def q(t):
  if len(t)<2:
    g=t[0]
    if a(f"Is it {g}?"):p("Good. That was soooo easy.")
    else:s=i("Oh. Well you win then -- What were you thinking of?");n=i(f"Please give me a question about {s}, so I can tell the difference between {s} and {g}.");t[0]=n;t+=[[g],[s]][::1-2*a(f"What is the answer for {s}?")];p("Thanks")
  else:q(t[2-a(t[0])])
p("Ok, please think of something");q(t);p(f"t={t};c=''{c!r}'';exec(c)")''';exec(c)

Harmless'ın ağaç temsiline verdiği cevaba oldukça benzer. Tek bir yanıt alıncaya kadar, tekrar tekrar listeye girerken bir sonraki soruyu sorar.

Ungolfed versiyonu (sorgulamadan)

tree = ['a pangolin']

def ask(question):
  answer = input(question + '\n')
  if answer.lower() in ['yes', 'no']:
    return answer.lower() == 'yes'
  else:
    print('Please answer "yes" or "no".')
    return ask(question)
    
def query(tree):
  if len(tree) == 1:
    guess = tree.pop()
    if ask(f'Is it {guess}?'):
      print('Good. That was soooo easy.')
      tree.append(guess)
    else:
      thing = input('Oh. Well you win then -- What were you thinking of?\n')
      new_question = input(f'Please give me a question about {thing}, so I can tell the difference between {thing} and {guess}.\n')
      answer = ask(f'What is the answer for {thing}?')
      print('Thanks')
      tree.append(new_question)
      if answer:
        tree.append([thing])
        tree.append([guess])
      else:
        tree.append([guess])
        tree.append([thing])
  else:
    if ask(tree[0]):
      query(tree[1])
    else:
      query(tree[2])
      
while True:
  input('Ok, please think of something\n')
  query(tree)
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.