Начнем с пустой последовательности с 1 индексом:
_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,...
На n- м шаге мы заполняем все пробелы a (n) целыми числами больше 1, начиная с первого оставшегося пробела, где a (n) - это n- ая запись в последовательности.
После первого шага:
2,_,3,_,4,_,5,_,6,_,7,_,8,_,9,_,10,_,11,_,12,_,13,_,...
Обратите внимание, что a (1) должно быть 2, потому что первое целое число больше 1 равно 2.
На втором шаге мы заполняем каждые a (2) пробелы. Будет очевидно, что a (2) должно быть 2.
2,2,3,_,4,3,5,_,6,4,7,_,8,5,9,_,10,6,11,_,12,7,13,_,...
На третьем шаге мы заполняем каждые a (3) пробелы. Из последовательности а (3) = 3.
2,2,3,2,4,3,5,_,6,4,7,_,8,5,9,3,10,6,11,_,12,7,13,_,...
На четвертом шаге мы заполняем каждые a (4) пробелы. Из последовательности а (4) = 2.
2,2,3,2,4,3,5,2,6,4,7,_,8,5,9,3,10,6,11,3,12,7,13,_,...
В итоге:
2,2,3,2,4,3,5,2,6,4,7,2,8,5,9,3,10,6,11,3,12,7,13,2,...
задача
Дано n, вернуть n- й элемент последовательности.
Первые 10 000 000 членов последовательности можно найти здесь .
Это код-гольф . Кратчайший ответ в байтах побеждает. Применяются стандартные лазейки .
Ответы:
Haskell ,
8067 байтПопробуйте онлайн!
Haskell - идеальный язык для определения бесконечного списка с точки зрения самого себя.
источник
let
охранниками.pattern1 | let pattern2 = expr2 = expr1
означает то же самое, что иpattern1 = let pattern2 = expr2 in expr1
(по той же причине, что[expr1 | let pattern2 = expr2]
означает то же самое, что и[let pattern2 = expr2 in expr1]
).let
паттерны (особенно, что они могут выполнять функции)! Кроме того,m=2:2:2`drop`g m
является байтом короче.(!!)$0:m
на два байта короче.2:2:
материал целиком с немного большей ленью:g ~(a:b)|...
иm=g m
.C, 123 байта
Попробуйте онлайн!
Прохождение
Выделите массив из n целых чисел для хранения первых n элементов последовательности. Это жесткие коды
sizeof(int)
как4
, что является безопасным допущением в большинстве случаев и, безусловно, я хочу сделать в контексте кода гольф. :)Все это счетчики:
i
для индекса шага, на котором мы находимся,j
для циклического прохождения последовательности в поисках пустых мест иk
для подсчета количества пустых мест.Прежде чем мы начнем наш основной цикл, мы пробираемся в инициализации первых двух элементов последовательности к
2
. (p[0]
=*(p + 0)
=*p
.) Это сбрасывает счётk
, хотя, но ...... мы также делаем скрытую инициализацию
k
, которая проверяет,i
меньше ли она,2
и корректирует начальное значение,k
если так. Здесь также начинается внутренний цикл, который повторяется на протяжении всей последовательности на каждом этапе.Эта строка может действительно использовать некоторые объяснения. Мы можем расширить это до:
коротким замыканием, а затем законами де Моргана и тем фактом, что
0
в C ложно:По сути, это гласит: «если это пространство пустое, увеличивайте его
k
. И еслиk
ранее было кратно размеру шага, выполните следующую инструкцию». Следовательно, мы запускаем оператор для каждого элемента размера шага , что в точности соответствует последовательности. Само утверждение просто; все это будет генерировать2
,3
,4
, ....Используя метод tricky-return-without-a-return, с которым
gcc
мы работаем, мы «возвращаем» последний элемент первых n членов в последовательности, который оказывается n- м членом.источник
Pyth, 29 байт
Попробуйте онлайн
Как это работает
Вместо того, чтобы дурачиться со списками, здесь используется простая рекурсивная формула.
источник
Haskell , 67 байт
Попробуйте онлайн!
Рекурсивное арифметическое решение, которое оказалось в основном тем же методом, что и ответ Питера Андерса Касерга .
Этот код покрыт бородавками - уродливыми частями, которые выглядят так, как будто их можно было убрать в гольф, но я не понял, как это сделать.
Функция
i%j
действительно хочет использовать охранник для проверкиmod i(f j)>0
и оценки одного из соответствующих двух выражений. Но оба выражения используютdiv i(f j)
. Обязательство, которое в охране не будет распространяться на обе стороны. Насколько я знаю, охранника нельзя заставить "распространять" на других охранников.let
иwhere
слишком длинные. Итак, код используетlast
для выбора одного из двух выражений, пока охранник связывает переменную. Тьфу.В идеале мы будем использовать,
divMod
потому что обаdiv
иmod
используются, но(d,m)<-divMod ...
это длинное выражение. Вместо этого мы по счастливой случайности проверим, что мод ненулевой, посмотрев, неdiv
превышает ли значение делителя кратное исходному значению.0%j=2
Случае не будет необходимость , если Haskell короткого замыканияdiv 0
, что это не так. В.pred
Преобразует 1-индексированный вход нуля индексированные, или иначе было бы-1
поправки везде.источник
%
1-индексированный, то вам нужно исправить пять байтов - что просто связывает. Тем не менее , вы можете встраиватьf
в%
бесплатно, а затемf
становится анонимным, поэтому вы экономите два байта в целом.f
без потери байтов.divMod
кажется на один байт дешевле, потому что позволяет ветвиться с!!(0^m)
. Пока у меня есть:1%j=2;i%j|(d,m)<-divMod(i-1)$j%1=[(i-d-1)%(j+1),d+2]!!(0^m);(%1)
.pred
.JavaScript (ES6),
989391 байтРекурсивная функция, которая останавливается, как только результат доступен.
Альтернативная версия, 90 байт
Предложил Шегги за -1 байт
Этот должен быть вызван с
f(n)()
. Хотя соответствующий пост в meta в настоящее время дает положительную оценку, этот синтаксис, очевидно, оспаривается.демонстрация
Показать фрагмент кода
источник
n=>g=(p,a=[...Array(n)])=>a[n-1]||g(-~p,a.map(c=>c?c:i?i++%k?c:++v:(i=1,v=2),i=0,k=a[p]||2))
должно работать на 92 байта. Назовите егоf(n)()
.Java 8, 124 байта
Лямбда-выражение.
Создает массив целых чисел и постоянно заполняет его, пока не будет заполнено n-е значение.
Предварительно объявив переменные в верхней части, чтобы сократить как можно больше объявлений, поскольку каждая из них
int
стоит 4 байта пространства, в отличие от добавления,n
которое равно 2.На
j
итерации вычисления число пропусков, которое нужно пропустить, равноa[j]
(или 2, если пусто). Получается, что если первое пустое пространство, которое мы должны заполнить, находится в позицииk
, тоk * a[j]
мы получаем «шаг» (s
).источник