รักษาระยะห่างของคุณ!


15

ผู้เล่นทุกคนมีหมายเลข คุณเป็นคนที่ไกลที่สุดจากพวกเขาทั้งหมดได้หรือ

ความต้องการ

เขียนฟังก์ชัน Java, Python 2 หรือ Ruby ชื่อchoose()ที่ยอมรับอาร์กิวเมนต์สามตัว:

  • จำนวนเต็ม - จำนวนรอบแล้วเสร็จ
  • จำนวนเต็ม - จำนวนผู้เล่น
  • อาร์เรย์ของสตริง - ผลลัพธ์ของแต่ละรอบก่อนหน้า
    • แต่ละสตริงเป็นรายการจำนวนเต็มคั่นด้วยช่องว่างเรียงจากต่ำสุดไปสูงสุด

ตัวอย่างเช่นchoose(2, 4, ["4 93 93 174", "1 84 234 555"])หมายถึง:

  • มีอยู่สองรอบแล้ว (นี่คือรอบที่สาม)
  • มีผู้เล่นทั้งหมดสี่คน
  • ในรอบแรกจำนวนที่เลือกคือ 4, 93, 93, 174
  • ในรอบที่สองจำนวนที่เลือกคือ 1, 84, 234, 555

คุณต้องส่งคืนจำนวนเต็มตั้งแต่ 1 ถึง 999 (รวม)

สำหรับผู้เล่นแต่ละคนคะแนนของคุณคือรากที่สองของระยะทางระหว่างหมายเลขของคุณกับพวกเขา คะแนนของคุณสำหรับรอบนั้นคือผลรวมของคะแนนทั้งหมดเหล่านี้

จะเล่น 100 รอบ คะแนนรวมสูงสุดชนะ!

กฎระเบียบ

  • รหัสของคุณไม่สามารถใช้ I / O ใด ๆ รวมถึงคอนโซลไฟล์เครือข่าย ฯลฯ
  • คุณต้องไม่รบกวนโปรแกรมควบคุมหรือเครื่องเล่นอื่น ๆ
  • โปรแกรมที่ดูเหมือนว่าพวกเขาละเมิดกฎข้างต้นจะถูกยกเว้น
  • การเรียกใช้ฟังก์ชันแต่ละครั้งควรใช้เวลาไม่เกินห้าวินาทีในคอมพิวเตอร์ของฉัน (Intel Core i5 2450M พร้อม RAM 8GB)
  • หากโปรแกรมโยนข้อยกเว้นหรือคืนค่าที่ไม่ถูกต้องโปรแกรมจะถูกจัดการเสมือนว่าส่งคืน 1
  • ผู้ใช้แต่ละคนสามารถส่งได้มากที่สุดหนึ่งโปรแกรม

เบ็ดเตล็ด

  • โปรแกรมควบคุมบน GitHub
  • มีผู้เล่นในตัวสามคน พวกเขาสามารถพบได้ในคำตอบนี้
  • ผู้ชนะจะถูกเลือกในวันที่ 28 มกราคม

ลีดเดอร์บอร์ด

ผู้ชนะคือผู้พิทักษ์

รางวัลชมเชยGustavผู้เล่นที่ทำคะแนนสูงสุดด้วยกลยุทธ์ที่ไม่คงที่

  • ผู้พิทักษ์ - 36226
  • สูง - 36115
  • FloorHugger - 35880
  • NumberOne - 35791
  • Overestimator - 35791
  • กุสตาฟ - 35484
  • ประวัติศาสตร์ - 35201
  • ตัวอย่าง - 34960
  • ตัวเพิ่มค่า - 34351
  • JumpRightIn - 34074
  • Vickrey - 34020
  • วัยรุ่น - 33907
  • Randu - 33891
  • นักยกน้ำหนัก - 33682
  • คนกลาง - 33647
  • BounceInwards - 33529
  • NastyMathematician - 33292
  • จัมเปอร์ - 33244
  • Copycat - 33049

ผลเต็มรูปแบบที่สามารถพบได้ที่นี่ (ฉันแนะนำให้ปิดการใช้งานการตัดข้อความ)


ฉันมีวิธีบอกหมายเลขของตัวเองในรอบก่อนหน้านี้ไหม?
Martin Ender

@ MartinBüttnerไม่
Ypnypn

1
ฉันไม่รู้จักภาษาเหล่านั้น :( คุณสามารถเพิ่ม JavaScript ได้หรือไม่ชอบเปิดใช้งานด้วย node.js หรือไม่
Cilan

1
@TheBobbuffet ฉันไม่รู้จักพวกเขาใด ๆ ไม่ได้ห้ามฉันจากการสร้างรายการ Python
ทำเครื่องหมาย

7
ฉันคิดว่ามันน่าจะน่าสนใจกว่านี้ถ้าพื้นที่เป็นวงกลม / วนรอบเพื่อให้ระยะห่างระหว่าง 1 ถึง 999 เป็น 1 นั่นจะทำให้ "เดาหมายเลขเดียวทุกเทิร์น" จากการมีอำนาจเหนือเนื่องจากไม่มี "ขอบ" ไปจอดบน เห็นได้ชัดว่าสายเกินไปที่จะเปลี่ยนแปลงในขณะนี้;)
Geobits

