मास्टरमाइंड रणनीति


19

मुझे केवल मास्टरमाइंड के लिए कोड-गोल्फ चुनौतियां मिल सकती हैं, इसलिए यहां एक कोड-चुनौती संस्करण है जिसे मैं खुद लेना पसंद करूंगा।

सामान्य मास्टरमाइंड गेम, MM (4,6) के लिए एक इष्टतम रणनीति 1993 में कोयामा और लाई द्वारा पाई गई, जिसका औसत # अनुमान = 5625/1296 ~ 4.34 था। MM (5,8) अभी भी अनसुलझा है, लेकिन अनुमान लगाया जाता है कि यह औसत # 5.5 है।

आपका कार्य एक MM (5,8) रणनीति बनाना है, जो 5 छेद और 8 रंगों के लिए है, जो सभी pow(8,5) = 32768संभावित विशिष्ट समाधानों को कवर करता है। जाहिर है, यह एक इष्टतम एक होने की जरूरत नहीं है। आपके पास दो विकल्प हैं:

  1. एक नियतात्मक कार्यक्रम पोस्ट करें जो रणनीति उत्पन्न करता है। कार्यक्रम को विंडोज 7, मैक ओएस एक्स या लिनक्स पर बिना किसी अतिरिक्त गैर-मुक्त सॉफ़्टवेयर के लिए संकलन योग्य / चलाने योग्य होना चाहिए।
  2. अपनी रणनीति (अपने StackExchange नाम के साथ) को इंटरनेट पर कहीं प्रकाशित करें और यहां URL पोस्ट करें।

दोनों मामलों में, उत्तर के शीर्षलेख में स्कोर (नीचे देखें) बताएं।

निम्नलिखित व्याकरण के अनुसार रणनीति को इनकोड किया जाना चाहिए:

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'

काले / सफेद कुंजी खूंटे की संख्या तय करने के लिए उपयोग किए जाने वाले एल्गोरिदम का वर्णन http://en.wikipedia.org/wiki/Mastermind_(board_game) में किया गया है

ध्यान दें कि उत्तर "50" (यानी सही अनुमान) निहित है और व्याकरण का हिस्सा नहीं है।

स्कोरिंग: एन = 32768 पथ / समाधान में से प्रत्येक के लिए अनुमानों की संख्या का योग। सबसे कम एन जीत के साथ रणनीति। पहला टाई-ब्रेक: अनुमानों की सबसे कम अधिकतम संख्या। दूसरा टाई-ब्रेक: पहला पोस्ट किया गया उत्तर। प्रतियोगिता 1 अगस्त 2014 को 0:00 GMT समाप्त होती है ।


स्कोर = 21 के साथ MM (2,3) के लिए एक रणनीति का एक उदाहरण:

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

इस रणनीति का उपयोग करते हुए, 9 संभावित गेम इस प्रकार होंगे:

  • एबी २०
  • एबी 10, एसी 20
  • एबी 10, एसी 10, एए 20
  • एबी 10, एसी 01, सीबी 20
  • एबी 10, एसी 00, बीबी 20
  • एबी 02, बीए 20
  • एबी 01, बीसी 20
  • एबी 01, बीसी 01, सीए 20
  • एबी 00, सीसी 20

मैं जल्द ही आपकी सुविधा के लिए जावा-आधारित MM (5,8) रणनीति सत्यापनकर्ता पोस्ट करूंगा।


मुझे यह समझने में मुश्किल समय हो रहा है कि एमएम (2,3) की उदाहरण रणनीति कैसे लागू होती है। क्या आप रणनीति को समझाते हुए एक नमूना गेम पोस्ट कर सकते हैं?

@tolos I ने सभी 9 :)
MrBackend

यह बहुत अच्छा होगा यदि आपका सत्यापनकर्ता एक स्कोर का भी उत्पादन कर सकता है!
नहीं है कि

@Charles करेंगे!
मि। बेकेंड

2
क्या आप कई प्रमुख खूंटी संयोजनों के समान प्रतिक्रिया की अनुमति देने के लिए अपना व्याकरण बदलने के लिए तैयार होंगे? पसंद है {AB:{10|01:BB}}? मेरे पास एक उत्तर है, लेकिन यह बहुत अच्छा है और व्याकरण की वृक्ष-संरचना के कारण यह बिल्कुल भी अच्छा नहीं है (4 छेद, 3 रंग, एक 147MB रणनीति उत्पन्न करता है, जिसे मैं भागों के संयोजन से महत्वपूर्ण रूप से काट सकता हूं । पेड़)।
मार्टिन एंडर

