Giữ khoảng cách!


15

Mỗi người chơi có một số. Bạn có thể là người xa nhất trong số họ?

Yêu cầu

Viết hàm Java, Python 2 hoặc Ruby có tên choose()chấp nhận ba đối số:

  • một số nguyên - số vòng đã hoàn thành
  • một số nguyên - số lượng người chơi
  • một chuỗi các chuỗi - kết quả của mỗi vòng trước
    • mỗi chuỗi là một danh sách các số nguyên được phân tách bằng dấu cách, được sắp xếp từ thấp nhất đến cao nhất

Ví dụ choose(2, 4, ["4 93 93 174", "1 84 234 555"]): có nghĩa là:

  • đã có hai vòng (đây là vòng thứ ba)
  • có tổng cộng bốn người chơi
  • trong vòng đầu tiên, các số được chọn là 4, 93, 93, 174
  • trong vòng thứ hai, các số được chọn là 1, 84, 234, 555

Bạn phải trả lại toàn bộ số từ 1 đến 999 (đã bao gồm).

Đối với mỗi người chơi khác, điểm của bạn là căn bậc hai của khoảng cách giữa số của bạn và số của họ. Điểm của bạn cho vòng thi là tổng số của tất cả các điểm số này.

100 vòng sẽ được chơi. Tổng số điểm cao nhất chiến thắng!

Quy tắc

  • Mã của bạn không được sử dụng bất kỳ I / O nào, bao gồm bảng điều khiển, tệp, mạng, v.v.
  • Bạn không được can thiệp vào chương trình điều khiển hoặc bất kỳ người chơi nào khác.
  • Các chương trình trông giống như chúng vi phạm các quy tắc trên sẽ bị loại trừ.
  • Mỗi cuộc gọi của một chức năng sẽ mất dưới năm giây trên máy tính của tôi (Intel Core i5 2450M với 8GB RAM).
  • Nếu một chương trình đưa ra một ngoại lệ hoặc trả về một giá trị không hợp lệ, nó sẽ được xử lý như thể nó trả về 1.
  • Mỗi người dùng có thể gửi tối đa một chương trình.

Điều khoản khác

  • Chương trình kiểm soát là trên GitHub .
  • Có ba người chơi tích hợp. Họ có thể được tìm thấy trong câu trả lời này .
  • Người chiến thắng sẽ được chọn vào ngày 28 tháng 1.

Bảng xếp hạng

Người chiến thắng là người bảo thủ .

Đề cập đến danh dự của Gustav , cầu thủ ghi bàn cao nhất với chiến lược không đổi.

  • Người bảo quản - 36226
  • Cao - 36115
  • TầngHugger - 35880
  • SốOne - 35791
  • Đánh giá quá cao - 35791
  • Gustav - 35484
  • Nhà sử học - 35201
  • Bộ lấy mẫu - 34960
  • Tăng - 34351
  • JumpRightIn - 34074
  • Vickrey - 34020
  • Thiếu niên - 33907
  • Randu - 33891
  • Cử tạ - 33682
  • Người đàn ông - 33647
  • BounceInwards - 33529
  • NastyMathicalian - 33292
  • Nhảy cầu - 33244
  • Sao chép - 33049

Các kết quả đầy đủ có thể được tìm thấy ở đây . (Tôi khuyên bạn nên vô hiệu hóa gói văn bản.)


Tôi có cách nào nói số nào là số của mình trong các vòng trước không?
Martin Ender

@ MartinBüttner số
Ypnypn

1
Tôi không biết bất kỳ ngôn ngữ nào trong số đó :( Bạn có thể thêm JavaScript không? Giống như, chạy nó với node.js?
Cilan

1
@TheWobbuffet, tôi cũng không biết ai trong số họ. Không ngăn tôi tạo một mục Python.
Đánh dấu

7
Tôi nghĩ sẽ thú vị hơn nếu không gian là một vòng tròn / vòng để khoảng cách giữa 1 và 999 là 1. Điều đó sẽ giữ cho "đoán một số duy nhất mỗi lượt" không bị chi phối, vì không có "cạnh" để đậu trên. Rõ ràng là quá muộn để thay đổi ngay bây giờ;)
Geobits

