거리를 유지해라!


15

모든 플레이어는 숫자가 있습니다. 당신은 그들로부터 가장 멀리있을 수 있습니까?

요구 사항

choose()세 가지 인수를 허용 하는 Java, Python 2 또는 Ruby 함수를 작성하십시오 .

  • 정수-이미 완료된 라운드 수
  • 정수-플레이어 수
  • 문자열 배열-각 이전 라운드의 결과
    • 각 문자열은 공백으로 구분 된 정수 목록으로, 가장 낮은 순서에서 높은 순서로 정렬됩니다.

예를 들어 다음을 choose(2, 4, ["4 93 93 174", "1 84 234 555"])의미합니다.

  • 벌써 두 라운드가 있었다 (이것은 세 번째 라운드이다)
  • 총 4 명의 선수가 있습니다
  • 첫 번째 라운드에서 선택한 숫자는 4, 93, 93, 174입니다.
  • 두 번째 라운드에서 선택한 숫자는 1, 84, 234, 555였습니다.

1-999 (포함)의 정수를 반환해야합니다.

다른 플레이어의 점수는 숫자와 숫자 사이의 거리의 제곱근입니다. 라운드 점수는이 모든 점수의 총합입니다.

100 라운드가 재생됩니다. 가장 높은 총 점수가 이깁니다!

규칙

  • 코드는 콘솔, 파일, 네트워크 등을 포함하여 I / O를 사용할 수 없습니다.
  • 컨트롤 프로그램이나 다른 플레이어를 방해 할 수 없습니다.
  • 위 규칙을 위반 한 것으로 보이는 프로그램은 제외됩니다.
  • 함수가 호출 될 때마다 내 컴퓨터 (8GB RAM이 장착 된 Intel Core i5 2450M)에서 5 초 미만이 소요됩니다.
  • 프로그램에서 예외가 발생하거나 유효하지 않은 값을 반환하면 1을 반환 한 것처럼 처리됩니다.
  • 각 사용자는 최대 하나의 프로그램을 제출할 수 있습니다.

여러 가지 잡다한

  • 제어 프로그램은 GitHub에 있습니다 .
  • 세 명의 내장 플레이어가 있습니다. 이 답변 에서 찾을 수 있습니다 .
  • 우승자는 1 월 28 일에 선택됩니다.

리더 보드

우승자는 콘서 베이터 입니다.

일관성 이없는 전략을 가진 최고 득점 선수 인 구스타브 에게 영광스럽게 언급합니다 .

  • 콘서 베이터-36226
  • 높음-36115
  • FloorHugger-35880
  • 넘버원-35791
  • 과대 평가자-35791
  • 구스타프-35484
  • 역사가-35201
  • 샘플러-34960
  • 인크 리 멘터-34351
  • JumpRightIn-34074
  • 비 크리-34020
  • 십대-33907
  • 란두-33891
  • 역도-33682
  • 중개인-33647
  • 바운스 안쪽-33529
  • 불쾌한 수학자-33292
  • 점퍼-33244
  • 모방-33049

전체 결과는 여기 에서 확인할 수 있습니다 . 텍스트 줄 바꿈을 비활성화하는 것이 좋습니다.


이전 라운드에서 자신의 번호를 알 수있는 방법이 있습니까?
Martin Ender

@ MartinBüttner No.
Ypnypn

1
? 내가 그 모든 언어를 모르는 :( 당신은 Node.js를 함께 실행, 자바 스크립트처럼를 추가 할 수 있을까요?
Cilan

1
@ TheWobbuffet, 나는 그들 중 어느 것도 모른다. 파이썬 항목 작성을 막지 않았습니다.
Mark

7
만약 공간이 원형 / 루프라면 1과 999 사이의 거리가 1이면 더 흥미 로웠을 것입니다. "가장자리"가 없기 때문에 "각 턴마다 하나의 숫자를 추측하는 것"을 막을 것입니다. 주차. 분명히 변경하기에는 너무 늦었지만;)
Geobits

답변:


9

파이썬, 콘서 베이터

def choose(round, players, scores):
    return 999

모든 예외는 1을 발생시키기 때문에 가능한 한 멀리 떨어져 있습니다. 약한 사람을 희생하여 재산을 만듭니다.

재미있는 사실 : 나는 그것을 향상시키는 것에 대해 생각했지만, 모퉁이에 숨어있는 것보다 더 좋은 방법을 찾을 수 없었습니다.


