Rimuovi una lettera per creare un palindromo


15

Problema

Diciamo che una parola è quasi un palindromo se è possibile rimuovere una delle sue lettere in modo che la parola diventi un palindromo. Il tuo compito è quello di scrivere un programma che per una determinata parola determina quale lettera rimuovere per ottenere un palindromo.

Vince il codice più breve per farlo in qualsiasi linguaggio di programmazione.

Ingresso

L'input consiste in una parola di lettere maiuscole da 2 a 1000 caratteri.

Produzione

Stampa la posizione 1 indicizzata (la lettera più a sinistra ha la posizione 1, la successiva ha la posizione 2 e così via) della lettera che dovrebbe essere rimossa. Se ci sono possibili scelte che portano al palindromo, emetti una di quelle posizioni. Si noti che è necessario rimuovere una lettera anche se la parola data è già un palindromo. Se la parola data non è quasi un palindromo, genera -1.


Esempio

L'input:

racercar

potrebbe produrre l'output:

5

perché la rimozione della 5lettera th produce racecar, che è un palindromo.

Inoltre, l'input

racecar

può ancora produrre l'output

4

perché rimuovere la 4lettera da produrre raccarè ancora un palindromo.


5
Nessun esempio pubblicato? E cosa produrre se non è possibile effettuare l'input in un Palindrome?
Programmatore:

3
@ Arm103 ti mancano ancora gli esempi a cui ti riferisci
Martin Ender,

27
Attenzione: "(vedi esempio 3)". Ciò suggerisce che si tratta di compiti a casa poiché non sono mai stati pubblicati esempi.
Justin,

3
@Quincunx Assicurati di leggere anche il thread sull'invio di Mathematica. :-)
Chris Jester-Young,

3
Questa domanda sembra essere fuori tema perché l' esempio 3 manca dalla domanda.
Devnull

Risposte:


10

J - 31 25 caratteri

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

Tariffa in gran parte standard per J, quindi sottolineo solo le cose interessanti.

  • L'avverbio \.si chiama Outfix . x u\. yrimuove ogni infisso di lunghezza xda ye si applica ual risultato di ogni rimozione. Qui, xè 1, yè la stringa di input ed uè (-:|.)un test per verificare se la stringa corrisponde al suo contrario. Quindi il risultato di questa applicazione di \.è un elenco di booleani, 1 al posto di ogni personaggio la cui rimozione rende l'input un palindromo.

  • I.crea un elenco di tutti gli indici (origine 0) dall'alto dove c'era un 1. Aggiungendo 1 con si 1+ottengono questi indici 1 origine. Se nessun indice era 1, l'elenco è vuoto. Ora proviamo a prendere l'ultimo elemento con _1{. (Siamo autorizzati a produrre una qualsiasi delle lettere rimovibili!) Se funziona, torniamo. Tuttavia, se l'elenco era vuoto, non c'erano affatto elementi, quindi {genera un errore di dominio che intercettiamo ::e restituiamo -1 con [.

Utilizzo (ricorda che NB.è per i commenti):

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

Dovrei imparare J. Qualche tutorial per un programmatore Python?
3ıʇǝɥʇuʎs

1
@Synthetica quello ufficiale è buono
John Dvorak,

2
@Synthetica Niente di specifico per Pythoners, ma J for C Programmers è un'ottima risorsa per chiunque stia migrando dalla programmazione imperativa.
algoritmo

10

Non-PHP Python (73):

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

Dove a è la stringa che si desidera controllare. Questo, tuttavia, genera un errore se non è possibile trasformarlo in un palindromo. Invece, potresti usare

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: No, aspetta, funziona!

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)

Grazie, questo aumenta davvero il contenuto php di questo script di circa il 25% (è quello che vuoi, giusto?)


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

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

2
@ User011001 Dove si adatterebbe?
3ıʇǝɥʇuʎs

1
Puoi salvare un carattere ciascuno scrivendo 1>0invece Truee rimuovendo lo spazio tra ]e forin...[::-1] for g...
Kaya,

1
@Kaya Puoi semplicemente usare anche al 1posto di True. 1 == True, Dopotutto.
Arshajii,

5

Mathematica, 106 98 87 91 caratteri

Suppongo di essere leggermente handicappato dai nomi delle funzioni lunghe, ma problemi come questo sono abbastanza divertenti in Mathematica:

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

Emette alcuni avvertimenti, perché il l_modello corrisponde anche a tutti i personaggi all'interno, sui quali Reversenon è possibile operare. Ma ehi, funziona!

Abbastanza ungolfed:

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

2
@ Arm103 Potrei, ma lo lascerò a qualcun altro. ;)
Martin Ender,

