Падіння хаосу (побудова мінімально аперіодичної послідовності)


9

Ідея тут полягає у створенні майже повторюваного шаблону. Тобто, послідовність, що будується, змінюється в останній момент, щоб уникнути повторення деякої послідовності. Необхідно уникати наслідків типу AA та ABA (де B не більше A).

Приклади:

Я продовжу з початку, перерахувавши всі невеликі приклади, щоб зробити свій опис яснішим. Почнемо з 0.

Дійсно: 0

Недійсний: 00 (візерунок AA)
Дійсно: 01

Недійсний: 010 (візерунок ABA)
Недійсний: 011 (шаблон АА)
Дійсно: 012

Дійсна: 0120
Недійсний: 0121 (шаблон ABA)
Недійсний: 0122 (візерунок AA)

Недійсний: 01200 (візерунок AA)
Недійсний: 01201 (візерунок ABA; 01-2-01)
Недійсний: 01202 (візерунок ABA)
Дійсна: 01203

Тепер я твердо вірю, що 4ніколи не потрібно, хоча я не маю доказів, тому що я легко знайшов послідовності сотень символів довгими, які використовують лише 0123. (Це, мабуть, тісно пов’язано з тим, як потрібні лише три символи, щоб мати нескінченні рядки, що не мають жодного шаблону AA. На цьому є сторінка Вікіпедії .)

Введення-виведення

Введення - це єдине, додатне, ненульове ціле число n. Ви можете припустити, що n <= 1000.

Вихід - nпослідовність -характер без підзакон, що відповідають забороненому шаблону (AA або ABA).

Зразкові входи та виходи

>>> 1
0

>>> 2
01

>>> 3
012

>>> 4
0120

>>> 5
01203

>>> 50
01203102130123103201302103120132102301203102132012

Правила

  • Допускаються лише символи 0123.
  • Чи не Б не довше ніж , ніж А. Це дозволяє уникнути ситуації , при якій 012345повинен бути слідують , 6тому що 0123451є це: 1-2345-1. Іншими словами, послідовність була б тривіальною і нецікавою.
  • nможе бути введено будь-яким потрібним методом, крім жорсткого кодування.
  • Вихід може бути списком або рядком, залежно від того, що простіше.
  • Без грубої сили ; час роботи повинен бути на порядку хвилин, не більше години на дійсно повільній машині, протягом n=1000. (Це покликане дискваліфікувати рішення, які просто проходять цикл через nвселінійні перестановки {0,1,2,3}, так що трюк та подібні трюки заборонені.)
  • Стандартні лазівки заборонено, як зазвичай.
  • Оцінка балів у байтах. Це є, тому виграє найкоротший запис (можливо - див. бонус).
  • Бонус: виберіть найнижчу дозволену цифру на кожному кроці. Якщо 1і 3можливі варіанти для наступної цифри в послідовності, виберіть 1. Відніміть 5 байт від вашої оцінки. Однак візьміть на замітку нижче.

Примітка!

Можливі тупики. Ваша програма чи функція повинні уникати цього. Ось приклад:

Пень: 012031021301231032013021031201321023012031021320123021031201302310320123021320310230120321023120130210312301320310213012032102301320312302103201231021301203102303302303302303302303302303303302303
Пень: 012031021301231032013021031201321023012031021320123021031201302310320123021320310230120321023120130210312301320310213012032102301320312302103201231021301203103302303303303302303303302303303302303
Пень: 01203102130123103201302103120132102301203102132012302103120130231032012302132031023012032102312013021031230132031021301203210230132031230210320123102130120310330230330330230330230330230330230
Пень: 01203102130123103201302103120132102301203102132012302103120130231032012302132031023012032102312013021031230132031021301203210230132031230210320123102130120310330230330230330230330230330230330230330230330230

Кожну з цих послідовностей не можна більше продовжувати (без використання a 4). Але також зауважте, що між першими та другими двома є вирішальна різниця. Я заміню спільну початкову підданість на, Xщоб зробити це більш зрозумілим.

Пень: X2130120
Пень: X2130123
Пень: X320
Пень: X321301203102130

Останні дві цифри Xє 10, тому єдиним можливим вибором для наступної цифри є 2і 3. Вибір 2призводить до ситуації, коли послідовність повинна припинятися. Тут не спрацює жадібний алгоритм . (Все одно не без зворотних трекінгу.)


Чи можна використовувати грубу стратегію тестування кожної можливої ​​струни, навіть якщо вона не дасть результату в реалістичний час? Чи знаєте ви, що може бути рішення для всіх n? Якщо хтось дає евристичний напівжадливий алгоритм, як ви переконаєтесь, що він не стикається з проблемами дуже великої довжини? Загальна проблема є цікавою, і мені не вдалося знайти нічого щодо уникнення шаблону, де ми обмежуємо довжину частини шаблону. Якщо хтось може підготувати загальний рецепт, я очікую, що це найкращий підхід.
xnor

Я вважаю, що я заборонив грубу силу в правилах. Я, мабуть, мушу це виділити. У мене немає доказів того, що існує рішення для всіх n, але враховуючи, що пні, які моя програма знаходить, як правило, збільшуються в середньому на 10 цифр щоразу, я дуже впевнений, що існує нескінченна послідовність. Я не впевнений, як напівжадний алгоритм можна перевірити на довільно великі послідовності. Я можу обмежити вимогу до n= 1000 і просто не турбуватися про вище n.
El'endia Starman