Câu trả lời:


9

Python, người bảo quản

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

Vì mỗi ngoại lệ ném 1, nó tránh xa nó càng nhiều càng tốt. Làm cho tài sản của nó với chi phí của người yếu.

Sự thật thú vị: Tôi đã nghĩ đến việc cải thiện nó, nhưng không thể tìm ra cách nào tốt hơn là chỉ trốn trong một góc.


1
Hình như tôi chọn sai góc. :(
TheNumberOne

Nó tốt cho một lý do đơn giản: Những người khác cố gắng giảm thiểu khoảng cách với bạn. Họ sẽ tự động làm cho điểm số của bạn tốt hơn. Một người thay đổi trò chơi sẽ là một đối thủ cố gắng đến gần bạn nhất có thể.
Martin Thoma

1
À ... một dấu chấm phẩy trong Python?
KSFT

@KSFT hehe Tôi rất khó tính với Python và dù sao tôi cũng chưa bao giờ là chuyên gia đó
clabacchio

6

Số một, Java

Cái tên giải thích điều này hoàn toàn.

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

1
Tại sao bỏ phiếu xuống?
TheNumberOne

5
Tôi đặc biệt thích cách tên người dùng liên kết với bài nộp
Brian J

5

Con trăn, người cổ đại

Kiên quyết tin rằng tương lai sẽ giống hệt như quá khứ, nhưng tin rằng vòng cuối cùng quá gần với lịch sử, vì vậy nó chỉ lặp lại từ 1 - 999 và chọn những gì sẽ là vòng tốt nhất trước đó. Vòng 2 đầu tiên trả về 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

Con trăn, Vickrey

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)

Tạo một danh sách các số đã được chơi thường xuyên, giả sử rằng mọi người khác sẽ chơi tối ưu và chọn lần thứ hai cho danh sách tốt nhất.

Ví dụ: nếu các số phổ biến nhất là [1, 990, 999], thì Vickrey sẽ chèn phát tối ưu 200 để đưa ra [1, 200, 990, 999], sau đó chọn tùy chọn tốt nhất cho mảng mới (là 556).


4

Java, đánh giá quá cao

Như tên cho thấy, chương trình này giả định tất cả các chương trình khác sẽ cố gắng chơi "tốt" bằng cách chọn câu trả lời hay nhất dựa trên vòng cuối cùng - vì vậy "người đánh giá quá cao" này luôn chọn vị trí xấu nhất có thể dựa trên vòng trước.

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

Làm thế nào mà điều này chơi một "1" không đổi? Có lỗi không? Tâm trí bạn, chơi "1" tỏ ra khá thành công. :)
Emil

Đáng buồn là mã có một lỗi, vâng - nó thực sự không bao giờ phân tích điểm số mà nó đọc được từ vòng trước. (Nhưng tôi đã nhận ra nó quá muộn và có vẻ như đã sai khi chỉnh sửa bài dự thi, cộng với như bạn nói nó đang hoạt động khá tốt nên ... sao cũng được: p)
Alex Walker

4

Java - Cử tạ

Vòng qua 1-999 để tìm ra cái nào là tốt nhất cho mỗi vòng. Cân chúng theo lần truy cập gần đây (các vòng gần đây có trọng lượng lớn hơn) và trả về dự đoán tổng thể tốt nhất của nó. Hy vọng nếu các mẫu hình thành trong vòng sau, điều này sẽ có thể nhận ra nó.

