동전 던지기 시간 여행자


19

미래에 Time Travel (약칭 TT)이 일반적 일 때 코인 던지기는 심각한 정신 스포츠가 될 것입니다. 미래를 준비하기 위해 우리는 입장의 관점에서 시간 여행이 실제로 일어날 프로그램에 대한 경쟁을 만듭니다.

경쟁은 라운드 로빈 스타일의 King of the Hill로 Java 클래스 간의 동전 던지기 경기로 구성됩니다.

동전 던지기 경기 규칙

  • 두 선수와 100 라운드가 있습니다.
  • 매 라운드마다 동전이 던져지고 그 결과에 따라 플레이어 중 하나가 1 점을 얻습니다. 각 플레이어는 50 %의 확률로 점수를 얻습니다.
  • 던지기 후 두 선수 모두 레버를 당겨 시간을 제어 할 수 있습니다.
  • 당신이 당겨 경우 파란색 레버 (되돌리기 스토퍼를) 더 TT는 이전 라운드 더 이상 레버가 사용 된 원형 또는 어느 불가능합니다. TT가이 라운드에 가려고해도 효과가 없습니다.
  • 빨간색 레버 (리 버터) 를 당기면 시간을 이전 라운드로 되돌립니다. 성공한 경우 , 선택한 라운드 전에 상대의 메모리가 메모리로 되돌아 가고 선택한 라운드 에서 시작한 동전 던지기 결과도 삭제됩니다 . 상대에게 TT에 대한 유일한 표시는 되돌릴 수없는 사용되지 않은 레버의 수입니다.
  • 각 플레이어는 경기 시작시 5 개의 파란색 레버와 20 개의 빨간색 미사용 레버를 가지고 있습니다. 이 레버는 TT의 영향을받지 않습니다.
  • 100 라운드가 끝날 때 TT가 발생하지 않으면 게임이 종료되고 더 높은 점수를 얻은 플레이어가 승리합니다.

세부

  • 라운드는 1 기반 색인 (양식 1 ~ 100)을 갖습니다.
  • 라운드하기 전에 x사용 가능한 파란색과 빨간색 레버의 수가 제공되며, 동전은 턴 x(포함) 및 마지막 x-1라운드 의 메모리 까지 결과를 던집니다 .
  • 파란색 레버를 둥글게 당기면 x라운드 x또는 그 이전에 목적지가있는 TT가 중지됩니다 (동일한 정확한 라운드에서도 TT가 발생하면 TT가 차단됨).
  • 라운드로 되 돌리면 x다음 라운드가 라운드 x됩니다.
  • 두 선수가 라운드 종료시 되돌리기를 선택하면 시간이 차단되지 않은 이전 목적지로 되돌아갑니다. 이 시점으로 되돌리려 고 시도한 플레이어는 기억을 유지합니다.

기술적 세부 사항

  • 제공된 Bot 인터페이스를 구현하는 Java 클래스를 작성해야합니다.
  • 봇을 프로젝트에 추가하십시오.
  • Bot파일에 Bot 인스턴스를 추가 합니다 Controller.java.
  • 수업 중에는 통화간에 정보를 보관 해서는 안됩니다 . (대부분의 경우 final함수 외부에 변수 만있는 경우이 요구 사항을 충족합니다.)
  • memory반환 된 Action객체 의 필드 에서 컨트롤러에 정보를 제공 할 수 있습니다 . TT가 발생하지 않은 경우 다음 차례에 귀하에게 다시 제공됩니다. TT가 발생하면 해당하는 이전 메모리를 받게됩니다.
  • 클래스 의 totalScore()메소드를 사용하여 Game히스토리 문자열의 점수를 얻을 수 있습니다 .

