Мінімальні вставки для виготовлення паліндрому


15

Сьогодні ви будете робити ще один виклик паліндром!

Отже, ваше завдання сьогодні - взяти рядок і визначити мінімальну кількість букв, необхідних для вставки, щоб перетворити його на паліндром.

Наприклад, візьмемо рядок fishes.

У цьому випадку найкращим способом було б додати h if, тож результат був би 3.

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

Тепер спробуємо codegolf. Оскільки відбувається повторне o, ми можемо просто зробити:

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

щоб отримати результат 5.

Тестові справи

ppcg -> 2
codegolf -> 5
palindrome -> 9
stackexchange -> 8
programmingpuzzlesandcodegolf -> 20

1
Пов’язано , із вставками, які відбуваються лише праворуч.
xnor

2
Ого, знову ж таки, у мене була така точна ідея виклику два дні тому ... але система балів була б довжиною вашого коду + вихід, коли його код запускається через себе. (тобто код є ppcg, оцінка становить 4 + 2 = 6)
ETHproductions

5
Це приємне завдання, але я вважаю за краще, якби виклики однієї теми були більш рознесеними. Останні пару днів було багато паліндром.
xnor

1
Це може бути важко довести, що дана програма дійсно знаходить мінімальну кількість букв
edc65

Відповіді:


3

Pyth, 10 байт

тестовий набір.

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

Існує кілька еквівалентних характеристик значення, яке ми шукаємо:

  • Найменше вставок, необхідних для виготовлення паліндрому
  • Найменше видалення, необхідне для виготовлення паліндрому
  • Половина кількості операцій видалення або вставки, необхідних для перетворення рядка в його зворотний бік
  • Довжина введення з вилученою найдовшою паліндромною послідовністю
  • Довжина введення, видаляючи найдовший загальний підряд між ним та його зворотним. (Код використовує цей.)

Поширена ідея - "скелет" букв на вході, які зіставляються з літерами введення в кінцевому продукті.

  codeg  o lf
   *  *  *
fl o  gedoc 

flcodegedoclf

Цей скелет - це завжди паліндром, з літерами, що відповідають їх перевернутим аналогам. Кожен лист без скелета є незрівнянним і має бути вставлений його аналог.

Альтернатива однакової довжини замість цього використовує четверту умову, довжина введення мінус довжина її найдовшої паліндромної послідовності

l.-Qef_ITy

Посилання на тестовий набір.

Частина, яка є різною

f_ITy

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

Для обох, замість того, щоб видалити паліндромні підрядність із введення та взяти довжину, ми могли замість цього відняти її довжину від довжини введення. Або один витрати 4 байта: -lQlпроти l.-Q.


3

Пітон, 112 байт

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)

Дуже неефективно.

Спробуйте в Інтернеті! Потрібно почекати хвилину, коли остання справа закінчиться.

Дзвоніть e(<string>, 0, <length of string - 1>), наприклад, e ("рибки", 0, 5) `.

Безголів (вид) з поясненням:

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

3
Отримання додаткового введення даних (довжина списку) за замовчуванням не є законним. Ні введення 0, але ви можете виправити це аргументом за замовчуванням l=0.
xnor

@xnor Виправлено .---
Олівер Ні

@ edc65 я написав.
Олівер Ні


2

Брахілог , 9 байт

⊆P↔P;?lᵐ-

Спробуйте в Інтернеті!

Цей виклик справді потребував відповіді Brachylog v2, оскільки паліндромізація вставки настільки інтуїтивна на цій мові.

Пояснення

⊆P↔Pнасправді це те, що робить паліндромізація шляхом вставки (див. цей приклад )

⊆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

1

C, 89 121 байт

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

Безсоромний порт відповіді Олівера , не міг придумати жодного коротшого рішення.

gзвертається fза допомогою вказівника на перший і останній символьний рядок (останній знак є частиною рядка, а не the '\0'). Стає ще неефективнішим, оскільки fвикликається два рази для minсправи.

Безголівки:

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
 }

Використання:

int main(){
 char s[]="palindrome";
 printf("%d\n",g(s));
}

2
Отримання додаткового введення даних за замовчуванням не є законним
edc65

1

Brachylog v1 , 13 байт

,IrIs?:I:lar-

Спробуйте в Інтернеті!

Ви можете перевірити знайдені паліндроми за допомогою цього коду .

Пояснення

Я майже здивований, що це навіть працює, бачачи, як це смішно просто.

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

Це гарантовано знайде найменший паліндром, оскільки IrIбуде створюватися рядки збільшення довжини під час зворотного відстеження, починаючи з порожнього рядка.

Це недостатньо ефективно для обчислення останнього тестового випадку на TIO через використання s - Ordered subset.


0

Пакетна, 234 232 байти

@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%

Працює шляхом рекурсивної спроби вставити не збігаються символи з обох кінців, так дуже повільно (я не пробував останній тестовий випадок). Межі рекурсії означають, що це працює лише обмеженою довжиною рядка, так що 99це дещо довільно. Я повинен використовувати callпараметри як локальні змінні, оскільки я не міг приступити setlocalдо роботи для мене, це означає, що %1параметр :lпідпрограми - це вираз, який оцінює кількість вставлених до цього часу вставок.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.