1
내가 잘못된 코너를 골 랐던 것 같습니다. :(
TheNumberOne

간단한 이유로 좋습니다 : 다른 사람들이 당신과의 거리를 최소화하려고합니다. 그들은 자동으로 점수를 향상시킬 것입니다. 게임 체인저는 가능한 한 당신에게 가까이하려고하는 상대가 될 것입니다.
Martin Thoma

1
으 ... 파이썬에서 세미콜론?
KSFT

@KSFT hehe 저는 파이썬에 녹슬 었습니다. 어쨌든 그 전문가는 없었습니다
clabacchio

6

넘버 원, 자바

이름은 이것을 완전히 설명합니다.

public static int choose(int round, int players, String[] args) {
    return 1;
}

1
왜 다운 투표?
TheNumberOne

5
특히 사용자 이름이 제출물과 어떻게 연결되는지를 좋아합니다
Brian J

5

파이썬, 고대사

미래는 정확히 과거와 같을 것이라고 굳게 믿고 있지만, 마지막 라운드가 너무 오래되어서 오래 걸리지 않다고 믿기 때문에 1-999를 반복하고 마지막 라운드에서 마지막으로 실행 된 것 중 가장 좋은 것을 선택합니다. 첫 2 라운드는 500을 반환합니다.

def choose(round, players, scores):
    calc = lambda n, scores: sum([abs(int(i)-n)**.5 for i in scores.split(' ')])
    return max(range(1, 1000), key=lambda n: sum([calc(n, j) for j in scores[1:]])) if round>1 else 500

4

파이썬, 비커

def choose(rounds, players, results):        
    if not results:
        return (id(0)/7)%999 + 1

    def best(array):
        score = lambda x: sum(abs(x-y)**.5 for y in array)
        m = max(score(x) for x in range(1, 1000))
        return [x for x in range(1, 1000) if score(x) == m]

    def second_best(array):
        array.extend(best(array))
        options = best(array)
        return options[(id(0)/7) % len(options)]

    results = [map(int, s.split()) for s in results]
    counts = {}

    for round_ in results:
        for number in round_:
            counts[number] = counts.get(number, 0) + 1

    most_common = sorted([(c, n) for n,c in counts.items()], reverse=True)
    to_avoid = [t[1] for t in most_common[:players]]

    return second_best(to_avoid)

자주 연주되는 숫자 목록을 작성하고, 다른 모든 사람이 최적으로 재생한다고 가정 하고 목록에서 주어진 두 번째 최상의 선택을 선택합니다.

예를 들어, 가장 일반적인 숫자가 [1, 990, 999]이면 Vickrey는 제공 할 최적 재생 (200)을 삽입 [1, 200, 990, 999]한 다음 새 배열 (556)에 가장 적합한 옵션을 선택합니다.


4

자바, 과대 평가

이름에서 알 수 있듯이이 프로그램은 다른 모든 프로그램이 마지막 라운드를 기준으로 최고의 답변을 선택하여 "잘"재생하려고 시도한다고 가정합니다. 따라서이 "과대 평가자"는 항상 이전 라운드를 기준으로 가능한 최악의 위치를 선택합니다 .

 public static int choose(int round, int players, String[] args) {
     String[] lastRoundStrings = args[args.length - 1].split(" ");
     int[] lastRound = new int[lastRoundStrings.length];
     int worstSelection = 0;
     for (int i = 0; i < lastRound.length; i++) {
         double worstScore = Double.MAX_VALUE;
         for (int j = 1; j < 999; j++) {
             double computedScore = score(j, lastRound);
             if (computedScore < worstScore) {
                 worstScore = computedScore;
                 worstSelection = j;
             }
         }
     }
     return worstSelection;
 }

 public static double score(int position, int[] otherPositions) {
     double total = 0;
     for (int i = 0; i < otherPositions.length; i++) {
         total += Math.sqrt(Math.abs(otherPositions[i] - position));
     }
     return total;
 }

이것이 어떻게 지속적으로 "1"을 했습니까? 버그가 있었습니까? "1"을 연주하는 것은 매우 성공적인 것으로 판명되었습니다. :)
Emil