คำตอบ:


9

Python ผู้พิทักษ์

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

เนื่องจากข้อยกเว้นทุกครั้งจะมีค่า 1 ค่าจะอยู่ห่างเท่าที่เป็นไปได้ ทำให้โชคลาภด้วยค่าใช้จ่ายของผู้อ่อนแอ

สนุกจริง: ฉันคิดเกี่ยวกับการปรับปรุง แต่ไม่สามารถหาวิธีที่ดีกว่าซ่อนอยู่ในมุม


1
ดูเหมือนว่าฉันเลือกมุมผิด :(
TheNumberOne

มันเป็นเรื่องที่ดีด้วยเหตุผลง่ายๆ: คนอื่น ๆ พยายามลดระยะทางให้สั้นที่สุด พวกเขาจะทำให้คะแนนของคุณดีขึ้นโดยอัตโนมัติ ผู้เปลี่ยนเกมจะเป็นคู่ต่อสู้ที่พยายามเข้าใกล้คุณมากที่สุด
Martin Thoma

1
อืม ... อัฒภาคใน Python เหรอ?
KSFT

@KSFT ฮิฮิฉันเป็นสนิมกับ Python และฉันไม่เคยเป็นผู้เชี่ยวชาญมาก่อนเลย
clabacchio

6

อันดับหนึ่ง Java

ชื่ออธิบายอันนี้อย่างสมบูรณ์

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

1
ทำไมถึงลงคะแนน?
TheNumberOne

5
ฉันชอบโดยเฉพาะอย่างยิ่งว่าชื่อผู้ใช้เชื่อมโยงกับการส่งอย่างไร
Brian J

5

Python โบราณแห่งประวัติศาสตร์

เชื่อมั่นในอนาคตว่าจะเป็นเหมือนที่ผ่านมา แต่เชื่อว่ารอบสุดท้ายนั้นไม่นานนักที่จะเป็นนักประวัติศาสตร์ดังนั้นมันจึงวนซ้ำ 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

Python, 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)

สร้างรายการหมายเลขที่เล่นบ่อยสมมติว่าทุกคนจะเล่นได้อย่างเหมาะสมและเลือกตัวเลือกที่ดีที่สุดเป็นอันดับสองในรายการ

ตัวอย่างเช่นหากตัวเลขที่พบบ่อยที่สุดคือ[1, 990, 999]Vickrey แทรกการเล่นที่ดีที่สุด 200 เพื่อให้[1, 200, 990, 999]จากนั้นเลือกตัวเลือกที่ดีที่สุดสำหรับอาร์เรย์ใหม่ (ซึ่งคือ 556)


4

Java, Overestimator

ตามชื่อที่แนะนำโปรแกรมนี้จะถือว่าโปรแกรมอื่น ๆ ทั้งหมดจะพยายามเล่น "ดี" โดยเลือกคำตอบที่ดีที่สุดตามรอบสุดท้ายดังนั้น "overestimator" นี้จะเลือกตำแหน่งที่แย่ที่สุดที่เป็นไปได้ตามรอบก่อนหน้า

 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

Java - นักยกน้ำหนัก

วนรอบ 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 ก็เสร็จสมบูรณ์ภายในไม่กี่วินาทีบนพีซีของฉันที่ค่อนข้างช้า หากคุณใช้เวลานานเกินไปด้วยเหตุผลบางอย่างโปรดแจ้งให้เราทราบเพื่อ จำกัด การเรียกซ้ำ
Geobits

มันรวดเร็วมากในเครื่องของฉันเช่นกัน
Ypnypn

3

Ruby, Copycat

เพียงแค่คืนค่าหมายเลขที่ชนะครั้งสุดท้าย

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

กุสตาฟ (Python 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

ตัวเพิ่ม (Java)

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

FloorHugger (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

ออกจากรายการสถานที่เลือกสถานที่ที่ไกลที่สุดจากตัวเลขที่ใช้ล่าสุดโดยไม่สนใจรอบก่อนหน้า

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

เริ่มต้นที่ 1 มันจะค่อยๆเข้าใกล้ 500 ในขณะที่เด้งตัวเลือกสูงและต่ำ

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

1

NastyMathematician (Java)

ตรวจสอบสองรอบสุดท้าย (หากหมายเลขที่ดีที่สุดคือ 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

Python - ฉันไม่ต้องการคิดชื่อ ...

หากค่าเฉลี่ยของตัวเลขที่เลือกในรอบที่ผ่านมาน้อยกว่า 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 คนกลาง (ขึ้นอยู่กับผู้พิทักษ์โดย @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.