Другое решение
Это, на мой взгляд, одна из самых интересных проблем на сайте. Мне нужно поблагодарить deadcode за то, что он поднял его наверх.
^((^|xx)(^|\3\4\4)(^|\4x{12})(^x|\1))*$
39 байтов , без каких-либо условий или утверждений ... вроде. Чередования, поскольку они используются ( ^|
), являются условным способом выбора между «первой итерацией» и «не первой итерацией».
Это регулярное выражение можно увидеть здесь: http://regex101.com/r/qA5pK3/1
И PCRE, и Python правильно интерпретируют регулярное выражение, и оно также было протестировано в Perl до n = 128 , включая n 4 -1 и n 4 +1 .
Определения
Общая методика такая же, как и в других уже опубликованных решениях: определите самоссылающееся выражение, которое на каждой последующей итерации соответствует длине, равной следующему члену прямой разностной функции, D f , с неограниченным квантификатором ( *
). Формальное определение функции прямой разницы:
Кроме того, разностные функции более высокого порядка также могут быть определены:
Или, в более общем плане:
Функция прямой разности имеет много интересных свойств; это для последовательностей то же, что производная для непрерывных функций. Например, D й Апа п - го порядка многочлен всегда будет п-1 - го порядка многочлена, и для любого I , если D е я = D е + 1 , то функция F является экспоненциальным, во многом таким же образом , что производная е х равна себе. Простейшая дискретная функция, для которой f = D f, равна 2 n .
f (n) = n 2
Прежде чем мы рассмотрим вышеупомянутое решение, давайте начнем с чего-то более простого: регулярное выражение, которое соответствует строкам, длина которых представляет собой идеальный квадрат. Изучение функции прямой разницы:
Это означает, что первая итерация должна соответствовать строке длиной 1 , вторая - строке длины 3 , третья - строке длины 5 и т. Д., И, в общем, каждая итерация должна соответствовать строке на два длиннее предыдущей. Соответствующее регулярное выражение следует почти непосредственно из этого утверждения:
^(^x|\1xx)*$
Можно видеть, что первая итерация будет соответствовать только одной x
, а каждая последующая итерация будет соответствовать строке на два длиннее предыдущей, в точности так, как указано. Это также подразумевает удивительно короткий идеальный квадратный тест в Perl:
(1x$_)=~/^(^1|11\1)*$/
Это регулярное выражение может быть дополнительно обобщено, чтобы соответствовать любой n -угольной длине:
Треугольные числа:
^(^x|\1x{1})*$
Квадратные числа:
^(^x|\1x{2})*$
Пятиугольные числа:
^(^x|\1x{3})*$
Шестиугольные числа:
^(^x|\1x{4})*$
и т.п.
f (n) = n 3
Переходя к n 3 , еще раз исследуем функцию прямой разницы:
Как это реализовать, может быть не сразу понятно, поэтому мы также рассмотрим вторую функцию разности:
Таким образом, прямая разность не увеличивается на постоянную, а на линейную величину. Приятно, что начальное (' -1- е') значение D f 2 равно нулю, что сохраняет инициализацию на второй итерации. Полученное регулярное выражение выглядит следующим образом:
^((^|\2x{6})(^x|\1))*$
Первая итерация будет соответствовать 1 , как и раньше, вторая будет соответствовать строке на 6 длиннее ( 7 ), третья будет соответствовать строке 12 длиннее ( 19 ) и т. Д.
f (n) = n 4
Функция прямой разности для n 4 :
Вторая прямая разностная функция:
Третья функция прямой разности:
Теперь это безобразно. Начальные значения для D f 2 и D f 3 являются ненулевыми, 2 и 12 соответственно, что необходимо учитывать. Вы, наверное, уже поняли, что регулярное выражение будет следовать этой схеме:
^((^|\2\3{b})(^|\3x{a})(^x|\1))*$
Поскольку D f 3 должен соответствовать длине 12 на второй итерации, a обязательно равно 12 . Но поскольку он увеличивается на 24 каждого слагаемого, следующее более глубокое вложение должно использовать свое предыдущее значение дважды, подразумевая, что b = 2 . Последнее, что нужно сделать, это инициализировать D f 2 . Поскольку D f 2 напрямую влияет на D f , что в конечном итоге и соответствует, его значение можно инициализировать, вставив соответствующий атом непосредственно в регулярное выражение, в этом случае (^|xx)
. Окончательное регулярное выражение становится:
^((^|xx)(^|\3\4{2})(^|\4x{12})(^x|\1))*$
Высшие заказы
Полином пятого порядка можно сопоставить с помощью следующего регулярного выражения:
^((^|\2\3{c})(^|\3\4{b})(^|\4x{a})(^x|\1))*$
f (n) = n 5 является довольно простым упражнением, поскольку начальные значения для второй и четвертой прямых разностных функций равны нулю:
^((^|\2\3)(^|\3\4{4})(^|\4x{30})(^x|\1))*$
Для полиномов шести порядков:
^((^|\2\3{d})(^|\3\4{c})(^|\4\5{b})(^|\5x{a})(^x|\1))*$
Для полиномов седьмого порядка:
^((^|\2\3{e})(^|\3\4{d})(^|\4\5{c})(^|\5\6{b})(^|\6x{a})(^x|\1))*$
и т.п.
Обратите внимание, что не все полиномы могут быть сопоставлены именно таким образом, если любой из необходимых коэффициентов не является целым числом. Например, n 6 требует, чтобы a = 60 , b = 8 и c = 3/2 . Это можно обойти, в этом случае:
^((^|xx)(^|\3\6\7{2})(^|\4\5)(^|\5\6{2})(^|\6\7{6})(^|\7x{60})(^x|\1))*$
Здесь я изменил б до 6 и c на 2 , которые имеют тот же продукт, что и указанные выше значения. Важно, чтобы произведение не менялось, так как a · b · c ·… контролирует функцию постоянной разности, которая для полинома шестого порядка равна D f 6 . Присутствуют два атома инициализации: один для инициализации D f до 2 , как при n 4 , а другой для инициализации пятой разностной функции до 360 , одновременно добавляя недостающие два из b .