मोररा, नोबल गेम ऑफ किंग्स


28

पृष्ठभूमि

का खेल मोर्रा एक सरल खेल है। "मूल" संस्करण में, कई खिलाड़ी एक साथ सभी के हाथों की कुल राशि का अनुमान लगाते हुए अपने हाथों से 0-5 नंबर निकालते हैं। जो संस्करण मैं यहां उपयोग करूंगा उसे गैर-तुच्छ रणनीति की क्षमता बढ़ाने के लिए संशोधित किया गया है, और यह नीचे वर्णित है:

  • दो खिलाड़ी हैं।
  • रॉक-पेपर-कैंची की तरह, खिलाड़ी एक साथ चलते हैं।
  • प्रत्येक बारी, प्रत्येक खिलाड़ी 0-5 नंबर चुनता है और अपने विरोधियों की 0-5 की पसंद का भी अनुमान लगाता है । इसका मतलब है कि दो नंबर आउटपुट हैं प्रत्येक बारी। स्पष्ट करने के लिए, दोनों संख्याओं का आउटपुट 0-5 की सीमा में होना चाहिए।
  • यदि आप अपने प्रतिद्वंद्वी की पसंद का सही अनुमान लगाते हैं, लेकिन आपके प्रतिद्वंद्वी ने सही अनुमान नहीं लगाया है, तो आप खेले गए दो नंबरों के योग के बराबर अंकों की एक निश्चित संख्या जीतते हैं। उदाहरण के लिए, यदि खेले गए अंक 3 और 5 थे, तो एक सही अनुमान 8 अंकों का होगा।
  • यदि दोनों या दोनों खिलाड़ी सही ढंग से अनुमान लगाते हैं, तो कोई भी अंक प्रदान नहीं किया जाता है।
  • 1000 राउंड के बाद सबसे अधिक अंक वाला व्यक्ति उस गेम को जीतता है।

प्रतियोगिता

टूर्नामेंट एक राउंड-रॉबिन शैली में किया जाएगा और प्रतियोगी की प्रत्येक संभावित जोड़ी बनाकर चलाया जाएगा। प्रत्येक जीत के लिए, प्रतियोगी को 2 जीत अंक मिलते हैं। प्रत्येक टाई में 1 जीत बिंदु होता है। हार के लिए कोई जीत के अंक प्राप्त नहीं होते हैं।

सहज रूप से, टूर्नामेंट का विजेता दूसरों के खिलाफ सबसे अधिक जीत अंक के साथ प्रतियोगी होगा।


अंदर कैसे आएं

प्रतिस्पर्धा करने के लिए बॉट प्रस्तुत करने के दो तरीके होंगे। पहला, और बहुत पसंदीदा तरीका, नियंत्रक द्वारा आपूर्ति की गई जावा इंटरफ़ेस को लागू करना है। दूसरी विधि एक स्वतंत्र कार्यक्रम लिखना है।

पहले जावा विधि को कवर करते हैं। इंटरफेस आप को लागू करने की आवश्यकता होगी Playerऔर यह दो तरीकों को परिभाषित करता है: public String getName()अपने बॉट पहचान लेती है और public int[] getMove(String[] args)लेता है argsछह तार की एक सरणी के रूप में, mychoices myguesses myscore opponentchoices opponentguesses opponentscore। एक उदाहरण निम्नलिखित है:

042 045 0 324 432 6

इसका मतलब यह है कि मैंने पहले दौर में 0 को चुना था और अनुमान लगाया था कि मेरा प्रतिद्वंद्वी 0. फेंकने वाला है। मेरे प्रतिद्वंद्वी ने 3 फेंका और मैंने अनुमान लगाया कि मैं एक 4 फेंक दूंगा। तीसरे दौर में, मेरे प्रतिद्वंद्वी ने सही अनुमान लगाया कि मैं फेंक दूंगा 2, जिसका अर्थ है कि वह 2 + 4 = 6 अंक प्राप्त करता है।

आपका तरीका दो पूर्णांकों की एक सरणी लौटाएगा, जो क्रमशः आपकी पसंद और अनुमान हैं। एक उदाहरण {4,2}4 की पसंद और 2 के अनुमान के लिए है।

यहाँ एक पूर्ण जावा बॉट का एक उदाहरण एक विधि के रूप में लिखा गया है। यदि आप चाहते हैं, तो आपके सबमिशन में केवल वही शामिल होना है जो getMoveविधि में हो रहा है ।

import java.util.Random;
/**
 * A simple example Morra bot to get you started.
 */
public class ExampleBot implements Player
{
    public String getName()
    {
        return "ExampleBot";
    }

    public int[] getMove(String [] args)
    {
        //easiest way I know to break down to create a move history
        //(just contains their throw history)
        char[] theirThrowsC = args[3].toCharArray();
        int[] theirThrows = new int[theirThrowsC.length];
        for(int i = 0; i < theirThrowsC.length; i++)
        {
            theirThrows[i] = Integer.parseInt(Character.toString(theirThrowsC[i]));
        }

        //get my score
        int myScore = Integer.parseInt(args[2]);

        Random r = new Random();
        int guess = r.nextInt(6);
        if(theirThrows.length > 0)
        {
            guess = theirThrows[theirThrows.length-1];
        }

        //throws a random number, guesses what they threw last
        return new int[] {r.nextInt(6),guess}; 
    }

    public static int otherMethod(int example) //you can write additional static methods
    {
        return 0;
    }
}

एक स्वतंत्र कार्यक्रम के रूप में

मैं वर्तमान में अतिरिक्त भाषाओं के अपने समर्थन में सीमित हूं। जावा के अलावा, मैं पायथन 3.4, पर्ल 5, या रूबी 2.1.5 में लिखे कार्यक्रमों को स्वीकार कर सकता हूं। अगर कोई ऐसी भाषा है जिसे कई लोग चाहते हैं, तो मैं इसे जोड़ने की पूरी कोशिश करूंगा।

आपके प्रोग्राम का इनपुट कमांड लाइन पर तर्क होगा। यह इस तरह दिख सकता है:

perl awesomebot.plx 042 045 0 324 432 6

आपके प्रोग्राम का आउटपुट आपकी पसंद के अनुसार होना चाहिए, प्रत्येक व्हाट्सएप द्वारा।

कृपया अपने उत्तर में इसे चलाने के लिए आवश्यक सटीक उत्तर शामिल करें। ध्यान रखें कि मैं विंडोज 8.1 चला रहा हूं।


अतिरिक्त नियम

सेविंग स्टेट और टाइमआउट

आपके कार्यक्रम को स्थानीय निर्देशिका में एक पाठ फ़ाइल बनाने की अनुमति होगी, जहां आप जानकारी संग्रहीत कर सकते हैं। यह जानकारी पूरे टूर्नामेंट में रखी जाएगी लेकिन बाद में हटा दी जाएगी। फ़ाइल को एक नाम दें जिसे मैं पहचान सकता हूं।

आपके कोड का जवाब देने के लिए 500 मिलीसेकंड की समय सीमा है। समय सीमा में जवाब देने में विफलता (या एक अमान्य कदम) के परिणामस्वरूप उस विशेष मैच का लाभ होगा। जावा सबमिशन में वर्तमान में एक निष्क्रिय टाइमआउट है (जिसे मैं सक्रिय में अपग्रेड कर सकता हूं), जबकि गैर-जावा सबमिशन में एक सक्रिय टाइमआउट होता है जहां 500 मिली सेकेंड के बाद उनकी प्रक्रिया समाप्त हो जाती है।

अधिक सबमिशन नियम

  • आपको कई सबमिशन की अनुमति है, जब तक वे नियमों का पालन करते हैं और टैग-टीम नहीं करते हैं।
  • प्रत्येक प्रविष्टि अद्वितीय होनी चाहिए। आप किसी अन्य भाषा में किसी अन्य बॉट के तर्क की सटीक प्रतिलिपि नहीं बना सकते हैं।
  • बॉट एक दूसरे के साथ बातचीत नहीं कर सकते (किसी भी प्रकार की टीम बनाने के लिए)।
  • आप अपने बॉट के अंदर अन्य बॉट्स के तर्क का उपयोग नहीं कर सकते हैं, कहते हैं, अपने प्रतिद्वंद्वी की पहचान करें और उसके कार्यों की भविष्यवाणी करें। आप निश्चित रूप से अपने प्रतिद्वंद्वी की रणनीति को निर्धारित करने का प्रयास कर सकते हैं।
  • नियंत्रक, अन्य प्रतियोगियों या मेरे कंप्यूटर के साथ गड़बड़ करने का प्रयास न करें। बाहरी सूचना स्रोतों से कनेक्ट न करें।

नियंत्रक

