«Удобный палиндром» шашка

39

Если вы когда-либо пытались написать палиндромный код раньше, вы бы знали, сколько скобок мешает вам. ()()это не палиндром, даже если он выглядит так, как и должно быть, хотя ())(и ()(палиндромен, и оба выглядят очень тупыми. Разве это не было бы удобно, если бы это было наоборот?

Строка обычно является палиндромной, если она равна строке, полученной, когда в ее обращении перевернуты все скобки ( ()), скобки ( []) и фигурные скобки ( {}). Никакие другие символы не являются специальными и требуют переключения. ( <>иногда в паре, но часто не так, они не учтены.)

Ваша задача - написать на вашем языке программу (с вводом в STDIN) или функцию (с одним строковым аргументом), которая (a) дает непротиворечивое истинное значение *, когда ее аргумент удобно палиндромным и другой непротиворечивый ложный значение иначе, и (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, Брейнфак.

Это , поэтому выигрывает самый короткий код, но приветствуется любая длина кода.

* Под последовательными значениями true и false я подразумеваю, что вы можете вернуть одно из пары значений, например, 1для true и 0для false, или Falseдля true и "no"для false, если эти значения отличаются друг от друга и не переход от запуска к запуску вашей программы. Используйте то, что спасает ваших персонажей.

** Не путать с неисполненным : код, который является допустимым и может делать странные вещи, но никогда не вызывается, это хорошо.

algorithmshark
источник
Как насчет таких вещей, как if(false){some code}или неиспользуемые переменные? Они разрешены?
pastebin.com slash 0mr8spkT
@ace Если ваш язык каким-то образом анализирует или проверяет неисполненный код на соответствие типу или синтаксическую достоверность, это нормально. Если это равносильно комментарию, потому что ваш язык не проверяет внутреннюю часть этого блока, когда он выдаст синтаксическую ошибку, если это произойдет, это не хорошо. Я думаю, что если вы можете найти правильное применение (eslaf)fi, вы можете использовать if(false).
алгоритмическая
58
Мне потребовалось слишком много времени, чтобы понять, почему ()()не палиндром,
говорит Дэвид Восстановить Монику
Должен ли код работать с многострочным вводом?
Вентеро
@Ventero Символы новой строки и возврата каретки являются символами, и у них нет пар, которые можно перевернуть, поэтому я бы сказал, что они считаются обычными символами.
алгоритмическая

Ответы:

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являются Без операционное, но весь код выполняется.

Отпечатки -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его «удобный реверс» также был синтаксически верным - но я мог бы просто использовать тот же трюк, который я уже использовал, путы:, *который в первой половине анализируется как оператор сплат (используйте содержимое массива в качестве параметров функции) и оператор умножения (или повторения) массива во второй половине.

Рубин, 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
Ventero
источник
9

GolfScript, 61 символ

Хорошо, вот базовое решение в GolfScript. Я уверен, что это может быть улучшено:

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

Как обычно для GolfScript, эта программа считывает свой ввод со стандартного ввода. Это выводит:

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

если ввод является удобным палиндромом, как определено в задании выше, и:

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

если это не так.

Объяснение: Эта программа в значительной степени опирается на решение о том, что неисполненный код в порядке, если он анализируется. Он состоит из двух блоков кода, разделенных фигурными скобками ( { }), которые являются зеркальным отображением друг друга.

Первый блок кода выполняется ~следующим за ним и проверяет, является ли ввод удобным палиндромом, и выводит, 1если он есть, а 0если нет. Второй кодовый блок не выполняется, и поэтому он просто остается в стеке до тех пор, пока программа не завершится, и все в стеке не будет автоматически структурировано и напечатано интерпретатором GolfScript.

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

Ps. Если посмотреть на исполняемый код, он содержит несколько удобных палиндромных элементов, таких @[.]@как строковый литерал "([{}])"и даже цикл %{ ... }%. Это дает соблазнительное предположение о том, что «внутренне палиндромное» решение GolfScript, где бы полная палиндромная программа была бы выполнена и работало, могло бы быть действительно возможным. Так как я сам пока не смог его изготовить, я предлагаю вознаграждение +100 повторений первому человеку, которому удастся его создать!

Илмари Каронен
источник
3
подождите, ваш код сам по себе является палиндромом? : O
Fabricio
Я склонен считать это решение больше похожим на "n\";X;";X;"\n"комментирование, но я дам вам преимущество сомнения. Однако я действительно искал такие «изначально палиндромные» решения или, по крайней мере, те, где невыполнение блоков было немного более скрытным.
алгоритмистика
В моем ответе есть noop (неопределенная переменная) и несколько частей, которые ничего не делают (например, 1;). Это все еще считается полностью функциональным?
Деннис
@ Денис: Да, я думаю, что это так. Поздравляю, это, безусловно, достаточно впечатляет. Вопрос кажется достаточно новым, так что я пока не могу опубликовать награду за него, но вы получите его через несколько дней.
Ильмари Каронен
1
формат вывода leeway abuuuse :-)
Джон Дворжак
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("")
ETHproductions
источник
Вы можете сэкономить около 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функция возвращает значение Falsey.

Вы можете запустить этот код в консоли Firefox, запустив эту подкладку первую эмулировать readlineи printфункцию. Отредактируйте вход внутри readlineпри необходимости:

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

И вот быстрый пример вывода:

пример командной строки

nderscore
источник
Воспользоваться &&было действительно умно, я рекомендую вам (но это кажется немного обманчивым)
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„<>-
акролит
@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;пропустил код, он все равно вывел бы результат правильно, прежде чем он потерпел крах.

Габриэль Бенами
источник