Remova uma carta para criar um palíndromo


15

Problema

Digamos que uma palavra seja quase um palíndromo se for possível remover uma de suas letras para que a palavra se torne um palíndromo. Sua tarefa é escrever um programa que, para uma determinada palavra, determine qual letra remover para obter um palíndromo.

O código mais curto para fazer isso em qualquer linguagem de programação vence.

Entrada

A entrada consiste em uma palavra em letras maiúsculas de 2 a 1000 caracteres.

Resultado

Emita a posição indexada em 1 (a letra mais à esquerda tem a posição 1, a próxima a posição 2 e assim por diante) da letra que deve ser removida. Se houver opções possíveis que levem ao palíndromo, insira uma dessas posições. Observe que você precisa remover uma letra, mesmo que a palavra especificada já seja um palíndromo. Se a palavra dada não for quase um palíndromo, produza -1.


Exemplo

A entrada:

racercar

pode produzir a saída:

5

porque a remoção da 5letra th produz racecar, que é um palíndromo.

Além disso, a entrada

racecar

ainda pode produzir a saída

4

porque remover a 4letra th para produzir raccarainda é um palíndromo.


5
Nenhum exemplo publicado? E o que produzir se não for possível transformar a entrada em um Palíndromo?
ProgrammerDan

3
@ Arm103 você ainda estão faltando os exemplos que você está se referindo
Martin Ender

27
Aviso: "(veja o exemplo 3)". Isso sugere que este é um dever de casa, pois nenhum exemplo foi publicado.
Justin

3
@ Quincunx Certifique-se de ler também o tópico no envio do Mathematica. :-)
Chris Jester-Young

3
Esta pergunta parece estar fora do tópico porque o exemplo 3 está ausente.
devnull

Respostas:


10

J - 31 25 caracteres

