Побудуйте детермінований ШІ


11

Ось цікава проблема, яку я подумав днями, яка включає в себе біти коду, що конкурують з іншими бітами коду, не тільки у властивості, яку має код, але і граючи в гру проти цих інших бітів коду.

Ваше завдання - створити програму, яка приймає поточний стан дошки Go і визначає, який хід зробити чи пройти.

Ваша програма прийме як вхід:

  • 19 рядків, у кожному з 19 символів, що представляють фігури, що знаходяться на дошці Go. Символ 0являє собою порожній квадрат, 1чорний і 2білий.

  • Два числа, що представляють кількість в’язнів, яких має кожен гравець (чорний, потім білий).

  • Одне число, яке представляє, чия черга рухається (чорна або біла). Як і вище, 1чорний і 2білий.

і вивести одне з наступних:

  • Пара координат, що a bпредставляють координати, за якими рухатися. 1 1- верхній лівий квадрат, і перше і друге числа представляють рух відповідно вниз і вправо.

  • Рядок pass, який являє собою перехід до проходу.

Наприклад, програма може отримати такий вхід:

0000000000000000000
0000000000000000000
0000000000000000000
0001000000000002000
0000000000000000000
0000000000000000000
0001210000000000000
0000100000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0002000000000001000
0000000000000000000
0000000000000000000
0000000000000000000
0 0 1

яка представляє гру, в якій було зіграно лише кілька ходів.

Тоді програма може вивести 6 5, що означає "покласти чорний камінь на точку 6-го зверху та 5-ю зліва". Це захопило б білий камінь у 7 5. Тоді стан ради зміниться на:

0000000000000000000
0000000000000000000
0000000000000000000
0001000000000002000
0000000000000000000
0000100000000000000
0001010000000000000
0000100000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0000000000000000000
0002000000000001000
0000000000000000000
0000000000000000000
0000000000000000000
1 0 2