4
Я гадаю, AAце справді тип, ABAде Bпорожньо. Це, можливо, може допомогти впорядкувати деякі рішення.
mathmandan

Відповіді:


6

Сітківка , 86 байт - 5 = 81

$
_
(r`^(?<-2>.)+_((.)+)\b$
$1!
\b$
0
3#
#
0#
1
1#
2
2#
3
)r`\1(?<-2>.)*((.)+)$
$0#
!
<empty>

Де <empty>представлений порожній проміжний рядок. Ви можете запустити вищезазначений код з одного файлу з -sпрапором.

Вхід повинен бути наданий уніар , напр 111111. Я ще не перевіряв його на вихід на замовлення тисяч - два з регулярних виразів через деякий час можуть трохи повільніше - але за кілька секунд він може легко обробити пару сотень.

Пояснення

Це просте зворотнє рішення.

  1. Додайте а 0.
  2. Поки поточна послідовність є недійсною, видаліть усі трилімітні тричі та наростіть останні не- 3.
  3. Повторюйте, поки у нас не буде дійсна послідовність потрібної довжини.

Це зворотне відстеження реалізується циклом підстановок регулярних виразів, який перериває, коли рядок залишається незмінним через одну ітерацію.

$
_

Це додає _до входу, який використовується для відділення одинарного введення від послідовності, яку ми будуємо.

(r`^(?<-2>.)+_((.)+)\b$
$1!

Це перша підміна в циклі (вказана ведучою (). Регекс відповідає, якщо: а) в кінці рядка є символ слова (тобто цифра) (що означає, що рядок є дійсним - ми побачимо нижче, що недійсні послідовності позначені проривом #); б) принаймні стільки символів у послідовності, скільки вхідних (це перевіряється за допомогою балансуючих груп ). Якщо це так, ми видаляємо введення та додаємо a !. Це !служить для того, щоб усі реджекси в циклі вийшли з ладу, таким чином, що вони закінчуються.

\b$
0

Якщо в кінці є символ слова (тобто послідовність дійсна, і цикл не був припинений попереднім кроком), додайте a 0.

3#
#

Якщо (замість цього) послідовність була позначена недійсною і закінчилася 3, ми видаляємо її 3(але залишаємо послідовність як недійсну, оскільки немає можливого продовження поточного префікса ... тому наступний символ також повинен бути відкликаний).

0#
1
1#
2
2#
3

Якщо послідовність позначена недійсною і будь-яка цифра, яка 3є в кінці, ми збільшуємо цифру і видаляємо маркер.

)r`\1(?<-2>.)*((.)+)$
$0#

Остання підміна в циклі (як зазначено )). Він перевіряє, чи закінчується рядок у ABA(де Bне довше, Aале потенційно порожнє). Відносні довжини Aі Bзнову перевіряються за допомогою балансуючих груп, а повторення Aперевіряється простою референцією.

Якщо ця регулярна виразка збігається, додаємо послідовність недійсною шляхом додавання #.

!
<empty>

Як тільки цикл закінчується, все, що нам потрібно зробити, - це видалити !і потім залишити потрібний вихід.


2

Python 2, 175 - 5 = 170 байт

n=input();s='';u=j=-1
while n>len(s):
 while u>2:u=int(s[0]);s=s[1:]
 u+=1;t=`u`+s;m=c=0
 while t[c:]*0**m:c+=1;i=t[c:].find(t[:c]);m=j<i<=c
 if c>=len(t):s=t;u=j
print s[::j]

Це жадібний алгоритм із зворотним відстеженням. Я б хотів, щоб це було коротше. Я сподіваюся, що це правильно (див. Нижче).

Він будує рядок по одній цифрі за часом. Враховуючи рядок dцифр, який він вже знайшов, він намагається додати a у 0вигляді (d+1)st цифри. Якщо це не працює, то він намагається a 1, тоді a 2, a 3. Якщо жодне з цих не працює, то він повертається до dдесятої цифри і збільшує його (якщо менше 3) або видаляє (якщо дорівнює 3, в такому випадку збільшує попередній і т.д.).

Перевірка на валідність - це рядок із .findнею. У випадку, якщо хтось вирішить прочитати мій код, я повинен сказати, що ця програма насправді зберігає рядок назад, це означає, що вона додає цифри на передню частину . Таким чином, перевірка передбачає пошук місць, де перші c цифри з’являються пізніше в рядку (в будь-якому місці після перших cцифр), і якщо є такі місця, чи є інтервалом довжина максимум c.

(Звичайно, перед друком обертається рядок.)

Це також може бути швидше; Спочатку я мав можливість вийти з різних циклів рано для ефективності, але це коштувало дорогоцінних байтів. Хоча це все одно добре в діапазоні n=1000.

У будь-якому випадку, здається, програма виявляє перевагу до менших цифр, але це не дуже сильна перевага. Наприклад, запустивши його, n=2000дав мені рядок із 523нулями, 502одиницями, 497двіями та 478трійками, що закінчуються на 30210312013021. Тож якщо хтось інший працює над жадібним алгоритмом, можливо, він може підтвердити цей результат. Або n=1000я отримав [263, 251, 248, 238]для підрахунків цифрами.

Нарешті, я хотів би зазначити, що ці підрахунки є начебто натяком на симетрію, майже (хоча і не зовсім так), як якщо б ми почали з рівномірного розподілу, а потім перетворили частину 3"на 0", а кілька 2"на 1" с. Але очевидно, що це може бути просто збігом. Я поняття не маю!


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.