Тримайте відстань по колу


9

Це ґрунтується на цьому виклику та ідеї Geobits / CarpetPython щодо його вдосконалення:

Тримайте дистанцію!

Для цього завдання відстань між двома числами вимірюється на циклі, тому, наприклад, відстань між 0 і 999 дорівнює 1. Це має запобігати стратегіям, як завжди вибору найменшого чи найвищого числа, не вигравати майже кожного разу. Єдиною іншою зміною є те, що найменше число, яке можна вибрати, зараз 0, а не 1.

Я підсумую це тут:

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

Програма управління тут:

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

Таблиця лідерів

Виграє 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, тому дайте мені знати, чи я роблю щось не так.


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 haha
Оптимізатор

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

Це не працює. iє елементом scores.split(' '), тобто це рядок, а не int.
KSFT

@KSFT о стріляй, я справді повинен був перевірити, оновити.
Мальтісен

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)

Кемпери ще виграють. Повідомте мене, чи є у вас якісь пропозиції щодо цього.


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

Aww ... Я сподівався, що це піде назустріч
кемперам,

Лол. Я можу додати запис, який буде саботажу відпочивальників.
Jmac

На жаль, я дозволив лише один запис на людину.
KSFT

Я щойно сам розмістив запис до диверсійних лагерників.
KSFT

Моє не працює, тому що я не розумів, що попередні результати були відсортовані. Як ваші виявляють лагерників?
KSFT


1

WowThisGameIsSoDeep, Java

Я аналізував гру протягом 10 років на 1-мільйонному кластері і знайшов оптимальне рішення.

public static int choose(int round, int players,String[]spam) { return(int)(Math.random()*1e3); }


5
Це рішення не є оптимальним. Якщо ви хочете рівномірного розподілу, вам слід скористатися Random.nextInt(int).
Пітер Тейлор

Здається, це завжди повертається 1.
KSFT

@KSFT Я перевірив це і отримав багато різних цифр. Можливо, це саботаж?
feersum

4
Ага! Я полагодив це! Я випадково набрав "WowThisGameIsSoDeep.py", і він намагався запустити його як файл Python.
KSFT

1

Циркулярний екстраполятор, 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

Це дає цю помилку:NoMethodError: undefined method `split' for #<Array:0x720f56e2> choose at CircilinearExtrapolator.rb:2
KSFT

О, чи previous_choicesє масив значень типу ["1 6 500","2 8 503"]?
гістократ

Це є. Ти думав, що це щось інше? Якщо ні, я, ймовірно, просто переплутав щось із запуском.
KSFT

Я подумав, що це просто плоска струна, вибачте. Я відредагую.
гістократ

Відредаговано. Тепер усі знають, що я щось опублікував, не перевіряючи цього ...
гістократ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.