Chỉnh sửa: Bây giờ với + Inf% đệ quy nhiều hơn! Không thể lưu trữ / lưu / xem những gì bạn đã chọn trong các vòng trước là một trở ngại. Đưa đầu vào của riêng bạn vào tài khoản làm bạn bối rối khi cố gắng tìm hiểu những gì người khác sẽ làm. Vì vậy, hãy tính toán nó! Điều này bây giờ sẽ tái diễn để tìm ra những gì nó đã chọn ở vòng trước và bỏ qua điều đó khi tính toán bước tiếp theo.

Lưu ý rằng nó chỉ thực sự bỏ qua đầu vào của chính nó từ lượt cuối cùng, nhưng vì nó có trọng số cao nhất, nên nó có vẻ hoạt động tốt. Điều này có thể được khắc phục với công việc nhiều hơn một chút, nhưng tôi sẽ đợi bảng xếp hạng để xem có cần thiết không.

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

Lưu ý: Ngay cả ở vòng 100, nó hoàn thành dưới một giây trên PC hơi chậm của tôi. Nếu mất quá nhiều thời gian cho bạn vì một số lý do, hãy cho tôi biết để tôi có thể hạn chế đệ quy.
Geobits

Nó cũng rất nhanh trên máy của tôi.
Ypnypn

3

Ruby, Copycat

Đơn giản chỉ cần trả về số nào thắng lần trước.

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
Nó trở lại cho vòng đầu tiên là gì? Đưng bận tâm. Các ngoại lệ sẽ quay trở lại 1.
mbomb007

3

Ruby, 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

Đây có lẽ là chiến lược đơn giản nhất. Nó tìm thấy khoảng cách lớn nhất trong vòng cuối cùng, và chọn số ngay giữa khoảng trống đó.


Nó trở lại cho vòng đầu tiên là gì? 1?
mbomb007

@ mbomb007 ơi, tôi luôn quên những vòng ban đầu đầy phiền phức này. Cảm ơn, giờ nó trả lại 500.
Martin Ender

3

Gustav (Python 2)

Đây là một chiến lược meta khá thẳng về phía trước, được sao chép một cách đáng xấu hổ từ một trong những câu trả lời cũ của tôi trong một thử thách tương tự với KotH. Nó xem xét một vài chiến lược đơn giản, xem xét cách họ sẽ thực hiện trong tất cả các vòng trước đó, và sau đó theo sau điểm số cao nhất cho vòng tiếp theo.

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]

Bây giờ tôi nhận ra rằng thuật toán vẫn còn một số sai sót. Ví dụ, nó có thể tiếp tục "đuổi theo chính nó" bởi vì nó không phân biệt các bước di chuyển của chính nó với các đối thủ. Tuy nhiên, bây giờ tôi sẽ để nó như thế này.



1

Ba chương trình sau đây được tích hợp sẵn.

Cao (Ruby)

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

Tăng dần (Java)

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

TầngHugger (Python)

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

Python, Sampler

Trong danh sách các địa điểm, chọn địa điểm xa nhất so với các số được sử dụng gần đây, bỏ qua lượt trước đó.

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

Java, BounceInwards

Bắt đầu từ 1, nó dần dần tiến gần đến 500 trong khi nảy giữa tùy chọn cao hơn và thấp hơn.

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

1

NastyMathicalian (Java)

Kiểm tra hai vòng cuối cùng (nếu các số tốt nhất là 70 và 80, nó sẽ xuất 90). Thật khó chịu vì nó cố gắng chiếm số lượng cao nhất có thể để giành chiến thắng trước đối thủ của mình.

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

Python - Tôi không muốn nghĩ về một cái tên ...

Nếu trung bình của các số được chọn trong các vòng trước nhỏ hơn 500, nó chọn 999. Nó chọn 1 số khác.

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, Middman (dựa trên người bảo quản bởi @clabacchio)

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

Sau khi tôi nhận thấy rằng cạnh trên có điểm cao (và vượt trội so với cạnh dưới), tôi tự hỏi liệu có thể có gì tồi tệ hơn việc bị bắt ở giữa không.


0

Nhảy (Ruby)

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

Thay thế giữa đáy, giữa và trên. (5.500.995)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.