Створення Brainf *** NOPs


26

Іноді під час написання кодів для епізоду ви відчуваєте необхідність зробити його довше, ніж потрібно для заохочення налагодження. Ви можете це зробити, просто занурившись ><, але що це весело? Вам знадобиться щось довше і менше NOPey, щоб заплутати когось, хто читає ваш код.

Швидке знайомство з Brainfuck

Brainfuck - це езотерична мова програмування, створена в 1993 році Урбаном Мюллером, і відома своїм надзвичайним мінімалізмом. (Вікіпедія)

Brainfuck є мова , заснований на восьми команд: +-><,.[]. Код виконується на зразок машини Тюрінга: нескінченної стрічки, на якій можна змінювати значення. У цьому виклику ми зупинимося на перших чотирьох:

+    increment the value at the pointer
-    decrement the value at the pointer
>    move the pointer right
<    move the pointer left

Brainfuck НОП

NOP «мозговий ебать» - це послідовність персонажів, які виконуються мозком, які, виконуючись з будь-якого стану, не призводять до зміни стану. Вони складаються з чотирьох згаданих вище символів.

Змагання

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

Вхідні дані

Ви отримаєте як вхідне негативне парне ціле число n. (Непарні NOP неможливі n.)

Вихідні дані

Ви виведете випадковий NOP на довжину n.

Правила

  • Визначення NOP: коли вихід програми вставляється в будь-якій точці програми, що не є мозком, поведінка зазначеної програми не повинно жодним чином змінюватися. Іншими словами, він не повинен змінювати стан перекладача.
    • Зауважте, що, наприклад +>-<, невірно, оскільки він змінює значення двох комірок, не змінюючи їх назад. Будь ласка, протестуйте своє рішення для цього перед публікацією.
    • Також зауважте, що +>-<->+<це NOP, який не можна звести ні до чого, просто видаливши >< <> +- -+. Таким чином, ви не можете використовувати алгоритм, який просто вставляє їх всередину один одного.
  • Кожен дійсний NOP довжини nповинен мати ненульовий шанс появи у висновку. Однак розподіл не повинен бути рівномірним.
  • Розмовний інтерпретатор, про який йде мова, має подвійну нескінченну стрічку з клітинами довільної точності. Тобто, ви можете піти нескінченно в обидва напрямки, і збільшувати / зменшувати кожну клітинку на невизначений термін.
  • Програма повинна закінчитися протягом 1 хвилини на n= 100 на моїй машині, тому не створювати всіх можливих НОП і вибирати одну.
  • Якщо вам дано недійсне введення (не ціле число, мінус, непарність тощо), ви можете робити все, що завгодно, включаючи збій.

Оцінка балів

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

Приклади

Ось усі дійсні результати для n= 4:

++--    +-+-    +--+    --++    -+-+    -++-
>><<    ><><    ><<>    <<>>    <><>    <>><
><+-    ><-+    <>+-    <>-+
>+-<    >-+<    <+->    <-+>
+><-    -><+    +<>-    -<>+
+-><    -+><    +-<>    -+<>

Ось кілька можливих результатів для n= 20:

+>>->+<->-<<<->>++<<
>+>-<+<->+-<>->+<-<+
+--+-++--++-+--+-++-
>>>>>>>>>+-<<<<<<<<<

18
Ось надуманий НОП, який не використовується так, +-<>як ви просили:a
undergroundmonorail

1
Я не думаю, що існують непрості НОП, тому ви, ймовірно, можете зняти цю кваліфікацію. .має побічний ефект, ,замінює значення, яке неможливо відновити без використання []. Але []в кінцевому підсумку встановлення значення дорівнює нулю. Це також перезаписує значення (тому нам знадобиться інше, []щоб відновити його), якщо ми не можемо бути впевнені, що постраждала клітина для початку була нульовою. Однак нам би довелося шукати таку клітинку з чимось подібним [>], і неможливо надійно повернутися до позиції, з якої ми прийшли.
Мартін Ендер

4
@Eumel "Розмовний перекладач, у якого йде мова, має вдвічі нескінченну стрічку з довільними клітинами точності".
Мартін Ендер

2
Зверніть увагу, що "Brainfuck" більше не дозволений у заголовках питань на системному рівні. Здається, вам вдалося обійти обмеження, використовуючи символи, що не належать до ASCII. В майбутньому, будь ласка, дотримуйтесь цього обмеження.
Олексій А.

2
@undergroundmonorail Ну, це Тюрінг завершений ... тому технічно можна було написати в ньому PRNG так само, як і будь-яка інша мова. (Хоча висівати її може бути важко.)
PurkkaKoodari

Відповіді:


13

CJam, 62 59 байт

Завдяки nhahtdh за збереження 3 байт.

Оскільки немає жодної вимоги до будь-якого конкретного розподілу, доки кожен неопераційний доступ з’являється з обмеженою ймовірністю, ми можемо спростити це багато, просто генеруючи рядок, що містить збалансоване число, -+і <>, відповідно, перевіряючи, чи це NOP, і сортуючи його, якщо він ні.

Звичайно, для більш тривалих входів це майже завжди призведе до відсортованого виводу, але ви можете протестувати код з деяким входом, як 8побачити, що він може в принципі створювати будь-який NOP заданої довжини.

ri_0a*\2/{;"-+<>":L2/mR}%smr:SL["Xa.Xm"3/2e*L]z:sers~0-S$S?

Спробуйте в Інтернеті.


1
Так ... довільна межа повинна була становити n = 1000 менше 10 секунд. Сьогодні комп’ютери - це лише спосіб швидкого посту. ^^ Тому що алгоритмічна відповідь вирішує її за секунду навіть за n = 1000
Falco