नियंत्रक का वर्तमान संस्करण यहां पाया गया है । यह जावा 8. में लिखा गया है। "टूर्नामेंट" फ़ाइल मुख्य नियंत्रक है, जिसमें प्रतियोगियों की सूची भी शामिल है (यदि आप अपनी खुद की प्रतियोगिताओं की मेजबानी करना चाहते हैं)।


लीडरबोर्ड

मैं वास्तव में लीडरबोर्ड को बहुत बार अपडेट नहीं कर पाया हूं। मैं इस सप्ताह के अंत में व्यस्त हूं। "बल्कि व्यस्त" से मेरा मतलब है कि 6:30 पूर्वाह्न से 9:30 बजे तक कंप्यूटर तक पहुंच नहीं है। यहाँ 5 रन के बाद स्कोर हैं। "इको" बॉट किसी कारण से जब्त किया गया (मेरी गलती हो सकती है, मैंने अभी तक जांच नहीं की है)।

  170 - Quinn and Valor                         
  158 - Historian                               
  142 - DeltaMax                                
  140 - MorraCowbell                            
  132 - Extrapolator                            
  115 - Rainbolt                                
  102 - Popularity                              
  100 - Interpolator                            
   83 - CounterBot                              
   80 - Basilisk                                
   76 - Erratica                                
   65 - Trendy                                  
   63 - Scholar                                 
   62 - RandomGuesser                           
   60 - KingFisher                              
   59 - NullifierBot                            
   55 - EvolvedBot                              
   48 - Confused          

श्रेय

नियंत्रक के साथ मदद के लिए रेनबोल्ट और पीटर टेलर को बहुत धन्यवाद।


1
@ मार्टिनबटनर रूबी 2.1.5 जोड़ा गया है।
PhiNotPi

राउंड रॉबिन कैसे काम करता है? प्लेयर 1 बनाम प्लेयर 2 1000 बार, प्लेयर 1 बनाम प्लेयर 3 1000 बार आदि ... या क्या यह प्लेयर 1 बनाम प्लेयर 2 है, फिर प्लेयर 1 बनाम प्लेयर 3 एक बार आदि ...
वजुरा

@Vajura एक एकल टूर्नामेंट प्रत्येक जोड़ी के बीच 1 लड़ाई से बना है। एक लड़ाई में 1000 राउंड होते हैं, जिसमें लड़ाई के अंत में उच्चतम कुल स्कोर होता है, जो दो जीत अंक प्राप्त करता है। वर्तमान स्कोरबोर्ड 40 टूर्नामेंट के बाद कुल जीत बिंदु दिखाता है।
PhiNotPi

बोर्ड को अपडेट करने में देरी के लिए क्षमा करें। मैं इस सप्ताहांत बेहद व्यस्त हूं। आज रात और कल सुबह की अपेक्षा और अपडेट करें।
PhiNotPi

वाह, मैं अपने बॉट इतनी अच्छी तरह से करने की उम्मीद नहीं थी! इसके अलावा, परिणामों के पहले सेट से संख्याओं का क्या मतलब है ... जीत की संख्या?
mbomb007 21

जवाबों:


17

मोर्रा काऊबेल

इस बॉट के नाम में महत्व की तलाश में किसी के लिए, मोरा नाम मुझे अंतरिक्ष इतालवी के बारे में सोचता है , इसलिए मुझे लगता है कि मुझे उस नाम की आवश्यकता थी जो उस पर खेला गया था। अन्य उम्मीदवारों में मोररा मूर्ख और आप मेरे लिए शामिल थे ।

यह Playerइंटरफ़ेस को लागू करने वाला एक पूर्ण वर्ग है। नीचे स्पष्टीकरण।

import java.util.Random;

public class MorraCowbell implements Player {
    private final Random rnd = new Random();

    public String getName() {
        return "MorraCowbell";
    }

    public int[] getMove(String[] args) {
        int[] prior = new int[36];
        for (int i = 0; i < 36; i++) prior[i] = 1;
        // args: myChoices myGuesses myScore opponentChoices opponentGuesses opponentScore
        if (args.length == 6 && args[3].length() == args[4].length()) {
            for (int i = 0; i < args[3].length(); i++) prior[6*(args[3].charAt(i) - '0') + (args[4].charAt(i) - '0')]++;
        }

        int[] weights = new int[6];
        for (int r = 0; r < 6; r++) {
            for (int s = 0; s < 6; s++) {
                for (int t = 0; t < 6; t++) {
                    weights[r] += (r + s) * ((r + s == 5 ? 1 : 0) + (r == t ? -1 : 0)) * prior[s * 6 + t];
                }
            }
        }

        // Find the best window.
        int[][] magic = new int[][] {
            { 7776, 6480, 5400, 4500, 3750, 3125 }, { 3125, 2500, 2000, 1600, 1280, 1024 }, { 1875, 1500, 1200, 960,
            768, 640 }, { 1125, 900, 720, 576, 480, 400 }, { 1620, 1296, 1080, 900, 750, 625 }, { 1296, 1080, 900, 750,
            625, 500 }, { 750, 625, 500, 400, 320, 256 }, { 675, 540, 432, 360, 300, 250 }, { 648, 540, 450, 375, 300,
            250 }, { 375, 300, 250, 200, 160, 128 }, { 375, 300, 240, 200, 160, 128 }, { 450, 375, 300, 240, 192, 160,
            128 }, { 324, 270, 225, 180, 150, 125 }, { 270, 225, 180, 144, 120, 100, 80 }, { 225, 180, 150, 120, 96,
            80 }, { 225, 180, 144, 120, 96, 80 }, { 324, 270, 216, 180, 150, 125, 100, 80, 64 }, { 135, 108, 90, 72, 60,
            50 }, { 135, 108, 90, 75, 60, 50, 40, 32 }, { 108, 90, 75, 60, 48, 40, 32 }, { 54, 45, 36, 30, 25, 20, 16 },
            { 54, 45, 36, 30, 24, 20, 16 }
        };
        long bestN = 0;
        int bestD = 1, bestIdx = -1, bestA[] = null;
        for (int[] A : magic) {
            for (int i = 0; i < A.length - 5; i++) {
                long n = 0;
                int d = 0;
                for (int j = 0; j < 6; j++) {
                    n += weights[j] * A[i + j];
                    d += A[i + j];
                }
                if (n * bestD > bestN * d) {
                    bestN = n;
                    bestD = d;
                    bestIdx = i;
                    bestA = A;
                }
            }
        }

        int r = rnd.nextInt(bestD);
        for (int i = 0; i < 6; i++) {
            r -= bestA[bestIdx + i];
            if (r < 0) return new int[] { i, 5 - i };
        }

        // Just a precaution: this should be unreachable.
        return new int[] { 0, 5 };
    }
}

व्याख्या

मैंने कम उंगलियों के साथ खेलों का विश्लेषण करके शुरुआत की। सबसे सरल गैर-तुच्छ व्यक्ति कॉल की अनुमति देता है 0या 1उसके पास निम्न भुगतान तालिका है (मान पंक्ति खिलाड़ी के लिए भुगतान हैं):

       (0,0) (0,1) (1,0) (1,1)
      +-----------------------
(0,0) |  0     0    -1     0
(0,1) |  0     0     0     1
(1,0) |  1     0     0    -1
(1,1) |  0    -1     1     0

(0,0)रणनीति का प्रभुत्व है (0,1), तो हम करने के लिए मेज कम कर सकते हैं

       (0,1) (1,0) (1,1)
      +-----------------
(0,1) |  0     0     1
(1,0) |  0     0    -1
(1,1) | -1     1     0

अब (1,0)रणनीति का बोलबाला है (0,1), इसलिए हम तालिका को और कम कर सकते हैं

       (0,1) (1,1)
      +-----------
(0,1) |  0     1
(1,1) | -1     0

और अब (1,1) का प्रभुत्व है (0,1), इसलिए हम खत्म हो गए

       (0,1)
      +-----
(0,1) |  0  

इसलिए हमेशा खेलता रहा (0,1) एक नैश संतुलन है। लेकिन जिज्ञासु बात यह है कि यह केवल एक ही नहीं है। यह एक सममित शून्य-राशि का खेल है, इसलिए अपेक्षित अदायगी 0 है, और किसी भी मिश्रित रणनीति के संयोजन (0,1)और (1,0)जहां (0,1)कम से कम 50% समय लिया जाता है, वह भुगतान प्राप्त करता है। इसलिए हमारे पास नैश संतुलन का एक आयामी स्थान है।

यह मामला प्रतीत होता है, हालांकि मैंने इसे साबित नहीं किया है, लेकिन n-फिंगर मोरा में एn नैश इक्विलिब्रिया आयामी जो कि n+1 (pick, guess)जोड़े के बीच मिश्रित रणनीति है pick + guess = n

