Halten Sie Abstand auf einem Kreis

9

Dies basiert auf dieser Herausforderung und der Idee von Geobits / CarpetPython, sie zu verbessern:

Abstand halten!

Bei dieser Herausforderung wird der Abstand zwischen zwei Zahlen in einer Schleife gemessen, sodass beispielsweise der Abstand zwischen 0 und 999 1 beträgt. Dies sollte verhindern, dass Strategien wie die Auswahl der niedrigsten oder höchsten Zahl fast jedes Mal gewinnen. Die einzige andere Änderung ist, dass die niedrigste Zahl, die gewählt werden kann, jetzt 0 statt 1 ist.

Ich werde es hier zusammenfassen:

  • Schreiben Sie eine Funktion in Java, Python oder Ruby, die drei Argumente akzeptiert:
    • die Anzahl der bisher gespielten Runden
    • die Anzahl der Spieler
    • Die in den vorherigen Runden ausgewählten Zahlen als Array von durch Leerzeichen getrennten Zeichenfolgen
  • Es sollte eine Ganzzahl von 0 bis einschließlich 999 zurückgeben
  • Die Punktzahl für ein Programm in jeder Runde ist die Summe der Quadratwurzeln der Abstände zu den Zahlen, die jedes andere Programm ausgewählt hat
  • Das Programm mit der höchsten Punktzahl nach 100 Runden gewinnt.
  • Eine Antwort pro Person

Das Steuerungsprogramm ist hier:

https://github.com/KSFTmh/src/

Bestenliste

NumberOne von TheBestOne gewinnt.

  • NumberOne - 9700
  • NumberOnePlusFourNineNine - 9623
  • AncientHistorian - 9425
  • FindCampers - 9259
  • WowThisGameIsSoDeep - 9069
  • Sampler - 9014
  • SabotageCampers - 8545

Anscheinend funktioniert meine Camper-Sabotage ... ähm (?) Nicht sehr gut.

Hier sind die vollständigen Ergebnisse: https://github.com/KSFTmh/src/blob/master/results-3

Ich denke, das ist anders genug, um kein Duplikat zu sein.

Übrigens stelle ich zum ersten Mal eine Frage zu Stack Exchange. Lassen Sie mich wissen, wenn ich etwas falsch mache.

KSFT
quelle
4
Wollen wir wirklich eine ähnliche Frage?
Optimierer
5
@Optimizer Ein paar Leute in den Kommentaren schienen zu denken, dass dies eine gute Idee war. Die Antworten vom Original werden hier sehr unterschiedlich funktionieren, daher denke ich nicht, dass es sich um ein Duplikat handelt.
KSFT
1
Der Kredit für den Vorschlag der Herausforderung sollte an @Geobits gehen. Ich habe ihm nur zugestimmt.
Logic Knight
1
Mmm. Es scheint, dass eine konstante Zahl wieder gewinnt. Ich bin gespannt, warum das so ist. Könnten wir die 600 Ausgabenummern in der Frage oder auf Github oder Pastebin sehen? Ich vermute, einige unserer Prädiktoren haben Fehler. Möglicherweise meins :-(
Logic Knight
1
@CarpetPython Eine einfache Änderung wäre, den Abstand zwischen den Punkten der letzten Runde zusätzlich zu den Punkten aus dieser Runde zu berechnen.
TheNumberOne

Antworten:

3

Python 2, Sampler

Dieser Eintrag basiert auf dem gleichen Code für Abstand halten, Sampler-Eintrag . Ich hoffe, es wird hier besser, wo die Vorteile 1 und 999 nicht existieren.

Wählen Sie aus einer Liste von Orten diejenige aus, die am weitesten von den zuletzt verwendeten Zahlen entfernt ist, und ignorieren Sie dabei die vorherige Runde (da andere Einträge möglicherweise nur auf der Grundlage der vorherigen Runde vorhersagen).

def choose(turn, players, history):
    sample = map(int, (' '.join( history[-5:-1] )).split())
    def distance(x):
        return sum(min(1000-abs(x-y), abs(x-y))**0.5 for y in sample)
    score, place = max((distance(x), x) for x in range(1000))
    return place
Logikritter
quelle
Es sieht so aus, als würde dieser gewinnen, aber das könnte daran liegen, dass ich den Controller nicht richtig kompiliere und die anderen alle abstürzen.
KSFT
2

Nummer OnePlusFourNineNine, Java

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

Die Logik ist wirklich einfach. Sofern jemand keinen echten Algorithmus findet, der frühere Ergebnisse berücksichtigt, ist diese Antwort ziemlich optimiert.

Nachdem wir nun die Entfernung in einem Kreis gezählt haben, kann die maximale Entfernung von zwei beliebigen Punkten 500 betragen. Wenn nun alle Einträge Zufallszahlen (oder Pseudozufallszahlen basierend auf einem Algorithmus) generieren würden, wäre diese Antwort überhaupt nicht vorteilhaft gewesen . Es gibt jedoch mindestens einen Eintrag, der eine konstante Antwort ergibt, die eine fast maximale Entfernung aufweist. Das macht die Punktzahl zugunsten von 500, da in jeder Runde eine feste Quelle für die maximal mögliche Distanz vorhanden ist :)

Optimierer
quelle
Sie haben meine Antwort optimiert. ;)
TheNumberOne
@ TheBestOne haha
Optimierer
2

AncientHistorian - Python

Es ist der gleiche Algorithmus wie beim vorherigen, außer dass bei der Berechnung der potenziellen Bewertungen der Kreisabstand verwendet wird. Da ich schrecklich verliere und den Controller nicht zum Kompilieren bringen kann, versuche ich nur eine neue Strategie, bei der ich das Schlimmste aus den vorherigen Runden verwende.

