Kralların Asil Oyunu Morra


28

Arka fon

Oyunu Morra basit bir oyun. "Orijinal" versiyonda, birkaç oyuncu eşzamanlı olarak ellerindeki 0-5 sayılarını atarken, herkesin toplamını tahmin ediyor. Burada kullanacağım sürüm önemsiz olmayan stratejinin potansiyelini artırmak için değiştirildi ve aşağıda açıklandı:

  • İki oyuncu var.
  • Taş-kağıt-makaslarda olduğu gibi, oyuncular aynı anda hareket eder.
  • Her turlu, her oyuncu bir sayı 0-5 seçer ve ayrıca tahmin 0-5 rakiplerini seçim. Bu, her turda iki sayı çıktığı anlamına gelir. Açıklığa kavuşturmak için, her iki sayı çıkışı da dahil olmak üzere 0-5 aralığında olmalıdır.
  • Rakibinizin seçimini doğru tahmin edersiniz ancak rakibiniz doğru tahmin etmediyse, oynanan iki sayının toplamına eşit sayıda puan kazanırsınız. Örneğin, oynanan rakamlar 3 ve 5 olsaydı, doğru bir tahmin 8 puan değerinde olurdu.
  • Her ikisi de veya hiçbiri doğru tahmin edemezse, hiçbir puan verilmez.
  • 1000 turdan sonra en yüksek puana sahip olan kişi bu oyunu kazanır.

Turnuva

Turnuva yuvarlak robin tarzında yapılacak ve her olası yarışmacı eşleştirmesiyle gerçekleştirilecek. Her zafer için yarışmacı 2 zafer puanı kazanır. Her kravat 1 galibiyet puanı ile sonuçlanır. Kayıp için zafer puanı kazanılmaz.

Sezgisel olarak, turnuvanın kazananı, diğerlerine karşı en fazla zafer puanı kazanan yarışmacı olacaktır.


Nasıl Girilir

Yarışmak için bot göndermenin iki yöntemi olacak. İlk ve en çok tercih edilen yöntem, denetleyici tarafından sağlanan bir Java arayüzünün uygulanmasıdır. İkinci yöntem ise bağımsız bir program yazmaktır.

Önce Java yöntemini ele alalım. Uygulamanız gereken arayüz şudur Playerve iki yöntemi tanımlar: public String getName()botunuzu tanımlar ve altı karakter dizisi olarak public int[] getMove(String[] args)alır ,. Bir örnek:argsmychoices myguesses myscore opponentchoices opponentguesses opponentscore

042 045 0 324 432 6

Bu, ilk rauntta 0 seçtiğimi ve rakibimin 0 atacağını tahmin ettiğim anlamına gelir. Rakibim 3 attı ve tahmin edeceğim 4 atacaktı. Üçüncü rauntta rakibim atacak olduğumu doğru tahmin etti. a 2, 2 + 4 = 6 puan aldığı anlamına gelir.

Yönteminiz, sırasıyla seçiminiz ve tahmin ettiğiniz iki tam sayı dizisini döndürür. Bir örnek {4,2}4 seçimi ve 2 tahmini içindir.

İşte bir yöntem olarak yazılmış tam bir Java bot örneği. İsterseniz, gönderiminiz yalnızca getMoveyöntemde olanları içermelidir.

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

Bağımsız bir program olarak

Şu anda ek dil desteğimle sınırlıyım. Java dışında Python 3.4, Perl 5 veya Ruby 2.1.5 ile yazılmış programları kabul edebilirim. Birkaç kişinin istediği gibi bir dil varsa, eklemek için elimden geleni yapacağım.

Programınıza giriş komut satırındaki argümanlar olacaktır. Bu gibi görünebilir:

perl awesomebot.plx 042 045 0 324 432 6

Programınızın çıktısı seçiminiz, ardından tahminlerinizin ardından her biri beyaz boşluk bırakılmalıdır.

Lütfen cevabınıza çalıştırmak için gereken tam komutu ekleyin. Windows 8.1 kullandığımı unutmayın.


Ekstra Kurallar

Devlet ve Zaman Aşımlarını Kaydetme

