Mantén tu distancia en un círculo

9

Esto se basa en este desafío y en la idea de Geobits / CarpetPython de mejorarlo:

¡Mantén tu distancia!

Para este desafío, la distancia entre dos números se mide en un ciclo, por lo que, por ejemplo, la distancia entre 0 y 999 es 1. Esto debería evitar que estrategias como elegir siempre el número más bajo o más alto ganen casi todas las veces. El único otro cambio es que el número más bajo que se puede elegir ahora es 0 en lugar de 1.

Lo resumiré aquí:

  • Escriba una función en Java, Python o Ruby que tome tres argumentos:
    • la cantidad de rondas jugadas hasta ahora
    • la cantidad de jugadores
    • los números seleccionados en las rondas anteriores, como una serie de cadenas separadas por espacios
  • Debería devolver un número entero de 0 a 999, inclusive
  • El puntaje de un programa en cada ronda es la suma de las raíces cuadradas de las distancias a los números que el otro programa eligió.
  • El programa con la puntuación más alta después de 100 rondas gana.
  • Una respuesta por persona.

El programa de control está aquí:

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

Tabla de clasificación

NumberOne, de TheBestOne, está ganando.

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

Al parecer, mi sabotaje camper ... er (?) No funciona muy bien.

Aquí están los resultados completos: https://github.com/KSFTmh/src/blob/master/results-3

Creo que esto es lo suficientemente diferente como para no ser un duplicado.

Por cierto, esta es la primera vez que hago una pregunta en Stack Exchange, así que avíseme si estoy haciendo algo mal.

KSFT
fuente
44
¿Realmente queremos una pregunta tan similar?
Optimizador
55
@Optimizer Algunas personas en los comentarios parecían pensar que era una buena idea. Las respuestas del original funcionarán de manera muy diferente aquí, así que no creo que sea un duplicado.
KSFT
1
El crédito por sugerir el desafío debe ir a @Geobits. Solo estuve de acuerdo con él.
Logic Knight
1
Mmm Parece que un número constante gana de nuevo. Tengo curiosidad de por qué es eso. ¿Podríamos ver los 600 números de salida en la pregunta, o en github o pastebin? Sospecho que algunos de nuestros predictores tienen errores. Posiblemente mío :-(
Logic Knight
1
@CarpetPython Un cambio simple sería calcular la distancia entre los puntos de la última vuelta además de los puntos de esta ronda.
TheNumberOne

Respuestas:

3

Python 2, Sampler

Esta entrada se basa en el mismo código para mantener su distancia, entrada de muestra . Espero que sea mejor aquí donde las ventajas 1 y 999 no existen.

De una lista de lugares, elija el que esté más alejado de los números usados ​​recientemente, ignorando el turno anterior (porque otras entradas pueden predecir en función del turno anterior).

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
Caballero Lógico
fuente
Parece que este está ganando, pero eso podría deberse a que no estoy compilando el controlador correctamente y los demás están fallando.
KSFT 01 de
2

Number OnePlusFourNineNine, Java

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

La lógica es realmente simple. A menos que alguien encuentre un algoritmo real que tenga en cuenta los puntajes anteriores, esta respuesta está bastante optimizada.

Ahora que contamos la distancia en un círculo, la distancia máxima de dos puntos puede ser 500. Ahora, si todas las entradas generaran números aleatorios (o pseudoaleatorios basados ​​en algún algoritmo), esta respuesta no habría tenido ninguna ventaja . Pero hay al menos 1 entrada que produce una respuesta constante que es una distancia casi máxima. Esto hace que el puntaje sea a favor de 500 ya que hay una fuente fija de distancia máxima posible en cada ronda :)

Optimizador
fuente
Optimizaste mi respuesta. ;)
TheNumberOne
@TheBestOne jaja
Optimizer
2

AncientHistorian - Python

Es el mismo algoritmo del anterior, excepto que al calcular los puntajes potenciales utiliza la distancia circular. Como estoy perdiendo horriblemente y no puedo hacer que el controlador se compile, solo estoy probando una nueva estrategia, donde uso lo peor de las rondas anteriores.

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
fuente
Esto no funciona ies un elemento de scores.split(' '), lo que significa que es una cadena, no un int.
KSFT 01 de
@KSFT oh dispara, realmente debería haberlo probado, actualizando.
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)

Los campistas siguen ganando. Avíseme si tiene alguna sugerencia para esto.

KSFT
fuente
2

FindCampers - Python 2

Encuentra a todos los campistas de las últimas 10 rondas y mantente alejado de ellos. Espero que los predictores huyan de mí. Ahora ignoraré mis viejas elecciones.

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
fuente
Aww ... esperaba que esto fuera para los campistas cuando vi el nombre ...
KSFT
Jajaja Podría agregar una entrada que saboteará a los campistas.
Jmac
Lamentablemente, solo permití una entrada por persona.
KSFT
Acabo de publicar una entrada para sabotear a los campistas.
KSFT
El mío no funciona porque no me di cuenta de que los resultados anteriores estaban ordenados. ¿Cómo detecta el tuyo a los campistas?
KSFT
1

Número uno, Java

La primera respuesta Copiado de mi respuesta anterior .

public static int choose(int round, int players, String[] args) {
    return 1;
}
El numero uno
fuente
Alguien parece haber rechazado todas las respuestas.
KSFT
1

WowThisGameIsSoDeep, Java

He analizado el juego durante 10 años en un clúster de 1 millón de núcleos y encontré la solución óptima.

public static int choose(int round, int players,String[]spam) { return(int)(Math.random()*1e3); }
Feersum
fuente
Esto no es un código de golf
Optimizer
55
Esa solución no es óptima. Si desea una distribución uniforme, debe usar Random.nextInt(int).
Peter Taylor
Parece que esto siempre regresa 1.
KSFT
@KSFT Lo probé y obtuve muchos números diferentes. Tal vez es sabotaje después de todo?
fiesta
44
¡Ajá! ¡Lo arreglé! Accidentalmente escribí "WowThisGameIsSoDeep.py" e intentaba ejecutarlo como un archivo Python.
KSFT
1

Extrapolador Circilineal, Rubí

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
histocrat
fuente
Esto está dando este error:NoMethodError: undefined method `split' for #<Array:0x720f56e2> choose at CircilinearExtrapolator.rb:2
KSFT
Oh, ¿es previous_choicesun conjunto de valores como ["1 6 500","2 8 503"]?
histocrat
Está. ¿Creías que era otra cosa? Si no, probablemente haya estropeado algo al ejecutarlo.
KSFT
Pensé que era solo una cuerda plana, lo siento. Lo editaré
histocrat
Editado Ahora todo el mundo sabe que
publiqué