실험 계획안

  • 매번 당신의 takeTurn(...)메소드는 5 개의 인자로 호출됩니다 :

    • 사용되지 않은 파란색 레버의 수
    • 사용하지 않은 빨간색 레버의 수
    • 동전 던지기 기록, 1과 0으로 구성된 문자열은 이전 라운드에서 승리와 손실을 표시합니다. 첫 번째 문자는 첫 번째 동전 던지기에 해당합니다. (첫 번째 라운드에서 문자열의 길이는입니다 1.)
    • 문자열, 이전 라운드의 저장된 메모리
    • 이 라운드의 1 기반 인덱스
  • 매번 메서드는 다음을 Action포함 하는 객체를 반환합니다.

    • move조치를 설명 하는 필드 의 정수 :

      • 0 행동하지 않기 위해
      • -1 파란색 레버를 당기고 TT가이 라운드를 통과하는 것을 차단합니다.
      • x현재 레버보다 크지 않은 양의 정수로 , 빨간색 레버를 당기고 다시 라운드로 되돌리려 고합니다.x
      • 유효하지 않은 정수는로 취급됩니다 0.
    • 이 라운드의 메모리를 유지하고 싶은 문자열. 참고 메모리에 저장하는 것이 중요한 과제의 일부가 아니다 . 문자열에 유용한 데이터를 저장하지 않고 올바른 항목을 만들 수 있습니다. 첫 번째 라운드에서 문자열은 빈 문자열입니다.

  • 매치에서 평균 라운드 당 10ms를 넘지 않아야합니다.

  • 시간 제한을 정기적으로 실패하면 실격 처리됩니다.

채점

  • 한 경기에서 승리하면 두 선수 모두 2 점을 얻습니다. 손실은 포인트를 얻지 못합니다.
  • 봇의 점수는 수집 한 총 점수입니다.
  • 각 참가자 쌍 사이의 경기 수는 참가 횟수와 속도에 따라 다릅니다.

두 개의 간단한 예제 봇이 답변으로 게시됩니다.

컨트롤러와 첫 번째 커플 봇은 여기에서 사용할 수 있습니다 .

11 월 3 일까지 제출 된 봇으로 테스트 결과 :

총점 :

Oldschool: 3163
Random: 5871
RegretBot: 5269
Nostalgia: 8601
Little Ten: 8772
Analyzer: 17746
NoRegretsBot: 5833
Oracle: 15539
Deja Vu: 5491
Bad Loser: 13715

(컨트롤러는 Cat catcher challenge 컨트롤러를 기반으로합니다 . @flawr가이를 기본으로 제공합니다.)

보너스 : 비슷한 개념을 기반으로 한 멋진 6 분짜리 영화 .


1
이 규칙의 의미를 이해하지 못합니다. If you pull a blue lever (revert stopper) no TT is possible through that round anymore. TT's attempting to go through the round will have no effect."라운드 통과"는 무엇입니까?
feersum

@feersum 올바르게 이해하면 파란색 레버를 당기면 현재 라운드 (따라서 모든 이전 라운드)를 영구적으로 "고정"하여 시간 여행으로 결과를 수정할 수 없습니다. 파란색 레버를 당길 때보 다 빨리 TT를 시도하면 시도 할 수 없습니다.
PhiNotPi

@feersum @PhiNotPi가 맞습니다.이 버전이 더 명확합니까? If you pull a blue lever (revert stopper) no TT is possible to the round the lever was used or any earlier round anymore. TT's attempting to go to these rounds will have no effect.
randomra

빨간색 레버를 당기면 현재 진행중인 라운드를 선택하여 해당 라운드의 동전 던지기를 다시 실행할 수 있습니까?
TheNumberOne

@TheNumberOne 예, 랜덤 예제 봇 이하는 일입니다.
randomra

답변:


12

분석기

이것은 미래를 가장 잘 예측하기 위해 과거를 분석합니다.

편집 : 파란색 레버 시간을 피하십시오. 파란색 레버를 효과적으로 사용합니다. 빨간색 레버를 더 효과적으로 사용합니다. 할로윈 시즌에 대한 추가 사항이 추가되었습니다.

편집 : 1 오류로 수정되었습니다.

