Бесконечное слово Фибоначчи является специфическим, бесконечная последовательность двоичных цифр, которые вычисляются путем многократного конкатенации конечных двоичных слов.
Определим , что последовательность слов Фибоначчи типа (или FTW последовательность ) является любая последовательность ⟨W п ⟩ , который формируется следующим образом .
Начните с двух произвольных массивов двоичных цифр. Назовем эти массивы W -1 и W 0 .
Для каждого n> 0 пусть W n ≔ W n-1 ∥ W n-2 , где ∥ обозначает конкатенацию.
Следствием рекурсивного определения является то, что W n всегда является префиксом W n + 1 и, следовательно, всех W k таких, что k> n . В некотором смысле, это означает последовательность ⟨W п ⟩ сходится к бесконечному слову.
Формально, пусть W ∞ - единственный бесконечный массив, такой, что W n является префиксом W ∞ для всех n ≥ 0 .
Мы будем называть любое бесконечное слово, образованное описанным выше процессом, бесконечным FTW .
задача
Напишите программу или функцию, которая принимает два двоичных слова W -1 и W 0 в качестве входных данных и печатает W ∞ , соблюдая следующие дополнительные правила:
Вы можете принять слова в любом порядке; как два массива, массив массивов, две строки, массив строк или одна строка с разделителем по вашему выбору.
Вы можете печатать цифры бесконечного слова либо без разделителя, либо с постоянным разделителем между каждой парой соседних цифр.
Предположим, что вашему коду никогда не будет не хватать памяти и что его типы данных не переполняются.
В частности, это означает, что любой вывод в STDOUT или STDERR, который является результатом сбоя, будет игнорироваться.
Если я запускаю ваш код на моей машине (Intel i7-3770, 16 ГБ ОЗУ, Fedora 21) в течение одной минуты и направляет вывод на него
wc -c
, он должен вывести не менее миллиона цифр W ∞ для (W -1 , W 0 ) = (1, 0) .Применяются стандартные правила игры в гольф .
пример
Пусть W -1 = 1 и W 0 = 0 .
Тогда W 1 = 01 , W 2 = 010 , W 3 = 01001 , W 4 = 01001010 … и W ∞ = 010010100100101001010… .
Это бесконечное слово Фибоначчи.
Контрольные примеры
Все контрольные примеры содержат первые 1000 цифр бесконечного FTW.
Input: 1 0
Output: 0100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001
Input: 0 01
Output: 0100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001
Input: 11 000
Output: 0001100000011000110000001100000011000110000001100011000000110000001100011000000110000001100011000000110001100000011000000110001100000011000110000001100000011000110000001100000011000110000001100011000000110000001100011000000110000001100011000000110001100000011000000110001100000011000110000001100000011000110000001100000011000110000001100011000000110000001100011000000110001100000011000000110001100000011000000110001100000011000110000001100000011000110000001100000011000110000001100011000000110000001100011000000110001100000011000000110001100000011000000110001100000011000110000001100000011000110000001100000011000110000001100011000000110000001100011000000110001100000011000000110001100000011000000110001100000011000110000001100000011000110000001100011000000110000001100011000000110000001100011000000110001100000011000000110001100000011000000110001100000011000110000001100000011000110000001100011000000110000001100011000000110000001100011000000110001100000011000000110001100000011000110000001100000011
Input: 10 010
Output: 0101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001001010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010010100101001001010010100100101001001010010100100101001010010010100100101001010010010100100101001010010010100101001001010010010100101001001010010100100101001001010
Input: 101 110
Output: 1101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101101011101011101101011101101011101011101101011101011101101011101
Ответы:
Pyth, 8 байт
Ввод в форме
"W-1", "W0"
.Доказательство завершения:
Доказательство правильности:
Вот серия как внутренне сгенерированная. Он печатается в конкатенации программой.
Сравните со следующим, напечатанным в конкатенации, который является просто строкой, добавленной к предыдущей строке на каждом шаге:
Мы хотим доказать, что они эквивалентны.
Очевидно, они одинаковы в течение первых нескольких шагов. Давайте сравним их немного позже:
Мы видим, что пары строк поочередно имеют форму:
Где a и b - произвольные последовательности на 0 и 1. Давайте немного продолжим последовательность, чтобы доказать, что она продолжается навсегда по индукции:
2 шага спустя, он имеет правильную форму.
2 шага спустя, он имеет правильную форму.
Таким образом, по индукции строки всегда совпадают после объединения.
источник
W0
с печати, аW1
не печатаетW-1 || W0
, а печатает , что является «неправильным» порядком объединения. Я думаю, что это работает, чтобы быть эквивалентным, но я не представил доказательства ...Haskell, 15 байт
Инфиксная функция
%
создает бесконечную строку, которую Haskell печатает вечно, потому что Haskell такой крутой.Рекурсивная идея похожа на решение Згарба . Написание
f
для функции%
и+
для конкатенации строк, это реализует:Бесконечная выходная строка начинается с
w
, а остаток от нее является результатом для строк со смещением Фибоначчиw
иv+w
.Это не проблема генерировать миллион символов в минуту.
источник
Haskell, 31 байт
Это определяет инфиксную функцию,
#
которая принимает две строки и возвращает бесконечную строку. Использование:Если я запрашиваю миллионный элемент последовательности, определенной «1» и «0», даже онлайн-интерпретатор печатает результат менее чем за секунду:
объяснение
По сути, мы знаем, что
w#v == v#(v++w)
и начинаемw#v
с нихv
, и используем эти факты для определения результата. Поскольку Haskell ленив, это «волшебно» просто работает.источник
Пип, 8 байт
Эй, связан с Пифом!
Простое рекурсивное определение заимствовано из ответа Ханора на xnor . С пробелами, добавленными для ясности:
Каждая программа в Pip является неявной функцией, которая принимает аргументы командной строки в качестве аргументов (назначенных переменным
a
черезe
) и печатает свое возвращаемое значение.O
является оператором, который выводит, а затем возвращает свой операнд, поэтому первое, что здесь происходит, это второй аргумент, который отображается (без завершающего перевода строки).Теперь, вдохновленный Lisp синтаксис
(f x y)
в Pip - это вызов функции, эквивалентныйf(x,y)
в C-подобных языках.f
Переменная относится к текущей функции - в этом случае, программа верхнего уровня. Таким образом, программа рекурсивно вызывает себя сb
иa.b
в качестве новых аргументов.Я был приятно удивлен, обнаружив, что такой подход достаточно быстр:
На моем компьютере с Ubuntu требуется около 30 секунд, чтобы программа достигла максимальной глубины рекурсии, после чего она распечатала где-то более миллиарда цифр.
Это итеративное решение немного быстрее и требует меньше памяти за счет одного байта:
источник
CJam,
1211 байтовЭто займет два слова в отдельных строках, в обратном порядке, например
дает
объяснение
Идея состоит в том, чтобы создать слово наивно (запомнив текущее слово и добавив к нему предыдущее), и пока мы это делаем, мы печатаем все, что только что добавили (чтобы не повторять префикс, который уже был напечатан) , Чтобы избежать необходимости обрабатывать начальную точку отдельно, мы начинаем с пустого слова, так что W 0 - это первое, что мы добавляем (и печатаем).
источник
PowerShell,
9776 байтРедактировать - ммм, выписывание
$e.substring($b.length)
после того , как мы только что соединились,$a
и все$b
равно, что выписать просто$a
соединились ... сумасшедшего.Вау, многословно. По умолчанию PowerShell выдает новую строку каждый раз, когда вы что-то выводите. Действительно, единственный способ обойти это с
write-host -n
(сокращенно-NoNewLine
), и это абсолютно убивает длину здесь.По сути, это повторяет последовательность, создавая
$e
«текущий» W n, как мы идем. Однако, поскольку мы хотим построить бесконечное слово вместо последовательности, мы используем наши предыдущие переменные, чтобы распечатать суффикс,$a
который был заполнен в нашем предыдущем цикле. Затем мы устанавливаем наши переменные для следующего обхода и повторяем цикл. Обратите внимание, что это предполагает, что входные данные будут явно разделены в виде строк, иначе+
оператор будет использоваться для арифметики вместо конкатенации.Пример:
источник
APL,
2418Использование формулировки xnor позволило сбрить несколько персонажей.
На бесконечной машине за бесконечное время она фактически напечатала бы W ∞ трижды - сначала постепенно, во время выполнения цикла, а затем дважды в результате всего выражения, когда
⍣≡
оператор fixpoint наконец возвращается.Это не очень быстро, но достаточно быстро. В GNU APL:
источник
⍣≡
; это звучит очень полезно.Чистая Баш, 58
У меня заканчивается память до 1 минуты, но к тому времени у меня много цифр - через 10 секунд у меня 100 миллионов цифр:
источник
Mathematica, 56 байт
источник
С 76 (ГЦК)
Это довольно простой рекурсивный принтер, реализованный как вложенная функция (расширение GNU C, не поддерживаемое clang), чтобы избежать необходимости
v
обхода.p(n)
печатает W n-2 , где W -1 и W 0 должны быть указаны вv[1]
иv[2]
. Это изначально вызываетp(4)
для печати W 2 . Затем он зацикливается: он вызываетp(3)
печать W 1 , делая полный вывод W 2 W 1 , который равен W 3 . Затем он вызываетp(4)
для печати W 2 , делая полный вывод 4 W и т. Д. Производительность немного лучше, чем мой предыдущий ответ: я вижу 1875034112 значений в минуту.С, 81 (лязг)
Это совершенно другой подход из вышеперечисленного, который, как мне кажется, стоит поддержать, хотя и имеет худшие результаты.
Это имеет все виды неопределенного поведения, в основном для развлечения. Он работает с clang 3.6.2 в Linux и clang 3.5.2 в Cygwin для тестовых случаев, о которых идет речь, со специальными параметрами командной строки или без них. Он не ломается, когда оптимизация включена.
Это не работает с другими компиляторами.
Я принимаю слова в качестве аргументов командной строки в формате строки.
Я использую новую строку в качестве последовательного разделителя.
Я получаю доступ
s
за пределы. Это должно обязательно закончиться segfault или нарушением доступа в некоторый момент.s
случается, что он помещается в конец сегмента данных, поэтому он не должен забивать другие переменные и выдавать неправильный вывод перед этим segfault. С надеждой.При тестировании с использованием
{ ./program 1 0 | tr -d '\n' & sleep 60; kill $!; } | wc -c
я получаю 1816784896 цифр за одну минуту на моей машине, когда программа была скомпилирована-O3
, и 1596678144, когда она была скомпилирована с оптимизацией.Ungolfed, нет UB, с объяснением:
источник
s[]
трюк хорошо работает с Clang (только что установил его). Я очень удивлен, что это на самом деле работает. Предположим, что вашему коду никогда не будет не хватать памяти и что его типы данных не переполняются.К сожалению, это означает, что простая печать W97 не считается действительной. Не могли бы вы позвонитьp
рекурсивно? Это исключило бы необходимостьmain
.p
вp
себя, не добавляя больше кода, но если я найду способ, я снова отредактирую.Javascript (53 байта)
Входные данные должны быть строковыми, а не числовыми (
'0'
и не только0
).источник
Perl 5,
455549 байтов44 байта, плюс 1 для
-E
вместо-e
Используйте как например
Это печатает последовательные приближения к W ∞ и, таким образом, если вы будете ждать достаточно долго, печатает в последней строке вывода, W ∞ на любую желаемую длину, как требуется. Цифры слова объединяются без разделителя.
Так как я на Windows, я проверил его на "по крайней мере один миллион разрядов W ∞ », запустив его с перенаправленным выводом в файл и убив его примерно через 59 секунд, затем запустив GnuWin32.
wc -L
, который напечатал 701408733.Обновить:
ОП пояснил в комментарии к этому ответу (и, вероятно, я должен был все равно понять), что дополнительный вывод, предшествующий W ∞, дисквалифицирует вышесказанное. Итак, вместо этого есть 55-байтовое решение, которое печатает только W ∞ :
Используется так же, но с аргументами в обратном порядке , и не требует
-E
:Несомненно, это может быть дальше, но я не вижу, как это сделать прямо сейчас.
Дальнейшее обновление:
Деннис побрил пять байтов, используя
-a
(таким образом читая,<>
чтобы удалитьsub
) и переназначая параметр, переданныйprint
в концеredo
блока:С
-ane
и чтение из<>
(оба входа в одной строке, через пробел, в обратном порядке); 48 + 2 байта:И, исходя из этого, я побрил еще один байт (так же, как и выше, но теперь входы в правильном порядке); 47 + 2 байта:
источник
REXX , 48
ftw.rex
exec ftw.rex 0 1
В настоящее время не могу проверить производительность, потому что я использовал онлайн-компилятор, чтобы написать его. «Навсегда» можно заменить на любое число, где в качестве напечатанных номеров ftw (число + 2).
Я также написал небольшое (грязное) решение в Прологе. Не знаю, как проверить производительность с этим, но, вероятно, в любом случае это ужасно.
источник
Python 2, 67 байт
Принимает ввод как разделенную запятыми пару строк:
"1","0"
для примера в вопросе.Нет онлайн-переводчика, потому что бесконечные циклы плохие.
Буферизованный вывод заставил меня набрать много байтов. :(Спасибо Деннису за то, что он указал, что 1 цифра в строке действительна.Сроки на моей (значительно более слабой) машине:
источник
Дьялог АПЛ, 9
Этот использует
∇
для определения рекурсивной функции. Это прямой перевод этого xnor's Python 3 ответа . Он принимает W 0 в качестве правого и W -1 в качестве левого аргумента, оба должны быть символьными векторами.источник
Минколанг 0,11 , 62 байта
Попробуй это здесь. Ожидается ввод в порядке W 0 , W -1 с пробелом между ними.
объяснение
Мета-объяснение следующего заключается в том, что на данный момент у нас есть два числа, за которыми следует строка «0» и «1» без разделения. Если длины W 0 и W -1 равны
a
иb
, соответственно, то два числа в начале стека равны<a+b>
и<a>
, в этом порядке. Слово, образованное объединением W i + 1 и W i , то есть W i + 1 + W i , равно 2 * W i + 1 - W i . Таким образом, следующий код дублирует стек (2 * W i + 1 ), выскакивает сверху<a>
элементов (- W я ), а затем заменяет<a+b>
и<a>
со своими преемниками,<a+2b>
и<b>
.источник
Python 3, 32
Та же рекурсивная идея, что и в моем ответе на Haskell , за исключением того, что префикс напечатан, потому что Python не может обрабатывать бесконечные строки.
Использовал трюк из Sp3000 для печати без пробелов, поместив строку в качестве
end
аргумента в Python 3источник
Perl, 32 байта
Считая Шебанг как два, ввод берется из стандартного ввода, пространство отделяется как W 0 , W -1 . Вывод для 1 МБ раз в ~ 15 мс, большинство из которых можно отнести к запуску интерпретатора.
Образец использования
источник
Пролог, 69 байт
Пример ввода: p ('1', '0')
Не удалось удалить лишнюю запись.
Должен быть в состоянии улучшить это, если я пойму, как это сделать.
источник