文字を削除して回文を作成する


15

問題

単語がパリンドロームになるようにその文字の1つを削除できる場合、その単語はほとんどパリンドロームであるとしましょう。あなたの仕事は、特定の単語に対して、回文を取得するために削除する文字を決定するプログラムを書くことです。

プログラミング言語でこれを行う最短のコードが優先されます。

入力

入力は、2〜1000文字の大文字の単語で構成されます。

出力

削除する必要がある文字の1インデックス位置(左端の文字に位置1、次の位置に位置2など)を出力します。回文につながる可能性のある選択肢がある場合、それらの位置のいずれかを出力します。指定された単語がすでに回文である場合でも、文字を削除する必要があることに注意してください。指定された単語がほとんど回文ではない場合、-1を出力します。


入力:

racercar

出力を生成する可能性があります:

5

5th文字を削除するracecarと、回文であるが生成されるためです。

また、入力

racecar

それでも出力を生成できます

4

4生成するth文字を削除することraccarは、まだ回文です。


5
例が投稿されていませんか?また、入力をパリンドロームにすることができない場合に出力するものは何ですか?
ProgrammerDan 14

3
@ Arm103あなたはまだあなたが言及している例を見逃しています
マーティン・エンダー

27
警告:「(例3を参照)」。これは、例が投稿されていないため、これが宿題であることを示唆しています。
ジャスティン14

3
@Quincunx Mathematica提出のスレッドも必ず読んでください。:-)
クリスジェスターヤング14

3
例3が質問に含まれていないためこの質問はトピック外のようです。
devnull

回答:


10

J- 31 25文字

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

Jの大部分は標準的な運賃なので、クールな部分のみを指摘します。

  • 副詞\.Outfixと呼ばれますx u\. y長さのすべての中置を取り除きxからyして適用されるu各除去の結果に。ここで、xis 1 yは入力文字列、uisは(-:|.)文字列がその逆に一致するかどうかのテストです。したがって、このアプリケーションの結果\.、ブール値のリストであり、各文字の場所に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公式のものは良いです
ジョンドヴォルザーク

2
@Synthetica具体Pythonersは何もが、CプログラマのためのJは、命令型プログラミングから移行誰のための大きい資源です。
algorithmshark 14

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;)
マーティンエンダー14

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

2
@ User011001それはどこに収まるでしょうか?
ɐɔıʇǝɥʇuʎs

1
あなたは書き込むことによって、各文字を救うことができる1>0のではなく、Trueとの間のスペースを除去することによって、]そしてfor...[::-1] for g...
カヤ

1
@Kaya 同様1に、単に使用することもできTrueます。1 == True、 結局。
アルシャジー14

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できましたが、他の人に任せます。;)
マーティンエンダー14

2
@ Arm103待って、これはあなたの宿題ですか?
ジョンドヴォルザーク

2
@JanDvorak PHPを使用するCSコースはありますか?それは怖いでしょう。
クリスジェスターヤング14

2
@ Arm103いいえ できません;
ジョンドヴォルザーク

4
@JanDvorakうーん、Mathematicaのプログラムは何ですか?
マーティンエンダー14

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

もっと短い方法があるはずですが、私はそれを見つけられませんでした。
ハワード

RACECAR入力された単語がすでにパリンドロームである場合、削除する文字を指定する必要がありますか?
unclemeat

@unclemeat、はい。仕様の最後から2番目の文。
ピーターテイラー14

なんで-2]$-1=)?そのブロックの開始時には、スタック上に最大1つのアイテムがあるため、簡単にに短縮できます-2]0=)。(または同じ長さの場合、特別な場合]-2or)に愛することを学びましたor)。
ピーターテイラー14

2
@Howardもし私が...私はGolfscriptについてそのように感じたたびにニッケルを持っていた
algorithmshark

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 /引数「Rng01rpNl?A [ThdRMatCYaNieTrvCYt [Rnの]] R」「レースカー」。Rebmuのドキュメントは改善されており、最近の変更により少し強化されていることに注意してください。全員とDが使用を開始する前に、まだフィードバックを探しています。:-)
HostileForkがdont信頼SE言う

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
やったー!! :)
アルモ14

1
ゴルフバージョンでは、どこでR定義され使用されていますか?
歯ブラシ14

ええ、var R = s.Remove(i、1)と言う必要があります。良いキャッチ
ウィルニュートン

3

スタックス8 10 バイト

ú·àA÷¡%5Ñ╙

実行してデバッグする

このプログラムは、文字列から削除して回文を形成できる1から始まるすべてのインデックスを表示します。存在しない場合は、-1を示します。


2
これは、回文が見つからない場合、-1の代わりに最後のインデックスをaaabb出力します(つまり、の5代わりに出力-1)。
ケビンCruijssen

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

修正-1、ありがとう。しかし、それをメソッドから取り出すことに関してあなたが何を念頭に置いているのかわからない、私は考えます。
マイクキャンベル14

さて、船上であなたのアドバイスを受けて書き直しました:)、ty。
マイクキャンベル14

どういたしまして!今でははるかに良いです:) +1
draegtun 14

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)


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;

変数iに入力文字列が含まれることを予期するLINQpadステートメント。出力は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


0

ハスケル、118C

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インデックスを付けることができる場合は、2バイト短くすることができます

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

2つのより早い反復とさらに悪い反復:

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

オンラインでお試しください!

2 16 17バイトはceilingcatのおかげで削られました!ルールでは入力の最小長が2文字であると規定されているため、さらに3バイトです。したがって、空の文字列をチェックする必要はありません。

ゴルフをしていない:

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.スリーペン

-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

これは申し分なく働きました。この背後にあるロジックを説明できる人はいますか?
アリンダムロイチョードリー16

要件は、入力が余分な文字を含む回文ではない場合、-1を出力することです。たとえば、ifの場合s = "abcde"、-1が返されます。
G.スリーペン

-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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.