Mesafeni koru!


15

Her oyuncunun bir numarası vardır. Sizinki hepsinden en uzakta olabilir mi?

Gereksinimler

choose()Üç bağımsız değişkeni kabul eden bir Java, Python 2 veya Ruby işlevi yazın :

  • bir tam sayı - tamamlanmış tur sayısı
  • bir tam sayı - oyuncu sayısı
  • bir dizi dizi - önceki her turun sonuçları
    • her dize, en yüksekten en düşüğe doğru sıralanmış, boşlukla ayrılmış bir tamsayı listesidir

Örneğin, şu choose(2, 4, ["4 93 93 174", "1 84 234 555"])anlama gelir:

  • zaten iki tur vardı (bu üçüncü tur)
  • toplam dört oyuncu var
  • ilk turda seçilen sayılar 4, 93, 93, 174
  • ikinci turda seçilen sayılar 1, 84, 234, 555

1'den 999'a (dahil) bir tam sayı döndürmelisiniz.

Birbiriniz için oyuncu puanınız, numaranız ve onlarınki arasındaki mesafenin kareköküdür. Tur için aldığınız puan bu puanların toplamıdır.

100 tur oynanacak. En yüksek toplam puan kazanır!

kurallar

  • Kodunuzda konsol, dosyalar, ağ vb. G / Ç kullanılmayabilir.
  • Kontrol programına veya diğer oyunculara müdahale edemezsiniz.
  • Yukarıdaki kuralları ihlal ettiklerine benzeyen programlar hariç tutulacaktır.
  • Bir işlevin her çağrısının bilgisayarımda beş saniyeden az sürmesi gerekir (8GB RAM ile Intel Core i5 2450M).
  • Bir program bir istisna atarsa ​​veya geçersiz bir değer döndürürse, 1 döndürmüş gibi kabul edilir.
  • Her kullanıcı en fazla bir program gönderebilir.

Çeşitli

  • Kontrol programı GitHub'da .
  • Üç yerleşik oyuncu vardır. Bunlar bulunabilir bu cevap .
  • Kazanan 28 Ocak'ta seçilecek.

Liderler Sıralaması

Kazanan Konservatör .

Sürekli olmayan bir stratejiye sahip en yüksek puan alan oyuncu Gustav'a şerefli söz .

  • Konser - 36226
  • Yüksek - 36115
  • FloorHugger - 35880
  • Numara Bir - 35791
  • Aşırı tahmin edici - 35791
  • Gustav - 35484
  • Tarihçi - 35201
  • Örnekleyici - 34960
  • Artırıcı - 34351
  • JumpRightIn - 34074
  • Vickrey - 34020
  • Genç - 33907
  • Randu - 33891
  • Halterci - 33682
  • Aracı - 33647
  • BounceInwards - 33529
  • Olgunlaşmamış - 33292
  • Jumper - 33244
  • Taklitçi - 33049

Tam sonuçları burada bulabilirsiniz . (Metin kaydırmayı devre dışı bırakmanızı öneririm.)


Önceki turlarda kendi numaramın hangisi olduğunu söylemenin bir yolu var mı?
Martin Ender

@ MartinBüttner No.
Ypnypn

1
Şu dillerden hiçbirini bilmiyorum :( JavaScript ekleyebilir misiniz? Gibi, node.js ile çalıştırın?
Cilan

1
@TheWobbuffet, ben de hiçbirini tanımıyorum. Python girişi yapmama engel olmadı.
Mark

7
Ben bir boşluk / döngü olsaydı daha ilginç olurdu düşünüyorum böylece 1 ve 999 arasındaki mesafe 1 olduğunu. Bu "kenarları" olmadığı için, "her dönüşü tek bir sayı tahmin" hakim olmasını önler park etmek. Açıkçası şimdi değiştirmek için çok geç;)
Geobits

Yanıtlar:


9

Python, Konservatör

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

Her istisna 1 attığından, mümkün olduğunca uzak durur. Servetini zayıfların pahasına yapar.

Eğlenceli gerçek: Bunu geliştirmeyi düşündüm, ancak bir köşede saklanmaktan daha iyi bir yol bulamadım.


1
Görünüşe göre yanlış köşeyi seçtim. :(
TheNumberOne

Basit bir nedenden dolayı iyidir: Diğerleri size olan mesafeyi en aza indirmeye çalışır. Skorunuzu otomatik olarak daha iyi hale getireceklerdir. Bir oyun değiştirici size mümkün olduğunca yaklaşmaya çalışan bir rakip olacaktır.
Martin Thoma

1
Eww ... Python'da noktalı virgül mü?
KSFT

@KSFT hehe Python'da paslıyım ve daha önce hiç bu kadar uzman
olmadım

6

Bir Numara, Java

İsim bunu tamamen açıklıyor.

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

1
Neden aşağı oy?
TheNumberOne

5
Özellikle kullanıcı adının gönderime nasıl bağlandığını seviyorum
Brian J

5

Python, Antik Tarihçi

Geleceğin tam olarak geçmiş gibi olacağına inanıyor, ancak son turun histiry olmak için çok yeni olduğuna inanıyor, bu yüzden sadece 1 - 999 arasında dolaşıyor ve önceki turların sonuncusu için en iyi olanı seçiyor. İlk 2 raunt 500 döndürür.

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)