슬프게도 코드에는 버그가 있습니다. 예, 실제로 마지막 라운드에서 읽은 점수를 구문 분석하지 않습니다. (그러나 나는 그것을 너무 늦게 깨달았고 그때까지 제출물을 편집하는 것이 잘못 된 것처럼 보였고, 당신이 그렇게 잘하고 있다고 말하면서 ... p
Alex Walker

4

자바-역도

1-999를 반복하여 각 라운드에 가장 적합한 것을 알아냅니다. 최근 성 (최근 라운드는 더 많은 무게를 가짐)에 따라 무게를 측정하고 최상의 전체 추측을 반환합니다. 나중에 패턴이 형성되면이 패턴을 사용할 수 있기를 바랍니다.

편집 : 이제 + Inf % 더 많은 재귀가 가능합니다! 이전 라운드에서 선택한 것을 저장 / 저장 / 볼 수없는 것은 드래그입니다. 자신의 입력을 고려하면 다른 사람들 이 무엇을할지 알아낼 때 혼란에 빠집니다 . 계산해 봅시다! 이제 이전 라운드에서 선택한 것을 파악하고 다음 이동을 계산할 때 무시합니다.

그것은 단지주의 정말 마지막 차례에서 자신의 입력을 무시하지만, 그 하나가 가장 높은 가중치되어 있기 때문에, 괜찮 작동하는 것 같다. 좀 더 많은 작업으로 해결할 수 있지만 리더 보드가 필요한지 기다릴 것입니다.

int choose(int rounds, int players, String[] hist){
    if(rounds < 1)
        return 1;

    int lastChoice = choose(rounds-1,players,java.util.Arrays.copyOf(hist, hist.length-1));

    int[][] history = new int[hist.length][players];
    for(int i=0;i<hist.length;i++){
        String[] tokens = hist[i].split(" ");
        boolean flag = false;
        for(int j=0;j<tokens.length;j++){
            history[i][j] = Integer.parseInt(tokens[j]);
            if(i==history.length-1 && history[i][j]==lastChoice && !flag){
                flag = true;
                history[i][j] = -1;
            }
        }
    }

    double best = 0;
    int guess = 1;
    for(int i=1;i<1000;i++){
        double score = 0;
        for(int j=0;j<history.length;j++){
            double weight = (double)(j+1)/history.length;
            for(int k=0;k<history[j].length;k++){
                if(history[j][k] > 0)
                    score += Math.sqrt(Math.abs(history[j][k]-i)) * weight;
            }
        }
        if(score > best){
            best = score;
            guess = i;
        }
    }
    return guess;
}

참고 : 100 라운드에서도 약간 느린 PC에서 1 초 안에 완료됩니다. 어떤 이유로 든 당신에게 너무 오래 걸리는 경우, 재귀를 제한 할 수 있도록 알려주십시오.
Geobits

내 컴퓨터에서도 매우 빠릅니다.
Ypnypn

3

루비, 모방

마지막으로이긴 숫자를 간단히 반환합니다.

def choose r, p, hist
  last = hist.last.split.map &:to_i
  scores = last.map{|n| last.map{|m| (n-m).abs ** 0.5 }.inject :+ }
  last[scores.index scores.max]
end

1
첫 번째 라운드에서 무엇을 반환합니까? 오 괜찮아 예외는 1을 반환합니다.
mbomb007

3

루비, JumpRightIn

def choose(round, players, args)
    return 500 if args.size == 0
    last_round = args[-1].split.map(&:to_i) + [1000]
    max_gap = 0
    last = 0
    move = 1
    last_round.each { |i|
        gap = i - last - 1
        if gap > max_gap
            max_gap = gap
            move = (i + last)/2
        end
        last = i
    }
    move
end

아마도 가장 간단한 전략 일 것입니다. 마지막 라운드에서 가장 큰 간격을 찾아서 해당 간격의 중간에있는 숫자를 선택합니다.


첫 번째 라운드에서 무엇을 반환합니까? 1?
mbomb007

@ mbomb007 아, 나는 항상 성가신 초기 라운드를 잊어 버렸습니다. 감사합니다. 이제 500을 반환합니다.
Martin Ender

3

구스타프 (파이썬 2)

이것은 꽤 직선적 인 메타 전략입니다. 예전 대답 중 하나에서 뻔뻔스럽게 복사되었습니다. 비슷한 직전 비슷한 KotH 도전 과제에서 . 몇 가지 간단한 전략을 고려하고 이전 라운드에서 어떻게 수행했는지 살펴보고 다음 라운드에서 가장 높은 점수를 얻은 전략을 따릅니다.

def choose(k, N, h):
    if k<2: return 999
    H = [[int(x) for x in l.split()] for l in h]
    score = lambda x,l: sum(abs(x-y)**.5 for y in l)
    S = [range(1,1000)
         + [max(range(1,1000), key=lambda x: score(x, H[i-1]))]
         + [max(range(1,1000), key=lambda x: score(x, H[i-2]))]
         + [min(range(1,1000), key=lambda x: score(x, H[i-1]))]
         + [min(range(1,1000), key=lambda x: score(x, H[i-2]))]
         for i in range(2,k+1)]
    scores = [sum(score(s[j],l) for s,l in zip(S[:-1], H[2:]))
              for j in range(len(S[0]))]
    return max(zip(scores, S[-1]))[1]

알고리즘에 여전히 결함이 있음을 알고 있습니다. 예를 들어, 자신의 움직임을 상대방의 움직임과 구별하지 않기 때문에 "자체를 쫓는"상태를 유지할 수 있습니다. 그러나 지금은 이것을 그대로 두겠습니다.



1

다음 세 가지 프로그램이 내장되어 있습니다.

높음 (루비)

def choose(round, players, args)
    return 990
end

증 분자 (자바)

public static int choose(int round, int players, String[] args) {
    return round * 10 + 5;
}

FloorHugger (파이썬)

def choose(round, players, args):
    if len(args) == 0:
        return 10
    last = args[-1].split();

# next line from http://stackoverflow.com/a/7368801/3148067
    last = map(int, last)

    dist = 0
    for i in range(1, 999):
        if i in last:
            dist = 0
        else:
            dist = dist + 1
            if dist == 10:
                return i
    return 500

1

파이썬, 샘플러

장소 목록에서 이전 차례를 무시하고 최근에 사용한 숫자와 가장 먼 곳을 선택하십시오.

def choose(turn, players, history):
    sample = map(int, (' '.join( history[-5:-1] )).split())
    def distance(x): return sum(abs(x-y)**0.5 for y in sample)
    places = range(1, 1000, 13)
    score, place = max((distance(x), x) for x in places)
    return place

1

자바, 바운스

1부터 시작하여 점점 더 높은 옵션과 낮은 옵션 사이에서 튀는 동안 점차 500에 가까워집니다.

public static int choose(int round, int players, String[] args) {
    return round%2 == 0 ? round * 5 : 1000 - round * 5;
}

1

NastyMathematician (자바)

마지막 두 라운드를 검사합니다 (최고의 숫자가 70과 80이면 90을 출력합니다). 상대를 상대로 승리하기 위해 가능한 한 높은 숫자를 사용하기 때문에 불쾌합니다.

public static int choose(int round, int players, String[] args) {
    if (round == 0) {
        return 999;
    }

    int[][] results = new int[args.length][players];

    // parse input
    for (int i = 0; i < args.length; i++) {
        String[] rounds = args[i].split(" ");
        for (int j = 0; j < rounds.length; j++) {
            results[i][j] = Integer.parseInt(rounds[j]);
        }
    }

    int bestNumber = 0;
    double bestScore = -1;

    // get the best number for the last round
    for (int i = 1; i < 1000; i++) {
        double score = 0;
        for (int result : results[results.length - 1]) {
            score += Math.sqrt(Math.abs(i - result));
        }
        if (score >= bestScore) {
            bestScore = score;
            bestNumber = i;
        }
    }

    if (round == 1) {
        return bestNumber;
    }

    int bestNumber2 = 0;
    double bestScore2 = -1;

    // get the best number for the second last round
    for (int i = 1; i < 1000; i++) {
        double score = 0;
        for (int result : results[results.length - 2]) {
            score += Math.sqrt(Math.abs(i - result));
        }
        if (score > bestScore2) {
            bestScore2 = score;
            bestNumber2 = i;
        }
    }

    // add the difference between last round and second last round to get this rounds best number
    int difference = bestNumber - bestNumber2;
    bestNumber = bestNumber + difference;

    return bestNumber > 999 ? 999 : bestNumber;
}

1

파이썬-이름을 생각하고 싶지 않습니다 ...

지난 라운드에서 선택한 숫자의 평균이 500보다 작 으면 999를 선택합니다. 그렇지 않으면 1을 선택합니다.

def choose(a,b,c):
    total=0
    for i in c:
        for j in i.split(" "):
            total+=int(i)
    average=total/(a*b)
    if average<500:
        return 999
    return 1

0

Python, Middleman (@clabacchio의 콘서 베이터 기반)

def choose(round, players, scores):
    return 500;

상단 가장자리의 점수가 높고 하단 가장자리보다 성능이 우수하다는 것을 알았을 때 중간에 걸리는 것보다 더 나쁜 것이 있는지 궁금했습니다.


0

점퍼 (루비)

def choose(round, players, args)
    495*(round%3)+5
end

하단, 중간 및 상단 간을 전환합니다. (5,500,995)

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