(_1{ ::[1+[:I.1(-:|.)\.])

Em grande parte, a tarifa padrão para J, então vou apontar as partes legais.

  • O advérbio \.é chamado Outfix . x u\. yremove todos os infixa de comprimento xa partir de ye aplica-se uao resultado de cada remoção. Aqui, xé 1, yé a sequência de entrada e ué (-:|.)um teste para determinar se a sequência corresponde ao seu reverso. Portanto, o resultado dessa aplicação de \.é uma lista de booleanos, 1 no lugar de cada caractere cuja remoção torna a entrada um palíndromo.

  • I.cria uma lista de todos os índices (origem 0) de cima, onde havia um 1. A adição de 1 com 1+produz esses índices de origem 1. Se nenhum índice fosse 1, a lista estará vazia. Agora, tentamos usar o último elemento com _1{. (Temos permissão para emitir qualquer uma das letras removíveis!) Se isso funcionar, retornaremos. No entanto, se a lista estava vazia, não havia elementos, então {gera um erro de domínio com o qual capturamos ::e retornamos o -1 com [.

Uso (lembre-se de que NB.é para comentários):

   (_1{ ::[1+[:I.1(-:|.)\.]) 'RACECAR'    NB. remove the E
4
   (_1{ ::[1+[:I.1(-:|.)\.]) 'RAACECAR'   NB. remove an A
3
   (_1{ ::[1+[:I.1(-:|.)\.]) 'RAAACECAR'  NB. no valid removal
_1

Eu deveria aprender J. Algum tutorial para um programador python?
ɐɔıʇǝɥʇuʎs

1
@Synthetica a oficial é bom
John Dvorak

2
@Synthetica Nada especificamente para Pythoners, mas o J for C Programmers é um ótimo recurso para quem migra da programação imperativa.
algorithmshark

10

Python não PHP (73):

[a[:g]+a[g+1:]==(a[:g]+a[g+1:])[::-1] for g in range(len(a))].index(1)

Onde a é a sequência que você deseja verificar. Isso, no entanto, gera um erro se você não puder transformá-lo em um palíndromo. Em vez disso, você poderia usar

try:print [a[:g]+a[g+1:]==(a[:g]+a[g+1:])[::-1] for g in range(len(a))].index(True)
except ValueError:print -1

EDIT: Não, espere, ele funciona!

try: eval("<?php $line = fgets(STDIN); ?>")
except: print [a[:g]+a[g+1:]==(a[:g]+a[g+1:])[::-1] for g in range(len(a))].index(1)

Obrigado, isso realmente aumenta o conteúdo php deste script em cerca de 25% (é isso que você deseja, certo?)


10
+1 para "Not PHP";)
Martin Ender

1
<? php $ line = fgets (STDIN); ?>
User011001

2
@ User011001 Onde isso se encaixaria?
ɐɔıʇǝɥʇuʎs

1
Você pode economizar um char cada escrevendo 1>0em vez de Truee removendo o espaço entre ]e forem...[::-1] for g...
Kaya

1
@Kaya Você pode simplesmente usar em 1vez de Truetambém. 1 == True, depois de tudo.
precisa saber é o seguinte

5

Mathematica, 106 98 87 91 caracteres

Suponho que sou um pouco prejudicado pelos nomes longos das funções, mas problemas como este são bastante divertidos no Mathematica:

f=Tr@Append[Position[c~Drop~{#}&/@Range@Length[c=Characters@#],l_/;l==Reverse@l,{1}],{-1}]&

Emite alguns avisos, porque o l_padrão também corresponde a todos os caracteres internos, que Reversenão podem funcionar. Mas ei, isso funciona!

Um pouco não-destruído:

f[s_] := 
  Append[
    Cases[
      Map[{#, Drop[Characters[s], {# }]} &, Range[StringLength[s]]], 
      {_, l_} /; l == Reverse[l]
    ], 
    {-1}
  ][[1, 1]]

2
@ Arm103 eu poderia, mas vou deixar isso para outra pessoa. ;)
Martin Enders

2
@ Arm103 espera, este é seu dever de casa?
John Dvorak

2
@JanDvorak Existem cursos de CS que usam PHP? Isso seria assustador.
Chris Jester-Young

2
@ Arm103 no. Você não pode ;-)
John Dvorak

4
@JanDvorak hmmm, o que é um programa no Mathematica?
Martin Ender

5

GolfScript, 28 26 caracteres

:I,,{)I/();\+.-1%=}?-2]0=)

Obrigado a Peter pela redução de 2 caracteres. Experimente os casos de teste online :

> "RACECAR" 
4
> "RAACECAR" 
2
> "RAAACECAR" 
-1
> "ABCC1BA" 
5
> "AAAAAA" 
1
> "ABCDE" 
-1
> "" 
-1
> "A" 
1

Acho que deve haver um caminho mais curto, mas eu não o encontrei.
Howard

RACECARainda é um palíndromo com E. É necessário especificar um caractere para remover, quando a palavra inserida já é um palíndromo?
Unclemeat

@unclemeat, sim. Penúltima sentença da especificação.
31568 Peter

Por que -2]$-1=)? No início desse bloco, você tem no máximo um item na pilha, para que possa encurtar facilmente -2]0=). (Ou pelo mesmo tamanho, ]-2or)aprendi a amar orcasos especiais).
22468 Peter

2
@Howard Se eu tivesse um níquel para cada vez que me senti assim sobre Golfscript ...
algorithmshark

3

Rebol (81)

r: -1 repeat i length? s[t: head remove at copy s i if t = reverse copy t[r: i]]r

Exemplo de uso no console Rebol:

>> s: "racercar"
== "racercar"

>> r: -1 repeat i length? s[t: head remove at copy s i if t = reverse copy t[r: i]]r
== 5

>> s: "1234"
== "1234"

>> r: -1 repeat i length? s[t: head remove at copy s i if t = reverse copy t[r: i]]r 
== -1


Acima retorna o índice do último palíndromo encontrado. Uma solução alternativa (85 caracteres) que retorna todos os palíndromos encontrados seria:

collect[repeat i length? s[t: head remove at copy s i if t = reverse copy t[keep i]]]

Então, para "racercar"isso retornaria lista [4 5].


Se você usou o dialeto Rebmu, a primeira solução tem apenas 37 caracteres, apesar de ser basicamente o mesmo código :-) Invoque como rebmu / args "Rng01rpNl? A [ThdRMatCYaNieTrvCYt [Rn]] r" "carro de corrida" . Observe que a documentação do Rebmu foi aprimorada e as alterações recentes o reforçaram um pouco ... ainda procurando feedback antes de todos e seus D começarem a usá-lo. :-)
HostileFork disse que não confia em SE

3

C #, 134 caracteres

static int F(string s,int i=0){if(i==s.Length)return-1;var R=s.Remove(i,1);return R.SequenceEqual(R.Reverse())?i+1:F(s,i+1);}

Eu sei que perco :( mas ainda assim foi divertido : D

Versão legível:

using System.Linq;

// namespace and class

static int PalindromeCharIndex(string str, int i = 0)
{
    if (i == str.Length) return -1;
    var removed = str.Remove(i, 1);
    return removed.SequenceEqual(removed.Reverse()) 
        ? i+1
        : PalindromeCharIndex(str, i + 1); 
}

3
Yay divertido !!!!! :)
Almo

1
Na versão golfed, onde é Rdefinido e usado?
Escova de dentes

oh sim, ele deveria dizer var R = s.Remove (i, 1). boa captura
Will Newton

3

Stax , 8 10 bytes

ú·àA÷¡%5Ñ╙

Execute e depure

Este programa mostra todos os índices baseados em 1 que podem ser removidos da string para formar um palíndromo. E se não houver, mostra -1.


2
Isso gera o último índice em vez de -1 se nenhum palíndromo for encontrado (ou seja, aaabbgera em 5vez de -1).
Kevin Cruijssen

1
@KevinCruijssen: Você está certo. Corrigi-o ao custo de 2 bytes.
recursivo

2

Rubi (61):

(1..s.size+1).find{|i|b=s.dup;b.slice!(i-1);b.reverse==b}||-1

Aqui, tenha uma solução em rubi. Ele retornará a posição do personagem para remover ou -1 se não puder ser feito.

Não consigo deixar de sentir que há melhorias a serem feitas com a seção dup e slice, mas Ruby não parece ter um método String que removerá um caractere em um índice específico e retornará a nova string -__-.

Editado de acordo com o comentário, ty!


1
Você pode economizar espaço ao não agrupar uma função / método. No entanto, seu código atualmente retorna um índice baseado em 0 (precisa ser baseado em 1) e também precisa retornar -1se nenhum palíndromo for encontrado.
draegtun

Corrigido o -1, obrigado. Não sei ao certo o que você tem em mente no que diz respeito a usar um método, vou pensar.
perfil completo de Mike Campbell

Ok, aceitei o seu conselho e reescrevi :), ty.
Mike Campbell

