고귀한 왕의 게임 모라


28

배경

Morra 의 게임은 간단한 게임입니다. "원본"버전에서는 여러 플레이어가 동시에 모든 손의 총합을 추측하면서 손으로 숫자 0-5를 버립니다. 여기서 사용할 버전은 사소한 전략의 가능성을 높이기 위해 수정되었으며 아래에 설명되어 있습니다.

  • 두 선수가 있습니다.
  • 가위 바위 보처럼 플레이어도 동시에 움직입니다.
  • 매 턴마다 각 플레이어는 0-5의 숫자를 선택하고 상대방의 0-5 선택을 추측 합니다. 이것은 매 턴마다 두 개의 숫자가 출력됨을 의미합니다. 명확히하기 위해 두 숫자 출력은 0-5 범위에 있어야합니다.
  • 상대방의 선택을 정확하게 추측했지만 상대방이 정확하게 추측하지 못하면 두 숫자의 합과 같은 특정 수의 점수를 얻습니다. 예를 들어, 연주 한 숫자가 3과 5 인 경우 정확한 추측은 8 포인트입니다.
  • 둘 다 또는 두 선수 모두 정확하게 추측하지 않으면 점수가 부여되지 않습니다.
  • 1000 라운드 후 가장 많은 점수를 얻은 사람이 그 게임에서 승리합니다.

토너먼트

토너먼트는 라운드 로빈 스타일로 진행되며 가능한 각 참가자 쌍을 만들어 진행됩니다. 각 승리마다 참가자는 2 점을 얻습니다. 각 타이는 1 승점을 얻습니다. 손실로 인한 승점은 없습니다.

직관적으로 토너먼트의 승자는 다른 사람에 대해 가장 많은 승점을 가진 참가자가됩니다.


들어가는 방법

봇을 제출하여 경쟁하는 두 가지 방법이 있습니다. 가장 선호되는 첫 번째 방법은 컨트롤러가 제공하는 Java 인터페이스를 구현하는 것입니다. 두 번째 방법은 독립 프로그램을 작성하는 것입니다.

Java 메소드를 먼저 다루겠습니다. 당신이 구현해야하는 인터페이스입니다 Player: 그것은 두 가지 방법을 정의 public String getName()하여 로봇을 식별하고, public int[] getMove(String[] args)소요 args, 6 문자열의 배열로 mychoices myguesses myscore opponentchoices opponentguesses opponentscore. 예를 들면 다음과 같습니다.

042 045 0 324 432 6

이것은 내가 1 라운드에서 0을 선택했고 상대방이 0을 던질 것이라고 추측했다. 상대방은 3을 던지고 4를 던질 것이라고 추측했다. 2, 그는 2 + 4 = 6 포인트를 얻는 것을 의미합니다.

당신의 방법은 각각 당신이 선택하고 추측하는 두 정수의 배열을 반환합니다. 예를 들면{4,2} 4를 선택하고 2를 추측하는 것입니다.

다음은 메소드로 작성된 완전한 Java 봇의 예입니다. 원하는 경우 제출물에는 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;
    }
}

독립 프로그램으로

현재 추가 언어 지원이 제한되어 있습니다. Java 외에도 Python 3.4, Perl 5 또는 Ruby 2.1.5로 작성된 프로그램을 사용할 수 있습니다. 여러 사람들이 원하는 언어가 있다면 추가하기 위해 최선을 다하겠습니다.

프로그램에 대한 입력은 명령 행에서 인수가됩니다. 다음과 같이 보일 수 있습니다 :

perl awesomebot.plx 042 045 0 324 432 6

프로그램의 결과는 당신의 선택과 추측, 각각의 공백으로 이루어져야합니다.

답을 실행하는 데 필요한 정확한 명령을 답에 포함하십시오. Windows 8.1을 실행하고 있습니다.


추가 규칙

상태 및 시간 초과 저장

프로그램은 정보를 저장할 수있는 로컬 디렉토리에 하나의 텍스트 파일을 작성할 수 있습니다. 이 정보는 토너먼트 내내 유지되지만 나중에 삭제됩니다. 파일에 식별 가능한 이름을 지정하십시오.

코드 응답 시간이 500 밀리 초입니다. 제한 시간 내에 응답하지 않으면 (또는 유효하지 않은 이동을 제공) 특정 경기를 상실하게됩니다. Java 제출에는 현재 수동 시간 초과 (활성으로 업그레이드 할 수 있음)가 있지만 Java 이외의 제출에는 500 밀리 초 후에 프로세스가 종료되는 활성 시간 초과가 있습니다.