जवाबों:


6

जावा

एमएम (5,8) के लिए मेरा एल्गोरिथ्म 8 9 की अधिकतम गहराई के साथ 177902 178006 182798 182697 के साथ स्कोर करता है और केवल कुछ सेकंड (मेरे धीमे कंप्यूटर पर) की आवश्यकता होती है।

एमएम (2,3) के लिए एक रणनीति का उदाहरण आउटपुट स्कोर = 21 के साथ इस एल्गोरिदम द्वारा पाया जाता है:

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

मेरे एल्गोरिथ्म के साथ रोमांचक कुछ भी नहीं है। कोई आविष्कार नहीं। मैंने सिर्फ नेट में पाए जाने वाले व्यंजनों का पालन किया और उन्हें इस जावा कोड में संपीड़ित किया। मेरे द्वारा किया गया एकमात्र अनुकूलन कोड की लाइनों (एक तरह से) को अनुकूलित करने का प्रयास कर रहा है। यह इस प्रकार चलता है:

  1. वर्तमान सेट एस होने के लिए सभी संभावित कोड का प्रारंभिक सेट S0 बनाएं।
  2. एस के लिए कोडब्रेकर एक (लालची) अच्छा अनुमान लगाता है। प्रत्येक अनुमान एस के एक विभाजन पी की ओर जाता है, जहां प्रत्येक सबसेट एस 'अनुमान पर एक ही उत्तर वाले सभी कोड (एस से) एकत्र करता है। एक अच्छे अनुमान में एक अच्छा विभाजन होता है, क्योंकि एक अनुमान के लिए सबसे अधिक जानकारी देता है।
  3. अच्छा अनुमान लगाइए और इसके P. के लिए प्रत्येक nonempty S 'में P को कोडब्रेकर पुनरावर्ती (चरण 2) लागू करें।

@MrBackend: एक सत्यापनकर्ता लिखना कठिन है, मुझे लगता है। ;-)

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)+"}");
    }
}

कुछ टिप्पणी:

  1. कोई निरंतरता जांच की आवश्यकता नहीं है क्योंकि सेट एस और उनके विभाजन एक (ऑटो-) सुसंगत तरीके से निर्मित होते हैं।
  2. S0 (S के बजाय) से अच्छा अनुमान लगाना समझ में आता है। लेकिन मैं वर्तमान कोड में इस दृष्टिकोण का पालन नहीं करता हूं।
  3. मेरी लालची खोज कृत्रिम रूप से 200 कोशिशों से प्रभावित है।
  4. मुझे पता है, "अनुमान के लिए अधिकांश जानकारी देना" बहुत सटीक नहीं है। सरल विचार सबसे अधिक संख्या में सबसेट के साथ विभाजन को चुनना है।
  5. परिणाम बहुत हद तक इस बात पर निर्भर करता है कि आप उत्तर (..) की गणना कैसे करते हैं। अंत में मैंने डोनाल्ड नुथ की अभिव्यक्ति को अनुकूलित किया।

के लिए रणनीति MM(5,8) यहां पाई जा सकती है । GitHub में कुछ मुद्दे हैं जो लंबी लाइनों को प्रदर्शित करते हैं, इसलिए रॉ बटन पर क्लिक करें।


नमस्ते कैसे सुंदर github पाठ मुद्रित करने के लिए इतना है कि परिणामों को एक खोज गाइड में बदल दिया जा सकता है .. पहले शुरुआती बिंदु 'HHCAA' से .. और अगले कदम के जवाब पर निर्भर करता है ... और अगले और इतने पर। वर्तमान कच्चे पाठ प्रारूप यह मैनुअल स्कैनिंग के लिए आसान नहीं है .. तकनीक मैं बाद में है कि कैसे नेस्टेड कोष्ठक को पार्स किया जाए और एक अच्छा टेबल लेआउट प्राप्त करें जो प्रश्न में बुलेटेड सूची के समान अंत तक आसान हो। MM (2,3) के लिए। धन्यवाद। आशा है कि आप समझ सकते हैं कि मैं क्या हूँ। (पार्स str के लिए अजगर पसंद करते हैं)
ihightower

2

माणिक

संपादित करें: असंभव अनुमानों को बाहर करने के लिए कुछ तर्क जोड़े। इसलिए, रणनीतियाँ अब दिए गए प्रारूप का अनुपालन करती हैं और बहुत अधिक प्रबंधनीय हैं।

