Ще одне рішення
Це, на мій погляд, одна з найцікавіших проблем на сайті. Мені потрібно подякувати мертвому коду за те, що він повернувся до вершини.
^((^|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 є експоненціальним, багато в чому таким же чином , що похідна e x дорівнює самій собі. Найпростіша дискретна функція, для якої 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))*$
Тут я змінив b на 6 і c на 2 , які мають той самий продукт, що і вищезазначені значення. Важливо, щоб добуток не змінювався, оскільки · b · c ·… керує функцією постійної різниці, яка для поліному шостого порядку D f 6 . Присутні два атома ініціалізації: один для ініціалізації D f до 2 , як при n 4 , а інший для ініціалізації п’ятої різницевої функції до 360 , одночасно додаючи відсутні два з b .