ऊपर दिए गए कोड में जादू संख्याएँ नैश संतुलन के 5-आयामी पॉलीटोप के 32 कोने को सांकेतिक शब्दों में बदलना। मैंने उन्हें एक लीनियर प्रोग्रामिंग इंस्टैंस सेट करके पाया, जो पॉलीटोप का प्रतिनिधित्व करता था और फिर यादृच्छिक उद्देश्य कार्यों का उपयोग करता था। एक को चुनने के बजाय सभी 32 को एन्कोडिंग करने का कारण सरल है: अपेक्षित अदायगी 0 है, इसलिए मुझे एक जीत पाने की उम्मीद से बेहतर करने की आवश्यकता है। मैं अनिवार्य रूप से यह मानता हूं कि अन्य खिलाड़ी मिश्रित रणनीति का उपयोग कर रहे हैं और उनके पिक इतिहास के आधार पर वितरण का अनुमान लगा रहे हैं। फिर मैं उस बहुवचन शीर्ष का चयन करता हूं जो उस अनुमानित वितरण के खिलाफ मेरे अपेक्षित लाभ को अधिकतम करता है।

QuinnAndValor इस धारणा की भेद्यता को प्रदर्शित करता है कि अन्य खिलाड़ी मिश्रित रणनीति का उपयोग कर रहा है। नैश संतुलन से रणनीतियों का उपयोग करने वाले एक खिलाड़ी का पता लगाकर, यह एक यादृच्छिक वॉक मोड में स्विच करने में सक्षम है, जहां एक गैर-संतुलन रणनीति खेल रहा है, यह खोने के लिए औसतन उत्तरदायी है, लेकिन इसे केवल एक बार बढ़त हासिल करने की आवश्यकता है यह जोड़े को खेलने के लिए वापस ला सकता है pick + guess = n। तो एकल खेल के लिए नैश इक्विलिब्रिया दोहराया खेल के लिए नैश संतुलन को सामान्य रूप से सामान्य नहीं करता है, जो अधिक जटिल रणनीतियों की अनुमति देता है।


4
क्या यह संभव है कि आपके जादू में हेमिंग नंबरों का एक हिस्सा हो ? यह निश्चित रूप से उन सभी को शामिल नहीं करता है, लेकिन उनमें से कई ( या सभी? ) उस वेबसाइट पर सूची में हैं।
जाइंटट्री

@GiantTree, वे सभी हैमिंग नंबर हैं। दिलचस्प अवलोकन।
पीटर टेलर

कोई आश्चर्य नहीं कि आपका बॉट हैम जा रहा है। : D
mbomb007

11

क्विन और वेलोर (अपडेट किया गया)

क्विन और वेलोर एक कुलीन रेंजर टीम है। क्रॉसबो और पंजे के साथ, वे हर प्रतिद्वंद्वी को चीर देते हैं, उन्हें चुनौती देने की हिम्मत करते हैं।

import java.util.ArrayList;
import java.util.List;

interface Champion extends Player {
}

/*
 * Quinn and Valor are an elite ranger team. With crossbow and claw, they ...
 */
public class QuinnAndValor implements Champion {

    private final Champion quinn = new Quinn();
    private final Champion valor = new Valor();

    private int checker;
    private int myScore, opScore;
    private boolean ulted;
    private boolean teemoDetected;
    private boolean quinnNeverLose, valorNeverLose;
    private int quinnScore, valorScore;
    private int quinnRound, valorRound;

    public QuinnAndValor() {
        checker = check() ? 0 : 1;
    }

    // Check if is a fine use
    private static boolean check() {
        return Thread.currentThread().getStackTrace()[3].getClassName().equals(
                "Tournament");
    }

    @Override
    public String getName() {
        return quinn + " and " + valor;
    }

    @Override
    public int[] getMove(String[] args) {
        // Punish for bad usage
        switch (checker) {
        case 1:
            checker++;
            return new int[] { -1, -1 };
        case 2:
            checker++;
            return null;
        case 3:
            throw new Error("Mua he he heh!");
        default:
            if (checker > 0)
                throw new Error("Mua he he heh!");
            break;
        }

        int round = args[0].length();
        if (round == 0) {
            // Buy starting items
            myScore = opScore = 0;
            teemoDetected = false;
            quinnNeverLose = valorNeverLose = true;
            quinnScore = valorScore = quinnRound = valorRound = 0;
            ((Valor) valor).reset();
        }

        if (ulted = useUltimate(args)) {
            valorRound++;
            return valor.getMove(args);
        } else {
            quinnRound++;
            return quinn.getMove(args);
        }
    }

    /*
     * Quinn's ultimate has a lengthy cool-down, especially at lower ranks, so
     * we have to use it only when needed.
     */
    private boolean useUltimate(String[] args) {
        int round = args[0].length();
        int lastMyScore = myScore;
        int lastOpScore = opScore;
        myScore = Integer.parseInt(args[2]);
        opScore = Integer.parseInt(args[5]);
        int score = (myScore - opScore) - (lastMyScore - lastOpScore);
        if (ulted) {
            valorScore += score;
            valorNeverLose &= score >= 0;
        } else {
            quinnScore += score;
            quinnNeverLose &= score >= 0;
        }

        if (round < 100) {
            // Haven't hit level 6 yet
            return false;
        }

        if (myScore > opScore) {
            // We're already winning. Press on with strategy impossible to lose
            if (quinnNeverLose && quinnRound >= 50)
                return false;
            if (valorNeverLose && valorRound >= 50)
                return true;
        } else if (myScore < opScore) {
            // Although Quinn can blind others to counter them, she can be
            // counter be Teemo who also has blind! Don't fall for this!
            if (!teemoDetected) {
                teemoDetected = true;
                for (int i = round - 20; i < round; i++)
                    if (args[3].charAt(i) + args[4].charAt(i) != 'e')
                        teemoDetected = false;
            }
            if (teemoDetected)
                return true;
        }

        if (valorRound < 100) {
            // If we never use our ultimate, how can we know how strong it is?
            return true;
        }

        if (quinnScore < 0 && valorScore < 0)
            return valorRound < quinnRound;
        else
            return quinnScore * valorRound < valorScore * quinnRound;
    }

    @Override
    public String toString() {
        return getName();
    }

    /*
     * Quinn is a female Demacian elite ranger.
     * 
     * @see Valor
     */
    public static class Quinn implements Champion {
        @Override
        public String getName() {
            return "Quinn";
        }

        /*
         * Magic!
         */
        @Override
        public int[] getMove(String[] args) {
            int t = (int) ((Math.sqrt(Math.random() * 168 + 1) - 1) / 2);
            return new int[] { 5 - t, t };
        }

        @Override
        public String toString() {
            return getName();
        }
    }

    /*
     * Valor is Quinn's Demacian eagle.
     * 
     * @see Quinn
     */
    public static class Valor implements Champion {
        @Override
        public String getName() {
            return "Valor";
        }

        private int lastRound;
        private double[][] c;

        public void reset() {
            lastRound = 0;
            c = new double[6][6];
        }

        /*
         * Magic!
         */
        @Override
        public int[] getMove(String[] args) {
            int round = args[0].length();
            int[] b = new int[6];
            for (int i = round - 12; i < round; i++)
                b[args[0].charAt(i) - '0']++;
            {
                double deWeight = Math.pow(0.95, round - lastRound);
                for (int i = 0; i < 6; i++)
                    for (int j = 0; j < 6; j++)
                        c[i][j] *= deWeight;
                double weight = 1;
                for (int i = round - 1; i >= lastRound; i--) {
                    c[args[3].charAt(i) - '0'][args[4].charAt(i) - '0'] += weight;
                    weight *= 0.95;
                }
            }
            lastRound = round;

            List<int[]> pq = new ArrayList<>(1);
            double e = Integer.MIN_VALUE;
            for (int i = 0; i < 6; i++)
                for (int j = 0; j < 6; j++) {
                    double f = 0;
                    for (int k = 0; k < 6; k++)
                        f += (i + j) * c[j][k];
                    for (int k = 0; k < 6; k++)
                        f -= (i + k) * c[k][i];
                    // recently played moves are dangerous
                    f -= b[i] * b[i] * ((round + 11) / 12);
                    if (f >= e) {
                        if (f > e) {
                            pq.clear();
                            e = f;
                        }
                        pq.add(new int[] { i, j });
                    }
                }
            return pq.get((int) (Math.random() * pq.size()));
        }

        @Override
        public String toString() {
            return getName();
        }
    }
}

वे लगभग हमेशा मेरी मशीन पर सभी जावा समाधान के खिलाफ जीतते हैं।

संपादित करें:

मैं मानता हूं कि क्विन और वेलोर इतिहासकार को द्वंद्व करने में विफल रहे, लेकिन मुझे अभी भी टूर्नामेंट जीतने के लिए उन पर अच्छा विश्वास है।

मेरा सिद्धांत है, किसी भी समाधान के लिए choice + guess == 5, choice + guess == 5अपने लाभ को ध्यान में रखते हुए अनुदान के साथ खेलना ।