편집 :computeWinningProbability 기능이 향상되었습니다 . 이제 빨간색 레버와 파란색 레버를보다 적극적으로 사용합니다.

//Boo!
package bots;

import main.Action;
import main.Game;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created 10/24/15
 *
 * @author TheNumberOne
 */
public class Analyzer implements Bot{

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

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history,
                           String memory, int roundNumber) {
        /*System.out.println(Game.totalScore(history) + " : " + history);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }*/
        int roundsLeft = 100 - roundNumber;
        int myScore = (Game.totalScore(history) + roundNumber) / 2; //My number of wins.
        int enemyScore = roundNumber - myScore;                     //Enemy's number of wins.
        Map<Integer, Double> bestRounds = new HashMap<>();
        int timeLimit = 0;

        Scanner scanner = new Scanner(memory);
        if (scanner.hasNext()){     //No memory, first turn.
            boolean triedTimeTravel = scanner.nextBoolean();
            if (triedTimeTravel){
                int time = scanner.nextInt();
                if (roundNumber > time) {     //Failed.
                    timeLimit = time;
                }
            }
            timeLimit = Math.max(timeLimit, scanner.nextInt());
            int size = scanner.nextInt();
            for (int i = 0; i < size; i++) {
                bestRounds.put(scanner.nextInt(), scanner.nextDouble());
            }
        } else {
            bestRounds.put(1, 0.5);
        }

        clean(bestRounds, roundNumber, timeLimit);
        double winningProb = computeWinningProbability(myScore, enemyScore, roundsLeft);
        String newMemory = computeMemory(bestRounds, roundNumber, winningProb);

        if (winningProb >= new double[]{1.5, .75, .7, .65, .6, .55}[blue_levers]){ //Ensure success ... slowly.
            return getAction(-1, newMemory, timeLimit, roundNumber);
        }

        int bestRound = bestRound(bestRounds);
        double bestRoundProb = bestRounds.get(bestRound);

        if ((winningProb <= bestRoundProb - .05 || winningProb < .5 && bestRoundProb > winningProb) && red_levers > 0){
            return getAction(bestRound, newMemory, timeLimit, roundNumber);  //Let's find the best past.
        } else {
            return getAction(0, newMemory, timeLimit, roundNumber); //Let's wait it out :)
        }
    }

    //Should be combined with computeMemory.
    private static Action getAction(int actionNum, String newMemory, int timeLimit, int roundNumber){
        if (actionNum == -1){
            timeLimit = Math.max(timeLimit, roundNumber);
            newMemory = "false " + timeLimit + " " + newMemory;
            return new Action(actionNum, newMemory);
        }
        if (actionNum == 0){
            return new Action(actionNum, "false " + timeLimit + " " + newMemory);
        }
        if (actionNum > 0){
            return new Action(actionNum, "true " + actionNum + " " + timeLimit + " " + newMemory);
        }
        return null;
    }

    private static int bestRound(Map<Integer, Double> bestRounds) {
        int best = 0;           //If no previous rounds ... just go forward a round.
        double bestScore = -1;
        for (Map.Entry<Integer, Double> entry : bestRounds.entrySet()){
            if (entry.getValue() > bestScore){
                best = entry.getKey();
                bestScore = entry.getValue();
            }
        }
        return best;
    }

    private static String computeMemory(Map<Integer, Double> map, int roundNumber, double winningProb) {
        StringBuilder builder = new StringBuilder();
        builder.append(map.size() + 1).append(" ");
        for (Map.Entry<Integer, Double> entry : map.entrySet()){
            builder.append(entry.getKey()).append(" ").append(entry.getValue()).append(" ");
        }
        builder.append(roundNumber + 1).append(" ").append(winningProb);
        return builder.toString();
    }

    private static void clean(Map<Integer, Double> data, int round, int timeLimit) {
        data
                .entrySet()
                .stream()
                .filter(entry -> entry.getKey() > round || entry.getKey() <= timeLimit)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList()).forEach(data::remove);
    }

    private static double computeWinningProbability(int myScore, int enemyScore, int roundsLeft){ //Too complex for IntelliJ
        int height = myScore - enemyScore;
        double total = 0.0;
        for (int i = Math.max(height - roundsLeft, 2); i <= height + roundsLeft; i += 2){
            total += prob(roundsLeft, height, i);
        }
        total += prob(roundsLeft, height, 0) / 2;
        return total;
    }

    private static double prob(int roundsLeft, int height, int i){
        double prob = 1;
        int up = i - height + (roundsLeft - Math.abs(i - height))/2;
        int down = roundsLeft - up;
        int r = roundsLeft;
        int p = roundsLeft;
        while (up > 1 || down > 1 || r > 1 || p > 0){  //Weird algorithm to avoid loss of precision.
            //Computes roundsLeft!/(2**roundsLeft*up!*down!)

            if ((prob >= 1.0 || r <= 1) && (up > 1 || down > 1 || p > 1)){
                if (p > 0){
                    p--;
                    prob /= 2;
                    continue;
                } else if (up > 1){
                    prob /= up--;
                    continue;
                } else if (down > 1){
                    prob /= down--;
                    continue;
                } else {
                    break;
                }
            }
            if (r > 1) {
                prob *= r--;
                continue;
            }
            break;
        }
        return prob;
    }

}