तो यहाँ एक कोशिश यह हो रही है। यह बहुत भोला है (और बहुत सुपाठ्य नहीं है - यह पढ़ने में मदद करता है अगर / elsif / अन्यथा शाखा नीचे से ऊपर तक)।

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 '}'

: सबसे पहले, मैं कोशिश प्रत्येक रंग के 5 AAAAA, BBBBBकि मैं पता लगाने जो रंग वास्तव में पैटर्न में उपयोग किया जाता है से, आदि। और फिर मैं बस दिए गए रंगों के सभी क्रमपरिवर्तन का प्रयास करता हूं, उन सभी को छोड़ देता हूं जिन्हें पहले से ही काले खूंटे से खारिज किया गया है।

यहाँ MM(2,3)रणनीति है:

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

MM(5,8)376KB के लिए रणनीति यहां पाई जा सकती है । GitHub में कुछ मुद्दे हैं जो लंबी लाइनों को प्रदर्शित करते हैं, इसलिए रॉ बटन पर क्लिक करें।

अब यदि मुझे एक सत्यापनकर्ता मिलता है, तो मैं आपको यह भी बता सकता हूं कि मेरा वास्तविक स्कोर क्या है। :)


अभी तक प्रकाशित नहीं किए गए सत्यापनकर्ता के बारे में बुरा लग रहा है, लेकिन यह अपने रास्ते पर है ... आपकी (पहली) एमएम (2,3) रणनीति के साथ कुछ गड़बड़ है, उदाहरण के लिए अगर समाधान एबी है: अनुमान = एए; उत्तर = 10; लगता = बी बी; उत्तर = 10, जिसके लिए कोई रणनीति नहीं है। मैं उत्तरों को समूहीकृत करने के आपके सुझाव पर गौर करूंगा, लेकिन अच्छी रणनीतियों के लिए यह आवश्यक नहीं होना चाहिए, क्योंकि संभावित समाधानों का सेट अलग-अलग उत्तरों के लिए निराशाजनक है।
मि। बैकेंडेंड

@MrBackend अच्छा कैच, मैंने वहां एक मामले को छोड़ दिया। इसे अब ठीक किया जाना चाहिए। व्याकरण के रूप में, बेशक यह अच्छी रणनीतियों के लिए आवश्यक नहीं है , लेकिन मुझे लगा कि आप बार को थोड़ा कम करने के लिए तैयार हो सकते हैं। ;) अगर लोग सरल प्रविष्टियाँ जमा कर सकते हैं (मेरी तरह) तो आपके पास थोड़ा और अधिक सौभाग्य हो सकता है जो दिलचस्प सबमिशन प्राप्त कर रहे हैं, जो कि धीरे-धीरे सुधार करते हैं, बजाय सभी को शुरू से ही सही संयोजन के शामिल करने के।
मार्टिन एंडर

यहां सौदा है: मैं वर्तमान सत्यापनकर्ता को समाप्त करूंगा और इसे प्रकाशित करूंगा (वेब ​​ऐप के रूप में - यहां पेस्ट करना बहुत बड़ा है)। दुर्भाग्य से, यह बहुत सख्त हो सकता है, क्योंकि यह असंभव उत्तरों को एक त्रुटि मानता है। बाद में, मैं इसे कई उत्तरों का समर्थन करने के लिए अनुकूलित करूंगा और असंभव उत्तरों के लिए चेतावनी का अनुकरण करूंगा। कहा जा रहा है कि, आपकी 1.3G MM (4,4) रणनीति में बहुत से असंभव उत्तर और / या गैर-कम करने वाले अनुमान शामिल हैं, क्योंकि एक सभ्य MM (5,8) रणनीति का अनुमानित आकार मुट्ठी भर है।
श्रीबेकेंड

@MrBackend बेशक मेरी रणनीतियों में असंभव उत्तरों का एक टन है। यही मेरा मतलब है "मैं कॉम्बिनेटरिक्स नहीं कर रहा हूं"। ;) यदि यह आपके लिए एक बहुत अधिक परेशानी है कि आप इसका समर्थन करें और उत्तर दें, तो चिंता न करें, फिर मैं असंभव चीज़ों को छोड़ने पर ध्यान दूंगा।
मार्टिन एंडर

@MrBackend खुशखबरी, मैंने इसे ठीक किया। :) मुझे उम्मीद है कि रणनीति अब मान्य है। मुझे बताएं कि क्या अभी भी इसके साथ कोई समस्या है।
मार्टिन एंडर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.