Для ще більших n, я думаю, що можна просто сортувати вихід, якщо врівноважений рядок не є NOP. Розподіл страшенно перекошений, але це дозволено питанням.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ це ідеальна ідея.
Мартін Ендер

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Дякую, що тут також зберігається три байти.
Мартін Ендер

16

CJam, 118 116 байт

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

ri2/_)mr:R-"<>"R*mr_'=fm0\{1$+}%+__&e`]:\{mr1aa..+}*\@](\z:~\{~\("+-"*mr1$3$e=[{_,)mr_2$<@@>}*+]@@f{`1$`={(}@?\}W<}/

Перевірте це тут.

Це справляється N = 100майже миттєво. Я не маю часу написати повну розбивку коду зараз, ось ось алгоритм:

  • Створіть випадкову врівноважену рядок <і >з випадковою (парною) довжиною між 0та Nвключно.
  • Встановіть положення головки стрічки в цей масив. Напр. "<>><"Стає [0 '< -1 '> 0 '> 1 '< 0].
  • Отримайте список усіх позицій, досягнутих у процесі.
  • Для кожної такої позиції ініціалізуйте порожній рядок. Визначте також, скільки пар символів залишилось для досягнення рядка довжини N.
  • До кожної пари, що залишилася, додайте +-до рядка випадкової позиції.
  • Перемішайте всі ці рядки.
  • Для кожної позиції визначте, як часто ця позиція зустрічається в розмальованому масиві, і розділіть відповідний рядок на стільки фрагментів (випадкової довжини).
  • У нарізаному масиві замініть входження позиції його випадковими фрагментами.

Зроблено. Це ґрунтується на спостереженні, що:

  • Будь-який НОП повинен мати рівну кількість <і >повертати стрічку в початкове положення.
  • Код буде NOP до тих пір, поки кожна комірка стрічки збільшується так само часто, як і зменшена.

Розподіляючи випадкові, але врівноважені кількості +s і -s між усіма місцями, де головка стрічки знаходиться в даній комірці, ми гарантуємо, що ми знайдемо всі можливі НОП.


4

Математика, 350 байт

Quiet@(For[a="+",If[{##4}=={},#3!=0||Union@#!={0},Switch[#4,"+",#0[ReplacePart[#,#2->#[[#2]]+1],#2,#3,##5],"-",#0[ReplacePart[#,#2->#[[#2]]-1],#2,#3,##5],">",#0[#~Append~0,#2+1,#3+1,##5],"<",If[#2<2,#0[#~Prepend~0,1,#3-1,##5],#0[#,#2-1,#3-1,##5]]]]&@@{{0},1,0}~Join~Characters@a,a=""<>RandomSample@Flatten@RandomChoice[{{"+","-"},{">","<"}},#/2]];a)&

Шлях занадто довгий? Так. Мені навіть байдуже? Тільки поки хтось не опублікує правильну відповідь.


4
Ви б не хотіли додати пояснення, щоб люди насправді могли переконати себе, що це дійсно? :)
Мартін Ендер

Як саме робить цю роботу? Якщо я називаю функцію з номером, вона лише повертається +.
Мартін Ендер

@ MartinBüttner Фіксований ... В даний час, він просто генерує випадкові програми з однаковим числом +- -і <- >пар , поки не трапиться бути NOP. Половину його бере простий перекладач BF.
LegionMammal978

чи це насправді генерує дійсну неоперацію довжиною 100 за менше хвилини?
Мартін Ендер

@ MartinBüttner Так. В середньому я б сказав, що це займає близько 5 секунд. Спочатку я спробував повністю випадкові програми, але він ніколи не припинявся на довжину 100.
LegionMammal978


2

Пітон 3 , 163 байти

from random import*
n=int(input())
p=0;d=[0]*n;a=choices(b'+-<>',k=n)
for c in a:d[p]+=c%2*(44-c);p+=~c%2*(c-61)
if p|any(d):a=n//2*b'+-'
print(*map(chr,a),sep='')

Спробуйте в Інтернеті!

Повна програма, яка друкує результати на STDOUT. Рядок, на якому працює код BF, може бути зіграним.

Прийняв підхід Тийло; якщо згенерований код BF не є NOP, відкиньте його повністю і поверніться до '+-'повторного.


Час очікування для n = 100
l4m2

@ l4m2 Не помітили цієї вимоги. Виправлено.
Bubbler


1

Мова Вольфрама (Mathematica) , 224 байти

(s=RandomSample[##&@@@Table["<"">",(r=RandomInteger)[#/2]]];While[(g=Length@s)<#,s=Insert[s=Insert[s,"+",i=r@g+1],"-",RandomChoice@@Select[GatherBy[0~Range~++g,Count[#,"<"]-Count[#,">"]&@Take[s,#]&],!FreeQ[#,i]&]+1]];""<>s)&

Спробуйте в Інтернеті!

Ось версія для гольфу (а точніше, для гольфу):

Function[{n},
 k = RandomInteger[n/2];
 s = RandomSample[## & @@@ Table["<" ">", k]];
 While[Length[s] < n,
   s = Insert[s, "+", i = RandomInteger[Length[s]] + 1];
   p = GatherBy[Range[0, Length[s]], 
     Count[#, "<"] - Count[#, ">"]& @ Take[s, #]&];
   j = RandomChoice @@ Select[p, ! FreeQ[#, i] &]];
   s = Insert[s, "-", j + 1];
   ];
 ""<>s]

Спочатку ми вибираємо випадкове число <'s і >' s для використання і генеруємо випадковий список з рівним числом кожного.

Щоб заповнити решту символів, ми вибираємо позицію, в яку потрібно додати а +, потім знаходимо позицію, де вказівник вказує на те саме місце і додаємо -туди.

Повторюйте, поки список не має тривалості n, і впорядкуйте результат.

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