점수 (11 월 2 일 이후) :

Total Scores:
Oldschool: 3096
Random: 5756
RegretBot: 5362
Nostalgia: 8843
Little Ten: 8929
Analyzer: 17764
NoRegretsBot: 5621
Oracle: 15528
Deja Vu: 5281
Bad Loser: 13820

1
감동적인! 봇은 효과적으로 차단하고 최적의 시간에 되돌립니다. 이 봇을 만들 수있는 봇을 만드는 것은 매우 힘들 것입니다.
TNT

이 봇을 엉망으로 만들고 다른 봇을 강화하기 위해 특별히 설계된 많은 항목을 사용하지 않고이 봇이 멈출 수 있는지 확실하지 않습니다.
Mego

4

노스탤지어

package bots;

import main.Action;
import main.Game;

public class Nostalgia implements Bot {

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

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history,
            String memory, int roundNumber) {

        int current_score = Game.totalScore(history);

        // wait until the end to use blue levers
        if (current_score > 0 && blue_levers >= (100 - roundNumber)) {
            return new Action(-1, memory);
        }

        // become increasingly likely to go back as the gap between the good old days
        // and the horrible present increases
        if (current_score < 0 && red_levers > 0) {
            //identify the best time to travel back to
            int best_score = -100;
            int good_old_days = 1;
            int past_score = 0;

            int unreachable_past = 0;
            if(memory != "") {
              unreachable_past = Integer.parseInt(memory, 10);
            }

            for(int i = unreachable_past; i<roundNumber ; i++) {
              if(history.charAt(i) == '1') {
                past_score += 1;
                if(past_score > best_score) {
                  best_score = past_score;
                  good_old_days = i + 1;
                }
              }
              else {
                past_score -= 1;
              }
            }
            if(roundNumber >= 95 || Math.random() < (best_score - current_score) / 100.0) {
              return new Action(good_old_days, Integer.toString(good_old_days));
            }
        }

        // if neither action was needed do nothing
        return new Action(0, memory);
    }
}

테스트되지는 않았지만 (빨간색 레버를 거의 무작위로 잡아 당길 때 결정하기 때문에) 차단하기 어려운 봇을 만들려고 시도했지만 적절한 결정을 내립니다.

편집 : 나는이 규칙을 놓쳤다.

파란색 레버 (리버 트 스토퍼)를 당기면 더 이상 해당 라운드를 통해 TT를 사용할 수 없습니다

메모리를 사용해야하는 좋은 이유 인 것 같습니다. 주어진 라운드에서 TT를 시도한 것을 기억하면 실패했을 수 있으므로 해당 라운드로 TT를 다시 시도해서는 안됩니다. 이것을 피하기 위해 내 봇을 편집했습니다.


