尽量减少回文


15

今天,您将面临另一个回文挑战!

因此,您今天的任务是取一个字符串,并确定将其变成回文式所需要插入的最小字母数。

例如,让我们使用string 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
Related,仅在右侧发生插入。
xnor

2
哇,再次,我是在两天前提出了这个确切的挑战主意……但是,评分系统本来就是代码的长度+代码通过其自身运行时的输出。(即代码是ppcg,得分是4 + 2 = 6)
ETHproductions'Nov

5
这是一个很好的挑战,但是如果同一个主题的挑战间隔更大,我更愿意。最近几天出现了很多回文。
xnor

1
可能很难证明给定的程序确实找到了最少的字母
edc65

Answers:


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个字节:-lQlvs l.-Q


3

Python,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(“ fishes”,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

05AB1E,11个字节

使用CP-1252编码。

Âæsæäg¹g-Ä

在线尝试!或作为测试套件

说明

              # 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

2

Brachylog,9个字节

⊆P↔P;?lᵐ-

在线尝试!

这个挑战确实需要Brachylog v2答案,因为插入回文化在该语言中是如此直观。

说明

⊆P↔P通过插入进行palindromization确实是什么(请参见本示例

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

奥利弗无耻端口的答案,想不出任何更短的解决方案。

gf使用指向字符串的第一个和最后一个字符的指针进行调用(最后一个字符是字符串的一部分,而不是'\0')。效率更高,因为fmin案例被调用了两次。

取消高尔夫:

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

批处理,234232字节

@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是一个表达式,该表达式的计算结果是迄今为止完成的插入次数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.