Onde devo colocar meu espelho?

30

Este é um espelho: |. Acabei de descobrir que você pode colar um espelho no meio de uma string se a string puder ser espelhada em si mesma! Por exemplo, a sequência abccba. Se você cortá-lo ao meio, as duas metades são imagens espelhadas uma da outra:

abc  <-->  cba

Então, podemos colocar um espelho no meio da string, e nossa nova string é abc|cba. Às vezes, apenas parte da cadeia pode ser espelhada em si mesma. Por exemplo, a cadeia "espelho". Os dois r's são espelhados, mas o resto da string não é. Tudo bem, apenas removeremos as partes da sequência que não se espelham e obteremos a seguinte sequência:

r|r

Algumas seqüências de caracteres podem ser espelhadas em vários lugares. Por exemplo, "Olá, mundo, xyzzyx". Eu gosto de ter muito texto refletido no meu espelho, então você precisa encontrar o melhor lugar para colocar o meu espelho. Nesse caso, você deve gerar a string espelhada mais longa e, como no nosso último exemplo, remover todo o resto. Essa sequência se torna:

xyz|zyx

Algumas seqüências parecem poder ser espelhadas, mas na verdade não podem. Se uma sequência não puder ser espelhada em nenhum lugar, você não deverá produzir nada.

O desafio:

Dada uma string contendo apenas ascii imprimíveis, encontre o melhor lugar para colocar meu espelho. Em outras palavras,

Encontre a maior substring palindrômica de tamanho uniforme e, em seguida, imprima-a com um caractere de pipe '|' no meio disso.

A entrada terá de 1 a 50 caracteres.

Você pode assumir que a entrada não conterá espelhos |ou novas linhas. Além disso, todos os personagens imprimíveis-ascii são um jogo justo. Se a subseqüência espelhada mais longa estiver ligada entre duas subseqüências, você poderá escolher qual delas produzirá. Por exemplo, para a cadeia "abba ollo", você deve gerar "ab | ba" ou "ol | lo", mas não importa qual deles você produz. As strings diferenciam maiúsculas de minúsculas, por exemplo, "ABba" não deve gerar "AB | ba", deve gerar a string vazia.

IO de amostra:

"Hello World"     --> "l|l"
"Programming Puzzles and Code-Golf"     --> Either "m|m" or "z|z"
"abcba"           --> ""
"Hulluh"          --> "ul|lu"
"abcdefggfedcba"  --> "abcdefg|gfedcba"
"abcdefggfabc"    --> "fg|gf"
"AbbA"            --> "Ab|bA"
"This input is a lot like the last one, but with more characters that don't change the output. AbbA" --> "Ab|bA"

Como de costume, isso é código-golfe, então as brechas padrão se aplicam e a resposta mais curta em bytes vence!

DJMcMayhem
fonte
Existe um limite para o comprimento da entrada?
Mego
@Mego Desde que o seu algoritmo funcione teoricamente em qualquer entrada, não me importo quanto tempo leva / quanta memória é necessária.
DJMcMayhem
Perguntei porque os mecanismos regex baunilha são capazes apenas de combinar palíndromos de comprimento até um valor finito especificado (em oposição aos palíndromos arbitrariamente longos), e a possibilidade de uma solução baseada em regex dependeria da existência ou não de um valor superior limitado ao comprimento da entrada.
Mego
@ Mega Ah, isso faz sentido. Digamos que a entrada possa ter até 50 caracteres. Como isso soa?
DJMcMayhem

Respostas:

9

Pitão - 19 17 15 13 bytes

Obrigado a @FryAmTheEggman por me salvar dois bytes.

ARRGH o caso especial para nenhuma resposta. Resolvido isso!

e_I#jL\|cL2.:

Conjunto de Teste .

e                Last element in list, this works out to longest one
  _I             Invariance under reverse, this detect palindrome
   #             Filter
   jL            Map join
    \|           By "|"
    cL2          Map chop in two pieces
     .:Q)        Substrings. Implicit Q). ) makes it do all substrings.