4

신탁

메모리에서 파싱을 위해 Analyzer에서 코드를 뻔뻔스럽게 복사했습니다. 이 제출물은 파란색 레버를 일찍 당기려고 시도한 다음 천천히 리드를 쌓습니다. 이 봇의 성능이 못생긴 코드를 구성한다고 생각합니다. :)

package bots;

import java.util.*;
import java.util.Map.Entry;
import main.*;

public class Oracle implements Bot {

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

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        int roundsLeft = 100 - roundNumber;
        Map<Integer, Integer> rounds = new HashMap<>();
        int myScore = (Game.totalScore(history) + roundNumber) / 2;
        int difference = myScore*2 - roundNumber;
        int highestBlockedRound = -1;
        int bestScore = 0;
        boolean hasUsedBlueLever = false;

        Scanner scanner = new Scanner(memory);
        if (scanner.hasNext()) {
            //timeTravel toRound highestBlockedRound hasUsedBlueLever bestScore rounds round1 percent1 round2 percent2 round3 percent3...
            boolean triedTravel = scanner.nextBoolean();
            int time = scanner.nextInt();
            if (triedTravel){
                if (roundNumber > time) {
                    highestBlockedRound = time;
                }
            }
            highestBlockedRound = Math.max(highestBlockedRound, scanner.nextInt());

            hasUsedBlueLever = scanner.nextBoolean();
            bestScore = scanner.nextInt();

            int size = scanner.nextInt();
            for (int i = 0; i < size && i < roundNumber; i++) {
                int number = scanner.nextInt();
                int diff = scanner.nextInt();
                if (number < roundNumber) {
                    rounds.put(number, diff);
                }
            }
        }
        rounds.put(roundNumber, difference);
        final int blockedRound = highestBlockedRound;

        int roundToRevert = 0;
        if (rounds.size() > 2) {
            Optional<Entry<Integer, Integer>> bestRound = rounds.entrySet()
                    .stream()
                    .filter(x -> x.getKey() >= blockedRound && x.getKey() <= roundNumber)
                    .sorted(Comparator
                        .comparingInt((Entry<Integer, Integer> x) -> x.getValue()*-1)
                        .thenComparingInt(x -> x.getKey()))
                    .findFirst();
            if (bestRound.isPresent()) {
                roundToRevert = bestRound.get().getKey();
            }
        }

        if (roundsLeft + Game.totalScore(history) <= 0 && red_levers > 0) {
            roundToRevert = highestBlockedRound+1;
        } else if (blue_levers > 0 && roundToRevert == roundNumber && ((hasUsedBlueLever && difference >= bestScore*1.5) || (!hasUsedBlueLever && difference > 1))) {
            roundToRevert = -1;
            hasUsedBlueLever = true;
            bestScore = difference;
            highestBlockedRound = roundNumber;
        } else if (red_levers > 0 && roundToRevert > 0 && rounds.get(roundToRevert) > difference+2) {
            roundToRevert += 1;
        } else {
            roundToRevert = 0;
        }

        StringBuilder sb = new StringBuilder();
        sb.append(roundToRevert > 0).append(' ');
        sb.append(roundToRevert).append(' ');
        sb.append(highestBlockedRound).append(' ');
        sb.append(hasUsedBlueLever).append(' ');
        sb.append(bestScore).append(' ');
        sb.append(rounds.size()).append(' ');
        rounds.entrySet().stream().forEach((entry) -> {
            sb.append(entry.getKey()).append(' ').append(entry.getValue()).append(' ');
        });
        String mem = sb.toString().trim();
        scanner.close();
        return new Action(roundToRevert, mem);
    }
}

잘 했어! 나는 빨간 레버로 충분히 공격적이지 않다는 것을 알았습니다. 이제 분석기를 개선하십시오. ;)
TheNumberOne

3

후회 봇

우리의 삶이 끝날 무렵 , 우리는 과거의 실패를 후회하고 돌아가서 고치려고 시도합니다.

