Mastermind'i 6 ya da daha az hamle ile çözme


24

Amacınız, herhangi bir Mastermind bulmacasını 6 ya da daha az hamle ile çözecek bir program yazmaktır.

Arka fon

Beyni bir tahta oyunudur. Oyunun amacı, diğer oyuncu tarafından gizlenen 4 renkli mandalın kombinasyonunu (renkler ve sıra) tam olarak tahmin etmektir. Tahmin yapıldığında, diğer oyuncu 0 ile 4 arasında beyaz ve / veya kırmızı mandallarla tepki verir. Rengin ve yerin doğru olduğu yerde kırmızı bir mandal bulunur. Rengin kalan parçalarda temsil edildiği beyaz bir dübel, ancak yanlış yerdedir. Tahminde yinelenen renkler varsa, sırda karşılık gelen renk başına verilen yalnızca bir mandal olacaktır. (Yani - sır 1 Blue içeriyorsa ve tahmin doğru yerde bir tane olmak üzere 2 maviye sahipse, verilen bir kırmızı mandal olurdu). 6 farklı renk vardır ve kopyalar kullanılabilir.

Örneğin, bir oyun aşağıdaki gibi ilerleyebilir: (Çözümün Kırmızı Yeşil Yeşil Mavi olduğu varsayımıyla)

1:  Blue Purple Black Green - 2 white pegs
2:  Green Red Black Blue    - 2 white pegs, 1 red peg
3:  Green Green Green Blue  - 3 red pegs
4:  Red Green Green Blue    - 4 red pegs

Kurallar Wikipedia'da genişletildi

Gereksinimler

  • Program stdin'den okumalı ve stdout'a yazmalı
  • Basitlik için renkler yerine sayıları kullanacağım. Tahmin edilecek kombinasyon 1 ile 6 arasında 4 rakam olacaktır.
  • Tahminlerini, yeni bir çizgiyle sonuçlanan 1-6 arasında 4 boşlukla ayrılmış bir sayı dizisi olarak ortaya koymaları gerekir. Örneğin:

    1 5 2 2 \ n

  • Program daha sonra bir boşlukla ayrılmış ve yeni bir satırla sonuçlanan 2 ile 0 arasındaki 4 tamsayısının tahmin edilmesinden sonra girdi olarak alınacaktır. Birincisi beyaz mandal miktarı, ikincisi kırmızı mandal miktarı olacak.

  • "0 4" (4 kırmızı mandal) girişinde, program sonlandırılmalıdır
  • Program, herhangi bir bulmacayı 6 turdan daha kısa sürede çözebilmelidir (programınız çıktı verir, ardından cevap girişi 1 turdur). Daha az çözebilmek için bonus (ispat karmaşıklığı nedeniyle) yoktur.
  • Çözüm tamamen dahili olmalı ve kaynağa dahil edilmelidir. Sadece standart kütüphanelere izin verilir. Bu nedenle çözüm, başka dosyalara (sözlükler gibi) veya internete dayanmayabilir.

Örnek Giriş / Çıkış

> is your programs output
< is the responding input
Solution is 1 5 6 6

> 1 2 3 4
< 0 1
> 4 1 6 6
< 1 2
> 1 6 5 6
< 2 2
> 1 5 6 6
< 0 4 

puanlama

  • Bu saf ve basit Code Golf . En kısa çözüm bayt kazanır.

Bu benim ilk Code Golf sorum. Yanlış bir şey yaptıysam özür dilerim, ancak kesinlikle belirsizlik olmadığından emin olmak için elimden geldiğince gayret gösterdim ve olabildiğince fazla kurallara uymalarını önledim. Belirsiz ya da belirsiz davrandıysam, lütfen soru sormaktan çekinmeyin.


1
Örnekte girdi / çıktı 1 2 3 4geri dönmemeli 0 1mi?
Gaffi

1
Ve örnek metinde, "Yeşil Yeşil Yeşil Mavi" de (ilk Yeşil için) beyaz bir mandal vermemeli midir? EDIT - Wikipedia, sizin yazdığınız gibi beyazın verilmemesi gerektiğini açıklar. Ancak, siyah / beyaz kurallarının soruda açıkça belirtilmesi gerektiğini düşünüyorum.
23'te ugoren

Ne kadar yavaş çalışmasına izin verilecek?
saat

@Gaffi - Kesinlikle sağ - sabit
lochok

