Видаліть лист, щоб скласти паліндром


15

Проблема

Скажімо, що слово - це майже паліндром, якщо є можливість видалити одну з його літер, щоб слово стало паліндром. Ваше завдання - написати програму, яка для заданого слова визначає, яку букву видалити, щоб отримати паліндром.

Виграє найкоротший код для будь-якої мови програмування.

Вхідні дані

Введення складається з великих літер, довжиною від 2 до 1000 символів.

Вихідні дані

Виведіть 1-проіндексовану позицію (сама ліва літера має позицію 1, наступна - 2 та ін.) Листа, яку слід вилучити. Якщо можливі варіанти, які призводять до паліндрому, виведіть будь-яку з цих позицій. Зауважте, що вам потрібно видалити букву, навіть якщо це слово вже є паліндром. Якщо дане слово майже не паліндром, виведіть -1.


Приклад

Вхід:

racercar

може отримати результат:

5

тому що видалення 5букви утворює racecarпаліндром.

Також вхід

racecar

все ще може отримати вихід

4

тому що вилучення цього 4букви raccarвсе ще є паліндром.


5
Прикладів не розміщено? А що виводити, якщо неможливо зробити вхід у Паліндром?
ПрограмістDan

3
@ Arm103 Ви все ще не вистачаєте прикладів, про які ви посилаєтесь
Мартін Ендер

27
Попередження: "(див. Приклад 3)". Це говорить про те, що це домашнє завдання, оскільки жодного прикладу не було розміщено.
Джастін

3
@Quincunx Не забудьте також прочитати нитку в поданні Mathematica. :-)
Кріс Єстер-Янг

3
Це питання видається поза темою, оскільки приклад 3 відсутній у питанні.
devnull

Відповіді:


10

J - 31 25 char

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

Здебільшого стандартний тариф для J, тому я просто зазначу круті шматочки.

  • Прислівник \.називається Outfix . x u\. yвидаляє кожну інфіксацію довжини xз yі застосовується uдо результату кожного видалення. Ось, x1, yє вхідний рядок і uє (-:|.)тестом на відповідність рядку його зворотному. Звідси результат цього застосування \.списку булевих символів, 1 на місці кожного символу, видалення якого робить вхід паліндром.

  • I.створює список усіх індексів (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 офіційний - це добре
Джон Дворак

2
@Synthetica Нічого спеціально для Pythoners, але J для програмістів C - це чудовий ресурс для тих, хто мігрує з імперативного програмування.
алгоритм

10

Not-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

EDIT: Ні, зачекайте, це працює!

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
+1 для "Not PHP";)
Мартін Ендер

1
<? php $ line = fgets (STDIN); ?>
Користувач011001

2
@ User011001 Де це би вмістилося?
ɐɔıʇǝɥʇuʎs

1
Ви можете зберегти чарочку, написавши 1>0замість Trueі, видаливши пробіл між ]і forв...[::-1] for g...
Кая,

1
@Kaya Ви можете просто використовувати 1замість цього True. 1 == True, після всього.
Аршаджій

5

Математика, 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 hmmm, що таке програма в 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, так. Передостаннє речення спец.
Пітер Тейлор

Чому -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].


Якщо ви використовували діалект 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
Так весело !!!!! :)
Алмо

1
У версії для гольфу, де Rвизначено та використовується?
Зубна щітка

о так, слід сказати var R = s.Remove (i, 1). хороший улов
Уїлл Ньютон

3

Стакс , 8 10 байт

ú·àA÷¡%5Ñ╙

Запустіть і налагоджуйте його

Ця програма показує всі індекси на основі 1, які можна видалити з рядка, щоб утворити паліндром. А якщо таких немає, це показує -1.


2
Це виводить останній індекс замість -1, якщо паліндром не знайдений (тобто aaabbвиходи 5замість -1).
Kevin Cruijssen

1
@KevinCruijssen: Правильно ти є. Я зафіксував це ціною 2 байти.
рекурсивна

2

Рубін (61):

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

Тут є рішення для рубіну. Він поверне положення символу для видалення або -1, якщо цього зробити неможливо.

Я не можу допомогти, але відчуваю, що з розділом дублювання та зрізів слід покращити, але, здається, у 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);
    }
}

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

Haskell, 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

Брахілог , 24 байти

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

Спробуйте в Інтернеті!

Відчуває себе занадто довго.

Може бути на два байти коротше, якщо вихід може бути двоіндексованим :

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

Спробуйте в Інтернеті!

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просто прикро пояснювати :)
Г. Сліпен

-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) майже паліндром, але є часом ефективним і читабельним.


2
s[-(i+1)]можна скоротити до s[-i-1]. Крім того , я не впевнений , але ви можете бути в змозі замінити if...else...зreturn i+1 if ... else len(s)-1
user12205

Це спрацювало нормально ... Чи може хтось пояснити логіку цього?
Arindam Roychowdhury

Вимога полягає в тому, щоб він виводив -1, якщо вхід не є паліндром із зайвою літерою. Так, наприклад, якщо s = "abcde", він повинен повернути -1.
Г. Сліпен

-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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.