Удалить письмо, чтобы сделать палиндром

15

проблема

Допустим, слово является почти палиндромом, если можно удалить одну из его букв, чтобы слово стало палиндромом. Ваша задача - написать программу, которая по заданному слову определяет, какую букву убрать, чтобы получить палиндром.

Самый короткий код для этого на любом языке программирования выигрывает.

вход

Ввод состоит из заглавных букв длиной от 2 до 1000 символов.

Выход

Выведите 1 индексированную позицию (крайняя левая буква имеет позицию 1, следующая - 2 и т. Д.) Буквы, которую следует удалить. Если есть возможные варианты, которые ведут к палиндрому, выведите любое из этих положений. Обратите внимание, что вам необходимо удалить букву, даже если данное слово уже является палиндромом. Если данное слово не является почти палиндромом, выведите -1.


пример

Вход:

racercar

может произвести вывод:

5

потому что удаление этой 5буквы производит racecar, что палиндром.

Кроме того, вход

racecar

все еще может произвести вывод

4

потому что удаление этой 4буквы до raccarсих пор является палиндромом.

User011001
источник
5
Примеры не опубликованы? А что выводить, если не получается сделать вход в палиндром?
ProgrammerDan
3
@ Arm103, вы все еще скучаете по тем примерам, на которые вы ссылаетесь
Мартин Эндер,
27
Предупреждение: «(см. Пример 3)». Это говорит о том, что это домашнее задание, так как примеров не было.
Джастин
3
@Quincunx Обязательно прочитайте ветку в представлении Mathematica. :-)
Крис Шестер-Янг
3
Этот вопрос не по теме, потому что в вопросе отсутствует пример 3 .
devnull

Ответы:

10

J - 31 25 символов

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

В основном стандартный тариф для J, так что я просто укажу на интересные моменты.

  • Наречие \.называется Outfix . x u\. yудаляет каждый инфикс длины xиз yи применяется uк результату каждого удаления. Здесь x1 yравно входной строке и uявляется (-:|.)проверкой соответствия строки обратному. Следовательно, результатом этого применения \.является список логических значений, 1 на месте каждого символа, удаление которого делает ввод палиндромом.

  • I.создает список всех индексов (0-origin) сверху, где было 1. При добавлении 1 с получаются 1+эти индексы 1-origin. Если индексы не были равны 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
algorithmshark
источник
Я должен выучить J. Какие-нибудь учебники для программиста на питоне?
Aprıʇǝɥʇuʎs
1
@Synthetica - официальный, хороший
Джон Дворжак,
2
@Synthetica Ничего особенного для Python, но J для программистов на Си - отличный ресурс для любого, кто мигрирует с императивного программирования.
алгоритмшарк
10

Не-PHP Python (73):

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

Где это строка, которую вы хотите проверить. Это, однако, выдает ошибку, если вы не можете превратить его в палиндром. Вместо этого вы можете использовать

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% (это то, что вы хотите, верно?)

ɐɔıʇǝɥʇuʎs
источник
10
+1 за "Не PHP";)
Мартин Эндер
1
<? php $ line = fgets (STDIN); ?>
User011001
2
@ User011001 Где это будет соответствовать?
Aprıʇǝɥʇuʎs
1
Вы можете сохранить символ каждый, написав 1>0вместо Trueи удалив пробел между ]и forвнутри...[::-1] for g...
Kaya
1
@Kaya Вы можете просто использовать 1вместо того, чтобы True. 1 == True, в конце концов.
Аршаджи
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 Я мог бы, но я оставлю это кому-то другому. ;)
Мартин Эндер
2
@ Arm103 подожди, это твоя домашняя работа?
Джон Дворжак
2
@JanDvorak Есть курсы CS, которые используют PHP? Это было бы страшно.
Крис Шестер-Янг
2
@ Arm103 нет. Вы не можете ;-)
Джон Дворак
4
@JanDvorak Хммм, что за программа в Mathematica?
Мартин Эндер
5

GolfScript, 28 26 символов

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

Спасибо Петру за сокращение на 2 символа. Попробуйте тестовые случаи онлайн :

> "RACECAR" 
4
> "RAACECAR" 
2
> "RAAACECAR" 
-1
> "ABCC1BA" 
5
> "AAAAAA" 
1
> "ABCDE" 
-1
> "" 
-1
> "A" 
1
Говард
источник
Угадай, должно быть, есть более короткий путь, но я не нашел его.
Говард
RACECARвсе еще является палиндромом с E. Нужно ли указывать символ для удаления, когда введенное слово уже является палиндромом?
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"этого вернется список [4 5].

draegtun
источник
Если вы использовали диалект Rebmu, то первое решение состоит всего из 37 символов, несмотря на то, что это в основном тот же код :-) Вызывать как rebmu / args "Rng01rpNl? A [ThdRMatCYaNieTrvCYt [Rn]] r" "racecar" . Обратите внимание, что документация Rebmu была улучшена, а недавние изменения немного ее ужесточили ... все еще ожидая обратной связи, прежде чем все и их D начнут ее использовать. :-)
HostileFork говорит, что не доверяйте 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
Ура весело !!!!! :)
Almo
1
В версии для гольфа, где Rопределяется и используется?
Зубная щетка
о да, это должно сказать var R = s.Remove (i, 1). хороший улов
Уилл Ньютон
3

Stax , 8 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, который удаляет символ по определенному индексу и возвращает новую строку -__-.

Отредактировано согласно комментарию, ты!

Майк Кэмпбелл
источник
1
Вы можете сэкономить место, не заключая в функцию / метод. Однако ваш код в настоящее время возвращает индекс на основе 0 (должен быть на основе 1), а также должен возвращаться, -1если не найдено палиндрома.
draegtun
Исправил -1, спасибо. Не уверен, что ты имеешь в виду, принимая метод, хотя, я подумаю.
Майк Кэмпбелл
Хорошо, принял ваш совет на борту и переписал его :), ты.
Майк Кэмпбелл
Пожалуйста! Теперь это намного лучше :) +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

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);
    }
}
Mormegil
источник
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
Flonk
источник
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

Ungolfed:

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
danmcardle
источник
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

Брахилог , 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противном случае.

Jitse
источник
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 байт сбриты благодаря функциюcatcat! И еще 3 байта, поскольку в правилах указывается, что минимальная длина ввода составляет 2 символа, поэтому не нужно проверять наличие пустых строк.

Ungolfed:

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

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) почти палиндромом, но он эффективен по времени и удобочитаем.

nicofmay
источник
2
s[-(i+1)]можно сократить до s[-i-1]. Кроме того , я не уверен , но вы можете быть в состоянии заменить if...else...сreturn i+1 if ... else len(s)-1
user12205
Это сработало хорошо .. Кто-нибудь может объяснить логику этого?
Ариндам Ройховдхури
Требуется, чтобы он выводил -1, если ввод не является палиндромом с дополнительной буквой. Так, например, если s = "abcde", он должен вернуть -1.
Г. Слипен
-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();
   }
}
aliteralmind
источник
3
Это показывает отсутствие попыток игры в гольф.
mbomb007