降级为回文


47

给定一个string s,返回可以删除以创建回文的最小连续子字符串。


例子:

800233008   -> 2
racecarFOOL -> FOOL
abcdedcba   -> (empty string)
ngryL Myrgn -> "L " (or " M")
123456789   -> 12345678 (or 23456789)
aabcdbaa    -> c (or d)
[[]]        -> [[ (or ]])
a           -> (empty string)

用户的测试用例建议(如果您未列出边缘用例,请发表评论):

aabaab      -> b    | Suggested by Zgarb, some returned "aa".

规则

  • 输入中仅会显示可打印的ASCII字符(没有换行符,请保持简单)。
  • 不是一个真正的规则,但要注意<>/\()[]{}不是回文。

这是,最小字节数获胜。


阿德南声称+100悬赏


3
Tesf案:aabaab
Zgarb

14
我认为,如果避免使用诸如“ CMC”之类的组内术语(将其向上看,它似乎代表“聊天迷你挑战”,则我认为这意味着与聊天室相关的聊天室中发布了一个小的挑战)这个网站)。
ShreevatsaR

不是[[]]回文吗?
卡尔,

4
@Carl看起来像一个,但是当您反转字符时,您会得到]][[。考虑那aabb是同一件事,只是字符不同。
科纳·奥布莱恩

1
(将获得7/12的奖励) “是吗?
暴民埃里克(Erik the Outgolfer)'17

Answers:


8

果冻,16字节

Ḣ;Ṫµ=Ṛ
0,0jŒṖÇÞṪ

在线尝试!

这个怎么运作

0,0jŒṖÇÞṪ  Main link. Argument: s (string)

0,0j       Join [0, 0], separating by s. This prepends and appends a 0 to s.
    ŒṖ     Build all partitions of the resulting array.
      ÇÞ   Sort the partitions by the helper link.
           As a side effect, this will remove the first and last element of each
           partition. The 0's make sure that not removing any characters from s
           will still remove [0] from both sides.
        Ṫ  Tail; extract the last one.


Ḣ;Ṫµ=Ṛ     Helper link. Argument: A (array/partition)

Ḣ          Head; yield and remove the first chunk of A.
  Ṫ        Tail; yield and remove the last chunk of A.
 ;         Concatenate head and tail.
   µ=Ṛ     Compare the result, character by character, with its reverse.
           A palindrome of length l will yield an array of l 1's, while a
           non-palindrome of length l will yield an array with at least one 0 among
           the first l/2 Booleans. The lexicographically largest result is the one
           with the longest prefix of 1's, which corresponds to the longest
           palindrome among the outfixes.

10

J,24个字节

(0{::(-:|.)\.#&,<\)~i.@#

在线尝试!

说明

(0{::(-:|.)\.#&,<\)~i.@#  Input: array of chars S
                       #  Length of S
                    i.@   Range, [0, 1, ..., len(S)-1]
(                 )~      Dyadic verb on range and S
           \.               For each outfix of S of size x in range
        |.                    Reverse
      -:                      Matches input (is palindrome)
                <\          Box each infix of S of size x in range
             #&,            Flatten each and copy the ones that match
 0{::                       Fetch the result and index 0 and return

也许您可能想选择(;&quote f)&>作为测试工具动词?
科纳·奥布莱恩

7

Wolfram语言(Mathematica)53 51字节

字节数假定为CP-1252编码。

±{a___,Shortest@b___,c___}/;PalindromeQ[a<>c]:={b}

在线尝试!

定义一元运算符±(或函数PlusMinus)。输入和输出是字符列表。为了方便起见,测试套件会进行从实际字符串到实际字符串的转换。


Reverse然后比较这扭转原来的比PalindromeQ短?我不认识Mathematica,所以不知道。
魔术章

好的答案,但是难道不应该考虑字符串的拆分并将它们重新组合到字符数中吗? Characters@#/.{a___,Shortest@b___,c___}/;PalindromeQ[a<>c]:>b~~""&
凯利·洛德

@MagicOctopusUrn Reverse[x={a,c}]==x长两个字节。我不知道是否还有更短的选择。
马丁·恩德

@KellyLowder字符列表是PPCG上字符串的有效表示形式。在Mathematica中,这有点尴尬,您通常不使用该表示法,但是它仍然有效。我将挖掘一个元文章。
马丁·恩德

1
@KellyLowder我认为这是公认的政策。Mathematica之所以尴尬的主要原因是Mathematica没有实际的字符类型,因此这些字符最终都是单例字符串。
马丁·恩德


5

05AB1E,18个字节

ā<Œ¯¸«ʒRõsǝÂQ}éнèJ

使用05AB1E编码。在线尝试!


有趣的过滤器用法...我们试图做一个“ a不带b”类型的交易,但是如果子字符串有两个实例,我们将得到假阴性。看到这个大声笑之后,感觉就像我们过于复杂了。好的,我会在两天内给您100英镑的赏金。
魔术章鱼缸

ǝ真是个天才。
魔术章鱼缸



2

Japt26 22字节

¬£¬ËUjEY ꬩUtEY
c æ+0

在线测试!试图找出如何false在一个字节中映射到虚假的东西和任何字符串到真实的东西。目前我正在使用+0...



2

Prolog,271位元组

p([_]).
p([X,X]).
p([X|Y]):-append([P,[X]],Y),p(P).

s(P,M,S,R,N):-p(P),append([M,S],N).
s(P,M,S,S,N):-p(S),append([P,M],N).
s(P,M,S,P,M):-append([P,S],X),p(X).

d(Y,P,N):-
    findall([A,B,C],(append([R,M,X],Y),s(R,M,X,B,C),length(B,A)),S),
    sort(1,@>,S,[[_,P,N]|_]).

从某种意义上说,我意识到按代码高尔夫标准这将是巨大的,因此我保留了一些额外的空格以保持与未混淆版本的相似之处。但是我仍然认为这可能很有趣,因为这是解决问题的另一种方法。

非混淆版本:

palindrome([_]).
palindrome([X, X]).
palindrome([X | Xs]) :-
    append([Prefix, [X]], Xs),
    palindrome(Prefix).

palindrome_split(Prefix, Mid, Suffix, Prefix, N) :-
    palindrome(Prefix),
    append([Mid, Suffix], N).
palindrome_split(Prefix, Mid, Suffix, Suffix, N) :-
    palindrome(Suffix),
    append([Prefix, Mid], N).
palindrome_split(Prefix, Mid, Suffix, P, Mid) :-
    append([Prefix, Suffix], P),
    palindrome(P).

palindrome_downgrade(NP, P, N):-
    findall(
        [La, Pa, Na],
        (append([Prefix, Mid, Suffix], NP),
         palindrome_split(Prefix, Mid, Suffix, Pa, Na),
         length(Pa, La)),
        Palindromes),
    sort(1, @>, Palindromes, [[_, P, N] | _]).

2

C ++,254个 248 246字节

-6个字节归功于Zacharý-2个字节归功于Toby Speight

#include<string>
#define S size()
#define T return
using s=std::string;int p(s t){for(int i=0;i<t.S;++i)if(t[i]!=t[t.S-i-1])T 0;T 1;}s d(s e){if(!p(e))for(int i,w=1;w<e.S;++w)for(i=0;i<=e.S-w;++i){s t=e;t.erase(i,w);if(p(t))T e.substr(i,w);}T"";}

所以...

  • 我用作T宏定义是因为R""对字符串文字(作为定义原始字符串文字的前缀,请参阅cppreference以获取更多信息)的另一影响是在执行此操作时不存在T""
  • 预处理程序定义不能在同一行上,并且名称和内容之间至少要有一个空格
  • 2个功能:p(std::string)测试字符串是否是回文。如果是,则返回1强制转换为true,否则返回0,强制转换为false
  • 该算法会在每次擦除1个元素时循环回传整个字符串,以测试是否是回文,然后测试从第一个索引到擦除2个元素(将其循环到字符串的最大大小)the last index - number of erased char。如果发现擦除某个部分是回文,则返回。例如,当将字符串"aabcdbaa"作为参数传递时,cd都是有效答案,但是此代码将返回,c因为在测试是否擦除d并测试回文之前先进行擦除并测试是否为回文
  • 这是要测试的代码:

    std::initializer_list<std::pair<std::string, std::string>> test{
        {"800233008","2"},
        { "racecarFOOL","FOOL" },
        { "abcdedcba","" },
        { "ngryL Myrgn","L " },
        { "123456789","12345678" },
        { "aabcdbaa","c" },
        { "[[]]","[[" },
        { "a","" },
        { "aabaab","b" }
    };
    
    for (const auto& a : test) {
        if (a.second != d(a.first)) {
            std::cout << "Error on : " << a.first << " - Answer : " << a.second  << " - Current : " << d(a.first) << '\n';
        }
    }

这对最后一行有用吗?using s=std::string;int p(s t){for(int i=0;i<t.S/2;++i)if(t[i]!=t[t.S-i-1])T 0;T 1;}s d(s e){if(!p(e))for(int i,w=1;w<e.S;++w)for(i=0;i<=e.S-w;++i){s t=e;t.erase(i,w);if(p(t))T e.substr(i,w);}T"";}
扎卡里

可以/2省略吗?在整个长度上进行迭代只会重复我们已经完成的测试,这应该是无害的。您可能想扩展“其他效果”的含义R""(即,将其解析为原始字符串文字)。
Toby Speight

我已对此进行了修改,并将结果添加为我自己答案
Toby Speight


1

PHP 104 + 1字节

while(~($s=$argn)[$e+$i++]?:++$e|$i=0)strrev($t=substr_replace($s,"",$i,$e))==$t&&die(substr($s,$i,$e));

与管道一起运行-nR在线尝试


1

Haskell中109个 105字节

snd.minimum.([]#)
p#s@(a:b)=[(i,take i s)|i<-[0..length s],(==)<*>reverse$p++drop i s]++(p++[a])#b
p#_=[]

在线尝试!

编辑:感谢@ H.PWiz脱掉4个字节!我需要让那些单子变得更好!


1

JavaScript,90个字节

a=>a.map((_,p)=>a.map((_,q)=>k||(t=(b=[...a]).splice(q,p),k=''+b==b.reverse()&&t)),k=0)&&k

在线尝试!



1

JavaScript(ES6),91 78字节

(s,i=0,j=0,S=[...s],b=S.splice(i,j))=>S+''==S.reverse()?b:f(s,s[++i]?i:!++j,j)

输入和输出是字符列表。

递归地从输入中删除越来越大的切片,直到找到回文。

片段:


1

TSQL(2016)349B

不是最紧凑但最直接的解决方案:

DECLARE @i VARCHAR(255)='racecarFOOL'
;WITH DAT(v,i,l)AS(SELECT value,(ROW_NUMBER()OVER(ORDER BY value))-1,LEN(@i)FROM STRING_SPLIT(REPLICATE(@i+';',LEN(@i)+1),';')WHERE value<>'')
SELECT TOP 1C,S
FROM(SELECT LEFT(D.v, D.i)+SUBSTRING(D.v,D.i+E.i+1,D.l)C,SUBSTRING(D.v,D.i+1,E.i)S
FROM DAT D CROSS APPLY DAT E)C
WHERE C=REVERSE(C)
ORDER BY LEN(C)DESC

您可以将其@用作几个字节的变量。在CTE中,您可以使用where''=value)另一个,而无需返回C结果。
MickyT

1

外壳,18个字节

◄LfmS=↔†!⁰ṠM-Qŀ⁰Q⁰

在线尝试!

说明

◄LfmS=↔†!⁰ṠM-Qŀ⁰Q⁰  Input is a string, say s="aab"
              ŀ⁰    Indices of s: x=[1,2,3]
             Q      Slices: [[],[1],[1,2],[2],[1,2,3],[2,3],[3]]
          ṠM-       Remove each from x: [[1,2,3],[2,3],[3],[1,3],[],[1],[1,2]]
       †!⁰          Index into s: ["aab","ab","b","ab","","a","aa"]
   mS=↔             Check which are palindromes: [0,0,1,0,1,1,1]
  f             Q⁰  Filter the slices of s by this list: ["aa","aab","ab","b"]
◄L                  Minimum on length: "b"

1

Haskell98 94 81 80字节

""#0
(h#n)t|(==)=<<reverse$h++drop n t=take n t|x:r<-t=(h++[x])#n$r|m<-n+1=t#m$h

在线尝试!用法示例:""#0 $ "aabaab"yields "b"

编辑:-1个字节,感谢ØrjanJohansen。


1
您可以替换最后""通过t
与Orjan约翰森

1

C ++,189个 186 176 167字节

我从HatsuPointerKun的答案开始,将测试更改为仅将相等与反向字符串进行比较;然后我更改了枚举候选字符串的方式。此后,每个宏仅使用一次或两次,并且内联它们的时间较短。

#include<string>
using s=std::string;s d(s e){for(int i,w=0;;++w){s t=e.substr(w);for(i=-1;++i<=t.size();t[i]=e[i])if(t==s{t.rbegin(),t.rend()})return e.substr(i,w);}}

说明

等效的可读代码:

std::string downgrade(std::string e)
{
    for (int w=0; ; ++w) {
        std::string t = e.substr(w);
        for (int i=0;  i<=t.size();  ++i) {
            if (t == std::string{t.rbegin(),t.rend()})
                // We made a palindrome by removing w chars beginning at i
                return e.substr(i,w);
            t[i] = e[i];  // next candidate
        }
    }
}

枚举候选者首先初始化一个w省略了第一个字符的字符串,然后从原始字符中复制连续的字符以消除空白。例如,使用字符串foobarw== 2:

foobar
  ↓↓↓↓
  obar
foobar
↓
fbar
foobar
 ↓
foar
foobar
  ↓
foor
foobar
   ↓
foob

第一遍(w= = 0)是空操作,因此完整的字符串将被一遍又一遍地考虑。很好-高尔夫胜过效率!该循环的最后一次迭代将访问最后一个索引;我似乎可以通过GCC来解决这个问题,但是严格来说,这就是不确定的行为。

测试程序

HatsuPointerKun的答案直接得到提升:

static const std::initializer_list<std::pair<std::string, std::string>> test{
    { "800233008", "2" },
    { "racecarFOOL", "FOOL" },
    { "abcdedcba", "" },
    { "ngryL Myrgn", "L " },
    { "123456789", "12345678" },
    { "aabcdbaa", "c" },
    { "[[]]", "[[" },
    { "a","" },
    { "aabaab", "b" }
};

#include <iostream>
int main()
{
    for (const auto& a : test) {
        if (a.second != d(a.first)) {
            std::cout << "Error on: " << a.first
                      << " - Expected: " << a.second
                      << " - Actual: " << d(a.first) << '\n';
        }
    }
}

0

REXX,132个字节

a=arg(1)
l=length(a)
do i=1 to l
  do j=0 to l-i+1
    b=delstr(a,i,j)
    if b=reverse(b) & m>j then do
      m=j
      s=substr(a,i,j)
      end
    end
  end
say s


0

C(gcc),307字节

#define T malloc(K)
P(S,i,y,z,k,u,L,K,V)char*S;{char*M,*R,*E;K=strlen(S);M=T;R=T;E=T;for(i=0;i<K;++i){for(y=0;y<=K-i;++y){strcpy(M,S);for(z=y;z<y+i;E[z-y]=M[z],++z);for(k=y;k+i<=K;M[k]=M[k+i],++k);V=strlen(M);strcpy(R,M);for(u=0;u<V/2;L=R[u],R[u]=R[V-u-1],R[V-u-1]=L,++u);if(!strcmp(M,R))puts(E),exit(0);}}}

在线尝试!

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.