2
@ Arm103 aspetta, è questo il tuo compito?
John Dvorak,

2
@JanDvorak Ci sono corsi CS che usano PHP? Sarebbe spaventoso.
Chris Jester-Young,

2
@ Arm103 no. Non puoi ;-)
John Dvorak,

4
@ JanDvorak hmmm, cos'è un programma in Mathematica?
Martin Ender,

5

GolfScript, 28 26 caratteri

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

Grazie a Peter per accorciare di 2 caratteri. Prova i casi di test online :

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

Immagino che ci debba essere un modo più breve ma non l'ho trovato.
Howard,

RACECARè ancora un palindromo con la E. È necessario specificare un carattere da rimuovere, quando la parola immessa è già un palindromo?
Unlemeat

@unclemeat, sì. Penultima frase della specifica.
Peter Taylor,

Perché -2]$-1=)? All'inizio di quel blocco hai al massimo un oggetto in pila, quindi puoi accorciarlo facilmente -2]0=). (O per la stessa lunghezza ]-2or),. Ho imparato ad amare orper casi speciali).
Peter Taylor,

2
@Howard Se avessi un centesimo per ogni volta che sentivo in quel modo su 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

Esempio di utilizzo nella console di 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


Sopra restituisce l'indice dell'ultimo palindromo trovato. Una soluzione alternativa (85 caratteri) che restituisce ogni palindromo trovato sarebbe:

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

Quindi per "racercar"questo tornerebbe alla lista [4 5].


Se hai usato il dialetto Rebmu quella prima soluzione è di soli 37 caratteri, nonostante sia sostanzialmente lo stesso codice :-) Invoca come rebmu / args "Rng01rpNl? A [ThdRMatCYaNieTrvCYt [Rn]] r" "racecar" . Si noti che la documentazione di Rebmu è stata migliorata e le recenti modifiche l'hanno rafforzata un po '... ancora alla ricerca di feedback prima che tutti e la loro D inizino a usarlo. :-)
HostileFork dice di non fidarti di SE

3

C #, 134 caratteri

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);}

So di perdere :( ma è stato comunque divertente : D

Versione leggibile:

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 fun !!!!! :)
Almo,

1
Nella versione golfata, dove viene Rdefinita e utilizzata?
Spazzolino da denti

oh sì, dovrebbe dire var R = s.Remove (i, 1). buona cattura
Will Newton,

3

Stax , 8 10 byte

ú·àA÷¡%5Ñ╙

Esegui ed esegui il debug

Questo programma mostra tutti gli indici basati su 1 che possono essere rimossi dalla stringa per formare un palindromo. E se non ce ne sono, mostra -1.


2
Questo genera l'ultimo indice invece di -1 se non viene trovato palindromo (cioè aaabboutput 5invece di -1).
Kevin Cruijssen,

1
@KevinCruijssen: Hai ragione. L'ho risolto al costo di 2 byte.
ricorsivo il

2

Rubino (61):

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

Ecco una soluzione di rubino. Restituirà la posizione del personaggio da rimuovere o -1 se non può essere fatto.