(Зауважте, що хоча білий камінь був захоплений, він вважається в'язнем для чорного.)

Ваш код повинен додатково відповідати таким властивостям:

  • Якщо вашій програмі надається однаковий стан введення, вона завжди повинна виробляти однаковий вихід. Це детермінізм ШІ І. Він не повинен мати випадкової складової.

  • Вашій програмі не потрібно більше 60 секунд, щоб визначити, який крок зробити. Це правило не застосовуватиметься суворо через зміни в обчислювальній потужності, але воно повинно зробити крок за розумну кількість часу.

  • Вихідний код вашої програми не повинен перевищувати загалом 1 мегабайт (1048 576 байт).

  • Ваша програма завжди повинна робити юридичні кроки. Ваша програма не може рухатись там, де камінь уже існує, і не може розмістити фрагмент, який призведе до захоплення групи власних каменів. (Одним винятком із правил для цілей цього виклику є те, що програмі дозволяється створювати позицію, яка була спочатку там - оскільки вона задана лише поточною позицією ради, не можна очікувати, що вона зберігатиме, які кроки були зроблені раніше.)

Тоді ваше представлення буде грати в турнірі "всі грати" проти всіх інших подань, у грі Go, де стан дошки починається як порожній, і кожна програма по черзі подається на позицію дошки та робить рух .

Кожна пара подань буде грати два раунди - один раунд, кожен гравець має чорний колір. Оскільки AI в цій проблемі повністю детерміновані, два однакових AI, які грають разом, завжди призведуть до того, що будуть грати абсолютно однакові ігри.

Умови виграшу такі:

  • Якщо ваша програма зіграє до кінця гри, для визначення переможця будуть використані китайські правила зарахування Go. Коміші не застосовуються.

  • Якщо ваша програма грає до того, що досягнуто більш раннього стану, викликаючи таким чином нескінченний цикл, дві програми будуть оголошені зв'язаними.

Ваша заявка буде оцінена тим, скільки балів вона набрала проти інших матеріалів. Виграш коштує 1 бал, а нічия - пів бала. Подання з найбільшою кількістю балів - загальний переможець.


Це суперечливий виклик, в якому будь-хто може опублікувати новий запис у будь-який час, і класифікація буде періодично переоцінюватися, коли це станеться.


7
Гаразд, чекати на всі інші подання, а потім написати моє, щоб їх перемогти - повинно бути можливим, оскільки рішення детерміновані.
Говард

1
Здається, грати в ko так, що попередня позиція повторюється дозволена, але призводить до негайного нічиї (оскільки це спричиняє цикл). Цікаво ...
FireFly

2
Схоже, що ваша проблема надто складна, і ніхто не наполегливо працюватиме, щоб дати гідну відповідь (це дійсно багато роботи). Це приємна проблема, але працювати надто важко.
Віктор Стафуса

1
Чому б не використовувати меншу дошку? 9x9 досить поширений для початківців гравців. Це різко скорочує простір пошуку, але це не так вже й мало, що його ще "побили" за допомогою аналізу (я думаю, найбільший, що повністю вирішений, - це 5x6).
Геобіц

1
Як працює вхід? аргументи stdin чи командного рядка?
Ypnypn

Відповіді:


7

Ось мій запис, щоб зняти цей виклик з місця. Код Python:

print "pass"

Згідно з вашими правилами, завжди грати в "пас" - це дійсна (хоча і погана) стратегія.


Ваш код завжди втрачається проти будь-кого, хто проти нього грає. Все-таки приємна відповідь у базовій справі.
Джо З.

1
@JoeZ. І від зовнішнього вигляду він переміг із цим: P
Девід Малдер

4

Java: Виберіть місце, будь-яке місце

Просто вибирає плями на дошці, щоб перевірити справжність. Він використовує PRNG, але з набором насіння, так що це детерміновано. Він використовує різні шматки циклу PRNG залежно від того, скільки поворотів пройшло.

Для кожної позиції кандидата він перевіряє, чи це дійсний крок (але не те, що це розумний хід). Якщо це не так, він переходить до наступного кандидата. Якщо після 1000 спроб він не може знайти дійсний хід, він проходить.

import java.util.Random;
import java.util.Scanner;

public class GoNaive {

    int[][] board;
    boolean[] checked;
    int me;

    public static void main(String[] args) {
        new GoNaive().run();
    }

    void run(){
        int turns = init();
        Random rand = new Random(seed);

        for(int i=0;i<turns*tries;i++)
            rand.nextInt(size*size);

        for(int i=0;i<tries;i++){
            int pos = rand.nextInt(size*size);
            for(int c=0;c<size*size;c++)
                checked[c]=false;
            if(board[pos%size][pos/size] == 0)
                if(hasLiberties(pos, me)){
                    System.out.print((pos%size+1) + " " + (pos/size+1));
                    System.exit(0);
                }
        }
        System.out.print("pass");
    }

    boolean hasLiberties(int pos, int color){
        if(checked[pos])
            return false;
        checked[pos] = true;

        int x = pos%size, y=pos/size, n;

        if(x>0){
            n = board[x-1][y];
            if(n==0 || (n==me && hasLiberties(y*size+x-1, color)))
                return true;
        }
        if(size-x>1){
            n = board[x+1][y];
            if(n==0 || (n==me && hasLiberties(y*size+x+1, color)))
                return true;
        }
        if(y>0){
            n = board[x][y-1];
            if(n==0 || (n==me && hasLiberties((y-1)*size+x, color)))
                return true;
        }
        if(size-y>1){
            n = board[x][y+1];
            if(n==0 || (n==me && hasLiberties((y+1)*size+x, color)))
                return true;
        }
        return false;
    }

    int init(){
        int turns = 0;
        board = new int[size][size];
        checked = new boolean[size*size];
        turns = 0;
        Scanner s = new Scanner(System.in);
        String line;
        for(int i=0;i<size;i++){
            line = s.nextLine();
            for(int j=0;j<size;j++){
                board[j][i] = line.charAt(j)-48;
                if(board[j][i] > 0)
                    turns++;
            }
        }
        String[] tokens = s.nextLine().split(" ");
        turns += Integer.valueOf(tokens[0]);
        turns += Integer.valueOf(tokens[1]);
        me = Integer.valueOf(tokens[2]);
        s.close();
        return turns;
    }

    final static int size = 19;
    final static int seed = 0xdeadface;
    final static int tries = 1000;
}

2

Деякі Scala:

package go;

class Go {
  def main(args : Array[String]) {
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    System.out.printLn("1 1")
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    readLine()
    System.out.printLn("pass")
  }
}

Читаючи Вікіпедію, я думаю, що це переможе чинне рішення.


Насправді вона виграє на 361 бал в обох випадках.
Джо З.

Насправді, мені доведеться це повернути, це не відповідає специфікації. ШІ повинен бути без громадянства. Друкувати слід лише одне , враховуючи стан дошки, і ви зробили це друком двох ( 1 1і pass).
Джо З.

@JoeZ. Виправлено це. Не склав би все одно.
yayestechlab

Насправді це завжди буде надруковано 1 1, оскільки програма завжди запускається заново кожного разу при зміні плати.
Джо З.

1

Java

public class Go {
  public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    for (int i = 0; i < 361;) {
      char c = s.nextChar();
      if (c != '\n') {
        if (c == '0') {
          System.out.println((i % 19 + 1) + " " + (i / 19 + 1));
          System.exit(0);
        }
        i++;
      }
    }
  }
}

Вибирає перше порожнє місце. Виграє проти будь-якого з ШІ на час публікації.


2
Це не гарантує законного кроку. Якщо в першому доступному просторі немає свобод, його не можна відтворити. Наприклад, якщо цей AI грав сам: Після першого ряду змінних фігур, 1 1він буде захоплений білим (тепер порожнім) і не може бути відтворений чорним на наступному кроці.
Геобіць
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.