1
Beyaz mandallar için kurallar burada belirtilmemiştir. 1234'ü seçtiğinizi farz ediyorum ve sanırım 5611. Her ikisi de benim 1'im yanlış yerde doğru renktir, bu nedenle kuralları belirttiğiniz gibi 2 beyaz alacağımı söylerim. Ama hayır - Wikipedia 1 beyaz olduğunu söylüyor. Yanlış yöntemin programlanması da kolaydır (ancak Steven Rumbalski, Wikipedia'nın kurallarını doğru bir şekilde uyguladı).
Ugoren

Yanıtlar:


8

Python 2 Python 3, 359 365 338 karakter

from itertools import*
from collections import*
m=h=set(product(*['123456']*4))
def f(g,k):b=sum(x==y for x,y in zip(g,k));return'%s %s'%(sum(min(g.count(c),k.count(c))for c in set(g))-b,b)
while len(m)>1:g=min(h,key=lambda g:max(Counter(f(g,k)for k in m).values()));print(*g);s=input();m=set(x for x in m if s==f(g,x))
print(*(m.pop()))

Komik, beş karakterli değişken ismim olduğunu farketmem çok fazla değişiklik gerektirdi.

Uzun ithalatı sevmiyorum. collections.Counterİçe aktarma için tasarruf sağlayacak olanın yerine uygulayabilmem gerektiğini düşünüyor .

print(*(m.pop()))Sonunda da sevmiyorum . Bu süre döngüsünde kaybolması gerektiğini hissediyor, ancak bunu daha uzun yapmadan yapmanın bir yolunu bulamıyorum.


TypeError: join() takes exactly one argument (2 given)üzerinde return j(sum(min(g.count(c),k.count(c))for c in set(g))-b,b). Ayrıca, sum () bir int döndürürken, j (str.join) yinelenebilir olmalıdır
Blazer

Döngü yapım finalden kurtulur printve bence biraz daha kısadır. Ayrıca istenen davranışla daha iyi eşleşir (cevabı bilmek yerine "4 0" da durur). Ve len(m)>1== m[1:]. İthalat gerçekten can sıkıcı - iyi from a,b import *olurdu.
Ugoren

Bu program, doğru olduğunu düşündüğü zaman çıkacak gibi görünüyor. bir defasında koştum ve 5 tahminde durdu, doğru değildi. bir dahaki sefere 4 tahminde durdu ve doğruydu, ancak 4 0henüz nesnel ölçütlerde olan ve henüz bir istisna dışında çıkacak olan henüz giriş yapmadım :print(*(m.pop())) KeyError: 'pop from an empty set'
Blazer

@Blazer. Bu çıktıya neden olan test durumları nelerdir?
Steven Rumbalski,

@ Blazer: 4 0dört beyaz mandal. Sanırım skorun tersine döndü.
Steven Rumbalski,

7

Haskell, 317 304

q[0,4]_=error""
q[n,m]l=(\s->all(==4-m)[g s,n+g(u(foldr((u((.drop 1).(++)).).break.(==)))$unzip s)]).c(u(/=)).zip l
u=uncurry;m=map;g=length;c=filter
f a=[head.c(($(zipWith q(take n a)$f a)).all.flip($)).sequence$replicate 4[1..6]|n<-[0..]]
main=interact$unlines.m(unwords.m show).f.m(m read.words).lines

Tamamen işlevsel etkileşimli programlar yazmayı seviyorum! Ama elbette bu tarzın bazı sınırlamaları var: şimdi bir hatayla sonlanıyor, ancak bunun tamam olmadığını belirtmediniz. IOHatasız bir çıkış elde etmek için her şeyi monata yeniden yansıtmam gerekiyor.


6 hamlede doğru bir tahmin yapmayı garanti ediyor mu?
saat

Uh. Öyle olduğunu düşündüm (OP'nin örneği ve diğer çözümleri için işe yarıyor), ancak ayrıntılı testler bazen 7 tahmin gerektirdiğini gösteriyor. Bunun üzerinde çalışmam gerekecek!
saat

5

Python, 385 357 karakter, 5 hamlede çözüldü

Ne kadar çok değiştirirsem, Steven Rumbalski'ninki gibi daha da büyüyor ... Asıl fark, tamsayılardan ziyade dizelerle çalışması.
Uygulanan Knuth algoritması (şimdi doğru, umarım).
Steven Rumbalski'den puanlama işlevini ödünç aldım.
İlk tahminin oluşturulması uzun zaman alır, daha sonra daha iyi hale gelir.
Sabit kodlama ( g=len(A)==1296 and [1,1,2,2] or ...), denemek istiyorsanız hayatı kolaylaştırır.
4 yeni satır + sekme çifti saymıyorum, bunlar noktalı virgüllerle değiştirilebiliyor.

from collections import*
from itertools import*
a=B=A=list(product(*[range(1,7)]*4))
r=lambda g,k:(sum(x==y for x,y in zip(g,k)),sum(min(g.count(c),k.count(c))for c in set(g)))
while a!=4:
    g=A[1:]and min(B,key=lambda x:max(Counter(r(x,i)for i in A).values()))or A[0]
    print"%d "*4%tuple(g)
    b,a=map(int,raw_input().split())
    A=[x for x in A if r(g,x)==(a,a+b)]

"%d "*4%tuple(g)
gnibbler

from collections import*
gnibbler

a,b=map(int,raw_input())
gnibbler

product(*[range(1,7)]*4)
gnibbler

Counter(r(x,i)for i in A).values()
gnibbler
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.