Mantenha sua distância em um círculo

9

Isso se baseia nesse desafio e na idéia do Geobits / CarpetPython para melhorá-lo:

Mantenha distância!

Para esse desafio, a distância entre dois números é medida em um loop, portanto, por exemplo, a distância entre 0 e 999 é 1. Isso deve impedir que estratégias como sempre escolher o número mais baixo ou mais alto ganhem quase todas as vezes. A única outra alteração é que o número mais baixo que pode ser escolhido agora é 0 em vez de 1.

Vou resumir aqui:

  • Escreva uma função em Java, Python ou Ruby que aceite três argumentos:
    • o número de rodadas disputadas até agora
    • o número de jogadores
    • os números escolhidos nas rodadas anteriores, como uma matriz de sequências separadas por espaço
  • Ele deve retornar um número inteiro de 0 a 999, inclusive
  • A pontuação de um programa a cada rodada é a soma das raízes quadradas das distâncias dos números que o outro programa escolheu
  • O programa com a maior pontuação após 100 rodadas vence.
  • Uma resposta por pessoa

O programa de controle está aqui:

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

Entre os melhores

NumberOne, da TheBestOne, está ganhando.

  • NumberOne - 9700
  • NumberOnePlusFourNineNine - 9623
  • AntigoHistória - 9425
  • FindCampers - 9259
  • WowThisGameIsSoDeep - 9069
  • Amostrador - 9014
  • SabotageCampers - 8545

Aparentemente, minha sabotagem de campista ... er (?) Não funciona muito bem.

Aqui estão os resultados completos: https://github.com/KSFTmh/src/blob/master/results-3

Eu acho que isso é diferente o suficiente para não ser uma duplicata.

A propósito, esta é a primeira vez que faço uma pergunta no Stack Exchange, então, deixe-me saber se estou fazendo algo errado.

KSFT
fonte
4
Realmente queremos uma pergunta parecida?
Optimizer
5
@Optimizer Algumas pessoas nos comentários pareciam pensar que era uma boa ideia. As respostas do original funcionarão de maneira muito diferente aqui, então não acho que seja uma duplicata.
KSFT 31/01
11
O crédito para sugerir o desafio deve ir para @Geobits. Eu apenas concordei com ele.
Logic Knight
11
Mmm. Parece que um número constante vence novamente. Estou curioso sobre o porquê disso. Podemos ver os 600 números de saída na pergunta, ou no github ou pastebin? Suspeito que alguns de nossos preditores tenham bugs. Possivelmente meu :-(
Logic Knight
11
@CarpetPython Uma mudança simples seria calcular a distância entre os pontos da última volta além dos pontos desta rodada.
TheNumberOne

Respostas:

3

Python 2, Sampler

Esta entrada é baseada no mesmo código da entrada Mantenha distância, Sampler . Espero que faça melhor aqui, onde as vantagens 1 e 999 não existem.

Em uma lista de locais, escolha o que está mais distante dos números usados ​​recentemente, ignorando a curva anterior (porque outras entradas podem prever com base apenas na curva 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
Cavaleiro Lógico
fonte
Parece que este está ganhando, mas isso pode ser porque eu não estou compilando o controlador direito e os outros estão travando.
KSFT
2

Number OnePlusFourNineNine, Java

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

A lógica é realmente simples. A menos que alguém encontre um algoritmo real que leve em consideração as pontuações anteriores, essa resposta é bastante otimizada.

Agora que contamos a distância em um círculo, a distância máxima de dois pontos pode ser 500. Agora, se todas as entradas estivessem gerando números aleatórios (ou pseudo-aleatórios com base em algum algoritmo), essa resposta não teria nenhuma vantagem. . Mas há pelo menos uma entrada que produz uma resposta constante a uma distância quase máxima. Isso faz com que a pontuação seja a favor de 500, pois existe uma fonte fixa de distância máxima possível em cada rodada :)

Optimizer
fonte
Você otimizou minha resposta. ;)
TheNumberOne
@TheBestOne haha
Optimizer
2

AncientHistorian - Python

É o mesmo algoritmo do anterior, exceto no cálculo das pontuações potenciais que utiliza a distância circular. Como estou perdendo horrivelmente e não consigo compilar o controlador, estou apenas tentando uma nova estratégia, na qual uso o pior das rodadas 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
fonte
Isso não funciona. ié um elemento de scores.split(' '), o que significa que é uma string, não um int.
KSFT 01/02
@KSFT oh disparar, eu realmente deveria ter testado, atualizando.
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)

Os campistas ainda estão vencendo. Deixe-me saber se você tem alguma sugestão para isso.

KSFT
fonte
2

FindCampers - Python 2

Encontre todos os campistas das últimas 10 rodadas e fique longe deles. Espero que os preditores corram de mim. Agora vou ignorar minhas antigas escolhas.

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
fonte
Aww ... eu estava esperando que isso fosse direcionado para os campistas quando vi o nome ...
KSFT 07/02/15
Ri muito. Eu poderia adicionar uma entrada que sabotará os campistas.
Jmac
Infelizmente, permiti apenas uma entrada por pessoa.
KSFT
Acabei de publicar uma entrada para sabotar os campistas.
KSFT
O meu não funciona porque eu não percebi que os resultados anteriores foram classificados. Como o seu detecta os campistas?
KSFT
1

Número Um, Java

A primeira resposta Copiado da minha resposta anterior .

public static int choose(int round, int players, String[] args) {
    return 1;
}
O número um
fonte
Alguém parece ter rebaixado todas as respostas.
KSFT
1

WowThisGameIsSoDeep, Java

Analisei o jogo por 10 anos em um cluster de 1 milhão de núcleos e encontrei a solução ideal.

public static int choose(int round, int players,String[]spam) { return(int)(Math.random()*1e3); }
feersum
fonte
Isso não é código-golfe
Otimizador
5
Essa solução não é ótima. Se você deseja uma distribuição uniforme, use Random.nextInt(int).
Peter Taylor
Isso sempre parece retornar 1.
KSFT 02/02
@KSFT Eu testei e obtive muitos números diferentes. Talvez seja sabotagem, afinal?
feersum
4
Aha! Eu consertei isso! Digitei acidentalmente "WowThisGameIsSoDeep.py" e ele estava tentando executá-lo como um arquivo Python.
KSFT 02/02
1

Extrapolador circular, 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
histocrata
fonte
Isso está causando este erro:NoMethodError: undefined method `split' for #<Array:0x720f56e2> choose at CircilinearExtrapolator.rb:2
KSFT
Ah, é como previous_choicesuma matriz de valores ["1 6 500","2 8 503"]?
histocrat
Isto é. Você achou que era outra coisa? Caso contrário, provavelmente eu estraguei tudo ao executá-lo.
KSFT
Eu pensei que era apenas uma corda plana, desculpe. Eu vou editar.
Histocrat
Editado. Agora todo mundo sabe que eu postei algo sem testá-lo ...
histocrat