«Зручний паліндром»


39

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

Рядок зручно паліндромним, якщо він дорівнює рядку, отриманому, коли в його звороті є всі круглі дужки ( ()), дужки ( []) і дужки ( {}). Жоден інший символ не є спеціальним і не потребує гортання. ( <>іноді в парі, але часто не так, що їх залишають осторонь.)

Ваше завдання полягає в тому, щоб написати своєю мовою програму (приймаючи вклад на STDIN) або функцію (взявши аргумент єдиного рядка), яка (а) дає послідовне істинне значення *, коли його аргумент зручно паліндромний і інший, послідовно хибний значення інакше, і (b) є самим зручно паліндромним.

Наприклад, такі входи зручно паліндромними:

racecar
(a)(bb)(a)
void main(int argc, *char[] argv) {} (vgra []rahc* ,cgra tni)niam diov

А такі не:

non-palindrome
A nut for a jar of tuna?
(old [style] parens) )snerap ]elyts[ dlo(
ingirumimusnocte)etconsumimurigni

Ви не можете покладатися на будь-який зовнішній стан (конкретне ім'я файлу, структуру каталогів, інший ввід користувача, доступ до Інтернету тощо), крім прапорців інтерпретатора / компілятора.

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

{some code} // {edoc emos}
{some code} NB.BN {edoc emos}
"n\" ;{edoc emos} ;"; {some code}; "\n"

Очевидно, що це може охоплювати не кожен подібний випадок, але дух виклику тут полягає не у використанні коментарів та нерозбірливого коду ** для досягнення паліндромності, а замість того, щоб використовувати виправлені парени та дужки. Я дивлюся на тебе, LISP, Brainfuck.

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

* Під послідовними істинними та хибними значеннями я маю на увазі, що ви можете повернути одне з парних значень, наприклад 1для істинного та 0хибного, або Falseдля істинного та "no"хибного, доки ці значення відрізняються один від одного, і не перехід від запуску до запуску програми. Використовуйте те, що рятує вас персонажів.

** Не плутати з невиконаним : код, який є дійсним і може робити дивні речі, але ніколи не називається, це добре.


Що з речами на зразок if(false){some code}або невикористаними змінними? Вони дозволені?
ace_HongKongIndependence

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

58
Мені знадобилося занадто довго, щоб зрозуміти, чому ()()це не паліндром
Відновіть Моніку

Чи має код працювати з багаторядковим введенням?
Вентеро

@Ventero Newlines та повернення каретки - це символи, і у них немає пар, з якими можна перевернутись, тому я б сказав, що вони вважаються нормальними символами.
алгоритм

Відповіді:


13

J (60)

(|.-:'())([]][{}}{'&charsub) :: (busrahc&'}{{}][[])(()':-.|)

Це функція, яка бере аргумент:

   (|.-:'())([]][{}}{'&charsub) :: (busrahc&'}{{}][[])(()':-.|) 'ingirumimusnocte)etconsumimurigni'
0
   (|.-:'())([]][{}}{'&charsub) :: (busrahc&'}{{}][[])(()':-.|) '(a)(bb)(a)'
1

Пояснення:

  • f :: gзапускає функцію fнад входом і повертає результат, якщо він повертається без помилок. Якщо fне вдається, він gзамість цього працює .

  • fТут (|.-:'())([]][{}}{'&charsub), який робить фактичну роботу:

    • |.: реверс
    • -:: дорівнює
    • '())([]][{}}{'&charsub: заміна кожної дужки на її протилежну дужку
  • gФункція (busrahc&'}{{}][[])(()':-.|), яка є нонсенсом , але синтаксичний правильним. busrahcне визначено, але це не має значення, оскільки воно вирішується лише тоді, коли він запускається (і він не запускається).

Ви можете зберегти персонажа, перетворивши його f :: gна g@-@f. gеквівалент гака, (-.|)тому :виходи стають -1 і порожній список для зручно паліндромних, а не відповідно.
алгоритм

34

GolfScript, 107 91

.4:ab-1:ba=;1
%ba%{...fi@@=
c43.=;)('"([{
}])"'~?~'"([{
}])"')(;=.34c
=@@if...}%ab%
1;=ab:1-ba:4.

Новинки художні. fi, c43і cє noops, але весь код виконується.

Друкує -3-1-1зручні паліндроми, -4-1-1інакше. Спробуйте в Інтернеті!

