회문을 만들기 위해 편지를 제거


15

문제

단어가 회문 이되도록 글자 중 하나를 제거 할 수 있다면 단어가 거의 회문 이라고 가정 해 봅시다 . 당신의 임무는 주어진 단어에 대해 회문을 얻기 위해 제거 할 문자를 결정하는 프로그램을 작성하는 것입니다.

모든 프로그래밍 언어 에서이 작업을 수행하는 가장 짧은 코드가 승리합니다.

입력

입력은 2 ~ 1000 자의 대문자로 구성됩니다.

산출

제거해야 할 문자의 1 색인 위치 (가장 왼쪽 문자는 위치 1, 다음 문자는 위치 2 등)를 출력합니다. 회문으로 이어지는 가능한 선택이 있다면, 그 위치 중 하나를 출력하십시오. 주어진 단어가 이미 회 문인 경우에도 글자를 제거해야합니다. 주어진 단어가 거의 회문이 아닌 경우, -1을 출력하십시오.


입력 :

racercar

출력을 생성 할 수 있습니다 :

5

5th 글자를 제거하면 회 racecar문인을 생성 하기 때문 입니다.

또한 입력

racecar

여전히 출력을 생성 할 수 있습니다

4

4생산할 글자를 제거하는 raccar것은 여전히 ​​회문 이기 때문 입니다.


5
게시 된 예가 없습니까? 회문에 입력을 할 수 없다면 어떻게해야합니까?
ProgrammerDan

3
@ Arm103 당신은 여전히 ​​당신이 언급 한 예제를 놓치고 있습니다
Martin Ender

27
경고 : "(예 3 참조)". 이것은 예제가 게시되지 않았기 때문에 이것이 숙제임을 암시합니다.
Justin

3
@Quincunx Mathematica 제출의 스레드도 반드시 읽으십시오. :-)
Chris Jester-Young

3
예제 3 이 질문에서 누락 되었기 때문에이 질문은 주제를 벗어난 것으로 보입니다 .
devnull

답변:


10

J- 31 25 자

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

J에 대한 표준 요금이 대부분이므로 멋진 비트 만 지적하겠습니다.

  • 부사 \.Outfix 라고 합니다 . x u\. y길이마다 중위 제거 x발을 y인가한다 u각각의 제거의 결과. 여기서 x1 y은 입력 문자열 u이며 (-:|.), 문자열이 그 반대인지 여부에 대한 테스트입니다. 따라서이 응용 프로그램의 결과는 \.각 문자 대신에 부울 목록으로, 1을 제거하면 입력을 회문으로 만듭니다.

  • I.1이 있었던 위의 모든 색인 (0- 원본) 목록을 작성합니다. 1을 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를 배워야한다. 파이썬 프로그래머를위한 튜토리얼?
ɐɔıʇǝɥʇuʎs

1
@ Synthetica 공식 하나는 좋은
John Dvorak

2
@Synthetica Pythoners에게는 특별한 것은 아니지만 J for C 프로그래머 는 명령형 프로그래밍에서 마이그레이션하는 모든 사람에게 훌륭한 리소스입니다.
algorithmshark

10

비 PHP 파이썬 (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 내용을 약 25 % 증가시킵니다 (원하는 것입니까?)


10
"PHP 아님"에 +1;)
Martin Ender

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

2
@ User011001 어디에 적합합니까?
ɐɔıʇǝɥʇuʎs

1
당신은 서면으로 각각 문자를 절약 할 수 1>0대신 True사이의 공간을 제거 ]하고 for...[::-1] for g...
가야

1
@Kaya 1대신 사용할 수도 True있습니다. 1 == True결국.
arshajii

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

2
@ Arm103 잠깐만,이게 네 숙제 야?
John Dvorak

2
@JanDvorak PHP를 사용하는 CS 과정이 있습니까? 그것은 무서울 것입니다.
Chris Jester-Young

2
@ Arm103 번호 당신은 ;-) 수 없습니다
John Dvorak

4
@ JanDvorak hmmm, Mathematica 의 프로그램 은 무엇 입니까?
Martin Ender

5

GolfScript, 28 26 자

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

2 자씩 줄인 Peter에게 감사합니다. 온라인 테스트 사례를 사용해보십시오 .

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

더 짧은 방법이 있어야한다고 생각하지만 찾지 못했습니다.
Howard

RACECAR입력 된 단어가 이미 회 문인 경우 제거 할 문자를 지정해야합니까?
unclemeat

@unclemeat, 그렇습니다. 스펙의 두 번째 문장.
피터 테일러

-2]$-1=)? 해당 블록의 시작 부분에 스택에 최대 하나의 항목이 있으므로 쉽게 단축 할 수 있습니다 -2]0=). (또는 같은 길이 ]-2or)입니다. or특별한 경우 를 좋아 하는 법을 배웠습니다 ).
피터 테일러

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


기본적으로 동일한 코드 임에도 불구하고 첫 번째 솔루션이 37 자라는 Rebmu 방언 을 사용한 경우 :-) rebmu / args "Rng01rpNl? A [ThdRMatCYaNieTrvCYt [Rn]] r" "racecar" 로 호출하십시오 . Rebmu 문서가 개선되었으며 최근 변경으로 인해 조금씩 강화되었지만 모든 사람과 D 가 사용 하기 전에 피드백을 찾고 있습니다. :-)
HostileFork는

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

1
골프 버전에서는 어디에 R정의되고 사용됩니까?
칫솔

예, var R = s.Remove (i, 1) 라고 표시해야합니다 . 좋은 캐치
Will Newton

3

Stax , 8 10 바이트

ú·àA÷¡%5Ñ╙

실행 및 디버깅

이 프로그램은 현에서 제거되어 회문을 형성 할 수있는 모든 1 기반 지수를 보여줍니다. 그리고 아무것도 없으면 -1을 표시합니다.


2
회문이없는 경우 (즉 aaabb, 5대신 출력 -1) -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

고정 -1, 감사합니다. 당신이 생각하는 것을 방법을 취하는 것과 관련하여 확실하지 않다면, 나는 생각할 것입니다.
Mike Campbell

좋아, 당신의 조언을 받아 다시 작성 :), ty.
Mike Campbell

천만에요! 이제는 훨씬 낫습니다 :) +1
draegtun

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

하스켈, 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

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

하스켈, 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

두 가지 더 빠르고 더 나쁜 반복 :

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

온라인으로 사용해보십시오!

ceilingcat 덕분에 2 16 17 바이트가 줄었습니다! 규칙에 따르면 입력의 최소 길이는 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설명하기
끔찍하다

-1

파이썬, 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)이 거의 회문 (palindrome)인지 확인하지 않지만 시간 효율적이며 읽기 쉽습니다.


2
s[-(i+1)]로 단축 할 수 있습니다 s[-i-1]. 또한, 잘 모르겠어요하지만 당신은 대체 할 수 있습니다 if...else...으로return i+1 if ... else len(s)-1
user12205

이것은 잘 작동했습니다. 누구든지 이것의 논리를 설명 할 수 있습니까?
Arindam Roychowdhury

입력이 추가 문자가있는 회문이 아닌 경우 -1을 출력해야합니다. 예를 들어 if 인 경우 s = "abcde"-1을 반환해야합니다.
G. Sliepen

-2

내 첫 번째 코드 골프.

자바. 기본 (및 하위) 기능에서 ~ 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.