추가 제출 규칙

  • 규칙을 준수하고 팀을 태그하지 않는 한 여러 제출이 허용됩니다.
  • 각 항목은 고유해야합니다. 다른 언어로 다른 봇의 논리를 정확하게 복사 할 수 없습니다.
  • 봇은 서로 상호 작용할 수 없습니다 (모든 종류의 팀을 구성하기 위해).
  • 봇 내부의 다른 봇의 논리를 사용하여 경쟁 업체를 식별하고 해당 행동을 예측할 수는 없습니다. 물론 상대방의 전략을 결정할 수 있습니다.
  • 컨트롤러, 다른 참가자 또는 컴퓨터를 엉망으로 만들려고하지 마십시오. 외부 정보 소스에 연결하지 마십시오.

컨트롤러

현재 컨트롤러 버전은 여기에 있습니다 . 이 파일은 Java 8로 작성되었습니다. "토너먼트"파일은 주 컨트롤러이며 경쟁 업체 목록도 포함합니다 (자신의 경쟁을 주최하려는 경우).


리더 보드

리더 보드를 자주 업데이트 할 수 없었습니다. 나는 이번 주말에 오히려 바쁘다. "바쁘다"는 것은 6:30 AM부터 9:30 PM까지 컴퓨터에 액세스 할 수 없음을 의미합니다. 다음은 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          

신용

Rainbolt와 Peter Taylor에게 감사의 말을 전합니다.


1
@ MartinBüttner Ruby 2.1.5가 추가되었습니다.
PhiNotPi

라운드 로빈은 어떻게 작동합니까? Player1 대 Player2 1000 번, Player1 대 Player3 1000 번 등 ... 또는 Player1 대 Player2 한 번 다음 player1 대 플레이어 3 한 번 등 ...
Vajura

@Vajura 한 번의 토너먼트는 한 쌍의 전투로 구성됩니다. 한 전투에는 1000 라운드가 있으며, 전투가 끝날 때 총 점수가 가장 높은 사람이 두 개의 승리 점수를 얻습니다. 현재 점수 판에는 40 번의 토너먼트 후 총 승리 점수가 표시됩니다.
PhiNotPi

보드 업데이트가 지연되어 죄송합니다. 나는 이번 주말에 매우 바쁩니다. 오늘 밤과 내일 아침에 예상하고 업데이트하십시오.
PhiNotPi

와우, 나는 내 로봇이 그렇게 잘하지 않을 것이라고 기대했다! 또한 숫자는 첫 번째 결과 세트의 승리 수를 의미합니까?
mbomb007

답변:


17

모라 카우벨

이 봇의 이름에서 의미를 찾고있는 사람에게는 Morra 라는 이름 이 Space Italian를 생각하게 하므로 그 이름을 딴 이름이 필요하다고 생각했습니다. 다른 후보로는 Morra 바보 당신Morra 나를 위해 포함되어 있습니다 .

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 % 이상이 그 보수를 달성 촬상된다. 우리는 내쉬 평형의 1 차원 공간을 가지고 있습니다.

내가 증명하지는 않았지만,- n손가락 Morra는n 내쉬 평형 (Nash equilibria) 입체 폴리 토프 (polytope)를 이는 n+1 (pick, guess)쌍 사이에 혼합 된 전략 이다 pick + guess = n.

위 코드의 마술 숫자는 내쉬 평형의 5 차원 폴리 토프의 32 개의 정점을 인코딩합니다. 나는 polytope을 나타내는 선형 프로그래밍 인스턴스를 설정 한 다음 임의의 목적 함수를 사용하여 그것들을 발견했습니다. 하나를 선택하는 대신 32 개를 모두 인코딩하는 이유는 간단합니다. 예상 지불액은 0이므로 승리하기 위해 예상보다 더 잘해야합니다. 나는 본질적으로 다른 플레이어가 혼합 전략을 사용하고 그들의 선택 기록에 따라 분포를 추정한다고 가정합니다. 그런 다음 예상 분포에 대해 예상되는 이득을 최대화하는 폴리 토프 정점을 선택합니다.

