Minimalna liczba wstawek do wykonania palindromu

15

Dzisiaj wykonasz kolejne wyzwanie palindromowe!

Twoim dzisiejszym zadaniem jest pobranie ciągu znaków i określenie minimalnej liczby liter wymaganych do wstawienia, aby przekształcić go w palindrom.

Na przykład weźmy ciąg fishes.

W takim przypadku najlepszym sposobem byłoby dodanie h if, więc wynik wyniósłby 3.

fishe s
     h if
---------
fishehsif

Teraz spróbujmy z codegolf. Ponieważ jest to powtórzenie o, możemy po prostu zrobić:

  codeg  o lf
fl     ed c
-------------
flcodegedoclf

aby uzyskać wynik 5.

Przypadki testowe

ppcg -> 2
codegolf -> 5
palindrome -> 9
stackexchange -> 8
programmingpuzzlesandcodegolf -> 20
Oliver Ni
źródło
1
Powiązane , z wstawkami występującymi tylko po prawej stronie.
xnor
2
Wow, jeszcze raz miałem ten pomysł na wyzwanie dwa dni temu ... ale system punktacji byłby długością twojego kodu + wyniku, gdy jego kod zostanie przepuszczony przez siebie. (tj. kod to ppcg, wynik to 4 + 2 = 6)
ETHprodukcje
5
To miłe wyzwanie, ale wolałbym, gdyby wyzwania dotyczące tego samego tematu były bardziej rozłożone. Przez ostatnie kilka dni było dużo palindromu.
xnor
1
Może być trudno udowodnić, że dany program naprawdę znajduje minimalną liczbę liter
edc65

Odpowiedzi:

3

Pyth, 10 bajtów

pakiet testowy.

l.-Qe@y_Qy

         y   All subsequences of the input (implicit), sorted by length
      y_Q    All subsequences of the reversed input, sorted by length
     @       Their setwise intersection: the common subsequences
    e        Last element: the longest common subsequence
 .-Q         Remove it bagwise from the input: the letters not in this LCS
l            The length of that

Istnieje kilka równoważnych cech, których szukamy:

  • Najmniejszej liczby wstawek potrzebnych do utworzenia palindromu
  • Najmniej usunięć potrzebnych do utworzenia palindromu
  • Połowa liczby operacji usuwania lub wstawiania potrzebnych do przekształcenia łańcucha na jego odwrotność
  • Długość wejścia z usuniętą najdłuższą podsekwencją palindromiczną
  • Długość wejścia, usuwając najdłuższy wspólny podciąg między nim a jego odwrotnością. (Kod używa tego.)

Powszechnym pomysłem jest „szkielet” liter na wejściu, które są dopasowane do liter wejścia w produkcie końcowym.

  codeg  o lf
   *  *  *
fl o  gedoc 

flcodegedoclf

Ten szkielet jest zawsze palindromem, a litery pasują do odwróconych odpowiedników. Każda inna niż szkielet litery nie ma sobie równych i musi mieć wstawiony odpowiednik.

Zamiast tego alternatywa o tej samej długości wykorzystuje czwarty warunek, długość wejścia pomniejszoną o długość jego najdłuższej podsekwencji palindromicznej

l.-Qef_ITy

Link do pakietu testowego.

Ta część jest inna

f_ITy

    y   All subsequences of the input (implicit), sorted by length.
f       Filtered on:
 _IT     being invariant under reversal, i.e. a palindrome

W obu przypadkach zamiast usuwać podsekwencję palindromiczną z wejścia i przyjmować długość, moglibyśmy zamiast tego odjąć jej długość od długości wejścia. Albo jeden kosztuje 4 bajtów: -lQlvs l.-Q.

xnor
źródło
3

Python, 112 bajtów

d=lambda x,l,h:0if h<l else d(x,l+1,h-1)if x[l]==x[h]else-~min(d(x,l+1,h),d(x,l,h-1));e=lambda x:d(x,0,len(x)-1)

Bardzo nieefektywne.

Wypróbuj online! Musisz poczekać minutę na zakończenie ostatniej sprawy.