अद्यतन करें:

खैर ... सब कुछ बस जटिल हो गया।


1
मुझे लीग ऑफ लीजेंड्स संदर्भ पसंद है। मैं वास्तव में अब तेमो बॉट बनाना चाहता हूं। :)
mbomb007

6

पंडित

विद्वान अपने प्रतिद्वंद्वी की चालों से सीखने की कोशिश करता है, जिसमें से एक ने अपने उत्पीड़क को कम अनुमान लगाया और अपने प्रतिद्वंद्वी का सबसे अधिक उपयोग करने का अनुमान लगाया। लेकिन सिद्धांत सब कुछ नहीं है, इसलिए विद्वान बहुत अच्छा नहीं करता है ...

import java.util.HashMap;

public class Scholar implements Player
{
    public static int[] pm = new int[6];
    public static int[] pg = new int[6];
    public static HashMap<Integer, Integer> lm = new HashMap<>();
    public static HashMap<Integer, Integer> lg = new HashMap<>();

    public String getName()
    {
        return "Scholar";
    }

    public int[] getMove(String[] a)
    {
        int r = a[0].length();
        for (int i = 0; i < 6; i++) { pm[i]=0; pg[i]=0; }
        for (int i = 0; i < a[3].length(); i++) {
            int m = Integer.parseInt(String.valueOf(a[4].charAt(i)));
            int g = Integer.parseInt(String.valueOf(a[3].charAt(i)));
            pm[m]++; pg[g]++;
        }
        for (int i = 0; i < pm.length; i++) { lm.put(i, pm[i]); lg.put(i, pg[i]); }

        if (r < 1) {
            return new int[] { 3, 3 };
        } else {

            int mm = lm.entrySet().stream().min((x, y) -> x.getValue() > y.getValue() ? 1 : -1).get().getKey();
            int mg = lg.entrySet().stream().max((x, y) -> x.getValue() > y.getValue() ? 1 : -1).get().getKey();
            return new int[] { mm, mg };
        }   
    }
}

6

DeltaMax

(फ़ाइलों का उपयोग नहीं करने के लिए अद्यतन और एक नया खंड जोड़ा गया। इसके अलावा पहले खंड में बांधने के लिए संशोधित नहीं है।)

कुछ रणनीतियों से मिलकर जो सरल शुरू होते हैं और अधिक जटिल हो जाते हैं - यदि आप एक को साफ करते हैं, तो यह आपको अगले अनुभाग में ले जाता है।

  • धारा 1:{0, 5} लगातार अनुमान लगाओ
  • खंड 2: जाँच करें कि क्या आपके पिछले 4 अनुमानों में एक स्थिर, रैखिक या द्विघात पैटर्न है और पैटर्न को तब तक अनुमान लगाते रहें जब तक कि वह टूट न जाए
  • खंड 3: जांचें कि क्या आप किसी संख्या की असामान्य रूप से कम मात्रा (1/13 से कम) का अनुमान लगाते हैं और उस संख्या को चुनें
  • धारा 4: अपनी पसंद में बीग्रामों का विश्लेषण करें और देखें कि आगे क्या होने की संभावना है
  • धारा 5: पिछले 100 राउंड को देखें और उस (choice, guess)जोड़ी को चुनें जिसमें सबसे अच्छी उम्मीद होगी, भारित होगा ताकि हाल के दौर अधिक महत्वपूर्ण हों
  • अनुभाग अंतिम: बेतरतीब ढंग से अनुमान लगाओ, कम विकल्प और उच्च अनुमान होने की अधिक संभावना के साथ। यदि आप यहां पहुंचते हैं, तो DeltaMax ने हार मान ली है और "अच्छा खेल" कहना चाहेंगे।

यह पता लगाने के लिए कि अंत में किस स्ट्रैट का उपयोग किया गया था, को असंबद्ध करें

if (myChoices.length == 999) { System.out.println(strat); }

लाइन।

डरावने जावा के लिए क्षमा याचना, मैंने अपनी दोपहर की पीक बिट्स को एक साथ बिताया और भाषा को पुनः साझा किया :)

import java.io.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class DeltaMax implements Player
{
    private int strat = 100;

    public String getName() { return "DeltaMax"; }

    public int[] toInts(String s) {
        char [] chars = s.toCharArray();
        int[] ints = new int[chars.length];

        for (int i = 0; i < chars.length; i++){
            ints[i] = Integer.parseInt(Character.toString(chars[i]));
        }

        return ints;
    }

    public int mod6(int n) {
        n = n % 6;
        if (n < 0) { n += 6; }
        return n;
    }

    public int[] getMove(String [] args)
    {
       int[] myChoices = toInts(args[0]);
       int[] myGuesses = toInts(args[1]);
       int myScore = Integer.parseInt(args[2]);
       int[] opponentChoices = toInts(args[3]);
       int[] opponentGuesses = toInts(args[4]);
       int opponentScore = Integer.parseInt(args[5]);

       int rounds = myChoices.length;

       if (rounds == 0) { strat = 100; }
       Random r = new Random();

       // if (myChoices.length == 999) { System.out.println(strat); }

       if (strat == 100) { // Section 1 - {0, 5}
           if (opponentScore - myScore > 21 || (opponentScore >= myScore && rounds > 100)) {
               strat = 200;
           } else {
               return new int[] {0, 5};
           }
       }

       if (strat == 200) { // Section 2 - Mini interpolator
           int w = opponentChoices[opponentChoices.length - 4];
           int x = opponentChoices[opponentChoices.length - 3];
           int y = opponentChoices[opponentChoices.length - 2];
           int z = opponentChoices[opponentChoices.length - 1];

           if (w == x && x == y && y == z) { // Constant
               return new int[] { r.nextInt(4) + 2, w };
           }

           if (mod6(x-w) == mod6(y-x) && mod6(y-x) == mod6(z-y)) { // Linear
               return new int[] { r.nextInt(4) + 2, mod6(z + (z-y)) };
           }

           if (mod6((y-x) - (x-w)) == mod6((z-y) - (y-x))) { // Quadratic
               return new int[] { r.nextInt(4) + 2, mod6((z-y) + mod6((y-x) - (x-w))) };
           }

           strat = 300;
       }

       if (strat == 300) { // Section 3 - exploit least guessed
           int [] counts = new int[6];

           for (int i = 0; i < rounds; i++) {
               counts[opponentGuesses[i]] += 1;
           }

           int minCount = rounds;

           for (int i = 0; i < 6; i++) {
               if ((counts[i] <= 1 || counts[i] * 13 < rounds) && counts[i] < minCount) {
                   minCount = counts[i];
               }
           }

           if (minCount == rounds) {
               strat = 400;
           } else {
               ArrayList<Integer> choices = new ArrayList<Integer>();

               for (int i = 0; i < 6; i++) {
                   if (counts[i] == minCount) {
                       choices.add((Integer) i);
                   }
               }

               int choice = choices.get(r.nextInt(choices.size()));

               // {0, 0} is about the worst thing you can do, so DeltaMax tries to avoid that
               if (choice == 0) {
                   return new int[] { 0, r.nextInt(4) + 2 };
               } else {
                   return new int[] { choice, r.nextInt(6) };
               }
           }
       }

       if (strat == 400) { // Section 4 - bigrams
           if (opponentScore - myScore > 42 || (opponentScore >= myScore && rounds > 300)){
               strat = 500;
           } else {
               int[] opponentScores = new int[6];
               int opponentLast = opponentChoices[opponentChoices.length - 1];

               int[] myScores = new int[6];
               int myLast = myChoices[myChoices.length - 1];

               for (int i = 0; i < opponentChoices.length - 1; i++) {
                   if (opponentChoices[i] == opponentLast) {
                       opponentScores[opponentChoices[i+1]] += 1;
                   }

                   if (myChoices[i] == myLast) {
                       myScores[myChoices[i+1]] += 1;
                   }
               }

               int maxIndex = -1;
               int maxScore = 0;

               int minIndex = -1;
               int minScore = rounds;

               for (int i = 0; i < 6; i++) {
                   if (opponentScores[i] >= maxScore) {
                       maxScore = opponentScores[i];
                       maxIndex = i;
                   }

                   if (myScores[i] <= minScore) {
                       minScore = myScores[i];
                       minIndex = i;
                   }
               }

               if (minIndex == 0 && maxIndex == 0) {
                   return new int[] { 0, r.nextInt(4) + 2 };
               } else {
                   return new int[] { minIndex, maxIndex };
               }
           }
       }

       if (strat == 500) { // Section 5 - best expectation
           if (opponentScore - myScore > 84 || (opponentScore >= myScore && rounds > 800)){
               strat = 573;
           } else {
               int minLen = Math.min(rounds, 100);

               double bestScore = 0;
               int bestGuess = 0;
               int bestChoice = 5;

               for (int guess = 0; guess < 6; guess++) {
                   for (int choice = 0; choice < 6; choice++) {
                       double score = 0;
                       int start = rounds - minLen;

                       for (int i = start; i < rounds; i++) {
                           if (opponentGuesses[i] == choice && opponentChoices[i] != guess) {
                               score -= (choice + opponentChoices[i]) * ((double) i - start) / minLen;
                           } else if (opponentGuesses[i] != choice && opponentChoices[i] == guess) {
                               score += (choice + opponentChoices[i]) * ((double) i - start) / minLen;
                           }
                       }

                       if (score > bestScore) {
                           bestScore = score;
                           bestGuess = guess;
                           bestChoice = choice;
                       }
                   }
               }

               if (bestChoice == 0 && bestGuess == 0) {
                   return new int[] { r.nextInt(4) + 2, bestGuess };
               } else {
                   return new int[] {bestChoice, bestGuess};
               }
           }
       }

       // Section final - hope for the best
       int num = (int) Math.floor(Math.sqrt(r.nextInt(35)));
       return new int[] {5 - num, num};
    }
}