Seja bem-vindo! Agora que é muito melhor :) +1
draegtun 4/04/2014

2

05AB1E , 10 bytes

gL.Δõs<ǝÂQ

Experimente online ou verifique mais alguns casos de teste .

Explicação:

g           # Get the length of the (implicit) input-string
 L          # Create a list in the range [1,length]
          # Find the first value in this list which is truthy for:
            # (which will output -1 if none are truthy)
    õ       #  Push an empty string ""
     s      #  Swap to get the current integer of the find_first-loop
      <     #  Decrease it by 1 because 05AB1E has 0-based indexing
       ǝ    #  In the (implicit) input-String, replace the character at that index with
            #  the empty string ""
        Â   #  Then bifurcate the string (short for Duplicate & Reverse copy)
         Q  #  And check if the reversed copy is equal to the original string,
            #  So `ÂQ` basically checks if a string is a palindrome)
            # (after which the result is output implicitly)


1

Haskell, 107 caracteres:

(x:y)!1=y;(x:y)!n=x:y!(n-1)
main=getLine>>= \s->print$head$filter(\n->s!n==reverse(s!n))[1..length s]++[-1]

Como função ( 85 caracteres ):

(x:y)!1=y;(x:y)!n=x:y!(n-1)
f s=head$filter(\n->s!n==reverse(s!n))[1..length s]++[-1]

versão original não destruída:

f str = case filter cp [1..length str] of
          x:_ -> x
          _   -> -1
    where cp n = palindrome $ cut n str
          cut (x:xs) 1 = xs
          cut (x:xs) n = x : cut xs (n-1)
          palindrome x = x == reverse x

1

C # (184 caracteres)

Admito que essa não é a melhor linguagem para praticar golfe com código ...

using System.Linq;class C{static void Main(string[]a){int i=0,r=-1;while(i<a[0].Length){var x=a[0].Remove(i++,1);if(x==new string(x.Reverse().ToArray()))r=i;}System.Console.Write(r);}}

Formatado e comentado:

using System.Linq;

class C
{
    static void Main(string[] a)
    {
        int i = 0, r = -1;
        // try all positions
        while (i < a[0].Length)
        {
            // create a string with the i-th character removed
            var x = a[0].Remove(i++, 1);
            // and test if it is a palindrome
            if (x == new string(x.Reverse().ToArray())) r = i;
        }
        Console.Write(r);
    }
}