Sıklıkla oynanan sayıların bir listesini yapar, diğer herkesin en iyi şekilde oynayacağını varsayar ve listede verilen en iyi ikinci tercihi seçer .

Örneğin, en yaygın sayılarsa, [1, 990, 999]Vickrey vermek için en uygun oyunu 200 ekler [1, 200, 990, 999], ardından yeni dizi (556 olan) için en iyi seçeneği seçer.


4

Java, Aşırı Tahminci

Adından da anlaşılacağı gibi, bu program diğer tüm programların son tura göre en iyi cevabı seçerek "iyi" oynamaya çalışacağını varsayar - böylece bu "aşırı tahminci" her zaman bir önceki tura göre mümkün olan en kötü pozisyonu alır .

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

Neden bu sabit bir "1" oynadı? Bir hata var mıydı? Dikkat edin, "1" oynamanın oldukça başarılı olduğu kanıtlandı. :)
Emil

Ne yazık ki kodun bir hatası var, evet - aslında son turdan okuduğu puanları asla ayrıştırmıyor. (Ama çok geç fark ettim ve o zamana kadar bir gönderimi düzenlemek yanlış görünüyordu, artı söylediğiniz gibi oldukça iyi ... yani: p)
Alex Walker

4

Java - Halterci

Her turda hangisinin en iyi olacağını bulmak için 1-999 arasında dolaşır. Onları yeniliğe göre tartar (son turlarda daha fazla ağırlık vardır) ve en iyi genel tahminini döndürür. Umarım desenler daha sonraki turda oluşursa, bu onu alabilir.

Düzenleme: Şimdi + Inf% daha fazla özyineleme ile! Önceki turlarda seçtiklerinizi saklayamama / kaydetmeme / görmeme bir sürüklemedir. Kendi girdilerinizi hesaba katmak, başkalarının ne yapacağını anlamaya çalışırken sizi mahveder . Hadi hesaplayalım! Bu şimdi bir önceki turda neyi seçtiğini anlamak ve bir sonraki hareketi hesaplarken bunu görmezden gelmek olacaktır.

Sadece son dönüşten itibaren kendi girdisini gerçekten görmezden geldiğine dikkat edin, ancak biri en yüksek ağırlıklı olduğundan, iyi çalışıyor gibi görünüyor. Bu biraz daha fazla işle düzeltilebilir, ancak skor tablosunun gerekli olup olmadığını görmesini bekleyeceğim.

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

Not: 100. turda bile, biraz yavaş bilgisayarımda bir saniyenin altında tamamlanır. Herhangi bir nedenden ötürü çok uzun sürerse, özyinelemeyi sınırlayabilmem için bana bildirin.
Geobits

Makinemde de çok hızlı.
Ypnypn

3

Ruby, taklitçi

En son hangi sayıyı kazanırsa döndürür.

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
İlk tur için geri dönüş nedir? Oh boşver. İstisnalar 1 dönecekti.
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

Muhtemelen en basit stratejidir. Son turdaki en büyük boşluğu bulur ve bu boşluğun tam ortasındaki sayıyı seçer.


İlk tur için geri dönüş nedir? 1?
mbomb007

@ mbomb007 Oh, bu sinir bozucu ilk turları hep unuturum. Teşekkürler, şimdi 500 döndürüyor.
Martin Ender

3

Gustav (Python 2)

Bu, benzer bir KotH mücadelesinde eski cevaplarımdan utanmadan kopyalanan oldukça basit bir meta stratejidir . Birkaç basit stratejiyi göz önünde bulundurur, önceki turlarda nasıl performans göstereceklerine bakar ve bir sonraki tur için en yüksek skoru uygular.

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]

Şimdi algoritmanın hala bazı kusurları olduğunu anlıyorum. Örneğin, "kendini kovalamaya" devam edebilir, çünkü kendi hamlelerini rakiplerinin hareketlerinden ayırmaz. Ancak şimdilik böyle bırakacağım.



1

Aşağıdaki üç program yerleşiktir.

Yüksek (Yakut)

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

Arttırıcı (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, Örnekleyici

Yerlerin listesinden, son kullanılan sayılardan en uzak olanı seçin ve önceki dönüşü yok sayın.

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'den başlayarak, daha yüksek ve daha düşük seçenek arasında sıçrarken yavaş yavaş 500'e yaklaşıyor.

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

1

NastyMathematician (Java)

Son iki turu inceler (en iyi sayılar 70 ve 80 ise 90 çıktısı alır). Bu kötü çünkü rakiplerine karşı kazanmak için mümkün olduğunca yüksek sayılar almaya çalışıyor.

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 - Bir isim düşünmek istemiyorum ...

Geçmiş turlarda seçilen sayıların ortalaması 500'den azsa, 999'u seçer. Aksi takdirde 1'i seçer.

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 tarafından konser sağlayıcıya dayanmaktadır)

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

Üst kenarın yüksek puan aldığını (ve alt kenardan daha iyi performans gösterdiğini) fark ettikten sonra, sadece ortada yakalanmaktan daha kötü bir şey olup olmadığını merak ettim.


0

Jumper (Yakut)

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

Alt, orta ve üst arasında geçiş yapar. (5.500.995)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.