Держите дистанцию ​​по кругу

9

Это основано на этой задаче и идее Geobits / CarpetPython по ее улучшению:

Держи дистанцию!

Для этой задачи расстояние между двумя числами измеряется в цикле, поэтому, например, расстояние между 0 и 999 равно 1. Это должно помешать стратегиям, таким как всегда выбирать самое низкое или наибольшее число, почти каждый раз выигрывая. Единственное другое изменение заключается в том, что самое низкое число, которое можно выбрать, теперь равно 0 вместо 1.

Я подведу итог здесь:

  • Напишите функцию на Java, Python или Ruby, которая принимает три аргумента:
    • количество сыгранных раундов
    • количество игроков
    • числа, выбранные в предыдущих раундах, как массив строк, разделенных пробелом
  • Должен возвращать целое число от 0 до 999 включительно
  • Оценка для программы каждого раунда является суммой квадратных корней расстояний до чисел, выбранных каждой другой программой
  • Программа с наибольшим количеством очков после 100 раундов выигрывает.
  • Один ответ на человека

Управляющая программа здесь:

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

Leaderboard

NumberOne от TheBestOne побеждает.

  • NumberOne - 9700
  • NumberOnePlusFourNineNine - 9623
  • Древнеисторический - 9425
  • FindCampers - 9259
  • WowThisGameIsSoDeep - 9069
  • Пробоотборник - 9014
  • SabotageCampers - 8545

Видимо, саботаж моего туриста ... э-э (?) Не очень хорошо работает.

Вот полные результаты: https://github.com/KSFTmh/src/blob/master/results-3

Я думаю, что это достаточно отличается, чтобы не быть дубликатом.

Кстати, я впервые задаю вопрос на Stack Exchange, поэтому дайте мне знать, если я что-то не так делаю.

KSFT
источник
4
Мы действительно хотим вопрос, подобный этому?
Оптимизатор
5
@Optimizer Несколько человек в комментариях, казалось, думали, что это хорошая идея. Ответы из оригинала будут работать совсем по-другому, поэтому я не думаю, что это дубликат.
KSFT
1
Кредит для предложения проблемы должен пойти в @ Geobits. Я просто согласился с ним.
Логика Найт
1
Ммм. Кажется, что постоянное число снова выигрывает. Мне любопытно, почему это так. Можем ли мы увидеть 600 выходных чисел в вопросе, или на github или pastebin? Я подозреваю, что некоторые из наших предикторов имеют ошибки. Возможно, мое :-(
Логика Найт
1
@CarpetPython Простым изменением было бы вычисление расстояния между точками от последнего круга в дополнение к точкам этого раунда.
TheNumberOne

Ответы:

3

Python 2, Sampler

Эта запись основана на том же коде для « Сохраняйте дистанцию», «Запись сэмплера» . Я надеюсь, что это будет лучше здесь, где преимущества 1 и 999 не существуют.

Из списка мест выберите тот, который находится дальше всего от недавно использованных чисел, игнорируя предыдущий ход (поскольку другие записи могут прогнозироваться на основе только предыдущего хода).

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
Логика Найт
источник
Похоже, что этот выигрывает, но это может быть потому, что я неправильно компилирую контроллер, а остальные все рушатся.
KSFT
2

Номер OnePlusFourNineNine, Java

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

Логика действительно проста. Если кто-то не найдет реальный алгоритм, который учитывает предыдущие оценки, этот ответ довольно оптимизирован.

Теперь, когда мы посчитаем расстояние по кругу, максимальное расстояние любых двух точек может быть 500. Теперь, если бы все записи генерировали случайные числа (или псевдослучайные по некоторому алгоритму), этот ответ не имел бы никакого преимущества вообще , Но есть по крайней мере 1 запись, которая дает постоянный ответ, почти максимальное расстояние. При этом счет набирает 500 баллов, поскольку в каждом раунде есть фиксированный источник максимальной дистанции :)

оптимизатор
источник
Вы оптимизировали мой ответ. ;)
TheNumberOne
@TheBestOne хаха
Оптимизатор
2

Древнеисторический - питон

Это тот же алгоритм из предыдущего, за исключением того, что при расчете потенциальных баллов он использует круговое расстояние. Поскольку я ужасно проигрываю и не могу заставить контроллер скомпилироваться, я просто пробую новую стратегию, в которой я использую худшее из предыдущих раундов.

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
источник
Это не работает iявляется элементом scores.split(' '), то есть это строка, а не int.
KSFT
@KSFT Ох, я действительно должен был проверить, обновление.
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)

Туристы все еще побеждают. Дайте мне знать, если у вас есть предложения по этому поводу.

KSFT
источник
2

FindCampers - Python 2

Найдите всех отдыхающих за последние 10 раундов и держитесь подальше от них. Я надеюсь, что предикторы убегут от меня. Теперь я буду игнорировать мой старый выбор.

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
источник
Ооо ... Я надеялся, что это пойдет к отдыхающим, когда я увидел имя ...
KSFT
Лол. Я мог бы добавить запись, которая будет саботировать отдыхающих.
Jmac
К сожалению, я позволил только одну запись на человека.
KSFT
Я только что опубликовал запись о саботаже отдыхающих.
KSFT
Мой не работает, потому что я не понимал, что предыдущие результаты были отсортированы. Как ваши обнаруживают отдыхающих?
KSFT
1

Номер один, Java

Первый ответ. Скопировано из моего предыдущего ответа .

public static int choose(int round, int players, String[] args) {
    return 1;
}
Номер один
источник
Кто-то, кажется, отклонил все ответы.
KSFT
1

WowThisGameIsSoDeep, Java

Я анализировал игру в течение 10 лет на кластере с 1 миллионным ядром и нашел оптимальное решение.

public static int choose(int round, int players,String[]spam) { return(int)(Math.random()*1e3); }
feersum
источник
Это не код-гольф
Оптимизатор
5
Это решение не является оптимальным. Если вы хотите равномерного распределения, вы должны использовать Random.nextInt(int).
Питер Тейлор
Это, кажется, всегда возвращает 1.
KSFT
@KSFT Я проверил это и получил много разных номеров. Может быть, это саботаж в конце концов?
Feersum
4
Ага! Я починил это! Я случайно набрал «WowThisGameIsSoDeep.py», и он пытался запустить его как файл Python.
KSFT
1

Цилинейный Экстраполятор, Рубин

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
источник
Это дает эту ошибку:NoMethodError: undefined method `split' for #<Array:0x720f56e2> choose at CircilinearExtrapolator.rb:2
KSFT
О, previous_choicesэто массив значений как ["1 6 500","2 8 503"]?
гистократ
Это. Вы думали, что это было что-то еще? Если нет, то я, наверное, просто что-то напутал.
KSFT
Я думал, что это была просто плоская струна, извините. Я отредактирую
гистократ
Ред. Теперь все знают, что я опубликовал что-то без проверки ...
Гистократ