Zadzwoń e(<string>, 0, <length of string - 1>), np. E („ryby”, 0, 5) `.

Niegolfowane (w pewnym sensie) z wyjaśnieniem:

def minInsert(x, l, h):                # Declare func, arugments for x, l, h       # d=lambda x,l,h:
  if l >= h:                           # If l is the same or past h                #                 if h<l
    return 0                           #     then return 0                         #                0
  elif x[l] == x[h]:                   # If first and last character are the same  #                        else             if x[l]==x[h]
    return minInsert(x, l + 1, h - 1)  #     then return the min w/o first & last  #                             d(x,l+1,h-1)
  else:                                # If not, we shave off a character          #                                                      else
    a = minInsert(x, l, h - 1)         #     (last one)                            #                                                                d(x,l+1,h)
    b = minInsert(x, l + 1, h)         #     (first one)                           #                                                                           d(x,l,h-1)
    return min(a, b) + 1               #     and add one for the char we took off  #                                                          -~min(          ,          )
Oliver Ni
źródło
3
Uzyskiwanie dodatkowych danych wejściowych (długości listy) domyślnie nie jest legalne. Wejście nie jest równe 0, ale można to naprawić za pomocą domyślnego argumentu l=0.
xnor
@xnor Naprawiono. ---
Oliver Ni
@ edc65 I etited.
Oliver Ni
2

05AB1E , 11 bajtów

Wykorzystuje kodowanie CP-1252 .

Âæsæäg¹g-Ä

Wypróbuj online! lub jako pakiet testowy

Wyjaśnienie

              # implicit input
             # push a reversed copy
 æ            # compute powerset of the reversed string
  sæ          # compute powerset of the string
    äg       # get length of the longest common subset
      ¹g-     # subtract the length of the original string
         Ä    # take absolute value
Emigna
źródło
2

Brachylog , 9 bajtów

⊆P↔P;?lᵐ-

Wypróbuj online!

To wyzwanie naprawdę wymagało odpowiedzi Brachylog v2, ponieważ palindromizacja wstawiania jest w tym języku tak intuicyjna.

Wyjaśnienie

⊆P↔Ptak naprawdę działa palindromizacja przez wstawienie (zobacz ten przykład )

⊆P           P is an ordered superset of the input
 P↔P         P reversed is P (i.e. P is a palindrome)
   P;?lᵐ     Compute the length of both P and the input
        -    Subtraction
Fatalizować
źródło
1

C, 89 121 bajtów

#define g(a) f(a,a+strlen(a)-1)
f(char*a,char*b){return a>=b?0:*a-*b?f(a+1,b)<f(a,b-1)?f(++a,b)+1:f(a,--b)+1:f(++a,--b);}

Bezwstydny port odpowiedzi Olivera nie mógł wymyślić żadnego krótszego rozwiązania.

gwywołuje fze wskaźnikiem do pierwszego i ostatniego znaku ciągu (ostatni znak jest częścią ciągu, a nie '\0'). Staje się jeszcze bardziej nieefektywny, ponieważ w przypadku fjest wywoływany dwa razy min.

Nie golfowany:

f(char*a,char*b){
 return a>=b ? 0 :
   *a-*b ?    //if the pointed chars are not the same
     f(a+1,b)<f(a,b-1) ? f(a+1,b)+1 : f(a,b-1)+1    //min(f..,f..)+1
   : f(a+1,b-1);  //if they were the same, make it more narrow
 }

Stosowanie:

int main(){
 char s[]="palindrome";
 printf("%d\n",g(s));
}
Karl Napf
źródło
2
Uzyskiwanie dodatkowych danych wejściowych z danymi nie jest domyślnie
legalne
1

Brachylog v1 , 13 bajtów

,IrIs?:I:lar-

Wypróbuj online!

Za pomocą tego kodu możesz sprawdzić znalezione palindromy .

Wyjaśnienie

Jestem prawie zaskoczony, że to nawet działa, widząc, jak to jest absurdalnie proste.

,IrI             I reversed is I (i.e. I is a palindrome)
   Is?           The Input is an ordered subset of I
     ?:I:la      The list [length(Input), length(I)]
           r-    Output = length(I) - length(Input)

Gwarantuje to znalezienie najmniejszego palindromu, ponieważ IrIwygeneruje ciągi o większej długości podczas cofania, zaczynając od pustego ciągu.

Nie jest to wystarczająco wydajne, aby obliczyć ostatni przypadek testowy na TIO, ze względu na użycie s - Ordered subset.

Fatalizować
źródło
0

Partia, 234 232 bajty

@echo off
set n=99
call:l 0 %1
echo %n%
exit/b
:g
set/am=%1
if %m% lss %n% set/an=m
exit/b
:l
if "%2"=="" goto g
set s=%2
if %s:~,1%==%s:~-1% call:l %1 %s:~1,-1%&exit/b
call:l %1+1 %s:~1%
set s=%2
call:l %1+1 %s:~,-1%

Działa, rekurencyjnie próbując wstawić niepasujące znaki na obu końcach, więc bardzo wolno (nie próbowałem ostatniego przypadku testowego). Limity rekurencji oznaczają, że i tak działa to tylko dla ograniczonej długości łańcucha, więc 99jest to nieco arbitralne. Muszę używać callparametrów jako zmiennych lokalnych, ponieważ nie mogłem setlocalpracować dla siebie, co oznacza, że %1parametr :lpodprogramu jest wyrażeniem, które ocenia liczbę wykonanych do tej pory wstawek.

Neil
źródło