package bots;

import main.Action;
import main.Game;

public final class RegretBot implements Bot {

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

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        int actionNum = 0;
        if(roundNumber == 100) {
            // if it's the end of the game and we're losing, go back
            //  in time to the first loss, in hopes of doing better
            if(Game.totalScore(history)<=0 && red_levers > 0) {
                actionNum = history.indexOf("0")+1;
            }
            // if we're winning at the end, pull a blue lever if we can,
            //  to prevent our opponent from undoing our victory
            else if(blue_levers > 0) {
                actionNum = -1;
            }
        }
        // we don't need no stinkin' memory!
        return new Action(actionNum, null);
    }

}

2

리틀 텐

Little Ten은 10의 배수 인 숫자를 사용하고 10의 배수 인 라운드로 돌아가는 많은 10을 곱하고 나눕니다.

package bots;

import main.Action;
import main.Game;

public class LittleTen implements Bot {

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

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        int score = Game.totalScore(history);
        char c = history.charAt(history.length() - 1);
        if (memory.isEmpty())
            memory = "1";

        if (roundNumber == 100) {
            if (score >= 0)
                // We're tied or ahead by the end of the match. Prevent time
                // travel if we can; otherwise whatever happens happens.
                return new Action(blue_levers > 0 ? -1 : 0, memory);
            else {
                // Travel to earlier rounds the farther behind we are if we can
                // (of course using 10 as a reference)
                if (red_levers > 0) {
                    int i = Integer.parseInt(memory);
                    int round = score <= -10 ? i : 100 - ((100 - i) / (11 + (score <= -10 ? -10 : score)));
                    return new Action(round, memory);
                }
            }
        }
        else if (score >= 7 + roundNumber / 20 && blue_levers > 0) {
            // We're ahead; we don't want to lose our lead, especially if the
            // match is close to ending. But we don't want to use up our blue
            // levers too quickly.
            int choice = (int) (Math.random() * 100),
                bound = (roundNumber / 10 + 1) * 5 - ((6 - blue_levers) * 5 - 2);
            if (choice < bound) {
                memory = String.valueOf(roundNumber);
                return new Action(-1, memory);
            }
        }
        else if (score <= -3) {
            // Possibly use a red lever if we're falling too far behind
            if (red_levers > 0) {
                int choice = (int) (Math.random() * 100),
                    bound = score <= -11 ? 90 : 10 * (-3 - score + 1);
                if (choice < bound) {
                    // Check the first round that is the lower multiple of ten
                    // and decide if we've been successful up to that point; if
                    // so, travel back to that round, otherwise go back 10 more
                    int round = roundNumber / 10 * 10;
                    if (round < 10)
                        return new Action(1, memory);
                    String seq = history.substring(0, round-1);
                    int minRound = Integer.parseInt(memory);
                    while (Game.totalScore(seq) <= 0 && round > 10 && round > minRound) {
                        round -= 10;
                        seq = history.substring(0, round-1);
                    }
                    if (round == 0)
                        round = 1;
                    return new Action(round, memory);
                }
            }
        }
        return new Action(0, memory);
    }
}

편집 : 파란색 레버를 당길 때 발생하는 일에 대한 설명이 명확 해지면서 역학이 약간 변경되었습니다. 또한 약간의 재조정을 수행했습니다.


1

무작위

랜덤의 전략은 다음과 같습니다.

  • 블록리드에 있고 파란색 레버가 남아있는 경우 10 % 확률로
  • 점수가 뒤지고 빨간색 레버가 남아 있으면 10 % 확률 1 턴 (마지막 라운드 재생)으로 돌아갑니다.
package bots;

import main.Action;
import main.Game;