Programınızın, yerel bir dizinde bilgi saklayabileceğiniz bir metin dosyası oluşturmasına izin verilecek. Bu bilgi turnuva boyunca saklanacak ancak daha sonra silinecek. Dosyaya tanımlayabildiğim bir isim verin.

Kodunuzun yanıt vermesi için 500 milisaniye bir zaman sınırı vardır. Süre içinde cevap vermemek (veya geçersiz bir hamle yapmak), söz konusu karşılaşmanın kaybedilmesine neden olacaktır. Java gönderimleri şu anda pasif bir zaman aşımına sahiptir (aktif olarak yükseltebilirim), Java dışı gönderimler ise işlemlerinin 500 milisaniyeden sonra sonlandırıldığı etkin bir zaman aşımına sahiptir.

Diğer gönderim kuralları

  • Kurallara uydukları ve etiket takmadıkları sürece, birden fazla gönderiye izin verilir.
  • Her giriş benzersiz olmalıdır. Başka bir botun mantığının tam bir kopyasını farklı bir dilde yazamazsınız.
  • Botlar birbirleriyle etkileşime giremez (herhangi bir türden takım oluşturmak için).
  • Rakibinizi tanımlamak ve eylemlerini tahmin etmek için botunuzun içindeki diğer botların mantığını kullanamazsınız. Elbette, rakibinizin stratejisini belirlemeye çalışabilirsiniz.
  • Denetleyiciyle, diğer yarışmacılarla veya bilgisayarımla uğraşmaya çalışmayın. Harici bilgi kaynaklarına bağlanmayın.

Kontrol eden, denetleyici

Denetleyicinin geçerli sürümü burada bulunur . Java 8 ile yazılmıştır. "Tournament" dosyası, rakiplerin listesini de içeren ana denetleyicidir (kendi yarışmalarınızı düzenlemek istiyorsanız).


Liderler Sıralaması

Lider panosunu çok sık güncelleyemedim. Bu haftasonu oldukça meşgulüm. "Oldukça meşgul" derken 6: 30'dan 9: 30'a kadar bir bilgisayara erişim demek istemiyorum. İşte 5 çalışmadan sonra alınan puanlar. "Echo" botu bir sebepten vazgeçmeyi sürdürdü (benim suçum olabilir, henüz araştırmadım).

  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          

Kredi

Kontrolöre yardımlarından dolayı Rainbolt ve Peter Taylor'a çok teşekkürler.


1
@ MartinBüttner Ruby 2.1.5 eklendi.
PhiNotPi

Yuvarlak robin nasıl çalışır? Player1 Player2 vs 1000 kez, Player1 Player3 vs 1000 kez vs ... YA daha sonra Yürütücü1 kez çalar 3 vs Player2 vs Player1 kez vs ...
Vajura

@Vajura Tek bir turnuva, her bir çift arasındaki 1 savaştan oluşur. Bir savaşta 1000 tur var ve savaşın sonunda en yüksek puanı alan, iki galibiyeti kimin kazanacağını belirliyor. Mevcut skor tahtası, 40 turnuvadan sonra toplam zafer puanını göstermektedir.
PhiNotPi

Tahtayı güncellemedeki gecikmeler için özür dilerim. Bu haftasonu çok meşgulüm. Bu gece ve yarın sabahı bekleyin ve güncelleyin.
PhiNotPi

Vay, botumun bu kadar iyi yapmasını beklemiyordum! Ayrıca, ilk sonuçtaki sayıların anlamı ... galibiyet sayısı?
mbomb007

Yanıtlar:


17

Morra Cowbell

Bu bot adına önem arayanlar için, Morra ismi beni Space Italian hakkında düşündürüyor . Diğer adaylar arasında Morra sizi ve Morra'yı benim için kandırıyor .

Bu, Playerarayüzü uygulayan tam bir sınıftır . Aşağıdaki açıklama.

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

açıklama

Oyunları daha az parmakla analiz ederek başladım. En basit olmayan basit olan, aşağıdaki ödeme tablosuna çağrı yapılmasına izin verir 0veya 1bunlara sahiptir (değerler sıra oyuncu için kazançtır):

       (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)Strateji hakimdir (0,1)biz tabloyu azaltabilir, böylece

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