Maltysen
fonte
2
Nao! Ninja'd para a resposta pyth; _;
Downgoat 04/07/19
Explicação, por favor? : 3
Downgoat 04/07
@Downgoat ele tomou todas as substrings e pique em dois, junte-se cada par com |, filtro por simetria, acréscimo que para [k] e obter o último elemento (que é o mais longo)
busukxuan
@Downgoat done.
Maltysen 04/07/19
2
:Q)= Bignose
gcampbell
8

05AB1E , 19 17 14 bytes

Código:

Œévy2ä'|ý©ÂQi®

Explicação:

Œ                # Get all substrings of the input
 é               # Sort by length (shortest first)
  vy             # For each element...
    2ä           # Split into two pieces
      '|ý        # Join by "|"
         ©       # Copy this into the register
          Â      # Bifurcate, pushing a and reversed a
           Q     # Check if it's a palindrome
            i®   # If so, push that string again
                 # Implicit, the top element is outputted

Usa a codificação CP-1252 . Experimente online! .

Adnan
fonte
5

Python 2, 102 97 bytes

def f(s):h=len(s)/2;r=s[:h]+'|'+s[h:];return s and max(r*(r==r[::-1]),f(s[1:]),f(s[:-1]),key=len)

Bastante lento e ineficiente ... Verifique os casos de teste menores no Ideone .

Dennis
fonte
4

JavaScript, 100 99 bytes

s=>eval('for(O=i=0;s[i++];O=O[j+j]?O:o)for(o="|",j=0;(S=s[i-1-j])&&S==s[i+j++];o=S+o+S);O[1]?O:""')

ou

s=>eval('for(O="",i=0;s[i++];O=O[j+j]||j<2?O:o)for(o="|",j=0;(S=s[i-1-j])&&S==s[i+j++];o=S+o+S);O')
jrich
fonte
Apenas curioso, para que serve eval?
Gcampbell 04/07/19
@gcampbell evalpara evitarreturn
edc65
Você não pode usar o operador de vírgula para evitar o retorno?
MayorMonty
@SpeedyNinja nope. fornão é uma expressão, por isso, normalmente, requerem chaves e umreturn
jrich
3

Lua, 133 bytes

s=...for i=#s,1,-1 do for j=1,#s-i do m=j+i/2-i%2/2t=s:sub(j,m).."|"..s:sub(m+1,i+j)if t==t.reverse(t)then print(t)return end end end

Verifique todos os casos de teste em Ideone.com .

Freira Furada
fonte
1
Use t==t:reverse()para salvar um byte :)
Katenkyo 4/16
2

Retina , 66 bytes

A contagem de bytes assume a codificação ISO 8859-1.

