删除字母以形成回文


15

问题

假设一个单词几乎可以回文,如果可以删除其中一个字母,从而使该单词成为回文。您的任务是编写一个程序,该程序针对给定的单词确定删除哪个字母以得到回文。

以任何编程语言执行此操作的最短代码都会胜出。

输入值

输入由2到1000个字符长的大写字母组成。

输出量

输出应删除的字母的1索引位置(最左边的字母具有位置1,下一个字母具有位置2,依此类推)。如果有可能导致回文的选择,请输出其中任何一个。请注意,即使给定的单词已经是回文,您也需要删除字母。如果给定的单词几乎不是回文,则输出-1。


输入:

racercar

可能产生输出:

5

因为删除5字母th会产生racecar回文。

另外,输入

racecar

仍然可以产生输出

4

因为删除4字母th raccar仍然是回文。


5
没有发布示例吗?如果不可能输入回文报,该输出什么呢?
ProgrammerDan

3
@ Arm103您仍然缺少您所引用的示例
Martin Ender

27
警告: “(请参见示例3)”。这表明这是家庭作业,因为从未发布过任何示例。
贾斯汀2014年

3
@Quincunx确保也阅读有关Mathematica提交的主题。:-)
Chris Jester-Young

3
该问题似乎是题外话,因为该问题中缺少示例3
devnull

Answers:


10

J- 31 25个字符

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

基本上是J的标准票价,所以我只想指出一些很酷的地方。

  • 副词\.称为Outfix。从中x u\. y删除每个长度的后缀xy并适用u于每个除去的结果。在这里,x1 y是输入字符串,并且u(-:|.),用于测试字符串是否与其反向匹配。因此,此应用程序的结果\.是一个布尔值列表,在每个字符的位置均替换为1,布尔值的删除使输入成为回文。

  • I.从上面有1的位置开始创建所有索引(0起点)的列表。加1 1+会使这些1起点的索引。如果没有索引为1,则列表为空。现在,我们尝试使用来获取最后一个元素_1{。(允许我们输出任何可移动的字母!)如果可行,我们返回。但是,如果列表为空,则根本没有任何元素,因此{将引发域错误,我们将捕获该错误::并返回-1[

用法(记得NB.用于评论):

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

我应该学习J。Python程序员的任何教程吗?
ɐɔıʇǝɥʇuʎs

1
@Synthetica官方的一个很好
John Dvorak

2
@Synthetica没什么特别适合Pythoners的,但对于C程序员来说,J对于任何从命令式编程迁移的人来说都是一个很好的资源。
algorithmhark

10

非PHP Python(73):

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

其中a是要检查的字符串。但是,如果您不能在回文中打开它,则会抛出错误。相反,您可以使用

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

编辑:不,等等,它确实有效!

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)

谢谢,这确实使该脚本的php-contents大约增加了25%(这就是您想要的,对吧?)


10
为“不是PHP” +1;)
马丁·恩德

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

2
@ User011001哪里适合?
ɐɔıʇǝɥʇuʎs

1
你可以在每个写保存一个char 1>0,而不是True和之间移除空间]for...[::-1] for g...
卡亚

1
@Kaya您也可以直接使用1而不是True1 == True, 毕竟。
arshajii 2014年

5

Mathematica, 106 98 87 91个字符

我想我对长函数名称有一点障碍,但是在Mathematica中这样的问题相当有趣:

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

它会引发一些警告,因为 l_模式还会匹配其中的所有字符,从而Reverse无法操作。但是,嘿!

有点不符合要求:

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

2
@ Arm103我可以,但是我会留给别人。;)
Martin Ender 2014年

2
@ Arm103等待,这是您的作业吗?
John Dvorak 2014年

2
@JanDvorak有使用PHP的CS课程吗?那太可怕了。
克里斯·杰斯特·杨

2
@ Arm103号 您不能;-)
John Dvorak 2014年

4
@JanDvorak hmmm,Mathematica中的程序是什么?
Martin Ender 2014年

5

GolfScript,28个 26个字符

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

感谢Peter缩短了2个字符。在线尝试测试用例:

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

猜猜肯定有更短的方法,但我没有找到。
Howard

RACECAR仍然是E的回文。输入的单词已经是回文时,是否需要指定要删除的字符?
2014年

@unclemeat,是的。规格的倒数第二句。
彼得·泰勒

为什么-2]$-1=)呢 在该块的开始处,堆栈中最多包含一个项目,因此可以轻松地缩短至-2]0=)。(或相同的长度,]-2or)。我已经学会了爱or特殊情况)。
彼得·泰勒

2
@霍华德如果我每次都对Golfscript有这样的感觉……
algorithmhark

3

雷伯(81)