Альтернативна версія, 155 байт

Ціною 64 байти це можна покращити:

0!*1{!}\;:);0:f;0:i;-1:ab;9:ba;
...=;1%ab%{....i@f@@fi@@=@.=@\)
+""'"([{}])"'~+?+~'"([{}])"'""+
(\@=.@=@@if@@f@i....}%ba%1;=...
;ab:9;ba:1-;i:0;f:0;(:;\{!}1*!0

Як і раніше, весь код виконується, і кожен байт впливає на вихід.

Друкує 010зручні паліндроми, -100інакше. Спробуйте в Інтернеті!

Тести та приклади

$ base64 > palindrome.gs -d <<< LjQ6YWItMTpiYT07MSViYSV7Li4uZmlAQD1jNDMuPTspKCciKFt7fV0pIid+P34nIihbe31dKSInKSg7PS4zNGM9QEBpZi4uLn0lYWIlMTs9YWI6MS1iYTo0Lg==
$ wc -c palindrome.gs
91 palindrome.gs
$ rev palindrome.gs | tr '([{}])' ')]}{[(' | diff - palindrome.gs
$ echo -n 'r(a[c{"e"}c]a)r' | golfscript palindrome.gs
-3-1-1
$ echo -n 'totallynotapalindrome' | golfscript palindrome.gs
-4-1-1
$
$ base64 > pal.gs -d <<< MCEqMXshfVw7Oik7MDpmOzA6aTstMTphYjs5OmJhOy4uLj07MSVhYiV7Li4uLmlAZkBAZmlAQD1ALj1AXCkrIiInIihbe31dKSInfis/K34nIihbe31dKSInIiIrKFxAPS5APUBAaWZAQGZAaS4uLi59JWJhJTE7PS4uLjthYjo5O2JhOjEtO2k6MDtmOjA7KDo7XHshfTEqITA=
$ wc -c pal.gs
155 pal.gs
$ rev pal.gs | tr '([{}])' ')]}{[(' | diff - pal.gs
$ echo -n 'r(a[c{"e"}c]a)r' | golfscript pal.gs
010
$ echo -n 'totallynotapalindrome' | golfscript pal.gs
-100
$ for i in {1..154}; do head -c $i pal.gs > tmp.gs; tail -c +$[i+2] pal.gs >> tmp.gs
> [ "$(echo -n 'r(a[c{"e"}c]a)r' | golfscript tmp.gs 2> /dev/null)" = "010" ] && echo $i
> done; rm tmp.gs
1
for i in {1..154}; do head -c $i pal.gs > tmp.gs; tail -c +$[i+2] pal.gs >> tmp.gs
>  [ "$(echo -n '42' | golfscript tmp.gs 2> /dev/null)" = "-100" ] && echo $i
> done | grep '^1$'; rm tmp.gs

Як це працює

.             # Duplicate the input string.
4:ab-1:ba     # Save 4 in “ab” and -1 in “ba”.
=;            # Compare 4 to -1 and discard the result.
1%            # Save every element from the input string in a new string.
ab%           # Reverse the input string.
{             # For each character in the input string:
  ...         # Duplicate the character thrice.
  fi          # Variable “fi” is undefined; this does nothing.
  @@=         # Verify that the character is equal to itself; push 1.
  c43         # Variable “c43” is undefined; this does nothing.
  .=;         # Verify that 1 is equal to itself and discard the result.
  )(          # Increment and decrement the character.
  '"([{}])"'~ # Push that string and evaluate it. Result: '([{}])'
  ?           # Retrieve the character's position in '([{}])'. -1 means not found.
  ~           # Negate the position.. Examples: -1 -> 0    0 -> -1    2 -> -3
  '"([{}])"') # Push that string and pop its last element. Result: '"([{}])' 34
  (;          # Decrement 34 (the ASCII code of a double quote) and discard.
  =           # Retrieve the corresponding character.
  .34         # Duplicate the character and push 34.
  c           # Variable “c” is undefined; this does nothing.
  =           # If the character is a double quote, the index was -1.
  @@if        # In that case, replace the double quote with the original character.
  ...         # Duplicate the new character thrice.
}%            #
ab%           # Save every fourth element in a new string to discard dummy values.
1;            # Push 1 and discard.
=             # Push 1 if the modified string matches the original, 0 otherwise.
ab:1-         # Save 4 in “1” and subtract.
ba:4.         # Save -1 in “4” and duplicate.

0!*           # Pop and push the input string.
1{!}\;:);     # Make “)” an alias for “!”.
0:f;0:i;      # Variables.
-1:ab;9:ba;   # Moar variables.
...=;         # Duplicate the input string.
1%ab%         # Reverse the copy.
{             # For each character in the input string:
  ....        # Duplicate the character four times.
  i@          # Push 0 and rotate a string copy on top of it.
  f@@fi@@     # Push 0 and rotate 0 on top of it.
  =@          # Push 1 and rotate a string copy on top of it.
  .=@         # Push 1 and rotate 1 on top of it.
  \)+         # Negate a 1 and add. Result: 1
  ""          # Push that string.
  '"([{}])"'  # Push that string.
   ~+         # Evaluate the second string and concatenate. Result: '([{}])'
   ?          # Retrieve the characters position in '([{}])'. -1 means not found.
   +~         # Add 1 to the position and negate. Ex.: -1 -> -1 | 0 -> -2 | 1 -> -3
  '"([{}])"'  # Push that string.
  ""          # Push that string.
  +           # Concatenate. Result: '"([{}])"' 
  (\          # Pop the first double quote and swap it with the rest of the string.
  @=.         # Retrieve the corresponding character and duplicate it.
  @=          # If the character is a double quote, the index was -1.
  @@if        # In that case, replace the double quote with the original character.
  @@          # Rotate the modified character to the bottom.
  f@i....     # Push dummy values.
  }%          #
  ba%         # Save every ninth element in a new string to discard dummy values.
  1;          # Push 1 and discard.
  =           # Push 1 if the modified string matches the original, 0 otherwise.
  ...;        # Duplicate thrice and discard the last copy.
  ab:9;ba:1-; # Variables.
  i:0;f:0;    # Moar variables.
  (:;\        # Negate, override “;” and swap.
  {!}1*!0     # Negate twice and push 0.

13

Рубі, 110

(z=gets;r=z.tr *["([{}])",")]}{[("];p *z==r.reverse;1)||(1;esrever.r==z* p;[")]}{[(","([{}])"]* rt.z=r;steg=z)

Друкує, trueякщо введення є зручним паліндром, а falseякщо ні. Зауважте, що це рішення передбачає, що введення не закінчується новим рядком, тому протестуйте його за допомогою echo -n:

echo -n '(a)(bb)(a)' | ruby convpal.rb
true

echo -n '(a)(bb()a(' | ruby convpal.rb
false

# note that for this to work, the file must not contain a newline
# to remove a trailing newline, pipe it through tr -d $'\n'
cat convpal.rb | ruby convpal.rb
true

Це дещо простий порт моєї відповіді на Palindromic Palindrome Checker (і не дуже гольф поки що). Основна використана хитрість полягає в тому, що перший вираз в дужках завжди повертається 1, тому друга половина булевого виразу ніколи не оцінюється (але вона аналізується).

Єдина складність у адаптації цього полягала в тому, щоб з'ясувати, як додати виклик до z.trтого, щоб його "зручний зворотний бік" також був синтаксично дійсним - але я міг би просто використовувати той самий трюк, який я вже використав: put:, *який у першій половині розбирається як оператор splat (використовувати вміст масиву як параметри функції) та як оператор множення (або повторення) масиву у другій половині.

Рубі, 157 297, весь код виконаний

w=tsoh=gets p
o=rt=esrever=Gem
q=tsoh.tr *["([{}])",")]}{[("]
q==esrever.host=w=tsoh.reverse==q
[")]}{[(","([{}])"]* rt.host=q
meG=reverse=tr=o
p steg=host=w

Ця (трохи довша) версія виконує весь код, і всі, крім двох рядків, впливають на вихід, який друкується в останньому рядку - але всі рядки аналізуються та виконуються без помилок. Ця версія інтерпретує будь-який трейлінг нового рядка як частину введення, тому використовуйте або echo -nдля тестування його, або додайте до введення новий рядок. Він друкує, trueякщо на вході є зручний паліндром та falseінше.

Пояснення

# Read the input by calling gets(nil), which is achieved by passing the return
# value of a call to Kernel#p (which returns nil if no argument is supplied) to
# gets.
w=tsoh=gets p
# Assign the global Gem module to three variables.
# The variable names are the reversed names of methods we have to call later.
# This doesn't necessarily have to be the Gem module, any global module/variable
# (or class that allows object creation through a call to the module itself,
# e.g. Hash or GC) with a writable property would do, but Gem#host was
# the shortest one I could find. This is necessary because Ruby doesn't
# allow setting previously undefined properties through the dot syntax.
o=rt=esrever=Gem
# Replace the parentheses with the corresponding flipped one.
# sserts is the reverse of the property name we're going to use later.
q=tsoh.tr *["([{}])",")]}{[("]
# Do the convinient palindrome check and assign its result to a few variables
# and Gem's host property.
q==esrever.host=w=tsoh.reverse==q
# Here, the * is parsed as array join operator.
[")]}{[(","([{}])"]* rt.host=q
# Nothing special here.
meG=reverse=tr=o
# Print the result of the palindrome check, which was stored in w.
p steg=host=w

9

GolfScript, 61 символ

Гаразд, ось базове рішення в GolfScript. Я впевнений, що це може бути вдосконалено:

{.-1%{"([{}])".2$?~@[.]@+=}%=}~{=%{=+@[.]@~?$2."([{}])"}%1-.}

Як зазвичай для GolfScript, ця програма зчитує свої дані з stdin. Він виводить:

1{=%{=+@[.]@~?$2."([{}])"}%1-.}

якщо вхід є зручним паліндром, як визначено в виклику вище, і:

0{=%{=+@[.]@~?$2."([{}])"}%1-.}

якщо його немає.

Пояснення: Ця програма в значній мірі покладається на постанову про те, що невиконаний код є нормальним, доки він буде проаналізований. Він складається з двох кодових блоків, розділених фігурними дужками ( { }), які є дзеркальними зображеннями один одного.

Перший блок коду виконується ~наступним чином і перевіряє, чи є вхідним зручним паліндром, виводячи, 1чи є, 0чи ні. Другий блок коду не виконується, і так просто залишається на стеці до тих пір, поки програма не закінчиться і все, що знаходиться в стеку, не стане автоматично рафіноване і надруковано інтерпретатором GolfScript.

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

Пс. Дивлячись на фактично виконаний код, він містить кілька зручно паліндромних елементів, таких як @[.]@, рядковий літерал "([{}])"і навіть цикл %{ ... }%. Це дає приворотну думку про те, що "власне паліндромне" рішення GolfScript, де повна паліндромна програма буде виконуватися і функціонувати, може бути реально можливою. Оскільки я ще не встиг сам виготовити його, я пропоную винагороду в розмірі +100 першим, кому вдалося придумати його!


3
зачекайте, ур-код - це сам паліндром? : O
Fabricio

Я схильний розглядати це рішення більше, ніж "n\";X;";X;"\n"-вид коментування, але я скористаюся вами сумнівів. Я справді шукав таких "сутнісно паліндромних" рішень, для початку, принаймні, або, принаймні, тих, де невиконання блоків було дещо недоцільне.
Алгоритм

У моїй відповіді є noop (невизначена змінна) і кілька частин, які нічого не виконують (наприклад, 1;). Це все ще вважається повністю функціональним?
Денніс

@Dennis: Так, я думаю, що так і є. Вітаємо, це, безумовно, досить вражає. Питання, здається, є досить новим, що я ще не можу розмістити щедрість на ньому, але ви отримаєте його через кілька днів.
Ільмарі Каронен

1
формат виводу у світлиці зловживань :-)
Джон Дворак