नियंत्रक के वर्तमान कार्यान्वयन के साथ, फ़ाइल में चीजों को सहेजने की आवश्यकता नहीं है यदि डेटा केवल एक गेम के लिए उपयोग किया जाता है। यानी private int strat;काफी अच्छा है।
johnchen902

@ johnchen902 धन्यवाद, मुझे महसूस नहीं हुआ कि मैं ऐसा कर सकता हूं। इससे चीजें बहुत आसान हो जाती हैं।
Sp3000

6

इतिहासकार

(अपडेट किया गया: एक ही तर्क, छोटा कोड और 100 गुना तेज लेकिन आप एक टूर्नामेंट में केवल एक हिस्टोरियन बॉट का उपयोग कर सकते हैं।)

पिछले इतिहास के विरोधियों के खिलाफ केवल उस जोड़ी का उपयोग करने की प्रभावशीलता के आधार पर फेंक-अनुमान जोड़ी चुनने के लिए भारित यादृच्छिक का उपयोग करता है। वजन वर्ग के प्राप्य स्कोर हैं।

public class Historian implements Player {
    private static java.util.Random r = new java.util.Random();
    private static int[] sc=new int[36]; //reseted between games, use only one Historian bot
    public String getName() {return "Historian";}
    public int[] getMove(String [] a) {
        if (a[3].length()==0)  {sc=new int[36]; for(int i=0;i<6;i++) sc[i*6+(5-i)]=5-i;}
        else {int t=a[3].charAt(a[3].length()-1)-'0'; int g=a[4].charAt(a[3].length()-1)-'0';
            for(int i=0; i<6; i++) {sc[i*6+t]+=i+t; sc[g*6+i]-=t+g;}}
        int sum=0; for(int i=0; i<36; i++) {sum+=(sc[i]<1)?1:sc[i]*sc[i];}
        int seed=r.nextInt(sum);int mt=-1;
        while (seed>=0) {seed-=(sc[++mt]<1)?1:sc[mt]*sc[mt];}  
        return new int[] {(int)(mt/6),mt%6};} }

धड़कता है Quinn and Valor (अब नहीं) और हारता है Morra Cowbell। टूर्नामेंट में अधिकांश बॉट Historianके साथ दूसरे स्थान पर आता है Quinn and Valor


खैर, यह देखना अच्छा है कि मैं किसी की मशीन पर जीता हूं। मैं वर्तमान आधिकारिक नेता बोर्ड खो रहा हूं । मैं सोच रहा था कि यह दुर्भाग्य या कुछ अप्रत्याशित सूक्ष्म बग के कारण है।
johnchen902

@ johnchen902 मुझे मतिभ्रम होना चाहिए Morra Cowbell। पद का संपादन किया। यदि आप अप्रचलित हो जाते हैं तो आप टिप्पणियों को हटा सकते हैं।
यादृच्छिक

मुझे लगता है कि मैं अपने अपडेट के बाद अब हमारे द्वंद्व का 75% जीत सकता हूं!
johnchen902

5

एक्सट्रैपलेटर (v1.1)

एक सरल खेल के नैश-संतुलन में से एक से अत्यधिक एक्सट्रपलेशन।

मैं terse उत्तर प्रारूप का समर्थन करता हूं! (अजगर शैली में)

public class Extrapolator implements Player { 
    private static java.util.Random r = new java.util.Random();
    public String getName() { return "Extrapolator"; }
    public int[] getMove(String [] args) {
        int t=-1;
        for(int c=15,s=r.nextInt(60);s>=0;s-=c,c-=2,t++);
        return new int[] {t,5-t}; } }

मैजिक काउ (मोर्रा काउबेल) के साथ टाई करने के लिए लगता है और अन्य प्रविष्टियों को हराता है जिन्हें मैंने चेक किया था।


1
कृपया रैंडम आर को एक स्थिर फील्ड में ले जाएँ, ताकि आप इसे हर बार इनिशियलाइज़ न करें, इससे ओवरऑल परफॉर्मेंस में मदद मिलेगी!
फाल्को

वितरण में बदलाव क्यों?
पीटर टेलर

4

फैशनेबल

ट्रेंडी प्रतिद्वंद्वी के पिछले चालों पर एक नज़र डालते हैं, उन्हें पुनरावृत्ति द्वारा भारित करते हैं। सबसे वजन लगता है, और उस से थोड़ा ऊपर स्थानांतरित कर देता है। यहाँ यह अपनी महिमा में है:

public class Trendy implements Player{public String getName(){return "Trendy";}public int[]getMove(String[]a){float h=0,c[]=new float[6];int i=0,l=a[3].length(),p=0;for(;i<l;)c[a[3].charAt(i++)-48]+=(float)i/l;for(i=0;i<6;i++)if(c[i]>h)h=c[p=i];return new int[]{(p+2)%6,p};}}    

केवल एक चीज जिसकी मैं अब तुलना कर सकता हूं वह है काउबेल। यह समय के बहुमत से एक छोटे से अंतर से हार जाता है, लेकिन मेरी पसंद के लिए अक्सर शीर्ष पर आता है। हम देखेंगे कि यह अधिक प्रतियोगियों के साथ कैसे करता है।


7
आप कई लाइनों पर कोड प्रारूप कर सकते हैं? यह कोड गोल्फ नहीं है ...
mbomb007

7
@ mbomb007 यह इस तरह कम जगह लेता है। सामान्य रूप से कोठियों के दर्द में से एक प्रविष्टियों को देखने के लिए सभी स्क्रॉलिंग है। मैंने वर्णन किया है कि यह क्या करता है, और यह इच्छुक पार्टियों के लिए इसे प्रारूपित करने के लिए बहुत सीधा है।
Geobits

4

रैंडम गेसर

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

import java.util.Random;

public class RandomGuesser implements Player {
    private final Random rnd = new Random();
    public String getName() { return "RandomGuesser"; }

    public int[] getMove(String[] args) {
        return new int[] { rnd.nextInt(6), rnd.nextInt(6) };
    }
}

4

उलझन, पायथन 3

एक अनावश्यक रूप से जटिल प्रविष्टि। यहां तक ​​कि मुझे नहीं पता कि यह क्या करता है।

import sys
from random import *

