回文を作成するための最小限の挿入


15

今日は、別の回文チャレンジを行います!

したがって、今日のタスクは、文字列を取得し、それを回文に変換するために挿入するのに必要な文字の最小量を決定することです。

たとえば、文字列を取りましょうfishes

この場合、最善の方法はを追加することh ifであるため、結果は3になります。

fishe s
     h if
---------
fishehsif

で試してみましょうcodegolf。が繰り返されているのでo、次のことができます。

  codeg  o lf
fl     ed c
-------------
flcodegedoclf

5の結果を取得します。

テストケース

ppcg -> 2
codegolf -> 5
palindrome -> 9
stackexchange -> 8
programmingpuzzlesandcodegolf -> 20

1
関連、挿入は右側でのみ発生します。
xnor

2
繰り返しますが、2日前にこの正確なチャレンジのアイデアがありましたが、スコアリングシステムはコードの長さ+コードが実行されたときの出力でした。(つまり、コードはppcg、スコアは4 + 2 = 6)
-ETHproductions

5
これはいいチャレンジですが、同じトピックのチャレンジがもっと間隔を空けられたらいいと思います。ここ数日、多くの回文がありました。
-xnor

1
特定のプログラムが実際に最小量の文字を見つけることを証明するのは難しいかもしれません
-edc65

回答:


3

Pyth、10バイト

テストスイート。

l.-Qe@y_Qy

         y   All subsequences of the input (implicit), sorted by length
      y_Q    All subsequences of the reversed input, sorted by length
     @       Their setwise intersection: the common subsequences
    e        Last element: the longest common subsequence
 .-Q         Remove it bagwise from the input: the letters not in this LCS
l            The length of that

私たちが求めている値には、いくつかの同等の特性があります。

  • 回文を作成するのに必要な挿入数が最も少ない
  • 回文を作成するために必要な最小限の削除
  • 文字列を逆に変換するために必要な削除または挿入操作の数の半分
  • 最長の回文サブシーケンスが削除された入力の長さ
  • 入力の長さ。入力とその逆の間の最も長い共通サブシーケンスを削除します。(コードはこれを使用します。)

一般的な考え方は、最終製品の入力文字と一致する入力文字の「スケルトン」です。

  codeg  o lf
   *  *  *
fl o  gedoc 

flcodegedoclf

このスケルトンは常にパリンドロームであり、逆の文字に一致する文字があります。各非スケルトン文字は一致せず、対応する文字を挿入する必要があります。

同じ長さの代替では、代わりに4番目の条件、入力の長さからその最長パリンドロームサブシーケンスの長さを引いたものを使用します。

l.-Qef_ITy

テストスイートへのリンク。

異なる部分は

f_ITy

    y   All subsequences of the input (implicit), sorted by length.
f       Filtered on:
 _IT     being invariant under reversal, i.e. a palindrome

両方について、入力から回文のサブシーケンスを削除して長さを取得する代わりに、入力の長さからその長さを減算することができます。どちらも4バイトかかります:-lQlvs l.-Q


3

Python、112バイト

d=lambda x,l,h:0if h<l else d(x,l+1,h-1)if x[l]==x[h]else-~min(d(x,l+1,h),d(x,l,h-1));e=lambda x:d(x,0,len(x)-1)

非常に非効率的です。

オンラインでお試しください!最後のケースが終了するまで1分間待つ必要があります。

e(<string>, 0, <length of string - 1>)e( "fishes"、0、5) `のように、で呼び出します。

説明のないゴルフ(のような):

def minInsert(x, l, h):                # Declare func, arugments for x, l, h       # d=lambda x,l,h:
  if l >= h:                           # If l is the same or past h                #                 if h<l
    return 0                           #     then return 0                         #                0
  elif x[l] == x[h]:                   # If first and last character are the same  #                        else             if x[l]==x[h]
    return minInsert(x, l + 1, h - 1)  #     then return the min w/o first & last  #                             d(x,l+1,h-1)
  else:                                # If not, we shave off a character          #                                                      else
    a = minInsert(x, l, h - 1)         #     (last one)                            #                                                                d(x,l+1,h)
    b = minInsert(x, l + 1, h)         #     (first one)                           #                                                                           d(x,l,h-1)
    return min(a, b) + 1               #     and add one for the char we took off  #                                                          -~min(          ,          )

3
データ(リストの長さ)を使用して追加の入力を取得することは、デフォルトでは無効です。どちらも0の入力ではありませんが、デフォルトの引数で修正できますl=0
xnor

@xnor固定.---
オリバーニッケル

@ edc65私はエティテッド。
オリバーNi


2

Brachylog、9バイト

⊆P↔P;?lᵐ-

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

挿入回文化はその言語では非常に直感的であるため、この課題には本当にBrachylog v2の回答が必要でした。

説明

⊆P↔P挿入による回文化は実際に行われます(この例を参照)

⊆P           P is an ordered superset of the input
 P↔P         P reversed is P (i.e. P is a palindrome)
   P;?lᵐ     Compute the length of both P and the input
        -    Subtraction

1

C、89121バイト

#define g(a) f(a,a+strlen(a)-1)
f(char*a,char*b){return a>=b?0:*a-*b?f(a+1,b)<f(a,b-1)?f(++a,b)+1:f(a,--b)+1:f(++a,--b);}

オリバーの恥知らずなポートは、より短い解決策を考えることができませんでした。

gf文字列の最初と最後の文字へのポインタで呼び出します(最後の文字は文字列の一部であり、ではありません'\0')。fこのminケースでは2回呼び出されるため、さらに非効率になります。

ゴルフをしていない:

f(char*a,char*b){
 return a>=b ? 0 :
   *a-*b ?    //if the pointed chars are not the same
     f(a+1,b)<f(a,b-1) ? f(a+1,b)+1 : f(a,b-1)+1    //min(f..,f..)+1
   : f(a+1,b-1);  //if they were the same, make it more narrow
 }

使用法:

int main(){
 char s[]="palindrome";
 printf("%d\n",g(s));
}

2
データを使用して追加の入力を取得することはデフォルトでは無効です
-edc65

1

Brachylog v1バイト

,IrIs?:I:lar-

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

見つかった回文を確認できます このコードます

説明

私はこれがうまくいくことをほとんど驚いています。

,IrI             I reversed is I (i.e. I is a palindrome)
   Is?           The Input is an ordered subset of I
     ?:I:la      The list [length(Input), length(I)]
           r-    Output = length(I) - length(Input)

これにより、最小の回文が見つかることが保証されます。 IrIにより、空の文字列から開始してバックトラックするときに長さが増加する文字列が生成。

これは、を使用するため、TIOで最後のテストケースを計算するのに十分効率的ではありませんs - Ordered subset


0

バッチ、234 232バイト

@echo off
set n=99
call:l 0 %1
echo %n%
exit/b
:g
set/am=%1
if %m% lss %n% set/an=m
exit/b
:l
if "%2"=="" goto g
set s=%2
if %s:~,1%==%s:~-1% call:l %1 %s:~1,-1%&exit/b
call:l %1+1 %s:~1%
set s=%2
call:l %1+1 %s:~,-1%

両端に一致しない文字を再帰的に挿入しようとすると動作するため、非常に遅くなります(最後のテストケースは試しませんでした)。再帰制限は、これはとにかく限られた文字列の長さに対してのみ機能することを意味するため、これ99はややarbitrary 意的です。私は自分で作業するcallことができなかったため、ローカル変数としてパラメーターを使用する必要がありますsetlocal。つまり%1:lサブルーチンへのパラメーターは、これまでに行われた挿入の数を評価する式です。

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