4

JavaScript (ES6), 245 байт

Я хотів відповіді JS, яку можна запустити у браузері, так ось вона.

eurt=>eurt==(("",eurt))["split"||"nioj"]("")["map"||"esrever"](x=>({'{':'}','}':'{','[':']',']':'[','(':')',')':'('})[x]||x||[x]({')':'(','(':')',']':'[','[':']','}':'{','{':'}'})>=x)["reverse"||"pam"]("")["join"||"tilps"]((true,""))==true>=true

Видаляючи весь код, який ніколи насправді не виконується, ми отримуємо наступне:

eurt=>eurt==(("",eurt))["split"||"nioj"]("")["map"||"esrever"](x=>({'{':'}','}':'{','[':']',']':'[','(':')',')':'('})[x]||x||[x]({')':'(','(':')',']':'[','[':']','}':'{','{':'}'})>=x)["reverse"||"pam"]("")["join"||"tilps"]((true,""))==true>=true
eurt=>eurt==(("",eurt))["split"        ]("")["map"           ](x=>({'{':'}','}':'{','[':']',']':'[','(':')',')':'('})[x]||x                                                           )["reverse"       ]("")["join"         ]((true,""))==true>=true

Що можна спростити до цього:

eurt=>eurt==eurt.split("").map(x=>({'{':'}','}':'{','[':']',']':'[','(':')',')':'('})[x]||x).reverse("").join("")

