Beyni stratejisi


19

Mastermind için sadece kod-golf zorlukları bulabildim, işte kendime almak isteyeceğim bir kod-meydan okuma versiyonu.

1993 yılında Koyama ve Lai tarafından normal Mastermind oyunu MM (4,6) için en uygun strateji, ortalama # tahmin = 5625/1296 ~ 4.34 olarak bulundu. MM (5,8) hala çözülmemiştir, ancak ortalama tahmin sayısının ~ 5.5 olduğu tahmin edilmektedir.

Göreviniz, pow(8,5) = 32768olası tüm farklı çözümleri kapsayan 5 delik ve 8 renk için bir MM (5,8) stratejisi oluşturmaktır . Açıkçası, bunun optimal olması gerekmez. İki seçeneğiniz var:

  1. Stratejiyi oluşturan deterministik bir program yayınlayın. Program, herhangi bir ekstra özgür olmayan yazılım olmadan Windows 7, Mac OS X veya Linux'ta derlenebilir / çalıştırılabilir olmalıdır.
  2. Stratejinizi (StackExchange adınızla birlikte) İnternet'te bir yerde yayınlayın ve URL'yi buraya gönderin.

Her iki durumda da, yanıtın başlığında puanı (aşağıya bakın) belirtin.

Strateji aşağıdaki dilbilgisine göre kodlanmalıdır:

strategy : guessing-strategy | known-solution-strategy
guessing-strategy : '{' guess ':' branches '}'
known-solution-strategy : guess
guess : color color color color color
color : 'A'..'H'
branches : '{' branch (',' branch)* '}'
branch : reply ':' strategy
reply : number-of-blacks number-of-whites
number-of-blacks : number-of-key-pegs
number-of-whites : number-of-key-pegs
number-of-key-pegs : '0'..'5'

Siyah / beyaz tuş mandallarının sayısına karar vermek için kullanılan algoritma http://en.wikipedia.org/wiki/Mastermind_(board_game)

"50" cevabının (yani doğru tahmin) ima edildiğini ve gramerin bir parçası olmadığını unutmayın.

Puanlama: N = 32768 yol / çözümün her biri için tahmin sayısının toplamı. En düşük N değerine sahip strateji kazanır. İlk tie-break: En düşük maksimum tahmin sayısı. İkinci beraberlik: İlk gönderilen cevap. Yarışma 1 Ağustos 2014 0:00 GMT'de sona eriyor .


MM (2,3) puanı = 21 olan bir strateji örneği:

{AB:{10:{AC:{10:AA,01:CB,00:BB}},02:BA,01:{BC:{01:CA}},00:CC}}

Bu stratejiyi kullanarak, olası 9 oyun şu şekilde olacaktır:

  • AB 20
  • AB 10, AC 20
  • AB 10, AC 10, AA 20
  • AB 10, AC 01, CB 20
  • AB 10, AC 00, BB 20
  • AB 02, BA 20
  • AB 01, BC 20
  • AB 01, BC 01, CA 20
  • AB 00, CC 20

Size kolaylık sağlamak için yakında Java tabanlı bir MM (5,8) strateji doğrulayıcısı yayınlayacağım.


MM'nin (2,3) örnek stratejisinin nasıl uygulandığını anlamakta zorlanıyorum. Stratejiyi açıklayan örnek bir oyun yayınlayabilir misiniz?

@tolos 9'u da ekledim :)
MrBackend

Doğrulayıcınızın da bir puan vermesi harika olurdu!
Charles

@Charles Yapacak!
MrBackend