r: -1 repeat i length? s[t: head remove at copy s i if t = reverse copy t[r: i]]r

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


以上是找到的最后回文的返回索引。一个返回每个发现的回文的替代解决方案(85个字符)是:

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

因此,"racercar"这将返回list [4 5]


如果您使用Rebmu方言,则尽管基本代码相同,第一个解决方案仍只有37个字符:-)作为rebmu / args“ Rng01rpNl?A [ThdRMatCYaNieTrvCYt [Rn]] r”“ racecar”调用。请注意,Rebmu文档已得到改进,并且最近的更改将其收紧了一点……在所有人和他们的D开始使用它之前,仍希望获得反馈。:-)
HostileFork说不信任SE 2014年

3

C#,134个字符

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

我知道我输了:(但是还是很有趣:D

可读版本:

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
很好玩!!!!! :)
Almo 2014年

1
在高尔夫球版本中,R定义和使用位置是什么?
牙刷

哦,是的,应该说var R = s.Remove(i,1)。好捕获
牛顿将于2014年

3

Stax8个10 字节

ú·àA÷¡%5Ñ╙

运行并调试

该程序显示可以从字符串中删除以形成回文的所有基于1的索引。如果没有,则显示-1。


2
如果未找到回文,则输出最后一个索引而不是-1(即,aaabb输出5而不是-1)。
凯文·克鲁伊森

1
@KevinCruijssen:是的。我以2字节为代价修复了它。
递归

2

红宝石(61):

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

在这里,有一个红宝石解决方案。它会返回要删除的字符的位置;如果无法完成,则返回-1。

我忍不住觉得dup和slice部分有待改进,但是Ruby似乎没有String方法可以删除特定索引处的字符并返回新字符串-__-。

根据评论编辑,ty!


1
您可以通过不包装函数/方法来节省一些空间。但是,您的代码当前返回基于0的索引(需要基于1的索引),-1如果未找到回文,则还需要返回。
draegtun 2014年

修复了-1,谢谢。虽然不确定您的想法是采取一种方法,但我会考虑一下。
Mike Campbell

好的,请采纳您的建议并将其改写为:),ty。
Mike Campbell,

别客气!现在好多了:) +1
draegtun 2014年

2

05AB1E,10 个字节

gL.Δõs<ǝÂQ

在线尝试验证更多测试用例

说明:

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

不是PythonPHP85 83 81个字节

while($argn[$x])$s!=strrev($s=substr_replace($argn,'',$x++,1))?:die("$x");echo-1;
  • -2个字节感谢@ Night2!

在线尝试!

不必要的递归:

PHP,96字节

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

在线尝试!


1

Haskell,107个字符:

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

作为功​​能(85个字符):

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

原始的非高尔夫版本:

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个字符)

我承认这不是进行代码搜寻的最佳语言。

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

格式和评论:

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个字符)

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

LINQpad语句期望变量i包含输入字符串。输出存储在o变量中。


1

哈斯克尔,80

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

这样称呼:

λ> f "racercar"
5

1

Japt,8字节

a@jYÉ êS

尝试一下

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

哈斯克尔(118)

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

取消高尔夫:

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

果冻17 14字节

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

在线尝试!

           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.

由于我更改了方法的速度非常快,以至于旧版本不会出现在编辑历史记录中,因此是这样的: ŒPṚḊŒḂ€TṂ©’<La®o-


0

Brachylog,24个字节

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

在线尝试!

感觉太久了。

如果输出可以是2索引的,则可以短两个字节:

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

两个更早或更糟糕的迭代:

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

后者对全局变量的使用需要使用不同的测试头


0

Python 3,71个字节

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

在线尝试!

如果可以执行该操作,则返回1索引字符-1




0

C(GCC) 180个 168 159 157 140 139字节

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

在线尝试!

多亏了ceilingcat,将2 16 17个字节削减了!还有3个字节,因为规则规定输入的最小长度为2个字符,所以不必检查空字符串。

取消高尔夫:

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 &&!++p难以解释:)
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

这不检查输入(字符串s)是否几乎是回文,但是省时且可读。


2
s[-(i+1)]可以缩短为s[-i-1]。另外,我不确定,但是您可以if...else...return i+1 if ... else len(s)-1
user12205'4

这个工作正常。.任何人都可以解释其背后的逻辑吗?
Arindam Roychowdhury 2016年

要求是,如果输入的回文不是带有额外字母的回文,则输出-1。因此,例如,如果s = "abcde",则应返回-1。
G. Sliepen '19年

-2

我的第一个代码高尔夫球。

Java。主(和子)功能中的〜1200个字符。是的,宝贝。

类的顶部和用法:

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

全班:

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
这表明没有尝试打高尔夫球的代码。
mbomb007
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.