M!&`(.)+(?<-1>\1)+(?(1)¶)
O$#`.+
$.&
A-2`
^(.)+?(?=(?<-1>.)+$)
$&|

Experimente online! (A primeira linha permite testar vários casos de teste separados por avanço de linha de uma só vez.)

Hmmm, muito mais tempo do que eu gostaria ...

Martin Ender
fonte
2

JavaScript (ES6), 91

s=>[...s].map((d,i)=>{for(a='|',j=0;d=s[i-j],d&&d==s[i-~j];r=r[j+++j]?r:a)a=d+a+d},r='')&&r

Menos golfe

f=s=>
  [...s].map(
    (d,i) => {
    for(a='|', j=0; d=s[i-j], d&&d==s[i-~j]; r = r[j++ +j]? r : a)
      a = d+a+d
    }, r=''
  ) && r

Teste

F=
s=>[...s].map((d,i)=>{for(a='|',j=0;d=s[i-j],d&&d==s[i-~j];r=r[j+++j]?r:a)a=d+a+d},r='')&&r

;[["Hello World", "l|l"]
,["Programming Puzzles and Code-Golf", "m|m"]
,["abcba", ""]
,["Hulluh", "ul|lu"]
,["abcdefggfedcba", "abcdefg|gfedcba"]
,["abcdefggfabc", "fg|gf"]
,["AbbA", "Ab|bA"]
,["This input is a lot like the last one, but with more characters that don't change the output. AbbA", "Ab|bA"]]
.forEach(t=>{
  var i=t[0],k=t[1],r=F(i)
  console.log(k==r?'OK ':'KO ',i+' -> '+r,k!=r?'(check '+k+')':'')
})  

edc65
fonte
2

Perl 5, 105 100 98 + 1 = 106 101 99 bytes

/(?=((.)(?1)?\2)(?{[push@_,$1})(?!))/;($_)=sort{length$b<=>length$a}@_;substr($_,length>>1,0)='|'if$_

Eu só queria experimentar regexes recursivas. Precisa da -popção. Edit: Salvo (riscado 4) 7 bytes graças a @ msh210. (O byte ausente deve-se a uma economia que foi substituída pela última economia de @ msh210.)

Neil
fonte
Eu não testei nenhum deles, mas provavelmente isso pode ser abreviado de várias maneiras, incluindo: (1) @_=(@_,$1)pode ser push@_,$1. (2) Omita as novas linhas e a final ;. (3) Eu suspeito que há uma condição de ordenação mais curto que você pode usar (se nada mais, pelo menos --- --- talvez substituto -para <=>)
msh210
@ msh210 Obrigado pelos dois primeiros pontos, mas eu já tentei -e não funcionou (provavelmente precisa de parênteses de precedência, o que prejudica a economia).
Neil
Tente y...c>>1ou em y...c/2vez de length>>1. (Não testado.)
msh210 04/07
@ msh210 Eu, obviamente, deve ter ler as dicas para jogar golfe em Perl primeiro ...
Neil
Acho que seu último par de parênteses também pode ir.
Msh210
2

Python 2, 91 bytes

f=lambda s,p='':s and max((''<p<=s<p+'\x7f')*(p[::-1]+'|'+p),f(s[1:]),f(s[1:],s[0]+p),key=len)

Substitua \x7fpelo caractere real DEL, que é ASCII 127 (crédito para Dennis).

Isso segue uma estratégia semelhante à resposta de Dennis de usar maxe ramificar recursivamente para encontrar o intervalo palíndromo mais longo. Mas, em vez disso, encontra a metade esquerda, verificando se a metade direita espelhada correspondente vem logo depois com uma partida feita por ele mesmo .

A função adivinha se o primeiro caractere está na metade esquerda espelhada. Caso contrário, ele simplesmente o solta e se repete no restante. Se for, é adicionado à pilha pde caracteres invertidos. Se a sequência de caracteres começar com a pilha, a sequência de espelhos será gerada e considerada como um espelho mais longo possível. Para evitar |como saída, apenas pilhas não vazias são consideradas.

xnor
fonte
2

Geléia , 17 bytes

ẆŒḂÐfṪœs2j”|µẋLḂ$

Experimente online!

Feito com a ajuda do Sr. Xcoder e DJMcMayhem no chat

Como funciona

ẆŒḂÐfṪœs2j”|µẋLḂ$ - Main link. Argument s  e.g.    ; 'AbbA'

Ẇ                 - All contiguous sublists
   Ðf             - Keep elements that are...
 ŒḂ               -  Palindromic                   ; [['A'], ['b'], ['b'], ['A'], ['bb'], ['AbbA']]
     Ṫ            - Final element                  ; 'AbbA'
      œs2         - Split into 2 chunks            ; ['Ab', 'bA']
         j”|      - Join with "|"                  ; 'Ab|bA'
            µ     - New link with ^ as argument
              LḂ$ - Is the length odd?             ; 1
             ẋ    - Repeat the string ^ many times ; 'Ab|bA'
caird coinheringaahing
fonte
1

Haskell, 126 111 bytes

(!)=drop
f s|n<-length s=last$"":[a++'|':b|k<-[1..n],t<-map(!s)[1..n-k],let[a,b]=take k<$>[t,k!t],a==reverse b]
Lynn
fonte
1

TSQL 227 223 bytes

Eu codifiquei o comprimento para no máximo 99 bytes, isso salvou os bytes, mas o tornei mais lento. Ainda tem um desempenho decente.

Golfe:

DECLARE @t varchar(99)='AbccbA'

,@z char(99)='',@a INT=0,@ INT=0WHILE @a<LEN(@t)SELECT
@z=IIF(LEN(x)>LEN(@z)/2and @t LIKE'%'+x+REVERSE(x)+'%'COLLATE
Thai_bin,x+'|'+REVERSE(x),@z),@=IIF(@=50,1,@+1),@a+=IIF(@=1,1,0)FROM(SELECT
SUBSTRING(@t,@a,@)x)x PRINT @z

Ungolfed:

DECLARE @t varchar(99)='AbccbA'

,@z char(99)='',
@a INT=0,
@ INT=0
WHILE @a<LEN(@t)
  SELECT
    @z=IIF(LEN(x)>LEN(@z)/2and @t LIKE'%'+x+REVERSE(x)+'%'COLLATE Thai_bin,x+'|'
       +REVERSE(x),@z),
    @=IIF(@=99,1,@+1),
    @a+=IIF(@=1,1,0)
  FROM
    (SELECT SUBSTRING(@t,@a,@)x)x

PRINT @z

Violino

t-clausen.dk
fonte
1
Você pode raspar 2 byte se limitar a 99 como o último exemplo é apenas 99 caracteres de comprimento
Alex Carlsen
1
@VisualBean thankyou, mudou o roteiro para permitir que apenas 99 caracteres, também mudaram o agrupamento de Thai_CS_AS para thai_bin
t-clausen.dk
0

Python 2, 149 bytes

R,L,s=range,len,input()
t=max([s[i:j/2+i/2]for i in R(L(s))for j in R(L(s)+1)if s[i:j]==s[i:j][::-1]and(j-i)%2<1],key=L)
print t+'|'*(L(t)>0)+t[::-1]

Experimente online

Este programa encontra a primeira metade da maior substring palindrômica de comprimento par e imprime essa sequência, seguida de a |, seguida pela sequência invertida. Se não houver uma sequência adequada, tserá a sequência vazia e '|'*(L(t)>0)será avaliada como a sequência vazia.

Mego
fonte
0

Java 8, 294 283 232 bytes

s->{int l=s.length(),i=0,j,z,y=0;String a,b="";for(;i<l;i++)for(j=0;j<=l-i;)if((a=s.substring(i,i+j++)).equals(new StringBuffer(a).reverse()+"")&(z=a.length())%2<1&z>y){y=z;b=a;}return y>0?b.substring(0,y/=2)+"|"+b.substring(y):"";}

Explicação:

Experimente aqui.

s->{                               // Method with String as both parameter and return-type
  int l=s.length(),                //  Length of the input-String
      i=0,j,                       //  Index-integers
      z,y=0;                       //  Temp-integers
  String a,b="";                   //  Temp-Strings
  for(;i<l;i++)                    //  Loop (1) from 0 to `l` (exclusive)
    for(j=0;j<=l-i;                //   Inner loop (2) from 0 to `l-i` (inclusive)
      if((a=s.substring(i,i+j++))  //    Set the current substring to `a`
          .equals(new StringBuffer(a).reverse()+"")
                                   //    If `a` is a palindrome
         &(z=a.length())%2<1       //    And the length of `a` is even
         &z>y){                    //    And the length of `a` is larger than `y`
        y=z;                       //     Change `y` to `z`
        b=a;}                      //     Change `b` to `a`
                                   //   End of inner loop (2) (implicit / single-line body)
                                   //  End of loop (1) (implicit / single-line body)
  return y>0?                      //  If the result-length is not 0:
    b.substring(0,y/=2)+"|"+b.substring(y)
                                   //   Return the result
   :                               //  Else:
    "";                            //   Return an empty String
}                                  // End of method
Kevin Cruijssen
fonte