Ви можете зберегти 60 байтів, використовуючи n1 / 1n замість true / eurt, місцями коми через ||, а також переміщуючись за допомогою перемикача дужок: n1=>n1==(('',n1))['nioj','split']``['esrever','map'](c=>`()[]{}`[`()[]{}`['indexOf'](c)^1]||c||[1^(c)['fOxedni']`{}[]()`]`{}[]()`>=c)['pam','reverse']``['tilps','join']((1n,''))==1n>=1n(185 байт)
Yair Rand

3

Javascript (ES6) 288

Запускається в оболонці командного рядка Spidermonkey . Читає один рядок зі STDIN та виводить trueабо falseзалежно від того, чи є вхідним зручним паліндром.

((print)((eval)('r=readline()')==([0]['map']['call'](r,x=>({'{':'}','}':'{','[':']',']':'[','(':')',')':'('})[x]||x)['reverse']()['join']('')))&&((('')['nioj']()['esrever'](x||[x]({')':'(','(':')',']':'[','[':']','}':'{','{':'}'})>=x,r)['llac']['pam'][0])==('()enildaer=r')(lave))(tnirp))

Цей код синтаксично дійсний, але все після &&цього не виконується, оскільки printфункція повертає значення фальси.

Ви можете запустити цей код у консолі Firefox, спочатку запустивши цю прокладку для імітації readlineта printфункцій. Відредагуйте вхід всередині readline:

