Verificador “conveniente palíndromo”


39

Se você já tentou escrever código palindrômico antes, saberia quantos colchetes tendem a atrapalhar. ()()não é um palíndromo, embora kinda parece que deve ser, ao mesmo tempo ())(e ()(são ambos palíndromo e ambos muito burra procurando. Não seria conveniente se fosse o contrário?

Uma string é convenientemente palíndrica se for igual à string derivada quando seu reverso tiver todos os seus parênteses ( ()), colchetes ( []) e chaves ( {}) invertidos. Nenhum outro caractere é especial e requer inversão. ( <>às vezes são emparelhados, mas geralmente não são excluídos.)

Sua tarefa é escrever, em seu idioma, um programa (com entrada no STDIN) ou uma função (com um argumento de cadeia única) que (a) forneça um valor verdadeiro consistente * quando seu argumento for convenientemente palindrômico e um falso diferente e consistente valor caso contrário, e (b) é ele próprio convenientemente palindrômico.

Por exemplo, as seguintes entradas são convenientemente palíndricas:

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

E o seguinte não é:

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

Você não pode confiar em nenhum estado externo (nome do arquivo específico, estrutura de diretórios, outras entradas do usuário, acesso à web etc.), exceto sinalizadores de interpretador / compilador.

Além disso, você não pode usar o "truque de comentários" em que comenta ou processa um pedaço de código não utilizado, aproveitando os recursos de comentários do seu idioma. Por exemplo, todos os itens a seguir não são permitidos, porque contêm peças não funcionais que podem ser removidas ou destruídas com segurança (às custas da perda conveniente de palindrômico):

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

Obviamente, isso pode não abranger todos os casos, mas o espírito do desafio aqui não é usar comentários e código não analisado ** para obter palindrominess, em vez disso, usar os parênteses e parênteses corrigidos. Estou olhando para você, LISP, Brainfuck.

Este é um , portanto o código mais curto vence, mas todos os comprimentos de código são bem-vindos.

* Por valores verdadeiros e falsos consistentes, quero dizer que você pode retornar um de um par de valores, como 1verdadeiro e 0falso, ou Falseverdadeiro e "no"falso, desde que esses valores sejam diferentes um do outro e não mude de execução para execução do seu programa. Use o que salvar seus personagens.

** Não deve ser confundido com não executado : código válido e que pode fazer coisas estranhas, mas nunca chamado, é bom.


E quanto a coisas como if(false){some code}variáveis ​​não utilizadas? Eles são permitidos?
pastebin.com cortar 0mr8spkT

@ace Se o seu idioma, de alguma forma, analisa ou verifica o código não executado quanto a contrato de tipo ou validade sintática, tudo bem. Se isso equivale a um comentário, porque o seu idioma não verifica o interior desse bloco, quando isso geraria um erro de sintaxe, isso não é bom. Eu acho que se você pode encontrar um uso válido para (eslaf)fi, você começa a usar if(false).
algorithmshark

58
Levei muito tempo para descobrir por que ()()não é um palíndromo
David diz Reinstate Monica

O código precisa funcionar com entrada de várias linhas?
Ventero 20/05

@Ventero As novas linhas e os retornos de carro são caracteres, e eles não têm pares para trocar, então eu diria que eles contam como caracteres normais.
algorithmshark

Respostas:


13

J (60)

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

Esta é uma função que aceita um argumento:

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

Explicação:

  • f :: gexecuta a função fsobre a entrada e retorna o resultado se retornar sem erro. Se ffalhar, ele será executado g.

  • O faqui é (|.-:'())([]][{}}{'&charsub), que faz o trabalho real:

    • |.: marcha ré
    • -:: é igual a
    • '())([]][{}}{'&charsub: substituindo cada suporte pelo suporte oposto
  • A gfunção é (busrahc&'}{{}][[])(()':-.|)absurda, mas sintaticamente válida. busrahcnão está definido, mas isso não importa, porque só é resolvido quando é executado (e não é executado).

Você pode salvar um personagem transformando-o f :: gem g@-@f. gé equivalente ao gancho, (-.|)por :isso as saídas se tornam -1 e a lista vazia para convenientemente palíndrico e não, respectivamente.
algorithmshark

34

GolfScript, 107 91

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

Novas linhas são artísticas. fi, c43e csão noops, mas o código inteiro é executado.

Imprime -3-1-1para palíndromos convenientes, -4-1-1caso contrário. Experimente online!

Versão alternativa, 155 bytes

Ao custo de 64 bytes, isso pode ser aprimorado em:

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

Como antes, o código inteiro é executado e cada byte afeta a saída.

Imprime 010para palíndromos convenientes, -100caso contrário. Experimente online!

Testes e exemplos

$ 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

Como funciona

.             # 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

Ruby, 110

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

Imprime truese a entrada for um palíndromo conveniente e falsese não for. Observe que esta solução pressupõe que a entrada não seja finalizada por uma nova linha; portanto, teste-a comecho -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

Esta é uma porta um tanto direta da minha resposta ao Palindromic Palindrome Checker (e ainda não jogamos golfe). O principal truque usado é que a primeira expressão entre parênteses sempre retorne 1; portanto, a segunda metade da expressão booleana nunca é avaliada (mas é analisada).

A única dificuldade em adaptar isso foi descobrir como adicionar a chamada ao z.tr que seu "conveniente inverso" também fosse sintaticamente válido - mas eu poderia simplesmente usar o mesmo truque que já usei: - *, que no primeiro semestre é analisado como operador splat (use o conteúdo da matriz como parâmetros de função) e como operador de multiplicação (ou repetição) da matriz na segunda metade.

Ruby, 157 297, todo o código executado

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

Essa versão (um pouco mais longa) executa todo o código e todas as linhas, exceto duas, afetam a saída, que é impressa na última linha - mas todas as linhas são analisadas e executadas sem erros. Esta versão interpreta qualquer nova linha à direita como parte da entrada; portanto, use-a echo -npara testá-la ou acrescente uma entrada à sua nova linha. Imprime truese a entrada for um palíndromo conveniente ou falsenão.

Explicação

# 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 caracteres

OK, aqui está uma solução de linha de base no GolfScript. Tenho certeza de que poderia ser melhorado ainda mais:

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

Como de costume no GolfScript, este programa lê sua entrada do stdin. Emite:

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

se a entrada for um palíndromo conveniente, conforme definido no desafio acima, e:

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

Se não é.

Explicação: Este programa depende fortemente da decisão de que o código não executado está OK, desde que seja analisado. Consiste em dois blocos de código, delimitados por chaves ( { }), que são imagens espelhadas uma da outra.

O primeiro bloco de código é executado pelo ~seguinte e verifica se a entrada é um palíndromo conveniente, produzindo 1se é e 0se não é. O segundo bloco de código não é executado e, portanto, simplesmente permanece na pilha até que o programa termine e tudo na pilha seja automaticamente codificado e impresso pelo intérprete GolfScript.

Deve-se notar que o intérprete GolfScript faz muito poucas verificações de sintaxe no momento da análise (ou nunca, nesse caso); um literal de bloco de código GolfScript pode conter quase qualquer coisa, mesmo que possa travar quando executado. Ainda assim, alguns erros de sintaxe, como literais de cadeia não terminada, geram um erro mesmo em código não executado, então acredito que essa solução (apenas) se enquadra nas regras.

Ps. Observando o código real executado, ele contém alguns elementos convenientemente palindrômicos, como @[.]@a string literal "([{}])"e até o loop %{ ... }%. Isso oferece a sugestão tentadora de que uma solução GolfScript "intrinsecamente palindrômica", onde o programa palindrômico completo seria executado e funcional, seja realmente possível. Como ainda não consegui produzir um, ofereço uma recompensa de +100 representantes à primeira pessoa que conseguir criar um!


3
espere, seu código é um palíndromo? : O
Fabricio

Estou inclinado a considerar esta solução mais como a "n\";X;";X;"\n"espécie de comentar, mas darei a você o benefício da dúvida. Eu estava realmente procurando essas soluções "intrinsecamente palindrômicas" para começar, no entanto, ou pelo menos aquelas em que a não execução de blocos era um pouco mais discreta.
algorithmshark

Minha resposta tem um noop (variável indefinida) e algumas partes que não realizam nada (por exemplo, 1;). Isso ainda conta como totalmente funcional?
Dennis

@ Dennis: Sim, acho que sim. Parabéns, é certamente impressionante o suficiente. A pergunta parece ser nova o suficiente para que eu não possa postar a recompensa ainda, mas você a receberá em alguns dias.
Ilmari Karonen

1
saída formato margem de manobra abuuuse :-)
John Dvorak

4

JavaScript (ES6), 245 bytes

Eu queria uma resposta JS que pudesse ser executada no navegador, então aqui está.

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

Removendo todo o código que nunca é realmente executado, obtemos o seguinte:

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

O que pode ser simplificado para isso:

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

Você pode salvar cerca de 60 bytes usando n1 / 1n em vez de true / eurt, vírgulas em alguns lugares em vez de || e mexendo no alternador de colchetes: n1=>n1==(('',n1))['nioj','split']``['esrever','map'](c=>`()[]{}`[`()[]{}`['indexOf'](c)^1]||c||[1^(c)['fOxedni']`{}[]()`]`{}[]()`>=c)['pam','reverse']``['tilps','join']((1n,''))==1n>=1n(185 bytes)
Yair Rand

3

Javascript (ES6) 288

Executa no shell da linha de comando Spidermonkey . Lê uma única linha de STDIN e produz trueou falsedepende se a entrada é um palíndromo conveniente.

((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))

Este código é sintaticamente válido, mas tudo depois &&não é executado, pois a printfunção retorna um valor de falsey.

Você pode executar esse código no console do Firefox executando este calço primeiro para emular as funções readlinee print. Edite a entrada dentro readlineconforme necessário:

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

E aqui está um exemplo rápido da saída:

exemplo de linha de comando


Aproveitar &&foi realmente inteligente, recomendo-lhe (mas parece um pouco caro) #
MayorMonty

2

05AB1E, 35 bytes

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

Experimente online!

Explicação:

                     # 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.

Eu não acho que isso vai ajudar uma vez que a resposta é inválida, mas em vez de "()[]{}"você pode fazeržu„<>-
acrolith

@daHugLenny É válido agora
Oliver Ni

O restante do programa é qanalisado pelo menos quanto à validade sintática? Caso contrário, consideraria o mesmo que comentar a segunda metade do código.
algorithmshark

@algorithmshark Fixed.
Oliver Ni

1

CJam, 38 bytes

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

Imprime "=re%W_@%W_q"1se a entrada for convenientemente palíndrica ou "=re%W_@%W_q"0não.

Experimente online no intérprete CJam .

Como funciona

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.

Depois de executar o programa, o CJam imprime automaticamente todos os três itens na pilha: a sequência inspecionada, o Booleano da comparação de sequências e a sequência vazia.


0

Perl, 83 + 2 = 85 bytes

Correr com -nl

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

O código sai após a impressão da veracidade da entrada. Tudo após o ponto-e-vírgula é interpretado (e trava quando o script chega a esse ponto, não fosse pelos exitencontros), mas não executado. Se eu deixasse de exit;tixe;fora o código, ele ainda imprimiria o resultado corretamente antes de travar.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.