Şimdi (1,0)stratejiye hâkim olduğu (0,1)için, masayı

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

Ve şimdi (1,1)egemen olan (0,1), bu yüzden sonunda

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

Dolayısıyla her zaman oynamak (0,1)bir Nash dengesidir. Ama merak edilen şey, bunun tek olmadığı. Beklenen sonuç 0 yani bu, bir simetrik toplamı sıfır oyun ve bir karma strateji birleştirilmesi (0,1)ve(1,0) burada (0,1)zaman en az% 50 olduğu getiriyi elde alınır. Bu yüzden bir boyutlu Nash dengesi uzayına sahibiz.

Kanıtlanmış nolmamama rağmen, durumun çok farklı olduğu düşünülen Morra’nın iki taraf narasında karışık stratejiler olan Nash dengelerinin boyutsal bir polipopu n+1 (pick, guess)var.pick + guess = n .

Yukarıdaki koddaki sihirli sayılar, Nash dengelerinin 5 boyutlu polipropinin 32 köşesini kodlar. Bunları polytopu temsil eden doğrusal bir programlama örneği kurarak ve ardından rasgele objektif fonksiyonlar kullanarak buldum. Birini seçmek yerine 32'nin hepsini de kodlamanın nedeni basittir: beklenen kazanç 0'dır, bu yüzden kazanmak için beklenenden daha iyisini yapmam gerekir. Esasen diğer oyuncunun karma bir strateji kullandığını ve toplama tarihçelerine dayanarak dağılımı tahmin ettiğini farz ediyorum. Sonra bu tahmini dağılıma karşı beklenen kazancımı maksimize eden polytope vertex'i seçiyorum.

QuinnAndValor, diğer oyuncunun karışık bir strateji kullandığı varsayımının kırılganlığını göstermektedir. Nash dengelerinden stratejileri kullanan bir oyuncuyu tespit ederek, dengede olmayan bir stratejiyi oynayarak ortalama olarak kaybedebileceği rastgele bir yürüyüş moduna geçebilir; hangi için çift oynamaya geri dönebilirpick + guess = n . Dolayısıyla, tek bir oyun için Nash dengesi, daha karmaşık stratejilere izin veren, tekrarlanan oyun için Nash dengesine önemsiz şekilde genelleme yapmaz.


4
Sizin olması mümkün mü sihirli bir bölümünü içeren Hamming Numaraları ? Kesinlikle hepsini içermiyor, ancak birçoğu ( veya hepsi? ) Bu web sitesinde yer alıyor.
GiantTree

@ DevTree, hepsi Hamming sayıları. İlginç gözlem.
Peter Taylor

Botunun jambona gitmesine şaşmamak gerek. : D
mbomb007

11

Quinn ve Valor (Güncelleme)

Quinn ve Valor seçkin bir bekçi takımıdır. Tatar yayı ve pençeyle, her rakibi kendilerine meydan okumaya cesaret edemezler.

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();
        }
    }
}

Neredeyse her zaman makinemdeki tüm Java çözümlerine karşı kazanıyorlar.

Düzenle:

Quinn ve Valor'un Tarihçi'yi düelloya davet edemediklerini itiraf ediyorum, ancak turnuvayı kazanmaları için hala onlara iyi niyetim var.

Prensibim, herhangi bir çözüm için choice + guess == 5, aynı zamandachoice + guess == 5 avantajınızı koruyan hibe sahipleriyle .

Güncelleştirme:

Şey ... her şey daha karmaşık hale geldi.


1
League of Legends referansını beğendim. Şimdi gerçekten bir Teemo botu yapmak istiyorum. :)
mbomb007

6

Akademisyen

Scholar, rakibinin hamlelerini öğrenmeye çalışır, rakibinin daha az tahmin ettiği kişiyi seçer ve en çok kullandığı kişiyi tahmin eder. Ama teori her şey değildir, bu yüzden Scholar çok iyi yapmaz ...

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