if len(sys.argv) == 7:
    mn,mg,ms,on,og,os = [list(map(int, v)) for v in sys.argv[1:]]
    s,t = sum(mn+on)%5, sum(mg+og)%5
    n = [0]*3+list(range(6))*5+[5,0,5]
    m = [1,0,5,4]+n[:-2:s//9+1]
    numoptions = [n.extend(n[i+s::5+t]+[i]*i*(6+t)) for i in n[:]] and n
    guessoptions = [m.extend(m[i+t//2::8]+[i]*i*(5+s)) for i in m[:]] and m
    num = choice(numoptions)
    guess = choice(guessoptions)
else:
    num, guess = randint(0, 5), randint(0, 5)

sys.stdout.write('%u %u\n' % (num, guess))

यद्यपि यह उन्नत एल्गोरिथ्म इस टूर्नामेंट में यादृच्छिक से भी बदतर प्रदर्शन करता है, और महत्वपूर्ण मेमोरी और रन-टाइम का उपयोग करता है, इसमें 5 से अधिक मूल्यों के लिए आश्चर्यजनक परिणाम हैं; ;-)


4

Rainbolt

हमारे प्रतिद्वंद्वी द्वारा अनुमान लगाए गए अंतिम दो नंबरों के बीच का अंतर लेता है, जो हमारे प्रतिद्वंद्वी के नवीनतम अनुमानों को जोड़ता है, मापांक पाता है, और हर कीमत पर उस नंबर को चुनने से बचता है। उदाहरण के लिए, यदि आप {5,4,3} (एक से कम) का अनुमान लगाते हैं तो हम हर कीमत पर 2 चुनने से बचेंगे।

हमारे प्रतिद्वंद्वी द्वारा चुने गए अंतिम दो नंबरों के बीच का अंतर लेता है, जो हमारे प्रतिद्वंद्वी की नवीनतम पसंद को जोड़ता है, और उस संख्या का अनुमान लगाता है। उदाहरण के लिए, यदि आप {1,4,5,2} अनुमान लगाते हैं (थ्रेश से बढ़ रहा है) तो हम 5 का अनुमान लगाएंगे।

व्यर्थ या अवशिष्ट रोल के बहुत करीब।

public class Rainbolt implements Player {

    public String getName() { 
        return "Rainbolt"; 
    }

    public int[] getMove(String[] args) {
        int[] yourChoices = toIntArray(args[3]);
        int[] yourGuesses = toIntArray(args[4]);

        int myChoice;
        if (yourGuesses.length > 1) {
            int latest = yourGuesses[yourGuesses.length - 1];
            int secondLatest = yourGuesses[yourGuesses.length - 2];
            int numberToAvoid = (2 * latest - secondLatest + 6) % 6;
            do {
                myChoice = rollRandom();
            } while (myChoice == numberToAvoid);
        } else { 
            myChoice = rollRandom();
        }

        int myGuess;
        if (yourChoices.length > 1) {
            int latest = yourChoices[yourChoices.length - 1];
            int secondLatest = yourChoices[yourChoices.length - 2];
            myGuess = (2 * latest - secondLatest + 6) % 6;
        } else { 
            myGuess = rollRandom();
        }

        if ((myChoice + myGuess) < 3) {
            do {
                myGuess = rollRandom();
            } while ((myChoice + myGuess) < 3);
        }

        return new int[] { myChoice, myGuess };
    }

    private static int[] toIntArray(String arg) {
        int[] result = new int[arg.length()];
        for (int i = 0; i < arg.length(); i++)
            result[i] = Character.getNumericValue(arg.charAt(i));
        return result;
    }

    private static int rollRandom() {
        return (int) (Math.random() * 6);
    }
}

अपनी getMove()पद्धति को स्थिर न बनाएं । आप इस तरह एक गैर-स्थैतिक विधि को लागू नहीं कर सकते (कम से कम जावा 8 में नहीं)।
21

@GiantTree कि पकड़ने के लिए धन्यवाद।
21

3

विकसित बॉट

मैंने इस बॉट को सबसे अच्छा रैंडम बेस्ड बॉट बनाया।

import java.util.Arrays;

public class EvolvedBot implements Player {

    private static final double MUTATION_RATE = .2;
    private static final double CROSS_OVER_RATE = .5;

    private final double[] pickProbabilities;
    private final double pickSum;
    private final double[] guessProbabilities;
    private final double guessSum;

    public EvolvedBot(){
        this(new double[]{1.0069058661897903, 0.8949716031797937, 0.5249198534098369, 0.437811964976626, 0.2630925750209125, 0.4862172884617061},
                new double[]{0.6336558074769376, 0.13700756148363913, 0.9586621925124863, 0.11223159366330251, 0.8931390659502754, 0.662974949440039});
    }

    public EvolvedBot(double[] pickProbabilities, double[] guessProbabilities) {
        this.pickProbabilities = pickProbabilities;
        this.guessProbabilities = guessProbabilities;
        pickSum = Arrays.stream(pickProbabilities).sum();
        guessSum = Arrays.stream(guessProbabilities).sum();
    }

    @Override
    public String getName() {
        return "EvolvedBot"/* + ": " + Arrays.toString(pickProbabilities) + Arrays.toString(guessProbabilities)*/;
    }

    @Override
    public int[] getMove(String[] args) {
        int[] move = new int[]{5, 5};
        double pick = Math.random() * pickSum;
        double guess = Math.random() * guessSum;
        for (int i = 0; i < 6; i++){
            if (pick >= 0) {
                pick -= pickProbabilities[i];
                if (pick < 0) {
                    move[0] = i;
                }
            }
            if (guess >= 0){
                guess -= guessProbabilities[i];
                if (guess < 0){
                    move[1] = i;
                }
            }
        }
        return move;
    }

    public EvolvedBot mutate(double mutationRate){
        double[] pickProbabilities = Arrays.copyOf(this.pickProbabilities, 6);
        double[] guessProbabilities = Arrays.copyOf(this.guessProbabilities, 6);

        for (int i = 0; i < 6; i++){
            pickProbabilities[i] = Math.max(pickProbabilities[i] + (Math.random() * 2 - 1) * mutationRate, 0);
        }

        for (int i = 0; i < 6; i++){
            guessProbabilities[i] = Math.max(guessProbabilities[i] + (Math.random() * 2 - 1) * mutationRate, 0);
        }

        return new EvolvedBot(pickProbabilities, guessProbabilities);
    }

}

3

लोकप्रियता, पायथन 3

प्रतिद्वंद्वी द्वारा अतीत में उपयोग किए गए लोकप्रिय नंबरों के आधार पर गणना अनुमान। हाल ही में उपयोग किए गए नंबरों का वजन अधिक है। संख्या विकल्प अक्सर अनुमान के समान होता है।

import sys
from random import *

if len(sys.argv) == 7:
    mn,mg,ms,on,og,os = [list(map(int, v)) for v in sys.argv[1:]]
    n = list(range(6))
    guess = choice(n + on[-100:] + on[-20:]*8)
    num = choice(n + [guess]*6)
else:
    num, guess = randint(0, 5), randint(0, 5)

sys.stdout.write('%u %u\n' % (num, guess))

3

क्षेपक करनेवाला

(जावा के लिए स्विच किया गया क्योंकि पायथन समस्या पैदा कर रहा था)

प्रतिद्वंद्वी के अगले नंबर पर काम करने के लिए अंतिम 10 प्रतिद्वंद्वी विकल्पों पर बहुपद प्रक्षेप का उपयोग करता है, फिर अपनी पसंद के लिए भी यही करता है और उस नंबर को चुनने से बचता है । इसके अलावा, इंटरपोलर में 0 या 5 चुनने के खिलाफ एक मामूली पूर्वाग्रह है, और इसकी पसंद कभी-कभी इसके अनुमान से प्रभावित होती है:

  • यदि यह अनुमान लगाता है तो यह कभी भी 0 नहीं होगा
  • यदि यह 5 अनुमान लगाता है तो यह हमेशा 0 या 1 का चयन करेगा
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

public class Interpolator implements Player
{
    private final int TAIL_LENGTH = 10;

    public String getName()
    {
        return "Interpolator";
    }

    public int[] toInts(String s) {
        char [] chars = s.toCharArray();
        int[] ints = new int[chars.length];

        for (int i = 0; i < chars.length; i++){
            ints[i] = Integer.parseInt(Character.toString(chars[i]));
        }

        return ints;
    }

    public int mod6(int n) {
        n = n % 6;
        if (n < 0) { n += 6; }
        return n;
    }

    public int interpolate(int[] nums){
        boolean allEqual = true;

        for (int i = 0; i < nums.length; i++){
            if (nums[i] != nums[0]){
                allEqual = false;
            }
        }

        if (allEqual) {
            return nums[0];

        } else {
            int [] newNums = new int[nums.length - 1];

            for (int i = 0; i < nums.length - 1; i++){
                newNums[i] = nums[i+1] - nums[i];
            }

            return nums[nums.length - 1] + interpolate(newNums);
        }
    }

    public int[] tail(int[] nums) {
        int minLength = Math.min(TAIL_LENGTH, nums.length);
        int[] tailArray = new int[minLength];

        for (int i = 0; i < minLength; i++){
            tailArray[i] = nums[nums.length - minLength + i];
        }

        return tailArray;
    }

    public int[] getMove(String [] args)
    {
        Random r = new Random();

        if (args[0].length() == 0){
            return new int[] {r.nextInt(5), r.nextInt(5)};
        }

        int[] myChoices = toInts(args[0]);
        int[] opponentChoices = toInts(args[3]);
        int[] opponentGuesses = toInts(args[4]);

        int guess = mod6(interpolate(tail(opponentChoices)));
        int avoid = mod6(interpolate(tail(myChoices)));

        if (guess == 5){ return new int[] {r.nextInt(2), 5}; }

        int[] choiceArray = {0, 1, 1, 2, 2, 3, 3, 4, 4, 5};
        ArrayList<Integer> choices = new ArrayList<Integer>();
        for (int i = 0; i < choiceArray.length; i++) { choices.add(choiceArray[i]); }

        choices.removeAll(Collections.singleton((Integer) avoid));
        if (guess <= 0) { choices.removeAll(Collections.singleton((Integer) 0)); }
        int choice = choices.get(r.nextInt(choices.size())); 

        return new int[] {choice, guess};
    }
}

3

CounterBot

किसी को काउंटर नहीं करता है, बल्कि एक सर्कल में 0-5 से गिनती करता है ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4 ...)

import java.util.Random;

public class Counter implements Player {

    int lastChoice = new Random().nextInt(6); //Chooses a random starting number

    public String getName() {
        return "CounterBot";
    }

    public int[] getMove(String[] args) {
        int[] oChoices = new int[6]; //Array to store the amount of individual choices of the opponent

        for (int i = 0; i < args[3].length(); i++) {
            int index = Integer.parseInt(String.valueOf(args[3].charAt(i))); //get that choice
            oChoices[index]++; //Increment the number corresponding the choice
        }
        int guess = 0, last = 0;
        for (int i = 0; i < oChoices.length; i++) { //Increment over the choices' array
            if (oChoices[i] > last) { //If the number has been chosen more often than the one before
                last = oChoices[i]; //Set the new maximum value (later the last maximum value)
                guess = i; //Set it as the next guess
            }
        }
        lastChoice++; //Increment our choice
        lastChoice %= 6; //Make sure it's within the bounds of 0-5 ie. modulo 6 (6 modulo 6 = 0)
        return new int[]{lastChoice, guess}; //return our choice and guess
    }
}

2

बेसिलिस्क, पायथन

पौराणिक कथा के अनुसार, द बेसिलिस्क नागों का राजा है। ( स्रोत ) मुझे लगा कि एक बॉट के लिए एक उपयुक्त नाम है जो "द नोबल गेम ऑफ किंग्स" खेलता है और अजगर में लिखा गया है। = डी यह बॉट अन्य बॉट्स के दिल में डर पैदा करता है, और एक ही नज़र में मौत का कारण बनता है।

import sys
import random

args = sys.argv
argc = len(args)
if argc < 6:
    sys.exit()

myChoices = args[1]
myGuesses = args[2]
myScore = args[3]
opponentChoices = args[4]
opponentGuesses = args[5]
opponentScore = args[6]

if len(myChoices) == 0:
    print (random.randint(0, 5))
    print (random.randint(0, 5))
    sys.exit()

guesses = [0, 0, 0, 0, 0, 0]
for char in opponentGuesses:
    i = int(char)
    guesses[i] += 1

#Will default towards smaller guesses to minimize opponent winnings
#For example, if the guess list is
#[5, 3, 7, 3, 4, 8]
#This will return 1. (index of the first 3)
myNextMove = guesses.index(min(guesses))

list = [
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]]
i = 0

while i < len(myGuesses) - 1:
    myGuess = int(myGuesses[i])
    opponentResponse = int(opponentChoices[i+1])
    list[myGuess][opponentResponse] += 1
    i += 1

myPreviousGuess = int(myGuesses[-1])
relevantList = list[myPreviousGuess]

#Defaults towards higher moves.
#For example, if the list is
#[3, 8, 6, 8, 0, 7]
#This will return 3 (index of the last 8)
highestValue = -1
highestIndex = -1
for i in range(len(relevantList)):
    if relevantList[i] >= highestValue:
        highestValue = relevantList[i]
        highestIndex = i


myNextGuess = highestIndex

print (myNextMove)
print (myNextGuess)

यह काफी सरल रणनीति पर चलता है। मैं इसे जीतने की उम्मीद नहीं कर रहा हूं, लेकिन यह लिखने में मजेदार था। यह मेरी पहली KoTH चुनौती भी है, इसलिए मैं यह देखने के लिए उत्साहित हूं कि यह कितना अच्छा प्रदर्शन करता है।

यह अपने अगले कदम को कैसे उठाता है।

बेसिलिस्क हमेशा यह कदम उठाता है कि उसके प्रतिद्वंद्वी ने सबसे कम बार अनुमान लगाया है। एक टाई के मामले में, वह छोटी संख्या को चुनेगा। (विरोधियों की संख्या को कम करने के लिए।)

यह अपना अगला अनुमान कैसे लगाता है।

बेसिलिस्क अपने पिछले अनुमान के लिए सबसे अधिक संभावना प्रतिक्रिया उठाएगा। उदाहरण के लिए, यदि पिछली बार, यह 3 का अनुमान लगाता है, तो यह पिछली बार के सभी के माध्यम से वापस आ जाएगा कि इसने 3 का अनुमान लगाया है, और फिर 3 के अनुमान के बाद आने वाले सबसे आम प्रतिद्वंद्वी कदम को वापस लौटाएं। टाई के मामले में। , यह बड़ी संख्या (अंकों की अधिकतम संख्या को बढ़ा सकता है)।

तकनीकी नोट पर, क्या यह सही ढंग से चलेगा? क्या प्रिंट () पर्याप्त है, या क्या मुझे sys.stdout.write () की तरह कुछ का उपयोग करना चाहिए जैसे कि अन्य पायथनस्टेस ने किया है?


sys.stdout.write () या तो पायथन में काम करता है। प्रिंट () केवल पायथन 3 में काम करता है। हालांकि यह ठीक होना चाहिए।
TheNumberOne

नहीं, प्रिंट () दोनों में काम करता है, मुझे यकीन है। कोष्ठक 2.x में वैकल्पिक हैं
DJMcMayhem

के अनुसार इस , वे अलग तरह से काम। हालाँकि, जिस तरह से आप इसका उपयोग करते हैं, यह कोई फर्क नहीं पड़ता।
TheNumberOne

लेकिन क्या इससे कोई फर्क पड़ता है?
DJMcMayhem

जाहिरा तौर पर नहीं।
TheNumberOne

2

ठीक इसी प्रकार से

यह प्रतिद्वंद्वी में बदल जाता है, लेकिन एक अनुमान / पसंद से पीछे है।

import java.util.Random;

public class Ditto implements Player {
    private final Random rnd = new Random();
    public String getName() { return "Ditto"; }

    // myChoices myGuesses myScore oppChoices oppGuesses oppScore
    public int[] getMove(String[] args) {
        if(args[0] == null || args[0].isEmpty()) {
            return new int[] { rnd.nextInt(6), rnd.nextInt(6) };
        }
        int[] myChoices = toIntArray(args[0]);
        int[] myGuesses = toIntArray(args[1]);
        //int myScore = Integer.parseInt(args[2]);
        int[] oppChoices = toIntArray(args[3]);
        int[] oppGuesses = toIntArray(args[4]);
        //int oppScore = Integer.parseInt(args[5]);

        return new int[] { oppChoices[oppChoices.length-1], oppGuesses[oppGuesses.length-1] };
    }

    private static int[] toIntArray(String arg) {
        int[] result = new int[arg.length()];
        for (int i = 0; i < arg.length(); i++)
            result[i] = Character.getNumericValue(arg.charAt(i));
        return result;
    }
}

1

NullifierBot, Java

किसी भी प्रतिद्वंद्वी जीत को कम करने के लिए हमेशा 0 फेंकता है। यदि प्रतिद्वंद्वी कभी मेरी संख्या का अनुमान लगाते हैं, तो वे केवल वही कमाते हैं जो उन्होंने फेंक दिया था।

मेरी जीत को अधिकतम करने के लिए हमेशा 5 अनुमान लगाता है। चूंकि मुझे अपने थ्रो से कोई अंक नहीं मिल रहा है, इसलिए मैं प्रतिद्वंद्वी से कई अंक हासिल करना चाहता हूं। मैं बेतरतीब ढंग से अनुमान लगा सकता था, लेकिन उस में मज़ा कहाँ है?

public class NullifierBot implements Player
{
    public String getName()
    {
        return "NullifierBot";
    }

    public int[] getMove(String [] args)
    {
        // always throws 0 to minimize opponents score
        // always guesses 5 to maximize my score
        return new int[] {0, 5}; 
    }
}

मैं अनुमान लगा रहा हूं कि यह बॉट भयानक रूप से करेगा। बाधाओं का उपयोग करने वाले किसी भी बॉट को शायद पहले के बाद हर एक अनुमान सही मिलेगा।
mbomb007 21

@ mbomb007 हालांकि यह सबसे बुरा नहीं है! हालांकि यह आपके रैंडमबॉट से भी बदतर प्रदर्शन करता है।
ब्रायन जे।

1

इरेटिका, जावा

महान नहीं है, लेकिन यह मूल रूप से ज्यादातर यादृच्छिक होने के लिए डिज़ाइन किया गया था, जब तक कि ट्रेड-ऑफ का मूल्य मुझ पर नहीं निकला। लगातार हारने का प्रबंधन बनाम काउंटर बॉट> _ <

import java.util.Random;
class Erratica implements Player
{
    private final Random rnd = new Random();

    public String getName() {
        return "Erratica";
    }

    public int[] getMove(String[] args) {
        if(args[0] == null || args[0].isEmpty())
        {
            return new int[]{rnd.nextInt(4)/3+4,rnd.nextInt(4)/3};
        }
        int[] myChoices = toIntArray(args[0]);
        int[] myGuesses = toIntArray(args[1]);
        int myScore = Integer.parseInt(args[2]);
        int[] opponentChoices = toIntArray(args[3]);
        int[] opponentGuesses = toIntArray(args[4]);
        int opponentScore = Integer.parseInt(args[5]);
        int round = opponentChoices.length + 1;
        int choice=0;
        int guess=0;
        if(round<7)
        {
            if(rnd.nextFloat()<(0.1f*(float)round-0.1f))
            {
                choice=(opponentChoices[round-2]+opponentGuesses[round-2])%6;
            }else
            {
                choice=rnd.nextInt(6);
            }
            if(rnd.nextFloat()<(0.1f*(float)round-0.1f))
            {
                guess=opponentChoices[round-2];
            }else
            {
                guess=rnd.nextInt(6);
            }
            return new int[]{choice, rnd.nextInt(6)/5*(5-choice-guess)+guess};
        }else
        {
            int lastError=Math.abs(opponentGuesses[round-2]-myChoices[round-2]);
            for(int i=round-2; i>round-8;i--)
            {
                if(lastError<rnd.nextInt(6))
                {
                    lastError++;
                }else
                {
                    lastError--;
                }
                if(lastError<0)
                    lastError+=6;

            }
            lastError = lastError%6; //shouldn't change
            switch(rnd.nextInt(4))
            {
                case 0:
                    choice=(myChoices[round-2-lastError-round/10])%6;
                    break;
                case 1:
                    choice=(myChoices[lastError+round/10])%6;
                    break;
                default:
                    choice = rnd.nextInt(6);
                    break;
            }

            lastError=Math.abs(myGuesses[round-2]-opponentChoices[round-2]);
            for(int i=round-2; i>round-8;i--)
            {
                if(lastError<rnd.nextInt(6))
                {
                    lastError++;
                }else
                {
                    lastError--;
                }
                if(lastError<0)
                    lastError+=6;
            }
            lastError = lastError%6; //shouldn't change
            switch(rnd.nextInt(4))
            {
                case 0:
                    guess=(opponentChoices[round-2-lastError-round/10])%6;
                    break;
                case 1:
                    guess=(opponentChoices[lastError+round/10])%6;
                    break;
                default:
                    guess = rnd.nextInt(4);
                    break;
            }
        }

        if(myScore>opponentScore)
            switch(rnd.nextInt(2)){
                case 0:
                    choice=5-guess;
                    break;
                case 1:
                    guess=5-choice;
                    break;
                default:
                    break;
            }
        return new int[]{choice, guess};
    }

    private static int[] toIntArray(String arg) {
        int[] result = new int[arg.length()];
        for (int i = 0; i < arg.length(); i++)
            result[i] = Character.getNumericValue(arg.charAt(i));
        return result;
    }
}

1

इको, रूबी

mychoices, myguesses, myscore, opponentchoices, opponentguesses, opponentscore = $*

unless mychoices
 puts "0 5"
 exit
end

if mychoices.size > 990 && myscore == '0'
  nextchoice = rand(1..5)
else
  nextchoice = opponentchoices[-1].to_i
end

recentchoices = opponentchoices[/.{0,100}$/]

nextguess = (0..5).max_by do |choice|
  (recentchoices.count(choice.to_s)+1) * (nextchoice + choice)
end

puts "%s %s"%[nextchoice,nextguess]

आखिरी गेम को प्रतिद्वंद्वी बनाकर खेलते हैं, इस सिद्धांत पर कि कोई भी एक बॉट बना सकता है जिसे वे भविष्यवाणी नहीं कर सकते। सौ-चाल नमूने का उपयोग करके अपेक्षा के आधार पर अनुमान।


मुझे यह त्रुटि मिल रही है: echo.rb:3:in <main> ': अपरिभाषित विधि size' for nil:NilClass (NoMethodError)। यह केवल पहले दौर पर होता है, जब कोई इतिहास नहीं होता है।
PhiNotPi

जब मैंने परीक्षण किया, तो अजीब नहीं हुआ। मैं संपादित करूँगा।
हिस्टोक्रेट

if (mychoices.size > 990 && myscore == '0') nextchoice = rand(1..5)भाग की प्रासंगिकता क्या है ?
यादृच्छिक

यदि यह एक झुलसा हुआ टाई में समाप्त होने वाला है (जैसा कि होता है, उदाहरण के लिए, खुद के खिलाफ), यह बेतरतीब ढंग से खेलना शुरू कर देता है, क्योंकि ~ 50% जीत की संभावना कुछ भी नहीं से बेहतर है।
हिस्टोक्रेट

1

किंग फिशर

    import java.util.Random;
public class KingFisher {

    private Random rnd = new Random();
    private int wins = 0;
    private int loses = 0;
    private int median = 0;
    private int medianMoved = 0;
    private int[] weightedLow = {40,65,80,90,95};
    private int[] weightedHigh = {5,15,30,55,95};
    private boolean highWeightMethod = true;

    public String getName() {
        return "KingFisher";
    }

    public int[] getMove(String [] args)
    {
        char[] mc  = args[0].toCharArray();
        char[] mg  = args[1].toCharArray();
        char[] oc  = args[3].toCharArray();
        char[] og  = args[4].toCharArray();
        int len = mc.length;
        int currentGuess = 0;
        int currentChoice = 0;
        if(len < 10)
            return new int[] {rnd.nextInt(6),rnd.nextInt(6)}; 
        int[] guessWeight = {0,0,0,0,0,0};
        int[] guessWeightTotal = {0,0,0,0,0,0};
        for(int a = 0; a< len;a++)
            guessWeight[oc[a]-48]++;
        if(!highWeightMethod){

            int[] whiteList = {1,1,1,1,1,1};
            for(int b = 0;b<3;b++){

                int min = 0;
                int max = 0;
                int minIndex = 0;
                int maxIndex = 0;
                for(int a = 0;a<6;a++){

                    if(whiteList[a] == 1){

                        min = guessWeight[a];
                        max = guessWeight[a];
                        minIndex = a;
                        maxIndex = a;
                        break;
                    }
                }

                for(int a = 0; a<6;a++){

                    if(whiteList[a] == 1){

                        if(guessWeight[a]<min){

                            min = guessWeight[a];
                            minIndex = a;
                        }
                        if(guessWeight[a]>max){

                            max = guessWeight[a];
                            maxIndex = a;
                        }
                    }
                }
                guessWeight[maxIndex] = min;
                guessWeight[minIndex] = max;
                whiteList[maxIndex] = 0;
                whiteList[minIndex] = 0;
            }
        }

        for(int a = 0; a< 6;a++)
            for(int b = 0; b<=a;b++)
                guessWeightTotal[a]+=guessWeight[b];
        int randInt = rnd.nextInt(guessWeightTotal[5]);
        for(int a = 0; a<6;a++){

            if(randInt < guessWeightTotal[a]){
                currentGuess = a;
                break;
            }
        }

        if(mg[len-1] == oc[len-1]){
            wins++;
            median++;
        }
        if(og[len-1] == mc[len-1]){
            loses++;
            median--;
        }
        if(median > 2){

            medianMoved++;
            median = 0;
        }
        if(median < -2){

            medianMoved--;
            median = 0;
        }

        randInt = rnd.nextInt(95);
        if((wins-medianMoved)>(loses+medianMoved)){

            for(int a = 0; a<6;a++){

                if(randInt < weightedLow[a]){
                    currentChoice = a;
                    break;
                }
            }
        }
        else{

            for(int a = 0; a<6;a++){

                if(randInt < weightedHigh[a]){
                    currentChoice = a;
                    break;
                }
            }
        }
        if(medianMoved < -5){

            highWeightMethod = !highWeightMethod;
            medianMoved = 0;
        }
        return new int[] {currentChoice,currentGuess}; 

    }
}

यह आदमी बुरी तरह से अनुमान लगाने वाले अल्गोरिथम्स से मिलकर बनता है जो ज्यादातर भारित सरणियों का उपयोग करता है।


अगले अपडेट में होगा
PhiNotPi

1

उह उह। मैं जानता हूं तुम क्या सोच्र रहे हो। "वह पांच या कुछ और लेने वाला है?" अच्छी तरह से आपको इस सभी उत्साह में सच्चाई बताने के लिए मैं खुद पर यकीन नहीं कर रहा हूं, लेकिन यह एक .44 विधि है, जो दुनिया में सबसे शक्तिशाली तरीका है और यह आपके स्टैक को तुरंत अधिभार देगा, आपने खुद से एक सवाल पूछा होगा : "क्या मैं भाग्यशाली महसूस कर रहा हूं?"

अच्छा, हाँ, गुंडा?

public class DirtyHarry implements Player {

    @Override
    public String getName() {
        return "DirtyHarry";
    }

    @Override
    public int[] getMove(String[] args) {
        return new int[]{5, 5};
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.