def choose(round, players, scores):
    calc = lambda n, scores: sum([min(abs(int(i)-n), 1000-max(int(i),n)+min(int(i),n))**.5 for i in scores.split(' ')])
    return min(range(1000), key=lambda n: sum([calc(n, j) for j in scores[1:]])) if round>1 else 250
Maltysen
quelle
Das funktioniert nicht. iist ein Element von scores.split(' '), was bedeutet, dass es ein String ist, kein int.
KSFT
@KSFT oh schieß, ich hätte es wirklich testen und aktualisieren sollen.
Maltysen
2

SabotageCampers - Python

def choose(rounds, players, previous):
    if rounds<3:
        return 1
    prevchoices=[int(i) for i in " ".join(previous[-5:]).split(" ")]
    remove=[]
    for i in prevchoices:
        if prevchoices.count(i)<3:
            remove.append(i)
    campers=[i for i in prevchoices if i not in remove]
    return random.choice(campers)

Die Camper gewinnen immer noch. Lassen Sie mich wissen, wenn Sie Vorschläge dazu haben.

KSFT
quelle
2

FindCampers - Python 2

Finde alle Camper der letzten 10 Runden und halte dich von ihnen fern. Ich hoffe, dass Prädiktoren vor mir davonlaufen. Ich werde jetzt meine alten Entscheidungen ignorieren.

def choose(rounds, players, previous):
    from collections import Counter

    def distance(x, y):
        return min(1000 - abs(x-y), abs(x-y))

    pastRounds = list(map(lambda x: Counter(map(int, x.split())), previous))
    me = 751
    for (index, round) in enumerate(pastRounds):
        round.subtract((me,))
        pastRounds[index] = set(round.elements())
        campers = reduce(lambda x,y: x.intersection(y), pastRounds[max(1, index-9):index], pastRounds[max(0,index-10)])
        if campers:
            dist, me = max(min((distance(x, y), x) for y in campers) for x in range(1000))
        else:
            me = 751
    return me
Jmac
quelle
Aww ... Ich hatte gehofft, dass dies in Richtung der Camper gehen würde, als ich den Namen sah ...
KSFT
Lol. Ich könnte einen Eintrag hinzufügen, der Camper sabotiert.
Jmac
Leider habe ich nur einen Eintrag pro Person erlaubt.
KSFT
Ich habe gerade selbst einen Eintrag für Sabotage-Camper gepostet.
KSFT
Meins funktioniert nicht, weil ich nicht wusste, dass vorherige Ergebnisse sortiert wurden. Wie erkennt Ihr Camper?
KSFT
1

Nummer Eins, Java

Die erste Antwort. Von meiner vorherigen Antwort kopiert .

public static int choose(int round, int players, String[] args) {
    return 1;
}
Die Nummer eins
quelle
Jemand scheint alle Antworten abgelehnt zu haben.
KSFT
1

WowThisGameIsSoDeep, Java

Ich habe das Spiel 10 Jahre lang auf einem 1-Millionen-Kern-Cluster analysiert und die optimale Lösung gefunden.

public static int choose(int round, int players,String[]spam) { return(int)(Math.random()*1e3); }
Feersum
quelle
Dies ist kein Code-Golf
Optimizer
5
Diese Lösung ist nicht optimal. Wenn Sie eine gleichmäßige Verteilung wünschen, sollten Sie verwenden Random.nextInt(int).
Peter Taylor
Dies scheint immer 1 zurückzugeben.
KSFT
@KSFT Ich habe es getestet und viele verschiedene Nummern bekommen. Vielleicht ist es doch Sabotage?
Feersum
4
Aha! Ich habe es repariert! Ich habe versehentlich "WowThisGameIsSoDeep.py" eingegeben und versucht, es als Python-Datei auszuführen.
KSFT
1

Zirkilinearer Extrapolator, Ruby

def choose(round, players, previous_choices)
  previous_rounds = previous_choices.map{ |round| round.split.map(&:to_i) }
  optimal_past_choices = previous_rounds.map do |choices|
    (0..999).max_by { |i| choices.map{ |c| root_distance(i,c) }.inject(:+) }
  end
  if (last_round = optimal_past_choices.last)
    (last_round + average_delta(optimal_past_choices).round) % 1000
  else
    750
  end
end

def root_distance(i,j)
  dist = (i-j).abs
  dist = [dist, 1000 - dist].min
  dist ** 0.5
end

def directed_distance(i,j)
  dist = j - i
  if dist > 500
    dist - 1000
  elsif dist < -500
    dist + 1000
  else
    dist
  end
end

def average_delta(ary)
  ary.each_cons(2).map{ |x,y| directed_distance(x,y) }.inject(0,:+)/ary.count
end
Histokrat
quelle
Dies gibt diesen Fehler:NoMethodError: undefined method `split' for #<Array:0x720f56e2> choose at CircilinearExtrapolator.rb:2
KSFT
Oh, ist previous_choiceseine Reihe von Werten wie ["1 6 500","2 8 503"]?
Histokrat
Es ist. Hast du gedacht, es wäre etwas anderes? Wenn nicht, habe ich wahrscheinlich nur etwas durcheinander gebracht.
KSFT
Ich dachte, es wäre nur eine flache Schnur, sorry. Ich werde bearbeiten.
Histokrat
Bearbeitet. Jetzt weiß jeder, dass ich etwas gepostet habe, ohne es zu testen ...
Histokrat