QuinnAndValor는 다른 플레이어가 혼합 전략을 사용하고 있다는 가정의 취약성을 보여줍니다. 내쉬 평형에서 전략을 사용하는 플레이어를 감지하면 비평 형 전략을 플레이 할 때 평균적으로 잃을 수있는 무작위 보행 모드로 전환 할 수 있지만 한 번만 리드를 얻을 필요가 있습니다. 그것은 쌍을 연주로 되돌릴 수 있습니다 pick + guess = n. 따라서 단일 게임의 내쉬 평형은 반복되는 게임의 내쉬 평형으로 일반화되지 않으므로 더 복잡한 전략이 가능합니다.


4
그것은 당신의 가능성이 마법 의 일부가 들어 해밍 번호를 ? 확실히 모든 것을 포함하지는 않지만 그 중 많은 ( 또는 모두? )가 해당 웹 사이트의 목록에 있습니다.
GiantTree

@GiantTree, 그들은 모두 해밍 숫자입니다. 흥미로운 관찰.
피터 테일러

당신의 봇이 햄이 된 것도 당연합니다. : D
mbomb007

11

Quinn and Valor (업데이트 됨)

Quinn과 Valor는 엘리트 레인저 팀입니다. 석궁과 발톱으로 모든 상대를 감히 찢어 도전합니다.

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

그들은 거의 항상 내 컴퓨터의 모든 Java 솔루션에 대해 이깁니다.

편집하다:

나는 Quinn과 Valor가 Historian 결투에 실패했다는 것을 인정하지만, 여전히 토너먼트에서 이기기 위해 그들에게 좋은 믿음을 가지고 있습니다.

내 원칙은의 모든 솔루션에 대해 수혜자가 당신의 이익을 유지하면서 choice + guess == 5노는 choice + guess == 5것입니다.

최신 정보:

글쎄 ... 모든 것이 복잡해졌다.


1
리그 오브 레전드 레퍼런스가 마음에 듭니다. 나는 정말로 Teemo 봇을 만들고 싶다. :)
mbomb007

6

학자

학자는 상대방의 움직임을 통해 자신의 opponene이 덜 추측 한 것을 선택하고 상대방이 가장 많이 사용한 것을 추측합니다. 그러나 이론은 모든 것이 아니기 때문에 Scholar는 잘하지 않습니다 ...

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

델타 맥스

(파일을 사용하지 않도록 업데이트하고 새 섹션을 추가했습니다. 또한 첫 번째 섹션에서 더 이상 묶이지 않도록 수정되었습니다.)

간단하게 시작한 다음 더 복잡 해지는 전략으로 구성됩니다. 전략을 지우면 다음 섹션으로 이동합니다.

  • 섹션 1 :{0, 5} 일관성있게 추측
  • 섹션 2: 마지막 4 개의 추측이 상수, 선형 또는 2 차 패턴을 형성하는지 확인하고 패턴이 깨질 때까지 계속 추측합니다.
  • 섹션 3 : 비정상적으로 적은 수의 숫자 (1/1 미만)를 확인하고 해당 숫자를 선택하십시오
  • 섹션 4 : 선택에서 bigram 분석 및 다음에 나올 가능성을 살펴보십시오
  • 섹션 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 배 빠른 속도 이지만 토너먼트에서 하나의 Historian 봇만 사용할 수 있습니다.)

가중 랜덤을 사용하여 이전 기록 상대에 대해 해당 쌍만 사용하는 효과에 따라 스로우-게스 페어를 선택합니다. 가중치는 달성 가능한 점수의 제곱입니다.

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. 게시물을 수정했습니다. 더 이상 사용되지 않는 주석은 삭제할 수 있습니다.
randomra

내 업데이트 후 지금 결투의 75 %를 이길 수 있다고 생각합니다!
johnchen902

5

외삽 기 (v1.1)

더 간단한 게임의 내쉬-평형 중 하나에서 극단적으로 외삽.

간결한 답변 형식을 지원합니다! (파이썬 스타일로)

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

Magic Cow (Morra Cowbell)와 연결되어 있고 내가 확인한 다른 항목을 이겼습니다.


1
랜덤 r을 정적 필드로 옮기십시오. 매번 초기화하지 마십시오. 이것은 전반적인 성능에 도움이됩니다!
Falco

왜 유통이 바뀌 었습니까?
피터 테일러

4

유행

트렌디 (Trendy)는 상대의 과거 움직임을 살펴보고, 최근에 가중치를 부여합니다. 가장 무거운 것을 추측하고, 그것에서 약간 올라간 것을 고릅니다. 여기에 모든 영광이 있습니다.

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

내가 지금 비교할 수있는 유일한 것은 Cowbell입니다. 그것은 대부분의 시간 동안 작은 마진으로 잃어 버리지 만, 종종 내 취향에 따라 충분히 많이 나옵니다. 우리는 더 많은 경쟁 업체와의 관계를 살펴볼 것입니다.