1

C # (84 caracteres)

int x=0,o=i.Select(c=>i.Remove(x++,1)).Any(s=>s.Reverse().SequenceEqual(s))?x:-1;

Instrução LINQpad esperando que a variável icontenha a sequência de entrada. A saída é armazenada na ovariável


1

Haskell, 80

a%b|b<1=0-1|(\x->x==reverse x)$take(b-1)a++b`drop`a=b|1<2=a%(b-1)
f a=a%length a

Chamado assim:

λ> f "racercar"
5

1

Japonês , 8 bytes

a@jYÉ êS

Tente

a@jYÉ êS     :Implicit input of string
a            :Last 0-based index that returns true (or -1 if none do)
 @           :When passed through the following function as Y
  j          :  Remove the character in U at index
   YÉ        :    Y-1
      êS     :  Is palindrome?

0

Haskell, 118C

m s|f s==[]=(-1)|True=f s!!0
f s=[i|i<-[1..length s],r s i==(reverse$r s i)]
r s i=let(a,_:b)=splitAt (i-1) s in a++b

Ungolfed:

fix s
    |indices s==[] = (-1)
    |True = indices s!!0
indices s = [i|i<-[1..length s],remove s i==(reverse$remove s i)]
remove s i = let (a,_:b) = (splitAt (i-1) s) in a++b

0

Geléia , 17 14 bytes

ŒPṖLÐṀṚŒḂ€TXo-

Experimente online!

           X      A random
          T       truthy index
ŒP                from the powerset of the input
  Ṗ               excluding the input
   LÐṀ            and all proper subsequences with non-maximal length
      Ṛ           reversed
       ŒḂ€        with each element replaced with whether or not it's a palindrome,
            o-    or -1.

Desde que mudei minha abordagem com rapidez suficiente para a versão antiga não aparecer no histórico de edições, foi o seguinte: ŒPṚḊŒḂ€TṂ©’<La®o-


0

Brachylog, 24 bytes

{l+₁≥.ℕ₂≜&↔⊇ᶠ↖.tT↔T∨0}-₁

Try it online!

Feels way too long.

Could be two bytes shorter if the output could be 2-indexed:

l+₁≥.ℕ₂≜&↔⊇ᶠ↖.tT↔T∨_1

Two earlier and even worse iterations:

ẹ~c₃C⟨hct⟩P↔P∧C;Ȯ⟨kt⟩hl<|∧_1
l>X⁰ℕ≜<.&{iI¬tX⁰∧Ih}ᶠP↔P∨_1

The latter's use of a global variable necessitates a different testing header.


0

Python 3, 71 bytes

def f(s,i=1):n=s[:i-1]+s[i:];return(n==n[::-1])*i-(i>len(s))or f(s,i+1)

Try it online!

Returns the 1-indexed character if the operation can be done and -1 otherwise.




0

C (gcc), 180 168 159 157 140 139 bytes

f(char*s){int j=strlen(s),m=j--/2,p=-1,i=0;for(;p&&i<m;)p=s[i++]^s[j--]&&!++p?s[i]-s[j+1]?s[i-1]-s[j]?p:j--+2:i++:p;return p<0?m+1:p?p:-1;}

Try it online!

2 16 17 bytes shaved off thanks to ceilingcat! And 3 more bytes since the rules state the minimum length of the input is 2 characters, so don't have to check for empty strings.

Ungolfed:

f(char *s) {
  int j = strlen(s);             // j = length of input
  int m = j-- / 2;               // m = midpoint of string,
                                 // j = index of right character
  int p = -1;                    // p = position of extra character
                                 //     -1 means no extra character found yet
                                 //     0 means invalid input
  int i = 0;                     // i = index of left character

  for (; p && i < m; i++) {      // loop over the string from both sides,
                                 // as long as the input is valid.
    p = s[i] ^ s[j--]            // if (left character != right character
        && !++p ?                //     and we didn't remove a character yet*)
          s[i + 1] - s[j + 1] ?  //   if (left+1 char != right char)
            s[i] - s[j] ?        //     if (left char != right-1 char)
              p                  //       do nothing,
            :                    //     else
              j-- + 2            //       remove right char.
          :                      //   else
            ++i                  //       remove left char.
        :                        // else
          p;                     //     do nothing, or:
                                 //     *the input is marked invalid 
  } 

  return p < 0 ?                 // if (input valid and we didn't remove a character yet)
           m + 1                 //   return the midpoint character,
         :                       // else
           p ?                   //   if (we did remove a character)
             p                   //     return that character,
           :                     //   else
             -1;                 //     the input was invalid.
}
```

@ceilingcat That &&!++p is just devious to explain :)
G. Sliepen

-1

Python, 84

for i in range(len(s)):
    if s[i]!=s[-(i+1)]:
        if s[i]!=s[-(i+2)]:
            return i+1
        else:
            return len(s)-i

This does not check is the input (string s) is almost palindrome, but is time efficient and readable.


2
s[-(i+1)] can be shortened to s[-i-1]. Also, I'm not sure but you may be able to replace the if...else... with return i+1 if ... else len(s)-1
user12205

This worked alright..Can anyone explain the logic behind this ?
Arindam Roychowdhury

The requirement is that it outputs -1 if the input is not a palindrome with an extra letter. So for example, if s = "abcde", it should return -1.
G. Sliepen

-2

My first code-golf.

Java. ~1200 characters in the main (and sub) functions. Yeah baby.

Class top and usage:

public class ElimOneCharForPalindrome  {
   public static final void main(String[] ignored)  {
      System.out.println(getEliminateForPalindromeIndex("racercar"));
      System.out.println(getEliminateForPalindromeIndex("racecar"));
   }

The main function:

   public static final int getEliminateForPalindromeIndex(String oneCharAway_fromPalindrome)  {
      for(int i = 0; i < oneCharAway_fromPalindrome.length(); i++)  {
         String strMinus1Char = oneCharAway_fromPalindrome.substring(0, i) + oneCharAway_fromPalindrome.substring(i + 1);

         String half1 = getFirstHalf(strMinus1Char);
         String half2Reversed = getSecondHalfReversed(strMinus1Char);

         if(half1.length() != half2Reversed.length())  {
            //One half is exactly one character longer
            if(half1.length() > half2Reversed.length())  {
               half1 = half1.substring(0, (half1.length() - 1));
            }  else  {
               half2Reversed = half2Reversed.substring(0, (half2Reversed.length() - 1));
            }
         }

         //System.out.println(i + " " + strMinus1Char + " --> " + half1 + " / " + half2Reversed + "  (minus the singular [non-mirrored] character in the middle, if any)");

         if(half1.equals(half2Reversed))  {
            return  i;
         }
      }
      return  -1;
   }

Sub-functions:

   public static final String getFirstHalf(String whole_word)  {
      return  whole_word.substring(0, whole_word.length() / 2);
   }
   public static final String getSecondHalfReversed(String whole_word)  {
      return  new StringBuilder(whole_word.substring(whole_word.length() / 2)).reverse().toString();
   }
}

Full class:

public class ElimOneCharForPalindrome  {
   public static final void main(String[] ignored)  {
      System.out.println(getEliminateForPalindromeIndex("racercar"));
      System.out.println(getEliminateForPalindromeIndex("racecar"));
   }
   public static final int getEliminateForPalindromeIndex(String oneCharAway_fromPalindrome)  {
      for(int i = 0; i < oneCharAway_fromPalindrome.length(); i++)  {
         String strMinus1Char = oneCharAway_fromPalindrome.substring(0, i) + oneCharAway_fromPalindrome.substring(i + 1);

         String half1 = getFirstHalf(strMinus1Char);
         String half2Reversed = getSecondHalfReversed(strMinus1Char);

         if(half1.length() != half2Reversed.length())  {
            //One half is exactly one character longer
            if(half1.length() > half2Reversed.length())  {
               half1 = half1.substring(0, (half1.length() - 1));
            }  else  {
               half2Reversed = half2Reversed.substring(0, (half2Reversed.length() - 1));
            }
         }

         //System.out.println(i + " " + strMinus1Char + " --> " + half1 + " / " + half2Reversed + "  (minus the singular [non-mirrored] character in the middle, if any)");

         if(half1.equals(half2Reversed))  {
            return  i;
         }
      }
      return  -1;
   }
   public static final String getFirstHalf(String whole_word)  {
      return  whole_word.substring(0, whole_word.length() / 2);
   }
   public static final String getSecondHalfReversed(String whole_word)  {
      return  new StringBuilder(whole_word.substring(whole_word.length() / 2)).reverse().toString();
   }
}

3
This shows no attempt at golfing the code.
mbomb007
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.