(Dosyaları kullanmayacak şekilde güncellendi ve yeni bir bölüm eklendi. Ayrıca, ilk bölüme bağlı kalmayacak şekilde değiştirildi.)

Basit başlayan ve daha karmaşık hale gelen birkaç stratejiden oluşur - birini temizlerseniz, sizi bir sonraki bölüme taşır.

  • Bölüm 1:{0, 5} Sürekli olarak tahmin et
  • Bölüm 2: Son 4 tahmininizin sabit mi, doğrusal mı, karesel bir kalıp mı oluşturduğunu kontrol edin ve kalıp kırılıncaya kadar tahmin etmeye devam edin
  • Bölüm 3: Anormal derecede düşük bir miktar rakamı (1/13'ten az) tahmin edip etmediğinizi kontrol edin ve bu numarayı seçin.
  • 4. Bölüm: Seçimlerinizdeki bigramları analiz edin ve daha sonra çıkma ihtimalinin ne olduğuna bakın
  • Bölüm 5: Son 100 mermiye bakın ve (choice, guess)en iyi beklentiye sahip çifti seçin , ağırlıklı olarak yeni mermiler daha önemlidir.
  • Bölüm finali: Düşük seçeneklere ve yüksek tahminlere sahip olma ihtimalinin yüksek olmasıyla rastgele tahmin edin. Buraya gelirseniz, DeltaMax pes etti ve "iyi oyun" demek istiyor.

Sonunda hangi stratın kullanıldığını bulmak için

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

hat.

Korkunç Java için özür dilerim, öğleden sonra ekleme parçalarını birlikte geçirip dili yeniden öğrenerek geçirdim :)

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

Mevcut denetleyicinin uygulanmasıyla, veriler yalnızca tek bir oyunda kullanılıyorsa, şeyleri bir dosyaya kaydetmeye gerek yoktur. yani private int strat;, yeterince iyi.
johnchen902

@ johnchen902 Teşekkürler, yapabileceğimin farkında değildim. Bu işleri çok kolaylaştırıyor.
Sp3000

6

Tarihçi

(Güncelleme: aynı mantık, daha kısa kod ve 100 kat daha hızlı, ancak bir turnuvada yalnızca bir Tarihçi botu kullanabilirsiniz.)

Sadece önceki çifti rakiplere karşı kullanmanın etkinliğine dayalı bir tahmin-tahmin çifti seçmek için rastgele ağırlıklı kullanır. Ağırlıklar, elde edilebilecek puanların kareleridir.

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 (Artık değil) yener ve kaybeder Morra Cowbell. Turnuvada botların Historiançoğu ikinci sırada geliyor Quinn and Valor.


Birisinin makinesinde kazandığımı görmek güzel. Mevcut resmi lider kurulunu kaybediyorum . Merak ediyorum ya da şanssızlık ya da öngörülemeyen zekice bir böcek yüzünden.
johnchen902

@ johnchen902 Halüsinasyona uğramış olmalıyım Morra Cowbell. Gönderi düzenlendi. Eskiyse yorumları silebilirsiniz.
randomra

Galiba güncellememden sonra düellolarımızın% 75'ini kazanabilirim!
johnchen902

5

Ekstrapolatör (v1.1)

Daha basit bir oyunun Nash dengelerinden birinden aşırı ekstrapolasyon.

Ben kısa cevap formatını destekliyorum! (Python tarzında.)

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

Sihirli İnek (Morra Cowbell) ile bağ gibi görünüyor ve kontrol ettiğim diğer girişleri atıyor.


1
Lütfen Random r'yi statik bir alana getirin, böylece her seferinde başlatmazsınız, bu genel performansa yardımcı olacaktır!
Falco

Dağıtımdaki değişim neden?
Peter Taylor

4

modaya uygun

Trendy, rakibin geçmiş hareketlerine bir göz attı ve onları durgunlukla ağırladı. En ağır tahmin ve bir ondan hafifçe kaydırılmış alır. İşte şerefine:

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

Şimdi karşılaştırabileceğim tek şey Cowbell. Zamanın çoğunluğunu küçük bir farkla kaybeder, ancak benim isteklerime yetecek kadar sık ​​sık ortaya çıkar. Daha fazla rakiple nasıl olduğunu göreceğiz.