7
코드를 여러 줄로 형식화 할 수 있습니까? 이것은 코드 골프가 아닙니다 ...
mbomb007

7
@ mbomb007이 방법으로 공간을 덜 차지합니다. KotH의 고통 중 하나는 일반적으로 항목을 보는 스크롤입니다. 나는 그것이 무엇을하는지 설명했고, 이해 관계자들이 그것을 포맷하는 것은 매우 간단하다.
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

레인 볼트

상대가 추측 한 마지막 두 숫자의 차이를 취하여 상대의 최신 추측에 추가하고 계수를 찾고 모든 비용으로 해당 숫자를 선택하지 않습니다. 예를 들어 {5,4,3} (1 씩 감소)을 추측하면 모든 비용으로 2를 선택하지 않아도됩니다.

상대가 선택한 마지막 두 숫자의 차이를 취하여 상대의 최신 선택에 추가하고 그 숫자를 추측합니다. 예를 들어 {1,4,5,2} (3 씩 증가)를 추측하면 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()메서드를 정적으로 만들지 마십시오 . 정적이 아닌 메소드를 구현할 수는 없습니다 (적어도 Java 8에서는 그렇지 않음).
GiantTree

@GiantTree 감사합니다.
Rainbolt

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

인기도, Python 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 개 상대의 선택에 사용 다항식 보간은 자신의 선택과 동일한 않습니다, 상대의 다음 숫자를 해결하기 위해 피합니다 해당 번호를 선택. 또한 Interpolator는 0 또는 5를 선택하는 것에 대해 약간의 편차가 있으며 선택은 때때로 추측에 영향을받습니다.

  • 0을 추측하면 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

카운터 봇

하지 않습니다 카운터 사람 만 원에서 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

바실리스크, 파이썬

전설에 따르면, 바실리스크는 뱀의 왕입니다. ( 소스 ) 나는이 "왕의 고귀한 게임"을 재생하고 Python으로 작성된 봇에 대한 적절한 이름의 생각. = D이 봇은 다른 봇의 심장에 두려움을 느끼고 한 눈에 죽음을 초래합니다.

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을 추측 한 후 발생하는 가장 일반적인 상대 이동을 반환합니다. , 더 많은 수를 선택합니다 (점수를 최대화하기 위해).

기술 노트에서 올바르게 실행됩니까? print ()가 충분합니까, 아니면 다른 Pythonista와 마찬가지로 sys.stdout.write ()와 같은 것을 사용해야합니까?


sys.stdout.write ()는 어느 파이썬에서나 작동합니다. print ()는 Python 3에서만 작동합니다. 그래도 괜찮습니다.
TheNumberOne

아니요, print ()는 어느 쪽이든 작동합니다. 괄호는 2.x에서 선택 사항
DJMcMayhem

에 따르면 , 그들은 다르게 작동합니다. 그러나 사용 방법은 중요하지 않습니다.
TheNumberOne 2012

그러나 그것이 어떤 차이가 있습니까?
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, 자바

상대방의 승리를 최소화하기 위해 항상 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

@ mbomb007 그래도 최악은 아닙니다! RandomBot보다 성능이 좋지 않더라도.
Brian J

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> ': undefined method 오류가 발생 size' for nil:NilClass (NoMethodError)합니다. 이동 기록이없는 첫 번째 라운드에서만 발생하는 것으로 보입니다.
PhiNotPi

홀수, 테스트 할 때 발생하지 않았습니다. 편집하겠습니다.
histocrat

if (mychoices.size > 990 && myscore == '0') nextchoice = rand(1..5)부품 의 관련성은 무엇입니까 ?
randomra

(예를 들어, 그 자체와 같이) 무득점 넥타이로 끝나는 경우 무작위로 플레이하기 시작합니다. ~ 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

어 무슨 생각하는지 알아 "그가 5 개나 다른 것을 고를까?" 글쎄요.이 흥분에 대한 진실을 말하기 위해 나는 스스로 확신하지 못하지만 이것이 .44 방법이기 때문에 세계에서 가장 강력한 방법이며 스택에 즉시 과부하가 걸리므로 한 가지 질문을해야합니다. : "운이 좋습니까?"

그래, 펑크?

public class DirtyHarry implements Player {

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

    @Override
    public int[] getMove(String[] args) {
        return new int[]{5, 5};
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.