Контекст:
Миллиардер-затворник создал игровое шоу для привлечения лучших и самых ярких программистов мира. По понедельникам в полночь он выбирает одного человека из числа претендентов на участие в неделе и предоставляет им игру. Вы счастливчик на этой неделе!
Игра на этой неделе:
Хост предоставляет API-доступ к стопке из 10 000 цифровых конвертов. Эти конверты сортируются случайным образом и содержат внутри себя долларовую стоимость от 1 до 10000 долларов (никакие два конверта не содержат одинаковую долларовую стоимость).
В вашем распоряжении 3 команды:
Чтение (): чтение цифры доллара в конверте в верхней части стопки.
Возьмите (): добавьте долларовую цифру в конверте в свой кошелек для игрового шоу и вытяните конверт из стопки.
Pass (): выскочить из конверта на вершине стека.
Правила:
Если вы используете Pass () на конверте, деньги внутри будут потеряны навсегда.
Если вы используете Take () на конверте, содержащем $ X, с этого момента вы никогда не сможете использовать Take () на конверте, содержащем <$ X. Take () на одном из этих конвертов добавит $ 0 к вашему кошельку.
Напишите алгоритм, который заканчивает игру с максимальной суммой денег.
Если вы пишете решение на Python, не стесняйтесь использовать этот контроллер для проверки алгоритмов, предоставлено @Maltysen: https://gist.github.com/Maltysen/5a4a33691cd603e9aeca
Если вы используете контроллер, вы не сможете получить доступ к глобальным переменным, вы можете использовать только 3 предоставленные команды API и локальные переменные области действия. (@Beta Decay)
Примечания: «Максимальный» в этом случае означает медиану в вашем кошельке после N> 50 пробежек. Я ожидаю, хотя я бы хотел оказаться ошибочным, что медианное значение для данного алгоритма будет сходиться при увеличении N до бесконечности. Не стесняйтесь пытаться максимизировать среднее значение вместо этого, но у меня есть ощущение, что среднее значение, скорее всего, будет отброшено небольшим N, чем медиана.
Изменить: изменил количество конвертов до 10 КБ для упрощения обработки и сделал Take () более явным.
Изменить 2: условие приза было удалено, в свете этого поста на мета.
Текущие рекорды:
PhiNotPi - $ 805 479
Рето Коради - $ 803 960
Деннис - 770 272 долл. США (пересмотрено)
Алекс Л. - 714 962 $ (пересмотренный)
источник
Ответы:
CJam,
87143$, 700424$ 720327$ 727580$ 770272Эта программа имитирует всю игру несколько раз и вычисляет медиану.
Как бегать
Я набрал 100001 тестов:
Подходить
Для каждого конверта мы делаем следующее:
Оцените сумму денег, которая неизбежно будет потеряна, взяв конверт.
Если R - это содержание, а M - это максимум, который был взят, сумма может быть оценена как R (R-1) / 2 - M (M + 1) / 2 , что дает деньги всем конвертам с содержанием X в интервал (M, R) содержит.
Если конверты еще не были переданы, оценка будет идеальной.
Рассчитайте сумму денег, которая неизбежно будет потеряна, передавая конверт.
Это просто деньги, которые содержит конверт.
Проверьте, не является ли отношение обоих менее 110 + 0,016E , где E - количество оставшихся конвертов (не считая конверты, которые больше не могут быть взяты).
Если так, бери. В противном случае, пройти.
источник
Python,
$ 680646 ,$ 714,962Принимает все большие и большие суммы в размере от 125 до 190 долларов. Побежал с N = 10000 и получил медиану $ 714962. Эти размеры шагов получены методом проб и ошибок и, конечно, не являются оптимальными.
Полный код, включая модифицированную версию контроллера @ Maltysen, которая печатает гистограмму во время работы:
Адрес BitCoin: 1CBzYPCFFBW1FX9sBTmNYUJyMxMcmL4BZ7
Ух ОП доставлено! Спасибо @LivingInformation!
источник
max_taken
в своем собственном коде, поскольку он не является частью официального API игры. Но это тривиально.read()
,take()
иpass()
методы Опубликованная кода, поскольку те являются «3 команды в вашем распоряжении» , основанный на определении вопроса.С ++, 803 960 долл. США
Отмеченный результат - медиана из 10 001 игр.
источник
C ++, ~ 815 000 долларов
Основывается на решении Рето Коради, но переключается на более сложный алгоритм, когда остается 100 (действительных) конвертов, перемешивая случайные перестановки и вычисляя наиболее тяжелую возрастающую их подпоследовательность. Он будет сравнивать результаты взятия и не взятия конверта и жадно выберет лучший выбор.
источник
Ява, $ 806 899
Это из испытания 2501 раундов. Я все еще работаю над оптимизацией. Я написал два класса, обертку и плеер. Оболочка создает экземпляр игрока с количеством конвертов (для реальных вещей всегда 10000), а затем вызывает метод
takeQ
со значением верхнего конверта. Игрок затем возвращается,true
если они его принимают,false
если они его пропускают.игрок
обертка
Более подробное объяснение скоро появится, когда я закончу оптимизацию.
Основная идея заключается в том, чтобы иметь возможность оценить вознаграждение за игру в заданном наборе конвертов. Если текущий набор конвертов {2,4,5,7,8,9}, а верхний конверт - 5, то есть две возможности:
Если мы вычислим ожидаемое вознаграждение {7,8,9} и сравним его с ожидаемым вознаграждением {2,4,7,8,9}, мы сможем определить, стоит ли брать 5.
Теперь вопрос, учитывая набор конвертов типа {2,4,7,8,9}, какова ожидаемая стоимость? Я обнаружил, что ожидаемое значение кажется пропорциональным общей сумме денег в наборе, но обратно пропорционально квадратному корню из числа конвертов, на которые делятся деньги. Это произошло из-за «идеальной» игры в несколько небольших игр, в которых все конверты имеют почти одинаковую ценность.
Следующая проблема заключается в том, как определить « эффективное количество конвертов». Во всех случаях количество конвертов точно известно, отслеживая то, что вы видели и делали. Что-то вроде {234,235,236} определенно состоит из трех конвертов, {231,232,233,234,235} определенно равно 5, но {1,2,234,235,236} должно действительно считаться как 3, а не 5 конвертов, потому что 1 и 2 почти бесполезны, и вы никогда не пропустите на 234, поэтому позже вы могли бы взять 1 или 2. У меня была идея использовать энтропию Шеннона для определения эффективного числа конвертов.
Я нацелил свои расчеты на ситуации, когда значения конверта равномерно распределены по некоторому интервалу, что и происходит во время игры. Если я беру {2,4,7,8,9} и рассматриваю это как распределение вероятностей, его энтропия равна 1,50242. Затем я
exp()
получаю 4.49254 как эффективное количество конвертов.Расчетное вознаграждение от {2,4,7,8,9} составляет
30 * 4.4925^-0.5 * 4/3 = 18.87
Точное число есть
18.1167
.Это не точная оценка, но я действительно горжусь тем, насколько хорошо это подходит для данных, когда конверты равномерно распределены по интервалу. Я не уверен в правильном множителе (сейчас я использую 4/3), но вот таблица данных, исключая множитель.
Линейная регрессия между ожидаемым и фактическим дает значение R ^ 2 0,999994 .
Мой следующий шаг по улучшению этого ответа - улучшить оценку, когда количество конвертов начинает уменьшаться, то есть когда конверты распределены примерно неравномерно и когда проблема начинает становиться гранулированной.
Изменить: Если это считается достойным биткойнов, я только что получил адрес по адресу(Это было здесь с того момента, когда автор конкурса раздавал призы.)1PZ65cXxUEEcGwd7E8i7g6qmvLDGqZ5JWg
. Благодарность!источник