Вы катаетесь на каноэ по довольно быстрой реке Уайтуотер. Внезапно ваши весла взрываются, и вы попадаете в опасную ситуацию, быстро несущуюся по реке без каких-либо весел. К счастью, у вас все еще есть свои навыки программирования, поэтому вы решили вырезать программу на байдарке, чтобы помочь вам пережить пороги. Однако на стороне каноэ недостаточно места для написания вашей программы, поэтому вы должны сделать программу максимально короткой.
Река может быть представлена в виде сетки 8 на 16. Мы будем маркировать столбцы с номерами 0
до 7
и строк с номерами 0
к 15
.
y
--------15
--------14
--------13
--------12
--------11
--------10
--------9
--------8
--------7
--------6
--------5
--------4
--------3
--------2
--------1
--------0
01234567
x
Вверху: совершенно спокойная, обычная река без препятствий. Естественно, это не та река, на которой вы находитесь.
Вы начинаете с координаты (4, 0) и оттуда неконтролируемо двигаетесь вверх по реке (т.е. к вектору (0,1)
), пока не натолкнетесь на скалу (обозначенную o
в этих примерах как). Когда вы попадаете в камень, у вас будет 55% шанс пройти мимо камня влево (т.е. вектор (-1,1)
) и 45% шанс пройти мимо камня вправо (то есть вектор (1,1)
). Если каноэ находится в крайнем левом или правом столбцах, оно всегда будет двигаться к центру. Если нет камней, он будет двигаться прямо вверх.
y
----x---15
----xo--14
-o--x---13
----x---12
---ox---11
---x----10
---xo---9
---ox---8
----xo--7
-----x--6
----ox--5
-o--x---4
----x---3
----xo--2
----x---1
----x---0
01234567
Вверху: возможный маршрут, по которому может идти каноэ, представленный персонажем x
Учитывая карту реки, напишите программу, которая выведет вероятность окончания каноэ в данном столбце.
Принимайте ввод любым удобным для вашей программы способом (например, STDIN, аргумент командной строки raw_input()
, чтение из файла и т. Д.). Первая часть ввода представляет собой одно целое число от 0 до 7, представляющее столбец, для которого программа найдет вероятность. После этого приведен список кортежей в форме, x,y
представляющей положение камней.
Пример:
Входные данные:
4 4,1 5,5 3,5
Это указало бы на реку с камнями в позициях (4,1), (5,5) и (3,5), и спрашивает о вероятности окончания каноэ в 4-м столбце.
Выход:
0.495
Обратите внимание, что в этом примере положение пород было симметричным, что позволило решить проблему с биномиальным распределением. Это не всегда так!
Также река всегда будет проходимой. То есть никогда не будет двух камней, которые расположены рядом друг с другом по горизонтали. См . Комментарий Гленна для примера невозможного случая.
Это код гольф, поэтому выигрывает меньшее количество персонажей. Не стесняйтесь задавать вопросы в комментариях, если спецификация не ясна.
Ответы:
GolfScript, 105 символов
Версия GolfScript, которая стала намного длиннее, чем предполагалось, но каждая попытка с другим подходом была еще длиннее. Ввод должен быть дан на STDIN.
Пример:
Аннотированный код:
источник
Рубин,
204191172 персонажаОн рекурсивно моделирует все возможные результаты, отслеживая вероятность каждого отдельного результата, а затем добавляет эту вероятность к совокупному счетчику, когда
y == 15
.Необычные трюки:
c,*r=gets.split
- оператор «splat» (*
) берет все оставшиеся элементыgets.split
и помещает их вr
массивnext {something} if {condition}
: по существу эквивалентно«Обнаружен» путем эволюции отif condition; something; return; end
кreturn something if condition
кbreak something if condition
, и тогда я решил, что попробую более короткий «оператор цикла», чтобы посмотреть, сработает ли он (что, конечно, и так).Спасибо @ MartinBüttner за предложение использовать цепные троичные операторы (которые в итоге превратились в огромную третью строку в приведенном выше коде игры в гольф) и исключить вышеуказанный пункт (который сохранил 19 (!) Символов).
Я использовал несколько причудливый трюк с этим: я понял, что
s[foo],s[bar]
в Ruby это не работает для двух вызовов метода в одном выражении. Так что сначала я изменил его(_=s[foo],s[bar])
(переменный фиктивный), но потом я понял , что я мог бы просто добавить и выбросить возвращаемые значения:s[foo]+s[bar]
. Это работает только потому, что вызовыs
будут только «возвращать» другие вызовыs
или номер (o[x]+=p
), поэтому мне не нужно беспокоиться о проверкеnil
.Другие различные оптимизации:
p
вместо того,puts
чтобы печатать числа,<1
вместо==0
(поскольку каноэ никогда не покидает реку) и аналогичных сравнений где-либо еще,[0]*8
для начальных вероятностей, поскольку числа Руби всегда «передаются по значению»Ungolfed:
источник
next X if Y
во вложенные троичные операторы? Хорошая находка, тем не менее, вы можете добавить его к советам Ruby!C #
418364 байтаЗавершите программу на C #, ожидая ввода от STDIN. Работает, считывая камни в массив всех мест в реке, эффективно создавая карту, а затем выполняет 16 итераций перемещения вероятностей вокруг десятичного массива шириной 8, прежде чем выводить результат.
Форматированный код:
источник
for(;j-->0;)
). Вы можете избавиться от пары символов, заменив последнегоC.WriteLine
наC.Write
. Также, если вы используетеfloat
вместоdecimal
вас, вы можете сохранить еще пару байтов.decimal
потомуfloat
что не будет точным, но десятичные должны делать для этих проблем, но, вероятно, может сойти с рук, как вы говорите. Я вставлю,C.Write
если мне удастся еще поиграть в гольф, поскольку это, вероятно, ближе к спецификации, чем,C.WriteLine
поскольку я не думаю, что 4 байта требуют редактирования для этой программы размера;)Haskell, 256 байт
Вот очень неряшливая версия вместе с некоторыми уловками, которые были использованы:
Последним трюком, который я использовал, было отметить, что вы можете действовать так, как будто камни в одном ряду на самом деле разделены каким-то бесконечно малым количеством. Другими словами, вы можете применять преобразователь распределения вероятностей для каждой породы в одной и той же строке последовательно и в любом порядке, а не применять их все одновременно. Это работает только потому, что проблема не позволяет двум горизонтально смежным камням.
Таким образом, программа превращает местоположение каждого камня в трансформатор распределения вероятности, упорядоченный по координате y камня. Затем трансформаторы просто упорядочиваются и применяются к начальному распределению вероятностей. И это все!
источник
Perl 169 байт
Читает из STDIN.
Довольно прямолинейно, неявно использует столбцы -1 и 8 для сглаживания границ. Вероятности можно безопасно распространять на каждый следующий уровень, потому что нет соседних камней, поэтому достаточно одного прогона.
источник
PHP, 358
Использовать интеллектуальные возможности для определения возможных путей и их вероятностей сложно, и, вероятно, потребуется больше кода, чем просто симуляция 1 000 000 аварий на каноэ. О, человечество!
Пример:
Golfed:
Эта версия не выполняет красивую печать и выводит вероятность плавания на каноэ в указанной позиции.
источник
PHP, 274
Я не могу читать / писать GolfScript, чтобы спасти мою жизнь, но, глядя на представление @ Говарда, он направил меня в лучшем направлении, чем простая имитация 1 миллиона каноэ.
Начиная с массива вероятностей для стартовых позиций, мы можем просто разделить эти числа каждый раз, когда встречается камень.
Пример вывода:
Golfed:
Пример выполнения:
источник
Хаскелл, 237
Я просто надеюсь, что каноэ идет с установленным GHC ...
Уловка с бесконечным списком украдена у Мэтта Нунана, слава ему!
Я надеюсь, что я понял правильную логику, но пример Мэтта
"5 4,4 1,5 5,3 3,6 2,9 4,12 3,13"
уступает,0.5613750000000001
а пример OP"4 4,1 5,5 3,5"
дает0.49500000000000005
, что представляется правильным за исключением некоторых ошибок с плавающей точкой.Вот оно в действии:
источник