2
Birden çok tuş peg kombinasyonuna aynı yanıta izin vermek için dilbilginizi değiştirmek ister misiniz? Gibi {AB:{10|01:BB}}mi? Bir cevabım var, ama oldukça naif ve dilbilgisinin ağaç yapısı nedeniyle hiç iyi ölçeklenmiyor (4 delik, 3 renk, bölümlerini birleştirerek önemli ölçüde azaltabileceğim 147 MB'lik bir strateji oluşturuyor ağaç).
Martin Ender

Yanıtlar:


6

Java

İle MM (5,8) skorları için My algoritması 177.902 178.006 182.798 182697 maksimum derinliği 8 9 ve ihtiyaçları (benim yavaş bilgisayarda) sadece birkaç saniye.

MM (2,3) için bu algoritma tarafından bulunan skor = 21 olan bir stratejinin örnek çıktısı şuna benzer:

{BC:{00:AA,01:AB:{01:CA},02:CB,10:AC:{00:BB,01:BA,10:CC}}}

Algoritmamda heyecan verici bir şey yok. Buluş yok. Sadece net bulunan tarifleri takip ettim ve bu Java koduna sıkıştırdım. Yaptığım tek optimizasyon kod satırlarını (bir şekilde) optimize etmeye çalışıyor. Bu böyle devam ediyor:

  1. Olası tüm S kodlarının başlangıç ​​seti S0'ı mevcut set S olarak oluşturun.
  2. Kod kırıcı S için (açgözlü) iyi bir tahmin bulur. Her tahmin S'nin bir P bölümüne yol açar, burada her bir S 'alt kümesi, tahminte aynı cevaba sahip tüm kodları (S'den) toplar. İyi bir tahminin, tahminde en fazla bilgi veren bölümün iyi bir bölümü vardır.
  3. İyi tahminde bulunun ve P'yi alın. P'deki her boş olmayan S 'için kod kırıcı özyinelemesini uygulayın (adım 2).

@MrBackend: Doğrulayıcı yazmak zor, sanırım. ;-)

import java.util.TreeMap;
import java.util.Vector;

public class MM {
    Vector<String> codeset = new Vector<String>();
    String guess;
    TreeMap<Integer, MM> strategy = new TreeMap<Integer, MM>();

    public String toString() {
        String list="";
        for (Integer reply: strategy.keySet()) {
            if (strategy.get(reply)!=null) list+=(list.length()>0?",":"")+(reply<10?"0":"")+reply+":"+strategy.get(reply);
        }
        if (list.length()>0) return guess+":{"+list+"}"; else return guess;
    }

    MM() { }

    MM(int h, int c) {
        for (int i = 0; i < Math.pow(c, h); i++) {
            String code = "";
            for (int j = 0, p=i; j < h; j++) {
                code+="ABCDEFGH".charAt(p%c);
                p/=c;
            }
            codeset.add(code);
        }
    }

    int replyAccordingToDonaldKnuth(String secret, String guess) {
        int black=0;
        int totalHitsBlackAndWhite=0;
        for (char n = 'A'; n <= 'H'; n++) {
            int a=0, b=0;
            for (int i = 0; i < secret.length(); i++) {
                if (secret.charAt(i)==n) a++;
                if ( guess.charAt(i)==n) b++;
            }
            totalHitsBlackAndWhite+=Math.min(a, b);
        }
        for (int i = 0; i < secret.length(); i++) {
            if (secret.charAt(i) == guess.charAt(i)) black++;
        }
        return 10 * black + (totalHitsBlackAndWhite-black);
    }

    int reply(String secret, String guess) {
        return replyAccordingToDonaldKnuth(secret, guess);
    }

    MM codebreaker(Vector<String> permuts) {
        int fitness=0;
        MM protostrategy=null;
        for (int greedy = 0; greedy < Math.min(permuts.size(), 200); greedy++) {
            MM tmp=partition(permuts, permuts.get(greedy));
            int value=tmp.strategy.size();
            if (fitness<=value) {
                fitness=value;
                protostrategy=tmp;
                protostrategy.guess=permuts.get(greedy);
            }
        }
        if (protostrategy!=null) {
            for (Integer reply: protostrategy.strategy.keySet()) {
                protostrategy.strategy.put(reply, codebreaker(protostrategy.strategy.get(reply).codeset));
            }
        }
        return protostrategy;
    }

    MM partition(Vector<String> permuts, String code) {
        MM protostrategy=new MM();
        for (int c = 0; c < permuts.size(); c++) {
            int reply=reply(permuts.get(c), code);
            if (!protostrategy.strategy.containsKey(reply)) protostrategy.strategy.put(reply, new MM());
            if (permuts.get(c)!=code) protostrategy.strategy.get(reply).codeset.add(permuts.get(c));
        }
        return protostrategy;
    }

    public static void main(String[] args) {
        MM mm = new MM(5,8);
        System.out.println("{"+mm.codebreaker(mm.codeset)+"}");
    }
}

Bazı açıklamalar:

  1. Set S ve bölümleri (otomatik) tutarlı bir şekilde oluşturulduğundan tutarlılık kontrolü gerekmez.
  2. S0'dan (S yerine) iyi bir tahminde bulunmak mantıklı. Ama şu anki kodda bu yaklaşımı takip etmiyorum.
  3. Açgözlü aramam yapay olarak 200 denemede budanıyor.
  4. Biliyorum, "tahmin için en fazla bilgiyi vermek" çok kesin değil. Basit fikir, en fazla alt kümeye sahip bölümü seçmektir.
  5. Sonuç büyük ölçüde cevabı nasıl hesapladığınıza bağlıdır (..). Sonunda Donald Knuth'un ifadesini uyarladım.

Stratejisini MM(5,8) burada bulabilirsiniz . GitHub'ın bu kadar uzun satır görüntülemesinde bazı sorunları var, bu nedenle Raw düğmesine tıklayın.


merhaba github metnin nasıl güzel bir şekilde yazdırılacağı, böylece sonuçlar bir arama kılavuzuna dönüştürülebilir .. ilk başlangıç ​​noktasından 'HHCAA' .. ve cevaba bağlı olarak bir sonraki adım ... ve bir sonraki adım. Mevcut ham metin formatı manuel tarama için daha kolay değildir .. sonradan teknik, iç içe parantezleri ayrıştırma ve sorudaki madde işaretli listeye benzer şekilde sonuna kadar takip edilmesi daha kolay olan güzel bir tablo düzeninin nasıl alınacağıdır. MM için (2,3). Teşekkür ederim. Sonra ne olduğumu anlayabileceğini umuyorum. (
str'yi

2

Yakut

DÜZENLEME: İmkansız tahminleri hariç tutmak için bazı mantık eklendi. Bu nedenle, stratejiler artık verilen formata uygun ve çok daha yönetilebilir.

İşte bunun için bir girişim. Oldukça naif (ve çok okunaklı değil - if / elsif / else dalını aşağıdan yukarı okumanıza yardımcı olur).

Holes, Colors = ARGV.map &:to_i

ColorChars = ('A'..'H').to_a

def is_possible(guess, blacks, result)
    blacks == guess.chars.zip(result.chars).count {|chars| chars[0] == chars[1]}
end

def print_strategy(known_colors, remaining_permutations, next_color)
    char = ColorChars[next_color]
    if remaining_permutations
        guess = remaining_permutations[0]
        print guess
        if remaining_permutations.length > 1
            print ':{'
            (Holes-1).times do |i|
                new_permutations = (remaining_permutations - [guess]).select { |perm| is_possible(guess, i, perm) }
                next if new_permutations.empty?
                print "#{i}#{Holes-i}:"                
                print '{' if new_permutations.length > 1
                print_strategy(known_colors, new_permutations, next_color)
                print '}' if new_permutations.length > 1
                print ',' if i < Holes-2
            end
            print '}'
        end
    elsif known_colors.length == Holes
        print_strategy(known_colors, known_colors.chars.permutation.map(&:join).uniq, next_color)
    elsif next_color == Colors-1
        print_strategy(known_colors+char*(Holes - known_colors.length), remaining_permutations, next_color+1)
    else
        print char*Holes, ':{'

        (Holes - known_colors.length + 1).times do |i|
            break if i == Holes
            print "#{i}0:"
            print '{' if next_color < Colors-2 || i > 0 || known_colors.length > 0
            print_strategy(
                known_colors+char*i,
                remaining_permutations,
                next_color+1
            )
            print '}' if next_color < Colors-2 || i > 0 || known_colors.length > 0
            print ',' if i < (Holes - known_colors.length) && i < Holes-1
        end
        print '}'
    end
end

print '{'
print_strategy('', nil, 0)
puts '}'

İlk olarak, her bir rengin 5'ini deniyorum: AAAAA,, BBBBBvb. Bundan sonra desende hangi renklerin gerçekten kullanıldığını anladım. Ve sonra verilen renklerin tüm permütasyonlarını deniyorum, zaten siyah mandallar tarafından dışlanmış olanları atlıyorum.

İşte MM(2,3)strateji:

{AA:{00:{BB:{00:CC,10:{BC:{02:CB}}}},10:{BB:{00:{AC:{02:CA}},10:{AB:{02:BA}}}}}}

Strateji MM(5,8)376KB alır ve burada bulunabilir . GitHub'ın bu kadar uzun satır görüntülemesinde bazı sorunları var, bu nedenle Raw düğmesine tıklayın.

Şimdi bir doğrulayıcı alırsam, gerçek puanımın ne olduğunu da söyleyebilirim. :)


Henüz yayınlanmamış doğrulayıcı hakkında kötü hissetmek, ancak yolda ... İlk çözüm MM (2,3) stratejinizde bir sorun var, örneğin çözüm AB ise: Guess = AA; = 10 cevap; = BB tahmin; cevap = 10, ki bu strateji yok. Yanıtları gruplama önerinize bakacağım, ancak olası çözümler kümesi farklı yanıtlar için ayrık olduğundan iyi stratejiler için gerekli olmamalıdır.
MrBackend

@MrBackend İyi yakaladım, orada bir dava atladım. Şimdi düzeltilmelidir. Dilbilgisine gelince, elbette iyi stratejiler için gerekli değildir , ancak çıtayı biraz düşürmeye istekli olabileceğinizi düşündüm. ;) İnsanlar daha basit girişler (benimki gibi) gönderebilirlerse, tüm kombinatorikleri en baştan dahil etmek yerine, yavaş yavaş gelişen ilginç gönderimler almak için biraz daha şanslı olabilirsiniz.
Martin Ender

İşte anlaşma: Geçerli doğrulayıcıyı bitirip yayınlayacağım (bir web uygulaması olarak - buraya yapıştırmak için çok büyük). Ne yazık ki, imkansız cevapların bir hata olduğunu düşündüğü için çok katı olabilir. Daha sonra, birden fazla yanıtı destekleyecek ve imkansız yanıtlar için uyarılar yayınlayacağım. Bunu söyledikten sonra, 1.3G MM (4,4) stratejiniz, iyi bir MM (5,8) stratejisinin tahmini boyutu bir avuç meta olduğundan, bir çok imkansız cevap ve / veya azaltıcı olmayan tahmin içermelidir.
MrBackend

@MrBackend Tabii ki stratejilerim tonlarca imkansız cevap içeriyor. "Kombinatorik yapmıyorum" ile kastettiğim buydu. ;) Bunu desteklemeniz ve cevapları gruplandırmanız çok zorsa, endişelenmeyin, o zaman imkansız tahminleri atlamaya bakacağım.
Martin Ender

@MrBackend İyi haber, düzelttim. :) Umarım strateji şimdi geçerlidir. Hala herhangi bir sorun olup olmadığını bana bildirin.
Martin Ender
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.