readline = function(){ 
    return "void main(int argc, *char[] argv) {} (vgra []rahc* ,cgra tni)niam diov"; 
}, print = console.log.bind(console);

Ось короткий приклад результату:

Приклад командного рядка


Скориставшись &&справді розумним, я вітаю вас (але це здається трохи шахрайським)
MayorMonty

2

05AB1E, 35 байт

"{[()]}"DRr‡`rJ¹Q,Q¹Jr`‡rRD"{[()]}"

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

Пояснення:

                     # Implicit input
 "{[()]}"            # Push "{[()]}" onto the stack
         DR          # Pushes a reversed copy onto the stack
           r         # Reverse the order of the stack
            ‡        # Transliterate
             `       # Flatten array on stack
              r      # Reverse order of stack
               J     # Join stack
                ¹Q   # Check equality with first input
                  ,  # Print
                     # Everything after is still syntactically correct, but just does not print anything.

Я не думаю, що це допоможе, оскільки відповідь недійсна, але замість цього "()[]{}"можна зробитиžu„<>-
acrolith

@daHugLenny Це дійсно зараз
Олівер Ні

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

Виправлено @algorithmshark.
Олівер Ні

1

CJam, 38 байт

Q~"=re%W_@%W_q"`{[()]}`"q_W%@_W%er="~Q

Друкує, "=re%W_@%W_q"1якщо введення зручно паліндромним та "=re%W_@%W_q"0іншим способом.

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

Як це працює

Q~                                     e# Evaluate an empty string.
  "=re%W_@%W_q"                        e# Push that string.
               `                       e# Inspect. Pushes "\"=re%W_@%W_q\"".
                {[()]}                 e# Push that block.
                      `                e# Inspect. Pushes "{[()]}".
                       "           "~  e# Push and evaluate.
                        q              e# Read from STDIN.
                         _W%           e# Push a reversed copy.
                            @          e# Rotate "{[()]}" on top of the stack.
                             _W%       e# Push a reversed copy.
                                er     e# Perform transliteration.
                                  =    e# Compare to the input string.
                                     Q e# Push an empty string.

Після виконання програми CJam автоматично друкує всі три елементи на стеку: перевірену рядок, булеву систему зі порівняння рядків та порожню рядок.


0

Perl, 83 + 2 = 85 байт

Бігайте з -nl

say$_~~reverse y-"({[]})"-")}][{("-r;exit;tixe;r-")}][{("-"({[]})"-y esrever~~_$yas

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

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