Предположим, мы определяем бесконечную матрицу M
на N^2 -> {0, 1}
(откуда N
начинается 1
вместо 0
) следующим образом:
M(1, 1)
=0
.Для каждого
x > 1
,M(x, 1)
=1
еслиx
простой, и в0
противном случае.Для каждого
y > 1
,M(1, y)
=y
й член вThue-Morse sequence
.Для каждого
x, y > 1
,M(x, y)
=M(x, y-1) + M(x-1, y) mod 2
.
Верхний левый 16x16
раздел этой матрицы выглядит следующим образом (со x
строками и со y
столбцами):
0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0
1 0 1 1 0 0 0 1 0 0 0 1 1 0 1 1
1 1 0 1 1 1 1 0 0 0 0 1 0 0 1 0
0 1 1 0 1 0 1 1 1 1 1 0 0 0 1 1
1 0 1 1 0 0 1 0 1 0 1 1 1 1 0 1
0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 1
1 1 0 0 0 0 1 0 0 0 1 1 0 0 0 1
0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 1
0 1 0 1 0 1 1 1 1 1 0 0 0 0 0 1
0 1 1 0 0 1 0 1 0 1 1 1 1 1 1 0
1 0 1 1 1 0 0 1 1 0 1 0 1 0 1 1
0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1
1 1 0 0 1 0 1 1 0 1 1 1 0 1 1 0
0 1 1 1 0 0 1 0 0 1 0 1 1 0 1 1
0 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1
0 1 1 0 1 0 0 0 0 1 0 0 1 0 0 1
Ваша задача - построить программу, которая будет оценивать значение произвольной записи в этой матрице с максимально возможной точностью.
Ваша программа будет принимать два целых числа x
и в y
качестве входных данных, в любой выбранной вами форме, и возвращать M(x, y)
, что будет либо либо, 0
либо 1
.
Ваш код может быть написан на любом языке, но не должен превышать 64 килобайт (65 536 байт) размера исходного кода или 2 МБ (2 097 152 байт) общего использования памяти. Ваша программа должна начинаться с пустой памяти (то есть она не может загружать данные откуда-то еще) и запускаться независимо для каждого входа (то есть она может не хранить общие данные для нескольких запусков). Ваша программа также должна быть в состоянии оценить все записи в верхнем левом 8192x8192
квадрате за разумное время.
Программа, которая оценивает большинство записей правильно в верхнем левом 8192 x 8192
квадрате, будет победителем, с более коротким кодом, действующим как тай-брейк.
источник
Ответы:
J -
4238 символовДовольно быстрый, точный на 100% и хорошо вписывается в ограничения памяти.
Стратегия заключается в следующем: мы рассчитаем последовательные антидиагоналы этой матрицы, выполняя попарно XOR для движения вперед и добавляя текущие числа Ту-Морса и простые биты к концам. Затем мы вытаскиваем нужную цифру из антидиагонали, когда попадаем туда.
Объяснение взрывом:
Использование этого глагола
x m y
для M (x, y), как указано в вопросе, гдеm
глагол.Чтобы сохранить нажатия клавиш, мы не пытаемся определить, нужны ли нам еще простые биты или биты Тью-Морса, поэтому мы вычисляем всю антидиагональность, чтобы получить нужный бит. Тем не менее,
8192 m 8192
все еще работает менее чем за 0,07 с и около 100 КиБ на моем скромном ноутбуке.источник
Mathematica - точность 100%,
223193189 байтВот разборчивая версия:
Я в основном заранее вычисляю по диагонали константы
x+y
.Функции:
O(x*y)
.f[8192,8192]
занимает около 400 секунд. Я полагаю, что есть возможности для улучшения (возможно,RotateLeft
может заменить внутренний цикл).Он использует только один массив до
max(x,y)
промежуточных результатов в памяти. Таким образом, нет необходимости использовать более 32 тыс. (При условии 32-разрядных целых чисел) для самого алгоритма (плюс все, что использует Mathematica). Фактически, Mathematica использует 31M в моей системе, но это работает без проблем:источник
O(x*y)
временем, но общее время выполнения увеличивается быстрее. Я не совсем уверен, что происходит. Если бы какой-нибудь Гуру Математики мог просветить меня, какая операция в цикле неO(1)
была бы очень полезной! :) (ну,PrimeQ
иTotal@IntegerDigits
нет, но у меня они были там с самого начала, и они только звонилиO(y)
иO(x)
время соответственно)Matlab: точность 100%, 120 символов, необоснованное время выполнения
Использовать:
источник
M(8192, 8192)
, я не выдержу.Python, 192 символа
Точность 100%, вычисляет M (8192,8192) за ~ 10 секунд на моей машине.
источник
Haskell - 261 байт - 100% - 1MB - я не думаю, что это скоро закончится
Требуется около 10 секунд для
m 16 16
с-O2
, но, как я уже написал, я могу показать это, несмотря на эту проблему:Может быть, какой-то хороший Хаскеллер сможет это оптимизировать?
источник
f p|p=not|0<1=id
должны быть лучше. Кроме того, попробуйте использоватьmorse = False : concat $ iterate [True] (\a -> a ++ map not a)
для увеличения лени. Интересно, как это повлияет на производительность?True
чтобы0<1
иFalse
в0>1
.Perl, 137
Не для «победы» :-), но поскольку здесь еще нет Perl и код был написан в любом случае, вот он.
Занимает несколько секунд, если вызывается
print f(8192,8192)
, сохраняет одну строку матрицы в памяти (массив из 8192 целых чисел (скаляров)), около 3,5 Мб всего процесса Perl. Я попытался сделать это с помощью строки вместо массива (либо с помощью регулярных выражений, либо с помощью substr), занимал меньше памяти и в дальнейшем мог играть в гольф, но работает намного медленнее.Отступ:
источник
Хаскелл, 223
это имеет быстрое время выполнения (5,7 секунд с
-O3
). память еще не проверена, хотя она должна быть линейной.здесь используется алгоритм диагонали, который мы видели раньше.
Что касается скорости, то важны только диагональный алгоритм
-O3
и|foldr seq(0>1)s=0<1
защита, которая делает список строгим. все остальное реализовано довольно неэффективно - первичная проверка выполняется путем проверки всех меньших чисел на деление, элементы последовательности Морса пересчитываются постоянно. но это все еще достаточно быстро :-).источник