Non posso fare a meno di pensare che ci sia un miglioramento da apportare con la sezione dup e slice, ma Ruby non sembra avere un metodo String che rimuoverà un carattere in un indice specifico e restituirà la nuova stringa -__-.

Modificato come da commento, ty!


1
Puoi risparmiare un po 'di spazio non avvolgendo una funzione / metodo. Tuttavia, il tuo codice attualmente restituisce un indice basato su 0 (deve essere basato su 1) e deve anche restituire -1se non viene trovato alcun palindromo.
Draegtun,

Risolto il -1, grazie. Non sono sicuro di quello che hai in mente riguardo al fatto di metterlo fuori un metodo, ci penserò.
Mike Campbell,

Ok, ho preso il tuo consiglio a bordo e riscritto :), ty.
Mike Campbell,

Prego! Ora è molto meglio :) +1
draegtun

2

05AB1E , 10 byte

gL.Δõs<ǝÂQ

Provalo online o verifica alcuni altri casi di test .

Spiegazione:

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)

2

Non Python PHP ,85 83 81 byte

while($argn[$x])$s!=strrev($s=substr_replace($argn,'',$x++,1))?:die("$x");echo-1;
  • -2 byte grazie a @ Night2!

Provalo online!

Inutilmente ricorsivo:

PHP , 96 byte

function f($a,$b='',$d=1){return$a?$c==strrev($c=$b.$e=substr($a,1))?$d:f($e,$b.$a[0],$d+1):-1;}

Provalo online!


1

Haskell, 107 caratteri:

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

Come funzione ( 85 caratteri ):

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

versione originale non modificata:

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

Ammetto che questa non è la lingua migliore per giocare a golf ...

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);}}

Formattato e commentato:

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

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

Istruzione LINQpad che prevede che la variabile icontenga la stringa di input. L'output è memorizzato nella ovariabile.


1

Haskell, 80 anni

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

Chiamato così:

λ> f "racercar"
5

1

Japt , 8 byte

a@jYÉ êS

Provalo

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

Gelatina , 17 14 byte

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

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

Da quando ho cambiato il mio approccio abbastanza velocemente da non mostrare la vecchia versione nella cronologia delle modifiche, è stato questo: ŒPṚḊŒḂ€TṂ©’<La®o-


0

Brachylog , 24 byte

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

Provalo online!

Sembra troppo lungo.

Potrebbe essere più breve di due byte se l'output potesse essere indicizzato 2 :

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

Due iterazioni precedenti e anche peggiori:

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

L'uso di una variabile globale da parte di quest'ultimo richiede un'intestazione di test diversa .


0

Python 3 , 71 byte

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

Provalo online!

Restituisce il carattere 1-indicizzato se l'operazione può essere eseguita e in -1altro modo.




0

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

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;}

Provalo online!

2 16 17 byte eliminati grazie a ceilingcat! E altri 3 byte poiché le regole indicano che la lunghezza minima dell'input è di 2 caratteri, quindi non è necessario verificare la presenza di stringhe vuote.

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 Questo &&!++pè solo subdolo da spiegare :)
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

Questo non controlla se l'input (stringa) è quasi palindromo, ma è efficiente nel tempo e leggibile.


2
s[-(i+1)]può essere abbreviato in s[-i-1]. Inoltre, non sono sicuro, ma si può essere in grado di sostituire il if...else...conreturn i+1 if ... else len(s)-1
user12205

Funzionava bene ... Qualcuno può spiegare la logica dietro questo?
Arindam Roychowdhury,

Il requisito è che produca -1 se l'input non è un palindromo con una lettera in più. Ad esempio, se s = "abcde", dovrebbe restituire -1.
G. Sliepen,

-2

Il mio primo codice-golf.

Giava. ~ 1200 caratteri nelle funzioni principali (e secondarie). Si Bella.

Inizio e utilizzo della classe:

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

La funzione principale:

   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-funzioni:

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

Classe completa:

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
Questo non mostra alcun tentativo di giocare a golf il codice.
mbomb007,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.