7
Lütfen kodu birden fazla satıra biçimlendirir misiniz? Bu kod golf değil ...
mbomb007

7
@ mbomb007 Bu şekilde daha az yer kaplar. Genel olarak KotH'lerin acılarından biri, girişlere bakmak için bütün kaydırma. Ne yaptığını açıkladım ve ilgili tarafların formatlaması çok kolay.
Geobits

4

Rastgele Tahminci

Bu gerçekten yalındır. Etkili bir d6 atar ve tahminine göre bir önceki yuvarlamaya başka bir rulo ekler. Kazanmayacak, ama güzel bir kriter sağlayacak.

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

Şaşkın, Python 3

Gereksiz yere karmaşık bir giriş. Ben bile onun ne yaptığını bilmiyorum.

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))

Her ne kadar bu gelişmiş algoritma bu turnuvada rastlantısallıktan daha kötü performans gösteriyor olsa da, önemli hafıza ve çalışma zamanı kullanıyor olsa da, 5;


4

Rainbolt

Rakibimizin tahmin ettiği son iki rakam arasındaki farkı alır, rakibimizin en son tahminine ekler, modülü bulur ve bu rakamı ne pahasına olursa olsun seçmekten kaçınır. Örneğin, {5,4,3} (bir azalan) tahmin ederseniz o zaman ne pahasına olursa olsun 2 seçmekten kaçınırız.

Rakibimizin seçtiği son iki sayı arasındaki farkı alır, bunu rakibimizin en son tercihine ekler ve bu sayıyı tahmin eder. Örneğin, {1,4,5,2} (üçlü artırarak) tahmin ederseniz 5 olacağını tahmin ediyoruz.