public class RandomBot implements Bot {

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

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history,
            String memory, int roundNumber) {

        // if in the lead and has blocks left, blocks with a 10% chance
        if (Game.totalScore(history) > 0 && blue_levers > 0
                && Math.random() > 0.9) {
            return new Action(-1, null);
        }

        // if behind and has travels left, travel back the current step to
        // replay it with a 10% chance
        if (Game.totalScore(history) < 0 && red_levers > 0
                && Math.random() > 0.9) {
            return new Action(roundNumber, null);
        }

        // if neither action were needed do nothing
        return new Action(0, null);
    }
}

1

후회 봇

package bots;

import main.Action;
import main.Game;

public final class NoRegretsBot implements Bot {

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

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        // every 20 turns, pull a blue lever to lock in the past
        // hopefully this will thwart some of those pesky time-travelers
        return new Action(roundNumber%20==0?-1:0, null);
    }

}

1

나쁜 패자

이 봇은 메모리를 사용하지 않으며 놀랍도록 훌륭합니다 (하지만 Analyzer 나 Oracle을이기는 것은 아닙니다).

package main;

import bots.Bot;

/**
 * Created 11/2/15
 *
 * @author TheNumberOne
 */
public class BadLoser implements Bot{
    @Override
    public String getName() {
        return "Bad Loser";
    }

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history, String memory, int roundNumber) {
        if (history.contains("00") && red_levers > 0){       //Subtract a zero for better performance against
            return new Action(history.indexOf("00") + 1, "");// Analyzer and Nostalgia, and worse performance 
                                                             // against everything else.
        }
        int wins = 0;
        for (char c : history.toCharArray()){
            wins += c - '0';
        }
        if (wins >= new int[]{101, 51, 40, 30, 20, 10}[blue_levers]){
            return new Action(-1, "");
        }
        return new Action(0, "");
    }
}

0

오래된 학교

이 봇은 Oldschool이 시간 여행을 믿지 않기 때문에 어떤 행동도하지 않습니다.

package bots;

import main.Action;

public class OldschoolBot implements Bot {

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

    @Override
    public Action takeTurn(int blue_levers, int red_levers, String history,
            String memory, int roundNumber) {       
        // never tries to block or travel at all
        return new Action(0, null);
    }
}

0

데자뷰 봇

이 봇은 파란색을 당길 때 추적하여 해당 지역에 빨간색 당김을 피합니다. 점수에서 상당히 뒤쳐 질 때만 빨간색 레버를 당깁니다.

package bots;

import main.*;

public class Dejavu implements Bot
{
    @Override
    public String getName()
    {
        return "Deja Vu";
    }

@Override
public Action takeTurn(int blue_levers, int red_levers, String history,
                       String memory, int roundNumber) {

    if(roundNumber == 1)
    {
        memory = "-1";
    }
    int[] blevers = getBlueLevers(memory);
    char[] hist = history.toCharArray();
    int ms = 0;
    int ts = 0;
    int rl = -1;
    boolean bl = false;
    boolean url = false;

    for(int i = 0; i < hist.length; i++)
    {
        switch(hist[i])
        {
            case '1':
            ms++;
            break;
            case '0':
            ts++;
            break;
        }
    }

    if(ts - ms >= 10)
    {   
        for(rl = hist.length - 1; ts - ms <= 5 && rl >= 0; rl--)
        {
            switch(hist[rl])
            {
                case '1':
                ms--;
                break;
                case '0':
                ts--;
                break;
            }
        }
        url = true;
    }

    if(ms - ts >= 7)
    {
        bl = true;
        url = false;
        memory += "," + roundNumber;
    }

    for(int i = 0; i < blevers.length; i++)
    {
        if(rl <= blevers[i])
        {
            rl = blevers[i] + 1;
        }
    }

    if(url)
    {
        return new Action(rl, memory);
    }
    else if(bl)
    {
        return new Action(-1, memory);
    }
    else
    {
        return new Action(0, memory);
    }              
}

private int[] getBlueLevers(String s)
{
    String[] b = s.split(",");

    int[] bl = new int[b.length];
    for(int i = 0; i < b.length; i++)
    {
        bl[i] = Integer.parseInt(b[i]);
    }

    return bl;
}

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.