Amaçsız veya amaçsız rulolara çok yakın önler.

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()Metodunuzu statik yapmayın . Buna benzer statik olmayan bir yöntem uygulayamazsınız (en azından Java 8'de değil).
GiantTree

@GiantTree Bunu yakaladığınız için teşekkürler.
Rainbolt

3

Gelişen Bot

Bu botu en iyi rastgele tabanlı bot olarak geliştirdim.

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

Popülerlik, Python 3

Geçmişte rakip tarafından kullanılan popüler sayılara dayalı tahmin tahmin edin. Son zamanlarda kullanılan sayılar daha fazla ağırlığa sahip. Sayı seçimi genellikle tahminle aynıdır.

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

interpolator

(Python sorunlara neden olduğundan beri Java’ya geçti)

Rakibin bir sonraki numarasını hesaplamak için son 10 rakip seçeneğinde polinom interpolasyonu kullanır, daha sonra kendi seçimlerine göre aynı şeyi yapar ve bu sayıyı seçmekten kaçınır . Ayrıca, İnterpolatör, 0 veya 5 seçimine karşı hafif bir önyargıya sahiptir ve seçimi bazen tahmininden etkilenir:

  • 0 tahmin ederse 0 seçmeyecektir
  • 5 tahmin ederse her zaman 0 veya 1 seçer
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

Kimseye karşı gelmez, fakat bir dairede 0-5 arasında sayılır ( 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

Basilisk, Python

Efsaneye göre, Basilisk yılanların kralıdır. ( kaynak ) Bunun "Kralların Asil Oyunu" oyununu oynadığı ve python ile yazılmış bir bot için uygun bir isim olduğunu düşündüm. = D Bu bot diğer botların kalbine korku vuruyor ve tek bakışta ölüme neden oluyor.

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)

Bu oldukça basit bir strateji üzerinde çalışır. Kazanmasını beklemiyorum ama yazmak çok eğlenceliydi. Bu aynı zamanda ilk KoTH mücadelem, bu yüzden ne kadar iyi performans gösterdiğini görmek için heyecanlıyım.

Bir sonraki hamlesini nasıl seçer?

Basilisk her zaman rakibinin en az sayıda tahmin ettiği hareketi yapar. Beraberlik durumunda daha küçük sayıyı seçecektir. (Rakip puan sayısını en aza indirmek için.)

Bir sonraki tahmininizi nasıl seçiyor.

Basilisk, önceki tahminine en olası yanıtı seçecek. Örneğin, son kez, bir 3 tahmin ederse, bir 3 tahmin ettiği önceki zamanların hepsine geri döner ve daha sonra 3 tahminden sonra gelen en yaygın rakip hamleyi geri döndürür. , daha büyük sayı seçer (yapabileceği puan sayısını maksimize etmek için.)

Teknik bir notta, bu doğru çalışacak mı? Print () yeterli mi, yoksa diğer Pythonistas'ın yaptığı gibi sys.stdout.write () gibi bir şey mi kullanmalıyım?


sys.stdout.write (), Python'da çalışır. print () yalnızca Python 3'te çalışır. Yine de iyi olmalı.
TheNumberOne

Hayır, print () da çalışır, bundan eminim. Parantez 2.x içinde isteğe bağlıdır
DJMcMayhem

Göre bu , onlar farklı çalışır. Ancak, onu kullanma şekliniz önemli değil.
TheNumberOne

Fakat bu herhangi bir fark yaratıyor mu?
DJMcMayhem

Görünüşe göre öyle değil.
TheNumberOne,

2

aynen

Bu, rakibe dönüşür, ancak bir tahmin / seçim ile geride kalır.

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

Rakip kazançları en aza indirmek için her zaman 0 atar. Eğer rakip numaramı tahmin ederse, sadece attıklarını kazanırlar.

Kazancımı en üst seviyeye çıkarmak için her zaman 5 tahmin eder. Atışımdan puan alamadığım için rakipten çok puan almak istiyorum. Rastgele tahmin edebilirim, ama bunun neresinde eğlenceli?

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

Tahminimce bu bot çok iyi olacak. Bahis oranlarını kullanan herhangi bir bot, ilk tahminlerden hemen sonra her tahminde bulunabilir.
mbomb007

@ mbomb007 Yine de en kötüsü değil! Her ne kadar RandomBot'undan daha kötü performans gösterse de.
Brian J

1

Erratica, Java

Büyük değil, ama başlangıçta rastgele olacak şekilde tasarlanmıştı, takas değeri bana gelene kadar. Sürekli olarak karşı Bot kaybetmeyi başarır - Karşı Bot> _ <

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

Yankı, Yakut

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]

Kimsenin tahmin edemediği bir bot yapabileceği teorisi üzerine, rakibin yaptığı son oyunu oynuyor. Yüz hamle örneği kullanarak beklenti değerine göre tahmin eder.


Bu hatayı alıyorum: echo.rb:3:in <main> ': tanımsız yöntem size' for nil:NilClass (NoMethodError). Taşınma geçmişi olmadığında sadece ilk rauntta meydana geldi.
PhiNotPi

Tuhaf, test ettiğimde olmadı. Düzenleyeceğim.
histocrat

Parçanın alaka düzeyi nedir if (mychoices.size > 990 && myscore == '0') nextchoice = rand(1..5)?
randomra

Eğer puansız bir bağla sona erecekse (örneğin, kendisine karşı olduğu gibi), rastgele oynamaya başlar çünkü% 50 kazanma şansı hiç olmadığı kadar iyidir.
histocrat

1

KRAL FISHER

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

    }
}

Bu adam çoğunlukla ağırlıklı dizileri kullanan kötü tahmin edici algoritmalardan oluşuyor.


Bir sonraki güncellemede olacak.
PhiNotPi

1

Ah. Ne düşündüğünü biliyorum. "Beş veya başka bir şey seçecek mi?" Size tüm bu heyecandaki gerçeği söylemek gerekirse kendimden emin değilim, ama bu bir .44 Metodu, dünyadaki en güçlü yöntem ve yığınınızı hemen aşırı yükleyecektiniz, kendinize bir soru sormanız gerekiyor : "Kendimi şanslı mı hissediyorum?"

Peki ya sen serseri?

public class DirtyHarry implements Player {

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

    @Override
    public int[] getMove(String[] args) {
        return new int[]{5, 5};
    }
}
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.